sv5ui 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/Accordion/Accordion.svelte +11 -0
  2. package/dist/Badge/badge.types.d.ts +1 -1
  3. package/dist/Calendar/Calendar.svelte +14 -1
  4. package/dist/Collapsible/collapsible.types.d.ts +1 -1
  5. package/dist/Command/command.types.d.ts +4 -2
  6. package/dist/Command/index.d.ts +1 -1
  7. package/dist/ContextMenu/ContextMenu.svelte +1 -1
  8. package/dist/Drawer/Drawer.svelte +4 -2
  9. package/dist/Drawer/DrawerTriggerTestWrapper.svelte +10 -0
  10. package/dist/Drawer/DrawerTriggerTestWrapper.svelte.d.ts +18 -0
  11. package/dist/Drawer/drawer.types.d.ts +13 -2
  12. package/dist/Editor/Editor.svelte +85 -61
  13. package/dist/Editor/SlashPopup.svelte +8 -1
  14. package/dist/Editor/SlashPopup.svelte.d.ts +2 -0
  15. package/dist/Editor/editor.extensions.d.ts +1 -1
  16. package/dist/Editor/editor.extensions.js +25 -16
  17. package/dist/Editor/editor.schemas.d.ts +1 -0
  18. package/dist/Editor/editor.schemas.js +24 -0
  19. package/dist/Editor/editor.slash.svelte.d.ts +0 -9
  20. package/dist/Editor/editor.slash.svelte.js +33 -7
  21. package/dist/Editor/editor.suggestion.js +23 -0
  22. package/dist/Editor/editor.toolbar.js +0 -8
  23. package/dist/Editor/editor.types.d.ts +20 -0
  24. package/dist/Editor/editor.variants.d.ts +0 -5
  25. package/dist/Editor/editor.variants.js +0 -15
  26. package/dist/Editor/index.d.ts +6 -4
  27. package/dist/Editor/index.js +6 -4
  28. package/dist/FileUpload/FileUpload.svelte +7 -0
  29. package/dist/Icon/icon.types.d.ts +1 -1
  30. package/dist/Input/index.d.ts +1 -1
  31. package/dist/Modal/Modal.svelte +4 -2
  32. package/dist/Modal/ModalTriggerTestWrapper.svelte +10 -0
  33. package/dist/Modal/ModalTriggerTestWrapper.svelte.d.ts +18 -0
  34. package/dist/Modal/modal.types.d.ts +13 -3
  35. package/dist/Pagination/pagination.types.d.ts +1 -1
  36. package/dist/Popover/Popover.svelte +1 -1
  37. package/dist/Popover/popover.types.d.ts +2 -0
  38. package/dist/Progress/Progress.svelte +14 -6
  39. package/dist/RadioGroup/RadioGroup.svelte +3 -1
  40. package/dist/Select/select.types.d.ts +1 -1
  41. package/dist/SelectMenu/SelectMenu.svelte +21 -5
  42. package/dist/SelectMenu/select-menu.types.d.ts +1 -1
  43. package/dist/Separator/separator.types.d.ts +1 -1
  44. package/dist/Skeleton/Skeleton.svelte +3 -5
  45. package/dist/Slideover/Slideover.svelte +4 -2
  46. package/dist/Slideover/SlideoverTriggerTestWrapper.svelte +10 -0
  47. package/dist/Slideover/SlideoverTriggerTestWrapper.svelte.d.ts +18 -0
  48. package/dist/Slideover/slideover.types.d.ts +13 -3
  49. package/dist/Stepper/Stepper.svelte +1 -3
  50. package/dist/Switch/Switch.svelte +12 -17
  51. package/dist/Table/table.utils.d.ts +7 -4
  52. package/dist/Table/table.utils.js +26 -25
  53. package/dist/Tabs/tabs.types.d.ts +1 -1
  54. package/dist/ThemeModeButton/ThemeModeButton.svelte +4 -3
  55. package/dist/Tooltip/Tooltip.svelte +1 -1
  56. package/dist/Tooltip/tooltip.types.d.ts +2 -0
  57. package/package.json +1 -1
@@ -19,11 +19,9 @@
19
19
  ...restProps
20
20
  }: Props = $props()
21
21
 
