Skip to content

Commit

Permalink
refactor FieldContextMenu making it hoverable
Browse files Browse the repository at this point in the history
  • Loading branch information
beliolfa committed Aug 28, 2023
1 parent 479885a commit 09aa72e
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 130 deletions.
11 changes: 6 additions & 5 deletions src/lib/editor/form/AbstractField.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
function handleHover(e: CustomEvent<boolean>) {
// @note: Prevent undesired hover events on other items while dragging
console.log(e.detail);
isHover = e.detail;
}
Expand Down Expand Up @@ -125,13 +126,13 @@
on:focusin={handleFocusIn}
on:focusout={handleFocusOut}
>
<div>
{#if showContextMenu}
<FieldContextMenu {field} on:addField={handleAddField} />
{/if}
<div class="relative p-0.5 pl-2.5 pr-0" class:pr-2.5={!field.children}>
<div class="flex">
<div class="flex-1 p-0.5 pl-2.5 pr-0" class:pr-2.5={!field.children}>
<svelte:component this={componentsMap[field.type] || FallbackField} {field} />
</div>
<span class={!showContextMenu ? "invisible" : ""}>
<FieldContextMenu {field} on:addField={handleAddField} />
</span>
</div>
</div>
{#if addMenu}
Expand Down
22 changes: 22 additions & 0 deletions src/lib/editor/form/FieldButton.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts">
import Tooltip from "$lib/ui/Tooltip.svelte";
import { Icon, type IconSource } from "svelte-hero-icons";
export let icon: IconSource;
export let tooltipText = "";
export let isDestructive = false;
</script>

<Tooltip>
<svelte:fragment slot="content">
<p class="whitespace-nowrap">{tooltipText}</p>
</svelte:fragment>
<button
on:click
class="flex items-center justify-start w-full p-2 {isDestructive
? 'hover:bg-red-400 hover:text-white'
: 'hover:bg-gray-200'}"
>
<Icon src={icon} class="h-4 w-4 p-0.5" />
</button>
</Tooltip>
95 changes: 24 additions & 71 deletions src/lib/editor/form/FieldButtons.svelte
Original file line number Diff line number Diff line change
@@ -1,95 +1,48 @@
<script lang="ts">
import Tooltip from "$lib/ui/Tooltip.svelte";
import { fade } from "svelte/transition";
import { Trash, DocumentDuplicate, ArrowUp, ArrowDown, Plus } from "svelte-hero-icons";
import { createEventDispatcher } from "svelte";
import type { UIModelField } from "./utils/model.js";
import { ArrowUp, ArrowDown } from "svelte-hero-icons";
import FieldButton from "./FieldButton.svelte";
export let field: UIModelField | undefined = undefined;
export let showAdd = true;
export let showOptions = true;
export let canMoveUp = false;
export let canMoveDown = false;
const dispatch = createEventDispatcher();
function handleClickAddButton(e: MouseEvent) {
e.ctrlKey;
dispatch("add", e.ctrlKey || e.altKey || e.metaKey || e.shiftKey);
}
function handleClickOptionsButton() {
dispatch("options");
}
function handleClickMoveUpButton() {
dispatch("moveUp");
}
function handleClickMoveDownButton() {
dispatch("moveDown");
}
$: classes = field?.is.calculated ? "bg-blue-100" : "bg-color2";
</script>

<div
id="fieldBackground"
class="absolute flex w-full h-full top-0 z-0 rounded {classes}"
transition:fade={{ duration: 200 }}
>
<div class="flex-shrink-0 absolute left-full h-9 ml-1 top-0 rounded {classes}">
<div class="flex align-middle text-grey-5 h-full">
<div id="fieldBackground" class="flex w-full h-full rounded {classes}" transition:fade={{ duration: 200 }}>
<div class="flex-shrink-0 left-full h-9 ml-1 top-0 rounded {classes}">
<ul class="flex align-middle text-grey-5 h-full">
{#if showAdd}
<Tooltip>
<svelte:fragment slot="content">
<p class="whitespace-nowrap">Add field</p>
</svelte:fragment>
<button on:click={handleClickAddButton} class="p-2.5 h-full pr-0.5 border border-transparent" tabindex="-1">
<svg viewBox="0 0 16 16" class="h-5 w-5 p-1 hover:bg-gray-100 rounded">
<path
fill="currentColor"
d="M7.977 14.963c.407 0 .747-.324.747-.723V8.72h5.362c.399 0 .74-.34.74-.747a.746.746 0 00-.74-.738H8.724V1.706c0-.398-.34-.722-.747-.722a.732.732 0 00-.739.722v5.529h-5.37a.746.746 0 00-.74.738c0 .407.341.747.74.747h5.37v5.52c0 .399.332.723.739.723z"
/>
</svg>
</button>
</Tooltip>
<li>
<FieldButton icon={Plus} tooltipText="Add field" on:click={() => dispatch("add")} />
</li>
{/if}
{#if field?.is.duplicable}
<li>
<FieldButton icon={DocumentDuplicate} tooltipText="Duplicate" on:click={() => dispatch("duplicate")} />
</li>
{/if}
{#if showOptions}
<Tooltip>
<svelte:fragment slot="content">
<p class="whitespace-nowrap">Options</p>
</svelte:fragment>
<button on:click={handleClickOptionsButton} class="p-2.5 h-full border border-transparent" tabindex="-1">
<svg viewBox="0 0 8 8" class="h-5 w-5 p-1 hover:bg-gray-100 rounded">
<path
fill="currentColor"
d="M3,2 C2.44771525,2 2,1.55228475 2,1 C2,0.44771525 2.44771525,0 3,0 C3.55228475,0 4,0.44771525 4,1 C4,1.55228475 3.55228475,2 3,2 Z M3,6 C2.44771525,6 2,5.55228475 2,5 C2,4.44771525 2.44771525,4 3,4 C3.55228475,4 4,4.44771525 4,5 C4,5.55228475 3.55228475,6 3,6 Z M3,10 C2.44771525,10 2,9.55228475 2,9 C2,8.44771525 2.44771525,8 3,8 C3.55228475,8 4,8.44771525 4,9 C4,9.55228475 3.55228475,10 3,10 Z M7,2 C6.44771525,2 6,1.55228475 6,1 C6,0.44771525 6.44771525,0 7,0 C7.55228475,0 8,0.44771525 8,1 C8,1.55228475 7.55228475,2 7,2 Z M7,6 C6.44771525,6 6,5.55228475 6,5 C6,4.44771525 6.44771525,4 7,4 C7.55228475,4 8,4.44771525 8,5 C8,5.55228475 7.55228475,6 7,6 Z M7,10 C6.44771525,10 6,9.55228475 6,9 C6,8.44771525 6.44771525,8 7,8 C7.55228475,8 8,8.44771525 8,9 C8,9.55228475 7.55228475,10 7,10 Z"
/>
</svg>
</button>
</Tooltip>
{#if field?.is.disposable}
<li>
<FieldButton icon={Trash} tooltipText="Remove" isDestructive={true} on:click={() => dispatch("remove")} />
</li>
{/if}
{#if canMoveUp}
<Tooltip>
<svelte:fragment slot="content">
<p class="whitespace-nowrap">Move Up</p>
</svelte:fragment>
<button on:click={handleClickMoveUpButton} class="p-2.5 h-full border border-transparent" tabindex="-1">
<ArrowUp />
</button>
</Tooltip>
<li>
<FieldButton icon={ArrowUp} tooltipText="Move Up" on:click={() => dispatch("moveUp")} />
</li>
{/if}
{#if canMoveDown}
<Tooltip>
<svelte:fragment slot="content">
<p class="whitespace-nowrap">Move Up</p>
</svelte:fragment>
<button on:click={handleClickMoveDownButton} class="p-2.5 h-full border border-transparent" tabindex="-1">
<ArrowDown />
</button>
</Tooltip>
<li>
<FieldButton icon={ArrowDown} tooltipText="Move Down" on:click={() => dispatch("moveDown")} />
</li>
{/if}
</div>
</ul>
</div>
</div>
58 changes: 4 additions & 54 deletions src/lib/editor/form/FieldContextMenu.svelte
Original file line number Diff line number Diff line change
@@ -1,69 +1,19 @@
<script lang="ts">
import { fade } from "svelte/transition";
import { Icon, Trash, DocumentDuplicate } from "svelte-hero-icons";
import { getFormEditorContext } from "./context/formEditor.js";
import { createEventDispatcher } from "svelte";
import FieldButtons from "$lib/editor/form/FieldButtons.svelte";
import type { UIModelField } from "./utils/model.js";
const { deleteField, duplicateField } = getFormEditorContext() || {};
const dispatch = createEventDispatcher();
export let field: UIModelField;
export let showOptionsMenu = false;
const { deleteField, duplicateField } = getFormEditorContext() || {};
function handleClickAddButton(e: CustomEvent<boolean>) {
showOptionsMenu = false;
dispatch("addField", e.detail);
}
function handleToggleOptionMenu() {
showOptionsMenu = !showOptionsMenu;
}
function handleRemove() {
deleteField(field);
showOptionsMenu = false;
}
function handleDuplicate() {
duplicateField(field);
showOptionsMenu = false;
}
</script>

<FieldButtons
{field}
showAdd={!field.parent?.is.complete}
showOptions={field.is.duplicable || field.is.disposable}
on:add={handleClickAddButton}
on:options={handleToggleOptionMenu}
on:add={() => dispatch("addField")}
on:duplicate={() => duplicateField(field)}
on:remove={() => deleteField(field)}
/>

{#if showOptionsMenu}
<div class="absolute top-11 -left-9 z-10 w-28" transition:fade={{ duration: 200 }}>
<ul class="grow-0 flex flex-col list-none bg-white border rounded-lg overflow-hidden" role="menu">
{#if field.is.duplicable}
<li>
<button
on:click={handleDuplicate}
class="flex items-center justify-start w-full p-2 border-b gap-2 hover:bg-gray-200"
>
<Icon src={DocumentDuplicate} class="h-4 w-4 p-0.5" /> Duplicate
</button>
</li>
{/if}
{#if field.is.disposable}
<li>
<button
on:click={handleRemove}
class="flex items-center justify-start w-full p-2 gap-2 hover:bg-red-400 hover:text-white"
>
<Icon src={Trash} class="h-4 w-4 p-0.5" /> Remove
</button>
</li>
{/if}
</ul>
</div>
{/if}

0 comments on commit 09aa72e

Please sign in to comment.