From 26f85a0f9d48b43721a3db2210a151c5c11feb9e Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Wed, 5 May 2021 01:22:51 +0200 Subject: [PATCH] Add API for adding new buttons, updating existing ones in ButtonGroup --- ts/components/ButtonGroup.svelte | 111 ++++++++++++++++----------- ts/components/ButtonGroupItem.svelte | 8 +- ts/components/Detachable.svelte | 11 +++ ts/components/LabelButton.svelte | 64 ++++++++------- ts/components/StickyBar.svelte | 2 +- ts/components/hideable.ts | 20 ----- ts/components/identifiable.ts | 92 ---------------------- ts/components/identifier.ts | 55 +++++++++++++ ts/editor/EditorToolbar.svelte | 10 ++- ts/editor/index.ts | 3 +- ts/editor/toolbar.ts | 2 + ts/sass/button_mixins.scss | 2 + 12 files changed, 187 insertions(+), 193 deletions(-) create mode 100644 ts/components/Detachable.svelte delete mode 100644 ts/components/hideable.ts delete mode 100644 ts/components/identifiable.ts create mode 100644 ts/components/identifier.ts diff --git a/ts/components/ButtonGroup.svelte b/ts/components/ButtonGroup.svelte index bad832a90..421f3b107 100644 --- a/ts/components/ButtonGroup.svelte +++ b/ts/components/ButtonGroup.svelte @@ -3,32 +3,83 @@ Copyright: Ankitects Pty Ltd and contributors License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html --> @@ -37,48 +88,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html div { display: flex; justify-items: start; - flex-wrap: var(--toolbar-wrap); padding: calc(var(--toolbar-size) / 10); margin: 0; - - > :global(button), - > :global(select) { - border-radius: calc(var(--toolbar-size) / 7.5); - - &:not(:nth-of-type(1)) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - } - - &:not(:nth-last-of-type(1)) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - } - } - - &.border-overlap-group { - :global(button), - :global(select) { - margin-left: -1px; - } - } - - &.gap-group { - :global(button), - :global(select) { - margin-left: 1px; - } - } } -
+
+ {#each dynamic as component} + + {/each}
diff --git a/ts/components/ButtonGroupItem.svelte b/ts/components/ButtonGroupItem.svelte index 1bb1e8f4a..7e886737d 100644 --- a/ts/components/ButtonGroupItem.svelte +++ b/ts/components/ButtonGroupItem.svelte @@ -3,11 +3,15 @@ Copyright: Ankitects Pty Ltd and contributors License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html --> - + + + diff --git a/ts/components/Detachable.svelte b/ts/components/Detachable.svelte new file mode 100644 index 000000000..d58037b37 --- /dev/null +++ b/ts/components/Detachable.svelte @@ -0,0 +1,11 @@ + + + +{#if !detach} + +{/if} diff --git a/ts/components/LabelButton.svelte b/ts/components/LabelButton.svelte index a999d4b61..a7cd701cf 100644 --- a/ts/components/LabelButton.svelte +++ b/ts/components/LabelButton.svelte @@ -4,35 +4,32 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html --> @@ -45,27 +42,36 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html font-size: calc(var(--toolbar-size) / 2.3); width: auto; height: var(--toolbar-size); + + border-radius: calc(var(--toolbar-size) / 7.5); + + &:not(:nth-of-type(1)) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + + &:not(:nth-last-of-type(1)) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } } @include button.btn-day; @include button.btn-night; - - - + diff --git a/ts/components/StickyBar.svelte b/ts/components/StickyBar.svelte index e3a9679c8..5f85b8802 100644 --- a/ts/components/StickyBar.svelte +++ b/ts/components/StickyBar.svelte @@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html --> diff --git a/ts/components/hideable.ts b/ts/components/hideable.ts deleted file mode 100644 index 4df9af725..000000000 --- a/ts/components/hideable.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright: Ankitects Pty Ltd and contributors -// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -interface Hideable { - hidden?: boolean; -} - -export function showComponent(component: T): T { - component.hidden = false; - return component; -} - -export function hideComponent(component: T): T { - component.hidden = true; - return component; -} - -export function toggleComponent(component: T): T { - component.hidden = !component.hidden; - return component; -} diff --git a/ts/components/identifiable.ts b/ts/components/identifiable.ts deleted file mode 100644 index f44015d19..000000000 --- a/ts/components/identifiable.ts +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright: Ankitects Pty Ltd and contributors -// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -export interface Identifiable { - id?: string; -} - -interface IterableIdentifiable extends Identifiable { - items: T[]; -} - -export type Identifier = string | number; - -function normalize( - iterable: IterableIdentifiable, - idOrIndex: Identifier -): number { - let normalizedIndex: number; - - if (typeof idOrIndex === "string") { - normalizedIndex = iterable.items.findIndex((value) => value.id === idOrIndex); - } else if (idOrIndex < 0) { - normalizedIndex = iterable.items.length + idOrIndex; - } else { - normalizedIndex = idOrIndex; - } - - return normalizedIndex >= iterable.items.length ? -1 : normalizedIndex; -} - -function search(values: T[], index: number): T | null { - return index >= 0 ? values[index] : null; -} - -export function insert( - iterable: IterableIdentifiable & T, - value: T, - idOrIndex: Identifier -): IterableIdentifiable & T { - const index = normalize(iterable, idOrIndex); - - if (index >= 0) { - iterable.items = iterable.items.slice(); - iterable.items.splice(index, 0, value); - } - - return iterable; -} - -export function add( - iterable: IterableIdentifiable & T, - value: T, - idOrIndex: Identifier -): IterableIdentifiable & T { - const index = normalize(iterable, idOrIndex); - - if (index >= 0) { - iterable.items = iterable.items.slice(); - iterable.items.splice(index + 1, 0, value); - } - - return iterable; -} - -function isRecursive(component: Identifiable): component is IterableIdentifiable { - return Boolean(Object.prototype.hasOwnProperty.call(component, "items")); -} - -export function updateRecursive( - update: (component: T) => T, - component: T, - ...identifiers: Identifier[] -): T { - if (identifiers.length === 0) { - return update(component); - } else if (isRecursive(component)) { - const [identifier, ...restIdentifiers] = identifiers; - const normalizedIndex = normalize(component, identifier); - const foundComponent = search(component.items, normalizedIndex); - - if (foundComponent) { - component.items[normalizedIndex] = updateRecursive( - update, - foundComponent as T, - ...restIdentifiers - ); - } - - return component; - } - - return component; -} diff --git a/ts/components/identifier.ts b/ts/components/identifier.ts new file mode 100644 index 000000000..7d29362c6 --- /dev/null +++ b/ts/components/identifier.ts @@ -0,0 +1,55 @@ +// Copyright: Ankitects Pty Ltd and contributors +// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html +export type Identifier = string | number; + +function find(collection: HTMLCollection, idOrIndex: Identifier): Element | null { + let element: Element | null = null; + + if (typeof idOrIndex === "string") { + element = collection.namedItem(idOrIndex); + } else if (idOrIndex < 0) { + const normalizedIndex = collection.length + idOrIndex; + element = collection.item(normalizedIndex); + } else { + element = collection.item(idOrIndex); + } + + return element; +} + +export function insert( + element: Element, + collection: Element, + idOrIndex: Identifier +): void { + const reference = find(collection.children, idOrIndex); + + if (reference) { + collection.insertBefore(element, reference); + } +} + +export function add( + element: Element, + collection: Element, + idOrIndex: Identifier +): void { + const before = find(collection.children, idOrIndex); + + if (before) { + const reference = before.nextElementSibling ?? null; + collection.insertBefore(element, reference); + } +} + +export function update( + f: (element: Element) => void, + collection: Element, + idOrIndex: Identifier +): void { + const element = find(collection.children, idOrIndex); + + if (element) { + f(element); + } +} diff --git a/ts/editor/EditorToolbar.svelte b/ts/editor/EditorToolbar.svelte index 217475d15..09bbccdc5 100644 --- a/ts/editor/EditorToolbar.svelte +++ b/ts/editor/EditorToolbar.svelte @@ -25,6 +25,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html export function clearActiveButtons() { resetAllState(false); } + + /* Export components */ + import LabelButton from "components/LabelButton.svelte"; + import IconButton from "components/IconButton.svelte"; + + export const editorToolbar = { LabelButton, IconButton };