22
- const classes = $derived.by(() => {
23
- const slots = skeletonVariants()
24
- return {
25
- root: slots.root({ class: [config.slots.root, className, ui?.root] })
26
- }
22
+ const slots = skeletonVariants()
23
+ const classes = $derived({
24
+ root: slots.root({ class: [config.slots.root, className, ui?.root] })
27
25
  })
28
26
  </script>
29
27
 
@@ -197,8 +197,10 @@
197
197
 
198
198
  <Dialog.Root bind:open onOpenChange={handleOpenChange} {onOpenChangeComplete}>
199
199
  {#if children}
200
- <Dialog.Trigger class={className as string}>
201
- {@render children()}
200
+ <Dialog.Trigger>
201
+ {#snippet child({ props })}
202
+ {@render children({ props })}
203
+ {/snippet}
202
204
  </Dialog.Trigger>
203
205
  {/if}
204
206
 
@@ -0,0 +1,10 @@
1
+ <script lang="ts">
2
+ import Slideover from './Slideover.svelte'
3
+ </script>
4
+
5
+ <Slideover title="Trigger test" description="D">
6
+ {#snippet children({ props })}
7
+ <button data-testid="trigger" {...props}>Open</button>
8
+ {/snippet}
9
+ {#snippet body()}<p>Body</p>{/snippet}
10
+ </Slideover>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const SlideoverTriggerTestWrapper: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type SlideoverTriggerTestWrapper = InstanceType<typeof SlideoverTriggerTestWrapper>;
18
+ export default SlideoverTriggerTestWrapper;
@@ -100,10 +100,20 @@ export interface SlideoverProps extends RootProps, ContentProps {
100
100
  */
101
101
  class?: ClassNameValue;
102
102
  /**
103
- * Default slot content used as the trigger element.
104
- * When provided, clicking this element opens the slideover.
103
+ * Trigger content. Spread the provided `props` onto your own focusable
104
+ * element (e.g. a `<Button>`) so the dialog's trigger ARIA and event
105
+ * handlers land on the real control instead of a nested wrapper button.
106
+ *
107
+ * @example
108
+ * ```svelte
109
+ * {#snippet children({ props })}
110
+ * <Button {...props}>Open</Button>
111
+ * {/snippet}
112
+ * ```
105
113
  */
106
- children?: Snippet;
114
+ children?: Snippet<[{
115
+ props: Record<string, unknown>;
116
+ }]>;
107
117
  /**
108
118
  * Custom content slot that replaces the entire default layout
109
119
  * (header, body, footer). Title and description are rendered
@@ -122,9 +122,7 @@
122
122
  }
123
123
  }
124
124
 
125
- $effect.pre(() => {
126
- api = apiInstance
127
- })
125
+ api = apiInstance
128
126
 
129
127
  const variantSlots = $derived(stepperVariants({ orientation, size, color }))
130
128
 
@@ -72,17 +72,16 @@
72
72
  disabled: isDisabled ? true : undefined
73
73
  })
74
74
 
75
- const classes = $derived.by(() => {
76
- const slots = switchVariants(variantOpts)
77
- return {
78
- root: slots.root({ class: [config.slots.root, className, ui?.root] }),
79
- base: slots.base({ class: [config.slots.base, ui?.base] }),
80
- container: slots.container({ class: [config.slots.container, ui?.container] }),
81
- thumb: slots.thumb({ class: [config.slots.thumb, ui?.thumb] }),
82
- wrapper: slots.wrapper({ class: [config.slots.wrapper, ui?.wrapper] }),
83
- label: slots.label({ class: [config.slots.label, ui?.label] }),
84
- description: slots.description({ class: [config.slots.description, ui?.description] })
85
- }
75
+ const slots = $derived(switchVariants(variantOpts))
76
+
77
+ const classes = $derived({
78
+ root: slots.root({ class: [config.slots.root, className, ui?.root] }),
79
+ base: slots.base({ class: [config.slots.base, ui?.base] }),
80
+ container: slots.container({ class: [config.slots.container, ui?.container] }),
81
+ thumb: slots.thumb({ class: [config.slots.thumb, ui?.thumb] }),
82
+ wrapper: slots.wrapper({ class: [config.slots.wrapper, ui?.wrapper] }),
83
+ label: slots.label({ class: [config.slots.label, ui?.label] }),
84
+ description: slots.description({ class: [config.slots.description, ui?.description] })
86
85
  })
87
86
 
88
87
  const iconClasses = $derived.by(() => {
@@ -91,15 +90,11 @@
91
90
  const iconUiClass = [config.slots.icon, ui?.icon]
92
91
  return {
93
92
  checked: hasCheckedIcon
94
- ? switchVariants({ ...variantOpts, checked: true, unchecked: loading }).icon({
95
- class: iconUiClass
96
- })
93
+ ? slots.icon({ class: iconUiClass, checked: true, unchecked: loading })
97
94
  : undefined,
98
95
  unchecked:
99
96
  hasUncheckedIcon && !loading
100
- ? switchVariants({ ...variantOpts, unchecked: true }).icon({
101
- class: iconUiClass
102
- })
97
+ ? slots.icon({ class: iconUiClass, unchecked: true })
103
98
  : undefined
104
99
  }
105
100
  })
@@ -35,17 +35,20 @@ export declare function resolveVisibleColumns<T extends Record<string, any>>(col
35
35
  left?: string[];
36
36
  right?: string[];
37
37
  }): TableColumn<T>[];
38
+ type PinOffset = {
39
+ side: 'left' | 'right';
40
+ offset: number;
41
+ };
42
+ type PinOffsets = Map<string, PinOffset>;
38
43
  /**
39
44
  * Compute cumulative left/right offsets for pinned columns.
40
45
  */
41
46
  export declare function computePinOffsets<T extends Record<string, any>>(columns: TableColumn<T>[], columnSizing: Record<string, number>, columnPinning?: {
42
47
  left?: string[];
43
48
  right?: string[];
44
- }): Map<string, {
45
- side: 'left' | 'right';
46
- offset: number;
47
- }>;
49
+ }): PinOffsets;
48
50
  /**
49
51
  * Format cell value for display — handles null/undefined/empty string.
50
52
  */
51
53
  export declare function formatCellValue(value: unknown): string;
54
+ export {};
@@ -17,20 +17,26 @@ export function getRowKey(row, rowKey, index) {
17
17
  return row[rowKey];
18
18
  return index;
19
19
  }
20
+ function isNullish(v) {
21
+ return v === null || v === undefined;
22
+ }
23
+ function compareBooleans(a, b) {
24
+ return a === b ? 0 : a ? -1 : 1;
25
+ }
20
26
  /**
21
27
  * Default sort comparator — handles string, number, boolean, null/undefined.
22
28
  */
23
29
  function defaultCompare(a, b) {
24
30
  if (a === b)
25
31
  return 0;
26
- if (a === null || a === undefined)
32
+ if (isNullish(a))
27
33
  return 1;
28
- if (b === null || b === undefined)
34
+ if (isNullish(b))
29
35
  return -1;
30
36
  if (typeof a === 'number' && typeof b === 'number')
31
37
  return a - b;
32
38
  if (typeof a === 'boolean' && typeof b === 'boolean')
33
- return a === b ? 0 : a ? -1 : 1;
39
+ return compareBooleans(a, b);
34
40
  return String(a).localeCompare(String(b));
35
41
  }
36
42
  /**
@@ -128,33 +134,28 @@ export function resolveVisibleColumns(columns, columnVisibility, columnPinning)
128
134
  const right = visible.filter((c) => rightKeys.has(c.key));
129
135
  return [...left, ...center, ...right];
130
136
  }
137
+ function pinOffsetsForSide(keys, side, columns, columnSizing) {
138
+ const entries = [];
139
+ let offset = 0;
140
+ for (const key of keys) {
141
+ const col = columns.find((c) => c.key === key);
142
+ if (!col)
143
+ continue;
144
+ entries.push([key, { side, offset }]);
145
+ offset += columnSizing[key] ?? col.width ?? 150;
146
+ }
147
+ return entries;
148
+ }
131
149
  /**
132
150
  * Compute cumulative left/right offsets for pinned columns.
133
151
  */
134
152
  export function computePinOffsets(columns, columnSizing, columnPinning) {
135
- const offsets = new Map();
136
153
  if (!columnPinning)
137
- return offsets;
138
- const leftKeys = columnPinning.left ?? [];
139
- const rightKeys = columnPinning.right ?? [];
140
- let leftOffset = 0;
141
- for (const key of leftKeys) {
142
- const col = columns.find((c) => c.key === key);
143
- if (!col)
144
- continue;
145
- offsets.set(key, { side: 'left', offset: leftOffset });
146
- leftOffset += columnSizing[key] ?? col.width ?? 150;
147
- }
148
- let rightOffset = 0;
149
- for (let i = rightKeys.length - 1; i >= 0; i--) {
150
- const key = rightKeys[i];
151
- const col = columns.find((c) => c.key === key);
152
- if (!col)
153
- continue;
154
- offsets.set(key, { side: 'right', offset: rightOffset });
155
- rightOffset += columnSizing[key] ?? col.width ?? 150;
156
- }
157
- return offsets;
154
+ return new Map();
155
+ return new Map([
156
+ ...pinOffsetsForSide(columnPinning.left ?? [], 'left', columns, columnSizing),
157
+ ...pinOffsetsForSide([...(columnPinning.right ?? [])].reverse(), 'right', columns, columnSizing)
158
+ ]);
158
159
  }
159
160
  /**
160
161
  * Format cell value for display — handles null/undefined/empty string.
@@ -84,7 +84,7 @@ export interface TabsSlotProps {
84
84
  */
85
85
  export interface TabsProps extends Pick<TabsRootProps, 'id' | 'style' | 'title' | 'role' | 'tabindex' | 'aria-label' | 'aria-labelledby' | 'aria-describedby' | 'onclick' | 'onkeydown' | 'onmouseenter' | 'onmouseleave' | 'onfocus' | 'onblur'> {
86
86
  /** Custom data attributes are forwarded to the root element. */
87
- [key: `data-${string}`]: unknown;
87
+ [key: `data-${string}`]: string | number | boolean | null | undefined;
88
88
  /**
89
89
  * Bindable reference to the root DOM element.
90
90
  */
@@ -34,7 +34,8 @@
34
34
 
35
35
  const isDark = $derived(mode.current === 'dark')
36
36
 
37
- const slots = $derived(themeModeButtonVariants())
37
+ const slots = themeModeButtonVariants()
38
+ const baseClass = $derived(slots.base({ class: [config.slots.base, className, ui?.base] }))
38
39
 
39
40
  const iconName = $derived(isDark ? lightIcon : darkIcon)
40
41
  </script>
@@ -48,7 +49,7 @@
48
49
  {disabled}
49
50
  {square}
50
51
  {block}
51
- class={slots.base({ class: [config.slots.base, className, ui?.base] })}
52
+ class={baseClass}
52
53
  aria-label={isDark ? 'Switch to light mode' : 'Switch to dark mode'}
53
54
  onclick={toggleMode}
54
55
  {...restProps}
@@ -65,7 +66,7 @@
65
66
  {square}
66
67
  {block}
67
68
  icon={iconName}
68
- class={slots.base({ class: [config.slots.base, className, ui?.base] })}
69
+ class={baseClass}
69
70
  aria-label={isDark ? 'Switch to light mode' : 'Switch to dark mode'}
70
71
  onclick={toggleMode}
71
72
  {...restProps}
@@ -133,7 +133,7 @@
133
133
  {#if children}
134
134
  <Tooltip.Trigger>
135
135
  {#snippet child({ props })}
136
- <span {...props} class={className as string}>
136
+ <span {...props} class={[className]}>
137
137
  {@render children({ open })}
138
138
  </span>
139
139
  {/snippet}
@@ -8,6 +8,8 @@ type ProviderProps = Pick<TooltipProviderPropsWithoutHTML, 'delayDuration' | 'di
8
8
  type RootProps = Pick<TooltipRootPropsWithoutHTML, 'open' | 'onOpenChange' | 'disableCloseOnTriggerClick' | 'ignoreNonKeyboardFocus' | 'disabled'>;
9
9
  type ContentProps = Pick<TooltipContentPropsWithoutHTML, 'side' | 'sideOffset' | 'align' | 'alignOffset' | 'avoidCollisions' | 'collisionBoundary' | 'collisionPadding' | 'sticky' | 'hideWhenDetached' | 'onEscapeKeydown' | 'forceMount'>;
10
10
  export interface TooltipProps extends ProviderProps, RootProps, ContentProps {
11
+ /** Custom data attributes are forwarded to the content element. */
12
+ [key: `data-${string}`]: string | number | boolean | null | undefined;
11
13
  /**
12
14
  * Bindable reference to the content DOM element.
13
15
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sv5ui",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "A modern Svelte 5 UI component library with Tailwind CSS",
5
5
  "author": "ndlabdev",
6
6
  "license": "MIT",