Skip to content

Commit

Permalink
Add new layout for simplfied arrays (strings)
Browse files Browse the repository at this point in the history
  • Loading branch information
beliolfa committed Sep 26, 2024
1 parent 646a6fd commit 5768cae
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 61 deletions.
80 changes: 47 additions & 33 deletions src/lib/editor/form/AbstractField.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import BooleanField from "./BooleanField.svelte";
import clsx from "clsx";
import { getBuilderContext } from "$lib/store/builder";
import type { Schema } from "./utils/schema";
const dispatch = createEventDispatcher();
Expand All @@ -34,6 +35,7 @@
export let readOnly = false;
$: childrenType = (field.schema.items as Schema)?.type;
$: isHover = $activeItem === field.id;
$: highlight = $highlightedItem === field.id;
$: showContextMenu = !readOnly && isHover;
Expand All @@ -42,19 +44,20 @@
const offset = top + height - window.innerHeight;
contextMenuOffset = offset > 0 ? offset : 0;
}
$: isParent = ["object", "array"].includes(field.type);
$: isParent = ["object", "array"].includes(field.type) && childrenType !== "string";
$: isSection = isParent && field.parent?.is.root;
$: wrapperClasses = clsx({
"bg-neutral-50 border-neutral-100": isHover && !isParent,
"border-transparent": !isHover,
"border-l border-t border-b": !isParent,
"border-l border-t border-b": !["object", "array"].includes(field.type),
"border-r rounded-r": readOnly && !isParent,
"pl-2": isParent && !isSection,
});
$: classes = clsx({
"bg-neutral-50": isHover,
"border-workspace-accent-500": highlight,
"border-neutral-200": !highlight,
"border-l border-t border-b": childrenType !== "string",
});
$: contextMenuClasses = clsx({
"mt-1": isParent && !isSection && !field.is.root,
Expand All @@ -78,20 +81,29 @@
function handleAddField() {
showAddMenu = false;
// Children of string arrays can add items directly from the row
if (field.type === "string" && field.parent?.type === "array") {
addFieldToArray(field.parent);
return;
}
// @note: Add field directly instead of showing the dropdown option list
if (field.type === "array" || field.controlType === "dictionary") {
const [childOption] = field.options || [];
const newField = field.addChildField(childOption);
newField?.tryFocus();
dispatch("fieldAdded", newField);
addFieldToArray(field);
return;
}
showAddMenu = true;
}
function addFieldToArray(f: UIModelField) {
const [childOption] = f.options || [];
const newField = f.addChildField(childOption);
newField?.tryFocus();
dispatch("fieldAdded", newField);
}
function focusNextField(nextField = field.getNextFocusableField()) {
if (!nextField) return;
nextField.tryFocus(5, 0);
Expand Down Expand Up @@ -156,7 +168,7 @@
>
<div class="{wrapperClasses} rounded-l flex" class:my-1={isParent}>
{#if isParent && !isSection && !field.is.root}
<div class="{classes} w-2 border-l border-t border-b flex-none rounded-l"></div>
<div class="{classes} w-2 flex-none rounded-l"></div>
{/if}
<div class="flex-1">
<svelte:component
Expand All @@ -172,31 +184,33 @@
/>
</div>
</div>
<div class="absolute top-0 right-0 w-9 h-10 -mr-9">
<span
class="{contextMenuClasses} absolute top-0 left-0 -ml-px pt-[7px] pr-2 pb-[5.5px] bg-neutral-50 border-t border-b border-r border-neutral-100 rounded-r border-l-neutral-50 border-l"
class:invisible={!showContextMenu}
>
<FieldContextMenu
{field}
on:addField={handleAddField}
on:fieldDeleted
on:fieldDuplicated
on:fieldMoved
on:fieldValueUpdated
on:fieldKeyUpdated
/>
</span>
{#if showAddMenu}
<div
class="absolute top-12 -right-8 w-64 z-20"
style={`margin-top: -${contextMenuOffset}px`}
bind:this={addMenuRef}
{#if childrenType !== "string"}
<div class="absolute top-0 right-0 w-9 h-10 -mr-9 bg-transparent">
<span
class="{contextMenuClasses} absolute top-0 left-0 -ml-px pt-[7px] pr-2 pb-[5.5px] bg-neutral-50 border-t border-b border-r border-neutral-100 rounded-r border-l-neutral-50 border-l"
class:invisible={!showContextMenu}
>
<AddFieldMenu on:fieldAdded {field} on:closeAddFieldMenu={() => (showAddMenu = false)} />
</div>
{/if}
</div>
<FieldContextMenu
{field}
on:addField={handleAddField}
on:fieldDeleted
on:fieldDuplicated
on:fieldMoved
on:fieldValueUpdated
on:fieldKeyUpdated
/>
</span>
{#if showAddMenu}
<div
class="absolute top-12 -right-8 w-64 z-20"
style={`margin-top: -${contextMenuOffset}px`}
bind:this={addMenuRef}
>
<AddFieldMenu on:fieldAdded {field} on:closeAddFieldMenu={() => (showAddMenu = false)} />
</div>
{/if}
</div>
{/if}
</div>

<style>
Expand Down
12 changes: 7 additions & 5 deletions src/lib/editor/form/FieldButtons.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
const dispatch = createEventDispatcher();
$: showAdd = ["object", "array"].includes(field?.type || "");
$: parentIsArray = field?.parent?.type === "array";
$: isArrayStringChildren = parentIsArray && field?.type === "string";
$: showAdd = ["object", "array"].includes(field?.type || "") || isArrayStringChildren;
$: addLabel = field?.type === "array" ? "Add Row" : "Add Property";
$: canMove = field?.parent?.type === "array";
$: canMoveUp = canMove && Number(field?.key) > 0;
$: canMoveDown = canMove && Number(field?.key) < Number(field?.parent?.children?.length) - 1;
$: canDuplicate = field?.is.duplicable && !isArrayStringChildren;
$: canMoveUp = parentIsArray && Number(field?.key) > 0;
$: canMoveDown = parentIsArray && Number(field?.key) < Number(field?.parent?.children?.length) - 1;
</script>

<ul
Expand All @@ -25,7 +27,7 @@
<FieldButton icon={Plus} tooltipText={addLabel} on:click={() => dispatch("add")} />
</li>
{/if}
{#if field?.is.duplicable}
{#if canDuplicate}
<li>
<FieldButton icon={DocumentDuplicate} tooltipText="Duplicate" on:click={() => dispatch("duplicate")} />
</li>
Expand Down
25 changes: 19 additions & 6 deletions src/lib/editor/form/FieldTitle.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
import { clsx } from "clsx";
import type { UIModelField } from "$lib/editor/form/utils/model.js";
import { Calculator, Hashtag, Icon } from "svelte-hero-icons";
import type { Schema } from "./utils/schema";
export let field: UIModelField<unknown>;
$: childrenType = (field.schema.items as Schema)?.type;
$: arrayTitle = field.schema.title || "";
$: isParent = ["object", "array"].includes(field.type);
$: isParent = ["object", "array"].includes(field.type) && childrenType !== "string";
$: isSection = field.is.root || (field.parent?.is.root && isParent);
$: classes = clsx({
"font-medium text-neutral-800": isParent,
Expand All @@ -17,14 +19,25 @@
</script>

<span
class="{classes} whitespace-nowrap flex items-center"
class="{classes} whitespace-nowrap flex items-center w-full"
class:capitalize={!field.schema.title && !field.is.editableKey}
>
{#if field.parent?.isArray()}
<span class="flex items-center justify-start">
<Icon src={Hashtag} class="h-4 w-4" />
{arrayTitle}
{Number(field.key) + 1}
<span
class:justify-start={field.type !== "string"}
class:justify-between={field.type === "string"}
class="flex items-center w-full"
>
<span>
{#if field.key === "0"}
{field.parent.schema.title || field.parent.key}
{/if}
</span>
<span class="flex items-center">
<Icon src={Hashtag} class="h-4 w-4" />
{arrayTitle}
{Number(field.key) + 1}
</span>
</span>
{:else}
<span class="flex items-center space-x-1">
Expand Down
15 changes: 13 additions & 2 deletions src/lib/editor/form/RootField.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import type { UIModelRootField, UIModelField } from "$lib/editor/form/utils/model.js";
import AbstractField from "./AbstractField.svelte";
import SectionWrapper from "./SectionWrapper.svelte";
import type { Schema } from "./utils/schema";
export let field: UIModelRootField;
export let readOnly = false;
Expand All @@ -10,8 +11,18 @@
$: children = field.children?.filter((f) => f.key !== "$schema") || emptyChildren;
// @todo: Add title field to schema object on gobl
$: complexFields = children.filter((f) => ["array", "object"].includes(f.type));
$: simpleFields = children.filter((f) => !["array", "object"].includes(f.type));
$: complexFields = children.filter((f) => {
if ((f.schema.items as Schema)?.type === "string") {
return false;
}
return ["array", "object"].includes(f.type);
});
$: simpleFields = children.filter((f) => {
if ((f.schema.items as Schema)?.type === "string") {
return true;
}
return !["array", "object"].includes(f.type);
});
</script>

<SectionWrapper {readOnly} {field}>
Expand Down
33 changes: 19 additions & 14 deletions src/lib/editor/form/SectionWrapper.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import clsx from "clsx";
import { getContext } from "svelte";
import { getBuilderContext } from "$lib/store/builder";
import type { Schema } from "./utils/schema";
const { envelopeIsSigned } = getBuilderContext();
Expand Down Expand Up @@ -34,16 +35,18 @@
let element: HTMLElement;
let open = true;
$: childrenType = (field.schema.items as Schema)?.type;
$: label = $envelopeIsSigned
? "Document is signed and can not be edited"
: `${field.schema.description || ""}${field.is.calculated ? " (calculated)" : ""}`;
$: isParent = ["object", "array"].includes(field.type);
$: isParent = ["object", "array"].includes(field.type) && childrenType !== "string";
$: isSection = field.is.root || (isParent && field.parent?.is.root);
$: wrapperClasses = clsx({
"rounded-r": readOnly,
"border-neutral-100 bg-neutral-50": isActive,
"border-l rounded-l": isSection,
"border-transparent": !isActive,
"border-t border-b border-r": childrenType !== "string",
});
$: isActive = field.id === $activeItem;
Expand Down Expand Up @@ -71,25 +74,27 @@
}
</script>

<div bind:this={element} id={field.id} title={label} class="{wrapperClasses} border-t border-b border-r">
<div bind:this={element} id={field.id} title={label} class={wrapperClasses}>
{#if isSection}
<div use:intersect={intersectOptions}></div>
{/if}
<div class="py-2 pl-3 pr-2">
<button
class="flex items-center justify-start cursor-pointer"
on:click={() => {
open = !open;
}}
>
<FieldTitle {field} />
<ExpandButton {open} />
</button>
</div>
{#if isParent}
<div class="py-2 pl-3 pr-2">
<button
class="flex items-center justify-start cursor-pointer"
on:click={() => {
open = !open;
}}
>
<FieldTitle {field} />
<ExpandButton {open} />
</button>
</div>
{/if}

{#if open}
<div transition:slide class:overflow-hidden={!open} on:focusin|capture={handleFocusInner}>
<div class="grid grid-cols-1 w-full pb-1">
<div class:pb-1={isParent} class="grid grid-cols-1 w-full">
<slot />
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/editor/form/utils/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class UIModelField<V extends SchemaValue | unknown = unknown> {
root?: UIModelRootField,
) {
this.id = `${this.parent?.id ? `${this.parent.id}` : `${this.uniqueId}`}-${this.key}`.replace(
/[^a-zA-Z0-9-_\\$]/g,
/[^a-zA-Z0-9-_]/g,
"",
);
this.type = this.schema.type as string;
Expand Down

0 comments on commit 5768cae

Please sign in to comment.