From 19f555d252d58d7ca5629ca237ba3f23e10e36ea Mon Sep 17 00:00:00 2001 From: hbs9999 Date: Tue, 7 Jan 2025 11:52:11 +0300 Subject: [PATCH 1/4] next: migrate to svelte 5 --- packages/svelte-ux/package.json | 2 +- packages/svelte-ux/src/docs/Blockquote.svelte | 9 +- packages/svelte-ux/src/docs/Header1.svelte | 11 +- packages/svelte-ux/src/docs/Layout.svelte | 10 +- packages/svelte-ux/src/docs/Link.svelte | 17 +- .../src/docs/ViewSourceButton.svelte | 68 +- packages/svelte-ux/src/lib/actions/types.d.ts | 16 +- .../src/lib/components/ApiDocs.svelte | 232 ++--- .../src/lib/components/AppBar.svelte | 62 +- .../src/lib/components/AppLayout.svelte | 44 +- .../src/lib/components/Avatar.svelte | 23 +- .../src/lib/components/Backdrop.svelte | 47 +- .../svelte-ux/src/lib/components/Badge.svelte | 43 +- .../src/lib/components/BarStack.svelte | 53 +- .../src/lib/components/Breadcrumb.svelte | 50 +- .../src/lib/components/Button.svelte | 872 +++++++++--------- .../src/lib/components/ButtonGroup.svelte | 41 +- .../svelte-ux/src/lib/components/Card.svelte | 63 +- .../src/lib/components/Checkbox.svelte | 81 +- .../svelte-ux/src/lib/components/Code.svelte | 32 +- .../src/lib/components/Collapse.svelte | 110 ++- .../src/lib/components/CopyButton.svelte | 39 +- .../src/lib/components/DateButton.svelte | 64 +- .../src/lib/components/DateField.svelte | 160 ++-- .../src/lib/components/DatePickerField.svelte | 285 +++--- .../src/lib/components/DateRange.svelte | 127 +-- .../lib/components/DateRangeDisplay.svelte | 47 +- .../src/lib/components/DateRangeField.svelte | 319 ++++--- .../src/lib/components/DateSelect.svelte | 37 +- .../src/lib/components/Dialog.svelte | 126 ++- .../src/lib/components/DividerDot.svelte | 8 +- .../src/lib/components/Drawer.svelte | 108 ++- .../src/lib/components/Duration.svelte | 45 +- .../src/lib/components/EmptyMessage.svelte | 17 +- .../lib/components/ErrorNotification.svelte | 135 +-- .../src/lib/components/ExpansionPanel.svelte | 61 +- .../svelte-ux/src/lib/components/Field.svelte | 164 ++-- .../svelte-ux/src/lib/components/Form.svelte | 80 +- .../svelte-ux/src/lib/components/Gooey.svelte | 49 +- .../svelte-ux/src/lib/components/Grid.svelte | 73 +- .../src/lib/components/Header.svelte | 67 +- .../svelte-ux/src/lib/components/Icon.svelte | 178 ++-- .../src/lib/components/InfiniteScroll.svelte | 25 +- .../svelte-ux/src/lib/components/Input.svelte | 142 +-- .../svelte-ux/src/lib/components/Kbd.svelte | 30 +- .../src/lib/components/LanguageSelect.svelte | 30 +- .../svelte-ux/src/lib/components/Lazy.svelte | 50 +- .../src/lib/components/ListItem.svelte | 164 ++-- .../svelte-ux/src/lib/components/Menu.svelte | 121 ++- .../src/lib/components/MenuButton.svelte | 82 +- .../src/lib/components/MenuField.svelte | 249 +++-- .../src/lib/components/MenuItem.svelte | 51 +- .../svelte-ux/src/lib/components/Month.svelte | 94 +- .../src/lib/components/MonthList.svelte | 25 +- .../src/lib/components/MonthListByYear.svelte | 58 +- .../src/lib/components/MultiSelect.svelte | 344 ++++--- .../lib/components/MultiSelectField.svelte | 300 +++--- .../src/lib/components/MultiSelectMenu.svelte | 211 +++-- .../lib/components/MultiSelectOption.svelte | 55 +- .../src/lib/components/NavItem.svelte | 52 +- .../src/lib/components/Notification.svelte | 129 ++- .../src/lib/components/NumberStepper.svelte | 70 +- .../src/lib/components/Overflow.svelte | 24 +- .../src/lib/components/Overlay.svelte | 25 +- .../src/lib/components/Paginate.svelte | 35 +- .../src/lib/components/Pagination.svelte | 130 +-- .../src/lib/components/Popover.svelte | 92 +- .../src/lib/components/Preview.svelte | 28 +- .../src/lib/components/Progress.svelte | 18 +- .../src/lib/components/ProgressCircle.svelte | 49 +- .../src/lib/components/QuickSearch.svelte | 30 +- .../svelte-ux/src/lib/components/Radio.svelte | 67 +- .../src/lib/components/RangeField.svelte | 93 +- .../src/lib/components/RangeSlider.svelte | 105 ++- .../src/lib/components/ResponsiveMenu.svelte | 36 +- .../src/lib/components/ScrollContainer.svelte | 18 +- .../src/lib/components/ScrollingValue.svelte | 58 +- .../src/lib/components/SectionDivider.svelte | 14 +- .../src/lib/components/SelectField.svelte | 533 ++++++----- .../src/lib/components/Selection.svelte | 39 +- .../src/lib/components/Settings.svelte | 14 +- .../svelte-ux/src/lib/components/Shine.svelte | 71 +- .../src/lib/components/SpringValue.svelte | 28 +- .../svelte-ux/src/lib/components/Stack.svelte | 40 +- .../svelte-ux/src/lib/components/State.svelte | 15 +- .../svelte-ux/src/lib/components/Step.svelte | 66 +- .../svelte-ux/src/lib/components/Steps.svelte | 34 +- .../src/lib/components/StoreSubscribe.svelte | 12 +- .../src/lib/components/Switch.svelte | 56 +- .../svelte-ux/src/lib/components/Tab.svelte | 34 +- .../svelte-ux/src/lib/components/Table.svelte | 154 ++-- .../src/lib/components/TableOfContents.svelte | 73 +- .../src/lib/components/TableOrderIcon.svelte | 8 +- .../svelte-ux/src/lib/components/Tabs.svelte | 50 +- .../src/lib/components/TextField.svelte | 403 ++++---- .../src/lib/components/ThemeSelect.svelte | 58 +- .../src/lib/components/ThemeSwitch.svelte | 14 +- .../svelte-ux/src/lib/components/Tilt.svelte | 42 +- .../src/lib/components/Timeline.svelte | 60 +- .../src/lib/components/TimelineEvent.svelte | 102 +- .../src/lib/components/Toggle.svelte | 36 +- .../src/lib/components/ToggleButton.svelte | 85 +- .../src/lib/components/ToggleGroup.svelte | 348 +++---- .../src/lib/components/ToggleOption.svelte | 53 +- .../src/lib/components/TogglePanel.svelte | 9 +- .../src/lib/components/Tooltip.svelte | 96 +- .../src/lib/components/TreeList.svelte | 29 +- .../src/lib/components/TweenedValue.svelte | 28 +- .../src/lib/components/ViewportCenter.svelte | 12 +- .../src/lib/components/YearList.svelte | 71 +- .../lib/components/_SelectListOptions.svelte | 70 +- .../svelte-ux/src/lib/types/typeHelpers.ts | 16 - packages/svelte-ux/src/lib/utils/icons.ts | 6 +- packages/svelte-ux/src/routes/+error.svelte | 4 +- packages/svelte-ux/src/routes/+layout.svelte | 178 ++-- packages/svelte-ux/src/routes/+page.svelte | 2 +- .../src/routes/customization/+layout.svelte | 9 +- .../svelte-ux/src/routes/docs/+layout.svelte | 39 +- .../routes/docs/components/Badge/+page.svelte | 10 +- .../docs/components/Breadcrumb/+page.svelte | 46 +- .../docs/components/Button/+page.svelte | 26 +- .../routes/docs/components/Card/+page.svelte | 74 +- .../docs/components/Collapse/+page.svelte | 14 +- .../components/InfiniteScroll/+page.svelte | 30 +- .../docs/components/Overflow/+page.svelte | 46 +- .../docs/components/Overlay/+page.svelte | 4 +- .../routes/docs/components/Paginate/+page.md | 34 +- .../docs/components/RangeField/+page.svelte | 4 +- .../components/ScrollContainer/+page.svelte | 18 +- .../docs/components/Settings/+page.svelte | 2 +- .../src/routes/docs/components/State/+page.md | 16 +- .../docs/components/Switch/+page.svelte | 26 +- .../routes/docs/components/Tabs/+page.svelte | 54 +- .../routes/docs/components/Toggle/+page.md | 12 +- .../docs/components/ToggleGroup/+page.svelte | 78 +- .../docs/components/YearList/+page.svelte | 10 +- .../svelte-ux/src/routes/theme/+page.svelte | 347 +++---- .../src/routes/theme/ColorField.svelte | 56 +- 138 files changed, 6528 insertions(+), 4555 deletions(-) diff --git a/packages/svelte-ux/package.json b/packages/svelte-ux/package.json index 5e8787ec..ce302ffa 100644 --- a/packages/svelte-ux/package.json +++ b/packages/svelte-ux/package.json @@ -72,7 +72,7 @@ "zod": "^3.24.1" }, "peerDependencies": { - "svelte": "^3.56.0 || ^4.0.0 || ^5.0.0" + "svelte": "^5.0.0" }, "main": "./dist/index.js", "exports": { diff --git a/packages/svelte-ux/src/docs/Blockquote.svelte b/packages/svelte-ux/src/docs/Blockquote.svelte index 68b959c6..861702ca 100644 --- a/packages/svelte-ux/src/docs/Blockquote.svelte +++ b/packages/svelte-ux/src/docs/Blockquote.svelte @@ -2,6 +2,13 @@ import { mdiInformation } from '@mdi/js'; import Icon from '../lib/components/Icon.svelte'; import { cls } from '$lib/utils/styles.js'; + import type { Snippet } from 'svelte'; + + interface Props { + children?: Snippet; + } + + let { children }: Props = $props();
- + {@render children?.()}
diff --git a/packages/svelte-ux/src/docs/Header1.svelte b/packages/svelte-ux/src/docs/Header1.svelte index ff25855a..95b923f6 100644 --- a/packages/svelte-ux/src/docs/Header1.svelte +++ b/packages/svelte-ux/src/docs/Header1.svelte @@ -1,5 +1,12 @@ - - + + {@render children?.()} diff --git a/packages/svelte-ux/src/docs/Layout.svelte b/packages/svelte-ux/src/docs/Layout.svelte index d182f8ea..71320435 100644 --- a/packages/svelte-ux/src/docs/Layout.svelte +++ b/packages/svelte-ux/src/docs/Layout.svelte @@ -1,15 +1,21 @@ - - +{@render children?.()} diff --git a/packages/svelte-ux/src/docs/Link.svelte b/packages/svelte-ux/src/docs/Link.svelte index e607ded3..19503a6b 100644 --- a/packages/svelte-ux/src/docs/Link.svelte +++ b/packages/svelte-ux/src/docs/Link.svelte @@ -1,5 +1,16 @@ + + - - - + + + {@render children?.()} diff --git a/packages/svelte-ux/src/docs/ViewSourceButton.svelte b/packages/svelte-ux/src/docs/ViewSourceButton.svelte index ae158e9f..df7a84ba 100644 --- a/packages/svelte-ux/src/docs/ViewSourceButton.svelte +++ b/packages/svelte-ux/src/docs/ViewSourceButton.svelte @@ -8,41 +8,51 @@ import Toggle from '../lib/components/Toggle.svelte'; import Tooltip from '../lib/components/Tooltip.svelte'; - export let label: string; - export let source: string | undefined = undefined; - export let href: string | undefined = undefined; - export let icon: ComponentProps - -
-
-
{label}
-
{href}
-
+ + {#snippet children({ on: open, toggle, toggleOff })} + + +
+
+
{label}
+
{href}
+
- {#if href} - - {/if} -
+ {#if href} + + {/if} +
-
- -
+
+ +
-
- -
-
+ {#snippet actions()} +
+ +
+ {/snippet} + + {/snippet} {:else if href} diff --git a/packages/svelte-ux/src/lib/actions/types.d.ts b/packages/svelte-ux/src/lib/actions/types.d.ts index 5c7a1ff7..316d25db 100644 --- a/packages/svelte-ux/src/lib/actions/types.d.ts +++ b/packages/svelte-ux/src/lib/actions/types.d.ts @@ -2,23 +2,23 @@ declare namespace svelteHTML { interface HTMLAttributes { // use:intersection - 'on:intersecting'?: (event: CustomEvent) => void; + 'onintersecting'?: (event: CustomEvent) => void; // use:mutate - 'on:mutate'?: (event: CustomEvent) => void; + 'onmutate'?: (event: CustomEvent) => void; // use:movable - 'on:movestart'?: (event: CustomEvent<{ x: number; y: number }>) => void; - 'on:move'?: (event: CustomEvent<{ x: number; y: number; dx: number; dy: number }>) => void; - 'on:moveend'?: (event: CustomEvent<{ x: number; y: number }>) => void; + 'onmovestart'?: (event: CustomEvent<{ x: number; y: number }>) => void; + 'onmove'?: (event: CustomEvent<{ x: number; y: number; dx: number; dy: number }>) => void; + 'onmoveend'?: (event: CustomEvent<{ x: number; y: number }>) => void; // use:popover - 'on:clickOutside'?: (event: CustomEvent) => void; + 'onclickOutside'?: (event: CustomEvent) => void; // use:overflow - 'on:overflow'?: (event: CustomEvent<{ overflowX: number; overflowY: number }>) => void; + 'onoverflow'?: (event: CustomEvent<{ overflowX: number; overflowY: number }>) => void; // use:longpress - 'on:longpress'?: (event: CustomEvent) => void; + 'onlongpress'?: (event: CustomEvent) => void; } } diff --git a/packages/svelte-ux/src/lib/components/ApiDocs.svelte b/packages/svelte-ux/src/lib/components/ApiDocs.svelte index f0e50c84..5c185bc1 100644 --- a/packages/svelte-ux/src/lib/components/ApiDocs.svelte +++ b/packages/svelte-ux/src/lib/components/ApiDocs.svelte @@ -12,7 +12,11 @@ import ListItem from './ListItem.svelte'; import Tooltip from './Tooltip.svelte'; - export let api: SveldJson; + interface Props { + api: SveldJson; + } + + let { api }: Props = $props(); function parseSlotProps(slot_props: string) { return slot_props @@ -35,41 +39,47 @@ icon={mdiCodeBraces} avatar={{ size: 'sm', class: 'text-xs text-white bg-blue-500' }} > -
{prop.name}
- -
- {#if prop.description} - - {prop.description} - - {/if} -
- -
- {#if prop.isRequired} -
- Required -
- {/if} + {#snippet title()} +
{prop.name}
+ {/snippet} - -
- {prop.value} -
-
+ {#snippet subheading()} +
+ {#if prop.description} + + {prop.description} + + {/if} +
+ {/snippet} - -
- {prop.type ?? 'unknown'} -
-
-
+ {#snippet actions()} +
+ {#if prop.isRequired} +
+ Required +
+ {/if} + + +
+ {prop.value} +
+
+ + +
+ {prop.type ?? 'unknown'} +
+
+
+ {/snippet} {:else} No props @@ -119,31 +129,37 @@ icon={mdiGoogleCirclesGroup} avatar={{ size: 'sm', class: 'text-xs text-white bg-purple-500' }} > -
- {#if slot.default} - default - {:else} - {slot.name} - {/if} -
- -
- {slot.description ?? ''} -
- -
- {#if slot.slot_props != '{}'} - {#each parseSlotProps(slot.slot_props ?? '') as { key, value }} - -
- {key}: {value} -
-
- {/each} - {/if} -
+ {#snippet title()} +
+ {#if slot.default} + default + {:else} + {slot.name} + {/if} +
+ {/snippet} + + {#snippet subheading()} +
+ {slot.description ?? ''} +
+ {/snippet} + + {#snippet actions()} +
+ {#if slot.slot_props != '{}'} + {#each parseSlotProps(slot.slot_props ?? '') as { key, value }} + +
+ {key}: {value} +
+
+ {/each} + {/if} +
+ {/snippet} {:else} No slots @@ -162,22 +178,26 @@ icon={mdiBullhorn} avatar={{ size: 'sm', class: 'text-xs text-white bg-success-500' }} > -
{event.name}
+ {#snippet title()} +
{event.name}
+ {/snippet} -
- {#if event.element != null} + {#snippet actions()} +
+ {#if event.element != null} +
+ {event.element} +
+ {/if}
- {event.element} + {event.type}
- {/if} -
- {event.type}
-
+ {/snippet} {:else} No events @@ -199,41 +219,47 @@ icon={mdiCodeBraces} avatar={{ size: 'sm', class: 'text-xs text-white bg-blue-500' }} > -
{prop.name}
- -
- {#if prop.description} - - {prop.description} - - {/if} -
- -
- {#if prop.isRequired} -
- Required -
- {/if} + {#snippet title()} +
{prop.name}
+ {/snippet} - -
- {prop.value} -
-
+ {#snippet subheading()} +
+ {#if prop.description} + + {prop.description} + + {/if} +
+ {/snippet} - -
- {prop.type ?? 'unknown'} -
-
-
+ {#snippet actions()} +
+ {#if prop.isRequired} +
+ Required +
+ {/if} + + +
+ {prop.value} +
+
+ + +
+ {prop.type ?? 'unknown'} +
+
+
+ {/snippet} {:else} No exports diff --git a/packages/svelte-ux/src/lib/components/AppBar.svelte b/packages/svelte-ux/src/lib/components/AppBar.svelte index 73272ce9..8b86960e 100644 --- a/packages/svelte-ux/src/lib/components/AppBar.svelte +++ b/packages/svelte-ux/src/lib/components/AppBar.svelte @@ -7,26 +7,46 @@ import { cls } from '../utils/styles.js'; import { getComponentClasses } from './theme.js'; import { getSettings } from './index.js'; + import type { Snippet } from 'svelte'; - export let title: string | number | Array = ''; - export let menuIcon: string | null = mdiMenu; - let className: string | undefined = undefined; - export { className as class }; + interface Props { + title?: string | number | Array | Snippet; + menuIcon?: string | Snippet<[{ toggleMenu: () => void; isMenuOpen: boolean }]> | null; + class?: string; + /** + * Update head / document.title. Set to false to disable + */ + head?: boolean; + children?: Snippet; + actions?: Snippet; + } - /** - * Update head / document.title. Set to false to disable - */ - export let head = true; + let { + title = '', + menuIcon = mdiMenu, + class: className, + head = true, + children, + actions, + }: Props = $props(); const { showDrawer } = getSettings(); const settingsClasses = getComponentClasses('AppBar'); - $: titleString = Array.isArray(title) ? title.filter((x) => x).join(' › ') : title.toString(); + let titleString = $derived( + typeof title === 'function' + ? '' + : Array.isArray(title) + ? title.filter((x) => x).join(' › ') + : title.toString() + ); - $: if (BROWSER && head) { - // Appears to be needed for some reactive updates - document.title = titleString; - } + $effect(() => { + if (BROWSER && head) { + // Appears to be needed for some reactive updates + document.title = titleString; + } + }); function toggleMenu() { $showDrawer = !$showDrawer; @@ -37,13 +57,15 @@ class={cls('AppBar', 'px-4 flex items-center relative z-50', settingsClasses.root, className)} > {#if menuIcon} - -
diff --git a/packages/svelte-ux/src/lib/components/Backdrop.svelte b/packages/svelte-ux/src/lib/components/Backdrop.svelte index 3b0eb82b..4848d2d9 100644 --- a/packages/svelte-ux/src/lib/components/Backdrop.svelte +++ b/packages/svelte-ux/src/lib/components/Backdrop.svelte @@ -4,13 +4,36 @@ import { portal as portalAction, type PortalOptions } from '../actions/portal.js'; import { cls } from '../utils/styles.js'; import { getComponentClasses } from './theme.js'; + import type { Snippet } from 'svelte'; + import type { SvelteHTMLElements } from 'svelte/elements'; - export let blur: boolean = false; - export let portal: PortalOptions = false; - let className: string | undefined = undefined; - export { className as class }; + interface Props { + blur?: boolean; + portal?: PortalOptions; + class?: string; + fadeParams?: FadeParams; + onKeyDown?: SvelteHTMLElements['div']['onkeydown']; + onKeyUp?: SvelteHTMLElements['div']['onkeyup']; + onKeyPress?: SvelteHTMLElements['div']['onkeypress']; + onClick?: SvelteHTMLElements['div']['onclick']; + onMouseDown?: SvelteHTMLElements['div']['onmousedown']; + onMouseUp?: SvelteHTMLElements['div']['onmouseup']; + children?: Snippet; + } - export let fadeParams: FadeParams = { duration: 300 }; + let { + blur = false, + portal = false, + class: className, + fadeParams = { duration: 300 }, + onKeyDown, + onKeyUp, + onKeyPress, + onClick, + onMouseDown, + onMouseUp, + children, + }: Props = $props(); const settingsClasses = getComponentClasses('Backdrop'); @@ -23,16 +46,16 @@ settingsClasses.root, className )} - on:keydown - on:keyup - on:keypress - on:click - on:mousedown - on:mouseup + onkeydown={onKeyDown} + onkeyup={onKeyUp} + onkeypress={onKeyPress} + onclick={onClick} + onmousedown={onMouseDown} + onmouseup={onMouseUp} in:fade|global={fadeParams} out:fade={fadeParams} use:portalAction={portal} role="none" > - + {@render children?.()} diff --git a/packages/svelte-ux/src/lib/components/Badge.svelte b/packages/svelte-ux/src/lib/components/Badge.svelte index 6a33b9bf..2068a7cf 100644 --- a/packages/svelte-ux/src/lib/components/Badge.svelte +++ b/packages/svelte-ux/src/lib/components/Badge.svelte @@ -1,27 +1,41 @@
- + {@render children?.()}
- - {#if !dot} - {value || ''} - {/if} - + {#if valueIsSnippet} + {/* @ts-ignore */ null} + {@render value()} + {:else if !dot} + {value || ''} + {/if}
diff --git a/packages/svelte-ux/src/lib/components/BarStack.svelte b/packages/svelte-ux/src/lib/components/BarStack.svelte index 7c06fc68..c5487f60 100644 --- a/packages/svelte-ux/src/lib/components/BarStack.svelte +++ b/packages/svelte-ux/src/lib/components/BarStack.svelte @@ -1,34 +1,37 @@ -
+
{#each data as item} {@const valuePercent = item.value / (total ?? sum(data, (d) => d.value))} @@ -41,19 +44,23 @@ classes.item, item.classes?.root )} - on:click={() => dispatch('itemClick', item)} + onclick={() => onItemClick?.(item)} > - d.value)}> + {#if children} + {@render children({ item, total: total ?? sum(data, (d) => d.value) })} + {:else}
- d.value)}> + {#if bar} + {@render bar({ item, total: total ?? sum(data, (d) => d.value) })} + {:else}
-
+ {/if}
-
+ {/if} {/if} {/each} diff --git a/packages/svelte-ux/src/lib/components/Breadcrumb.svelte b/packages/svelte-ux/src/lib/components/Breadcrumb.svelte index a5f61175..5d6337e3 100644 --- a/packages/svelte-ux/src/lib/components/Breadcrumb.svelte +++ b/packages/svelte-ux/src/lib/components/Breadcrumb.svelte @@ -4,20 +4,32 @@ import Icon from './Icon.svelte'; import { cls } from '../utils/styles.js'; import { getComponentClasses } from './theme.js'; + import type { SvelteHTMLElements } from 'svelte/elements'; + import type { Snippet } from 'svelte'; - export let items: TItem[] = []; - export let divider: string | undefined = undefined; - export let inline = false; - let className: string | undefined = undefined; - export { className as class }; + interface Props { + items?: TItem[]; + divider?: string | Snippet; + inline?: boolean; + item?: Snippet<[{ item: TItem }]>; + } + + let { + items = [], + divider, + inline = false, + class: className, + item, + ...restProps + }: Props & Omit = $props(); const settingsClasses = getComponentClasses('Breadcrumb'); - $: displayItems = items?.filter((x) => x != null) ?? []; + let displayItems = $derived(items?.filter((x) => x != null) ?? []);
- {#each displayItems as item, index} - -
{item}
-
+ {#each displayItems as displayItem, index} + {#if item} + {@render item({ item: displayItem })} + {:else} +
{displayItem}
+ {/if} {#if index < displayItems.length - 1} - - {#if divider} -
{divider}
- {:else} - - {/if} -
+ {#if typeof divider === 'function'} + {@render divider()} + {:else if divider} +
{divider}
+ {:else} + + {/if} {/if} {/each}
diff --git a/packages/svelte-ux/src/lib/components/Button.svelte b/packages/svelte-ux/src/lib/components/Button.svelte index bab311d0..1673db4a 100644 --- a/packages/svelte-ux/src/lib/components/Button.svelte +++ b/packages/svelte-ux/src/lib/components/Button.svelte @@ -1,6 +1,6 @@ - {#if loading} @@ -478,5 +502,5 @@ {/if} - + {@render children?.()} diff --git a/packages/svelte-ux/src/lib/components/ButtonGroup.svelte b/packages/svelte-ux/src/lib/components/ButtonGroup.svelte index ef75efc8..5530895f 100644 --- a/packages/svelte-ux/src/lib/components/ButtonGroup.svelte +++ b/packages/svelte-ux/src/lib/components/ButtonGroup.svelte @@ -1,5 +1,5 @@ - -
- +
+ {@render children?.()}
diff --git a/packages/svelte-ux/src/lib/components/Card.svelte b/packages/svelte-ux/src/lib/components/Card.svelte index de6c37b6..55f6068e 100644 --- a/packages/svelte-ux/src/lib/components/Card.svelte +++ b/packages/svelte-ux/src/lib/components/Card.svelte @@ -1,5 +1,6 @@ @@ -32,7 +49,7 @@ -->
{/if} - {#if title || subheading || $$slots.header} + {#if title || subheading || header}
- + {#if header} + {@render header()} + {:else}
- + {/if}
{/if} - + {@render children?.()} - {#if $$slots.contents} + {#if contents}
- + {@render contents()}
{/if} - {#if $$slots.actions} + {#if actions}
- + {@render actions()}
{/if}
diff --git a/packages/svelte-ux/src/lib/components/Checkbox.svelte b/packages/svelte-ux/src/lib/components/Checkbox.svelte index d0facda6..4656098c 100644 --- a/packages/svelte-ux/src/lib/components/Checkbox.svelte +++ b/packages/svelte-ux/src/lib/components/Checkbox.svelte @@ -1,4 +1,5 @@
{ + onChange(); + _onChange?.(); + }} {value} class={cls('input', 'peer appearance-none absolute', settingsClasses.input, classes.input)} {required} @@ -109,7 +136,7 @@ /> - {#if $$slots.default} + {#if children} {/if}
diff --git a/packages/svelte-ux/src/lib/components/Code.svelte b/packages/svelte-ux/src/lib/components/Code.svelte index def72bcb..29777e82 100644 --- a/packages/svelte-ux/src/lib/components/Code.svelte +++ b/packages/svelte-ux/src/lib/components/Code.svelte @@ -5,20 +5,30 @@ import { cls } from '../utils/styles.js'; import CopyButton from './CopyButton.svelte'; - export let source: string | null = null; - export let language = 'svelte'; - export let highlightedSource = source - ? Prism.highlight(source, Prism.languages[language] ?? Prism.languages.text, language) - : ''; + interface Props { + source?: string | null; + language?: string; + highlightedSource?: string; + classes?: { + root?: string; + pre?: string; + code?: string; + }; + class?: string; + } - export let classes: { - root?: string; - pre?: string; - code?: string; - } = {}; + let { + source, + language = 'svelte', + highlightedSource = source + ? Prism.highlight(source, Prism.languages[language] ?? Prism.languages.text, language) + : '', + classes = {}, + class: className, + }: Props = $props(); -
+
{#if source}
-  import { createEventDispatcher } from 'svelte';
-  import { slide } from 'svelte/transition';
+  import { slide, type TransitionConfig } from 'svelte/transition';
   import { mdiChevronDown } from '@mdi/js';
   import { cls } from '../utils/styles.js';
 
   import Icon from './Icon.svelte';
   import type { TransitionParams } from '../types/typeHelpers.js';
   import { getComponentClasses } from './theme.js';
+  import type { Snippet } from 'svelte';
+  import type { SvelteHTMLElements } from 'svelte/elements';
 
-  /**
-   * @slot {{ active: number }} trigger - Primary content to trigger the show/hide
-   */
-
-  const dispatch = createEventDispatcher();
+  const settingsClasses = getComponentClasses('Collapse');
 
-  export let name = '';
-  export let value: any = undefined;
-  export let group: any = undefined;
-  export let open = false;
-  export let popout = false;
-  export let disabled = false;
-  export let icon = mdiChevronDown;
+  interface Props {
+    name?: string;
+    value?: any;
+    group?: any;
+    open?: boolean;
+    popout?: boolean;
+    disabled?: boolean;
+    icon?: string | Snippet<[{ open: boolean }]>;
+    transition?: (node: HTMLElement, params: TransitionParams) => TransitionConfig;
+    transitionParams?: TransitionParams;
+    classes?: {
+      root?: string;
+      trigger?: string;
+      icon?: string;
+      content?: string;
+    };
+    /**
+     * Controls how first, last, and gap between are calculated
+     *   - type: items are of the same type
+     *   - parent: items share a common parent
+     *   - group: closest element with 'group' class
+     */
+    list?: 'type' | 'parent' | 'group';
+    onChange?: ({ open, name }: { open: boolean; name: string }) => void;
+    trigger?: Snippet<[{ open: boolean }]>;
+    children?: Snippet<[{ open: boolean }]>;
+  }
 
-  export let transition = slide;
-  export let transitionParams: TransitionParams = {};
+  let {
+    name = '',
+    value,
+    group = $bindable(),
+    open = $bindable(false),
+    popout = false,
+    disabled = false,
+    icon = mdiChevronDown,
+    transition = slide,
+    transitionParams = {},
+    classes = {},
+    class: className,
+    list = 'parent',
+    onChange,
+    trigger,
+    children,
+    ...restProps
+  }: Props & Omit = $props();
 
-  export let classes: {
-    root?: string;
-    trigger?: string;
-    icon?: string;
-    content?: string;
-  } = {};
-  const settingsClasses = getComponentClasses('Collapse');
+  $effect(() => {
+    open = group !== undefined ? group === value : open;
+  });
 
-  /**
-   * Controls how first, last, and gap between are calculated
-   *   - type: items are of the same type
-   *   - parent: items share a common parent
-   *   - group: closest element with 'group' class
-   */
-  export let list: 'type' | 'parent' | 'group' = 'parent';
-
-  $: open = group !== undefined ? group === value : open;
-  $: dispatch('change', { open, name });
+  $effect(() => {
+    onChange?.({ open, name });
+  });
 
 
 
@@ -64,16 +86,20 @@ type="button" class="flex items-center w-full text-left select-text focus:outline-none" {disabled} - on:click={() => { + onclick={() => { open = !open; group = group === value ? undefined : value; }} > - {name} + {#if trigger} + {@render trigger({ open })} + {:else} + {name} + {/if} - + {#if typeof icon === 'function'} + {@render icon({ open })} + {:else}
-
+ {/if} {#if open} @@ -94,7 +120,7 @@ transition:transition={transitionParams} class={cls(settingsClasses.content, classes.content)} > - + {@render children?.({ open })}
{/if}
diff --git a/packages/svelte-ux/src/lib/components/CopyButton.svelte b/packages/svelte-ux/src/lib/components/CopyButton.svelte index 6b122ab8..ce142903 100644 --- a/packages/svelte-ux/src/lib/components/CopyButton.svelte +++ b/packages/svelte-ux/src/lib/components/CopyButton.svelte @@ -5,33 +5,44 @@ import Button from './Button.svelte'; import { getComponentSettings } from './settings.js'; import { slide } from 'svelte/transition'; - import { createEventDispatcher } from 'svelte'; - let className: string | undefined = undefined; - export { className as class }; - - const dispatch = createEventDispatcher<{ click: void }>(); + import type { ComponentProps } from 'svelte'; const { classes: settingsClasses, defaults } = getComponentSettings('CopyButton'); - export let value: string | (() => string); - export let message: string | null = 'Copied!'; - - let showMessage = false; - $: if (showMessage) { - setTimeout(() => (showMessage = false), 3000); + interface Props { + class?: string; + value: string | (() => string); + message?: string | null; + onClick?: () => void; } - $: restProps = { ...defaults, ...$$restProps }; + let { + class: className, + value, + message = 'Copied!', + onClick, + ...rest + }: Props & Omit, keyof Props> = $props(); + + let showMessage = $state(false); + + $effect(() => { + if (showMessage) { + setTimeout(() => (showMessage = false), 3000); + } + }); + + let restProps = $derived({ ...defaults, ...rest }); - -
- {#if clearable && value} -
+ {#snippet prepend()} + + + + {#if stepper} + + {/snippet} + {#snippet append()} +
+ {#if clearable && value} +
+ {/snippet} {/if} @@ -170,22 +203,24 @@ />
-
- - -
+ {#snippet actions()} +
+ + +
+ {/snippet} diff --git a/packages/svelte-ux/src/lib/components/DateRange.svelte b/packages/svelte-ux/src/lib/components/DateRange.svelte index f5a27ac9..b23d4b92 100644 --- a/packages/svelte-ux/src/lib/components/DateRange.svelte +++ b/packages/svelte-ux/src/lib/components/DateRange.svelte @@ -23,52 +23,44 @@ import { mdScreen } from '../stores/matchMedia.js'; import { getSettings } from './settings.js'; - export let selected: DateRange | null = { from: null, to: null, periodType: null }; - let className: string | undefined = undefined; - export { className as class }; - - /** Period types to show */ - export let periodTypes: PeriodType[] = [ - PeriodType.Day, - PeriodType.Week, - PeriodType.BiWeek1, - // PeriodType.BiWeek2Sun, - PeriodType.Month, - PeriodType.Quarter, - PeriodType.CalendarYear, - PeriodType.FiscalYearOctober, - ]; - export let getPeriodTypePresets = getDateRangePresets; + interface Props { + selected?: DateRange | null; + class?: string; + /** Period types to show */ + periodTypes?: PeriodType[]; + getPeriodTypePresets?: typeof getDateRangePresets; + /** + * Dates to disable (not selectable) + */ + disabledDates?: DisabledDate; + } - /** - * Dates to disable (not selectable) - */ - export let disabledDates: DisabledDate | undefined = undefined; + let { + selected = $bindable(), + class: className, + periodTypes = [ + PeriodType.Day, + PeriodType.Week, + PeriodType.BiWeek1, + // PeriodType.BiWeek2Sun, + PeriodType.Month, + PeriodType.Quarter, + PeriodType.CalendarYear, + PeriodType.FiscalYearOctober, + ], + getPeriodTypePresets = getDateRangePresets, + disabledDates, + }: Props = $props(); const settingsClasses = getComponentClasses('DateRange'); const { format, localeSettings } = getSettings(); - let selectedPeriodType = selected?.periodType ?? periodTypes[0]; - let selectedPreset: string | null = null; - let selectedDayOfWeek: DayOfWeek = - $format.settings.formats.dates.weekStartsOn ?? DayOfWeek.Sunday; - let activeDate: 'from' | 'to' = 'from'; - - $: periodTypeOptions = periodTypes.map((pt) => { - const value = adjustPeriodType(pt); - return { - label: $format.getPeriodTypeName(value), - value, - }; - }); - - $: presetOptions = getPeriodTypePresets($localeSettings, selectedPeriodType).map((preset) => { - return { - label: preset.label, - value: getDateRangeStr(preset.value), - preset, - }; - }); + let selectedPeriodType = $state(selected?.periodType ?? periodTypes[0]); + let selectedPreset: string | null = $state(null); + let selectedDayOfWeek: DayOfWeek = $state( + $format.settings.formats.dates.weekStartsOn ?? DayOfWeek.Sunday + ); + let activeDate: 'from' | 'to' = $state('from'); /** Get date range (without period type) as string */ function getDateRangeStr(range: DateRange) { @@ -124,8 +116,33 @@ } } + function adjustPeriodType(periodType: PeriodType) { + // Adjust value for currently selected day of week, if needed + return missingDayOfWeek(periodType) + ? replaceDayOfWeek(periodType, selectedDayOfWeek) || periodType + : periodType; + } + + let periodTypeOptions = $derived( + periodTypes.map((pt) => { + const value = adjustPeriodType(pt); + return { + label: $format.getPeriodTypeName(value), + value, + }; + }) + ); + let presetOptions = $derived( + getPeriodTypePresets($localeSettings, selectedPeriodType).map((preset) => { + return { + label: preset.label, + value: getDateRangeStr(preset.value), + preset, + }; + }) + ); // Update selection after changing `selectedDayOfWeek` - $: { + $effect(() => { if (hasDayOfWeek(selectedPeriodType)) { const newPeriodType = replaceDayOfWeek(selectedPeriodType, selectedDayOfWeek); @@ -159,18 +176,10 @@ // @ts-expect-error (null / undefined issue...) selected = newSelected; } - } - - function adjustPeriodType(periodType: PeriodType) { - // Adjust value for currently selected day of week, if needed - return missingDayOfWeek(periodType) - ? replaceDayOfWeek(periodType, selectedDayOfWeek) || periodType - : periodType; - } - - $: showPeriodTypes = periodTypeOptions.length > 1; - $: showPresets = presetOptions.length > 0; - $: showSidebar = showPeriodTypes || showPresets; + }); + let showPeriodTypes = $derived(periodTypeOptions.length > 1); + let showPresets = $derived(presetOptions.length > 0); + let showSidebar = $derived(showPeriodTypes || showPresets);
Type
onPeriodTypeChange(e.detail.value)} + onChange={(value) => onPeriodTypeChange(value)} variant="outline" inset vertical @@ -255,7 +264,7 @@ label="Type" bind:value={selectedPeriodType} options={periodTypeOptions} - on:change={(e) => onPeriodTypeChange(e.detail.value)} + onChange={({ value }) => onPeriodTypeChange(value)} /> {/if} {/if} @@ -269,7 +278,7 @@ {#each presetOptions as option} { + onclick={() => { onPresetChange(option.value); }} > @@ -283,8 +292,8 @@ label="Presets" bind:value={selectedPreset} options={presetOptions} - on:change={(e) => { - onPresetChange(e.detail.value); + onChange={({ value }) => { + onPresetChange(value); }} /> {/if} diff --git a/packages/svelte-ux/src/lib/components/DateRangeDisplay.svelte b/packages/svelte-ux/src/lib/components/DateRangeDisplay.svelte index f871371f..24dee64f 100644 --- a/packages/svelte-ux/src/lib/components/DateRangeDisplay.svelte +++ b/packages/svelte-ux/src/lib/components/DateRangeDisplay.svelte @@ -1,34 +1,41 @@ - - - - {#if stepper} - - -
- {#if clearable && (value?.periodType || value?.from || value?.to)} -
+ {#snippet prepend()} + + {@render prependRender?.()} + + {#if stepper} + + {/snippet} + {#snippet append()} +
+ {#if clearable && (value?.periodType || value?.from || value?.to)} +
+ {/snippet}
-
- - - -
+ {#snippet actions()} +
+ + + +
+ {/snippet} diff --git a/packages/svelte-ux/src/lib/components/DateSelect.svelte b/packages/svelte-ux/src/lib/components/DateSelect.svelte index dce7a84d..3722c397 100644 --- a/packages/svelte-ux/src/lib/components/DateSelect.svelte +++ b/packages/svelte-ux/src/lib/components/DateSelect.svelte @@ -10,24 +10,37 @@ import Month from './Month.svelte'; import MonthListByYear from './MonthListByYear.svelte'; import YearList from './YearList.svelte'; + import type { ComponentProps } from 'svelte'; - export let selected: SelectedDate = null; - export let periodType: PeriodType = PeriodType.Day; - export let activeDate: 'from' | 'to' = 'from'; + interface Props { + selected?: SelectedDate; + periodType?: PeriodType; + activeDate?: 'from' | 'to'; + /** + * Dates to disable (not selectable) + */ + disabledDates?: DisabledDate; + onDateChange?: ComponentProps['onDateChange']; + } - /** - * Dates to disable (not selectable) - */ - export let disabledDates: DisabledDate | undefined = undefined; + let { + selected = $bindable(), + periodType = PeriodType.Day, + activeDate = 'from', + disabledDates, + onDateChange, + }: Props = $props(); - // @ts-expect-error - $: startOfMonth = selected?.[activeDate] ? startOfMonthFunc(selected[activeDate]) : undefined; + let startOfMonth = $derived( + // @ts-expect-error + selected?.[activeDate] ? startOfMonthFunc(selected[activeDate]) : undefined + ); {#if periodType === PeriodType.Month || periodType === PeriodType.Quarter} {:else if periodType === PeriodType.CalendarYear} - + {:else if periodType === PeriodType.FiscalYearOctober} - + {:else} - + {/if} diff --git a/packages/svelte-ux/src/lib/components/Dialog.svelte b/packages/svelte-ux/src/lib/components/Dialog.svelte index 158fea54..53aa429d 100644 --- a/packages/svelte-ux/src/lib/components/Dialog.svelte +++ b/packages/svelte-ux/src/lib/components/Dialog.svelte @@ -1,5 +1,4 @@ {#if open} close()} - on:mouseup={(e) => { + onClick={() => close()} + onMouseUp={(e) => { // Do not allow event to reach Popover's on:mouseup (clickOutside) e.stopPropagation(); }} @@ -98,8 +130,8 @@ settingsClasses.root, classes.root )} - on:click={onClick} - on:keydown={(e) => { + onclick={onClick} + onkeydown={(e) => { if (e.key === 'Escape') { // Do not allow event to reach Popover's on:keydown e.stopPropagation(); @@ -114,15 +146,15 @@ 'dialog rounded bg-surface-100 elevation-4 overflow-y-auto pointer-events-auto relative outline-none', settingsClasses.dialog, classes.dialog, - $$props.class + className )} - style={$$props.style} + {style} in:scale|global={{ duration: 150, easing: quadIn }} out:scale={{ duration: 150, easing: quadIn }} - on:introstart - on:outrostart - on:introend - on:outroend + {onintrostart} + {onoutrostart} + {onintroend} + {onoutroend} bind:this={dialogEl} use:focusMove={{ restoreFocus: true }} role="dialog" @@ -133,19 +165,17 @@ {/if} - - {#if $$slots.title} -
- -
- {/if} -
+ {#if header} + {@render header({ open, close })} + {:else if title} +
+ {@render title?.({ open, close })} +
+ {/if} - + {@render children?.({ open, close })} - {#if $$slots.actions} + {#if actions}
- + {@render actions?.({ open, close })}
{/if}
diff --git a/packages/svelte-ux/src/lib/components/DividerDot.svelte b/packages/svelte-ux/src/lib/components/DividerDot.svelte index 25766409..826b28cc 100644 --- a/packages/svelte-ux/src/lib/components/DividerDot.svelte +++ b/packages/svelte-ux/src/lib/components/DividerDot.svelte @@ -2,7 +2,13 @@ import { cls } from '../utils/styles.js'; import { getComponentClasses } from './theme.js'; + interface Props { + class?: string; + } + + let { class: className }: Props = $props(); + const settingsClasses = getComponentClasses('DividerDot'); - + diff --git a/packages/svelte-ux/src/lib/components/Drawer.svelte b/packages/svelte-ux/src/lib/components/Drawer.svelte index 2c5f7382..6371ede1 100644 --- a/packages/svelte-ux/src/lib/components/Drawer.svelte +++ b/packages/svelte-ux/src/lib/components/Drawer.svelte @@ -1,5 +1,4 @@ {#if open} { + onClick={(e) => { close(); }} - on:mouseup={(e) => { + onMouseUp={(e) => { // Do not allow event to reach Popover's on:mouseup (clickOutside) e.stopPropagation(); }} @@ -68,7 +100,7 @@ {/if} {#if open} - +
{ + {onintrostart} + {onoutrostart} + {onintroend} + {onoutroend} + onkeydown={(e) => { if (e.key === 'Escape') { // Do not allow event to reach Popover's on:keydown e.stopPropagation(); @@ -116,9 +148,9 @@ {/if} - + {@render children?.({ open, close })} - {#if $$slots.actions} + {#if actions}
- + {@render actions?.({ open, close })}
{/if}
diff --git a/packages/svelte-ux/src/lib/components/Duration.svelte b/packages/svelte-ux/src/lib/components/Duration.svelte index b3f1277a..c1b91d74 100644 --- a/packages/svelte-ux/src/lib/components/Duration.svelte +++ b/packages/svelte-ux/src/lib/components/Duration.svelte @@ -9,14 +9,25 @@ import { getComponentClasses } from './theme.js'; import { cls } from '../utils/styles.js'; - export let start: Date | undefined = undefined; - export let end: Date | undefined = undefined; - export let duration: Partial | undefined = undefined; - export let minUnits: DurationUnits = DurationUnits.Millisecond; - export let totalUnits: number = 99; - export let variant: 'short' | 'long' = 'short'; - let className: string | undefined = undefined; - export { className as class }; + interface Props { + start?: Date; + end?: Date; + duration?: Partial; + minUnits?: DurationUnits; + totalUnits?: number; + variant?: 'short' | 'long'; + class?: string; + } + + let { + start, + end, + duration, + minUnits = DurationUnits.Millisecond, + totalUnits = 99, + variant = 'short', + class: className, + }: Props = $props(); const settingsClasses = getComponentClasses('Duration'); @@ -56,14 +67,16 @@ }, }); - $: displayDuration = humanizeDuration({ - start, - end: end ?? $timer, - duration, - minUnits, - totalUnits, - variant, - }); + let displayDuration = $derived( + humanizeDuration({ + start, + end: end ?? $timer, + duration, + minUnits, + totalUnits, + variant, + }) + ); {displayDuration} diff --git a/packages/svelte-ux/src/lib/components/EmptyMessage.svelte b/packages/svelte-ux/src/lib/components/EmptyMessage.svelte index 0f6f6630..a18e0caa 100644 --- a/packages/svelte-ux/src/lib/components/EmptyMessage.svelte +++ b/packages/svelte-ux/src/lib/components/EmptyMessage.svelte @@ -1,12 +1,23 @@
- + {@render children?.()}
diff --git a/packages/svelte-ux/src/lib/components/ErrorNotification.svelte b/packages/svelte-ux/src/lib/components/ErrorNotification.svelte index f2cb31e8..6e4ea14f 100644 --- a/packages/svelte-ux/src/lib/components/ErrorNotification.svelte +++ b/packages/svelte-ux/src/lib/components/ErrorNotification.svelte @@ -6,71 +6,96 @@ import Icon from './Icon.svelte'; import Notification from './Notification.svelte'; import Toggle from './Toggle.svelte'; + import type { ComponentProps } from 'svelte'; - export let title: string; - export let description: string; + interface Props { + title: string; + description: string; + message?: string; + stackTrace?: string; + onClose: ComponentProps['onClose']; + } - export let message: string = ''; - export let stackTrace: string = ''; + let { + title: titleString, + description: descriptionString, + message = '', + stackTrace = '', + onClose, + }: Props = $props(); - $: hasDetails = message || stackTrace; + let hasDetails = $derived(message || stackTrace); - - -
- -
-
{title}
- -
- {#if description} -
- {#each description.split('\n') as line} -
{line}
- {/each} + + {#snippet children({ on: open, toggle })} + + {#snippet icon()} +
+
- {/if} -
+ {/snippet} + {#snippet title()} +
{titleString}
+ {/snippet} -
- {#if hasDetails} - - {/if} - -
- + {#snippet description()} +
+ {#if descriptionString} +
+ {#each descriptionString.split('\n') as line} +
{line}
+ {/each} +
+ {/if} +
+ {/snippet} - -
- {#if message} - {#each message.split('\n') as msg} -
{msg}
- {/each} - {/if} -
+ {#snippet actions()} +
+ {#if hasDetails} + + {/if} + +
+ {/snippet} + -
- {#if stackTrace} + + {#snippet title()}
-
Stacktrace:
-
-            {stackTrace ?? ''}
-          
+ {#if message} + {#each message.split('\n') as msg} +
{msg}
+ {/each} + {/if}
- {/if} -
+ {/snippet} -
- -
-
+
+ {#if stackTrace} +
+
Stacktrace:
+
+              {stackTrace ?? ''}
+            
+
+ {/if} +
+ + {#snippet actions()} +
+ +
+ {/snippet} + + {/snippet} diff --git a/packages/svelte-ux/src/lib/components/ExpansionPanel.svelte b/packages/svelte-ux/src/lib/components/ExpansionPanel.svelte index 87dd209f..16465eef 100644 --- a/packages/svelte-ux/src/lib/components/ExpansionPanel.svelte +++ b/packages/svelte-ux/src/lib/components/ExpansionPanel.svelte @@ -1,31 +1,49 @@ - - + {#snippet trigger()} + {@render triggerRender?.()} + {/snippet} + {@render actions?.()} {#if enabled}
- + {@render children?.()}
{/if}
diff --git a/packages/svelte-ux/src/lib/components/Field.svelte b/packages/svelte-ux/src/lib/components/Field.svelte index fcf3ea25..51a4f393 100644 --- a/packages/svelte-ux/src/lib/components/Field.svelte +++ b/packages/svelte-ux/src/lib/components/Field.svelte @@ -1,5 +1,4 @@
{/if} - - -
+ + +
{#if label && ['inset', 'float'].includes(labelPlacement)} - - - - {#if value} - {value} - {:else if placeholder} - - {placeholder} - - {:else} -   - {/if} - - - + {@render prefix?.()} + + {#if children} + {@render children({ id })} + {:else if value} + {value} + {:else if placeholder} + + {placeholder} + + {:else} +   + {/if} + + {@render suffix?.()}
@@ -186,15 +214,15 @@ icon={mdiClose} {disabled} class="text-surface-content/50 p-1" - on:click={() => { + onclick={() => { value = Array.isArray(value) ? [] : typeof value === 'string' ? '' : null; - dispatch('clear'); + onClear?.(); labelEl?.focus(); }} /> {/if} - + {@render append?.()} {#if error} @@ -218,7 +246,7 @@
- + {@render root?.()}