- {#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 @@
-
-
+
+ {@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..2c9e54e7 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 });
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 (value && value.from && value.to && value.periodType) {
- const { difference, start, end, add } = getDateFuncsByPeriodType(
- $localeSettings,
- value.periodType
- );
- const offset = difference(value.from, value.to) - 1;
- value = {
- from: start(add(value.from, offset)),
- to: end(add(value.to, offset)),
- periodType: value.periodType,
- };
- dispatch('change', value);
- }
- }}
- />
- {/if}
-
-
- (open = true)}
- {id}
- >
-
-
-
-
- {#if clearable && (value?.periodType || value?.from || value?.to)}
- {
- value = _defaultValue;
- dispatch('clear');
- dispatch('change', value);
- }}
- />
- {/if}
-
-
-
- {#if stepper}
- {
- if (value && value.from && value.to && value.periodType) {
- const { difference, start, end, add } = getDateFuncsByPeriodType(
- $localeSettings,
- value.periodType
- );
- const offset = difference(value.to, value.from) + 1;
- value = {
- from: start(add(value.from, offset)),
- to: end(add(value.to, offset)),
- periodType: value.periodType,
- };
- dispatch('change', value);
- }
- }}
- />
- {/if}
-
+ {#snippet prepend()}
+
+ {@render prependRender?.()}
+
+ {#if stepper}
+ {
+ if (value && value.from && value.to && value.periodType) {
+ const { difference, start, end, add } = getDateFuncsByPeriodType(
+ $localeSettings,
+ value.periodType
+ );
+ const offset = difference(value.from, value.to) - 1;
+ value = {
+ from: start(add(value.from, offset)),
+ to: end(add(value.to, offset)),
+ periodType: value.periodType,
+ };
+ onChange?.(value);
+ }
+ }}
+ />
+ {/if}
+
+ {/snippet}
+
+ {#snippet children({ id })}
+ (open = true)}
+ {id}
+ >
+
+
+ {/snippet}
+ {#snippet append()}
+
+ {#if clearable && (value?.periodType || value?.from || value?.to)}
+ {
+ value = _defaultValue;
+ onClear?.();
+ onChange?.(value);
+ }}
+ />
+ {/if}
+
+ {@render appendRender?.()}
+
+ {#if stepper}
+ {
+ if (value && value.from && value.to && value.periodType) {
+ const { difference, start, end, add } = getDateFuncsByPeriodType(
+ $localeSettings,
+ value.periodType
+ );
+ const offset = difference(value.to, value.from) + 1;
+ value = {
+ from: start(add(value.from, offset)),
+ to: end(add(value.to, offset)),
+ periodType: value.periodType,
+ };
+ onChange?.(value);
+ }
+ }}
+ />
+ {/if}
+
+ {/snippet}
-