@x33025/sveltely 0.1.22 → 0.1.24

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 (65) hide show
  1. package/dist/components/Library/AnimatedNumber/AnimatedNumber.demo.svelte +3 -2
  2. package/dist/components/Library/ArticleEditor/Blocks/Table.svelte +133 -172
  3. package/dist/components/Library/Checkbox/Checkbox.demo.svelte +5 -4
  4. package/dist/components/Library/Checkbox/Checkbox.svelte +6 -5
  5. package/dist/components/Library/Checkbox/Checkbox.svelte.d.ts +2 -1
  6. package/dist/components/Library/ChipInput/ChipInput.demo.svelte +3 -2
  7. package/dist/components/Library/Dropdown/Dropdown.demo.svelte +17 -14
  8. package/dist/components/Library/Floating/Floating.svelte +5 -6
  9. package/dist/components/Library/Grid/Grid.svelte +13 -4
  10. package/dist/components/Library/Grid/Grid.svelte.d.ts +2 -1
  11. package/dist/components/Library/Grid/GridItem.svelte +12 -3
  12. package/dist/components/Library/Grid/GridItem.svelte.d.ts +2 -1
  13. package/dist/components/Library/HStack/HStack.svelte +4 -4
  14. package/dist/components/Library/HStack/HStack.svelte.d.ts +2 -1
  15. package/dist/components/Library/Image/Image.demo.svelte +3 -1
  16. package/dist/components/Library/Image/Image.demo.svelte.d.ts +2 -0
  17. package/dist/components/Library/ImageMask/ImageMask.demo.svelte +8 -6
  18. package/dist/components/Library/Label/Label.demo.svelte +4 -4
  19. package/dist/components/Library/Label/Label.svelte +20 -15
  20. package/dist/components/Library/NavigationStack/Link.svelte +1 -4
  21. package/dist/components/Library/Pagination/Pagination.demo.svelte +3 -2
  22. package/dist/components/Library/Popover/PopoverDebugOverlay.svelte +3 -3
  23. package/dist/components/Library/Portal/Content.svelte +20 -0
  24. package/dist/components/Library/Portal/Content.svelte.d.ts +10 -0
  25. package/dist/components/Library/Portal/Portal.svelte +4 -0
  26. package/dist/components/Library/Portal/Portal.svelte.d.ts +1 -0
  27. package/dist/components/Library/Portal/index.d.ts +1 -0
  28. package/dist/components/Library/Portal/index.js +1 -0
  29. package/dist/components/Library/ScrollView/ScrollView.svelte +12 -5
  30. package/dist/components/Library/SearchField/SearchField.demo.svelte +3 -2
  31. package/dist/components/Library/SearchField/SearchField.svelte +5 -5
  32. package/dist/components/Library/SearchField/SearchField.svelte.d.ts +2 -1
  33. package/dist/components/Library/SegmentedPicker/SegmentedPicker.demo.svelte +3 -2
  34. package/dist/components/Library/Sheet/Sheet.demo.svelte +3 -2
  35. package/dist/components/Library/Sheet/Sheet.svelte +3 -3
  36. package/dist/components/Library/Slider/Slider.demo.svelte +3 -2
  37. package/dist/components/Library/Spinner/Spinner.demo.svelte +3 -2
  38. package/dist/components/Library/Switch/Switch.demo.svelte +5 -4
  39. package/dist/components/Library/Switch/Switch.svelte +6 -5
  40. package/dist/components/Library/Switch/Switch.svelte.d.ts +2 -1
  41. package/dist/components/Library/Table/Column.svelte +3 -0
  42. package/dist/components/Library/Table/Column.svelte.d.ts +1 -0
  43. package/dist/components/Library/Table/Table.demo.svelte +222 -17
  44. package/dist/components/Library/Table/Table.svelte +98 -57
  45. package/dist/components/Library/Table/Table.svelte.d.ts +1 -2
  46. package/dist/components/Library/Table/types.d.ts +1 -0
  47. package/dist/components/Library/TextShimmer/TextShimmer.demo.svelte +3 -2
  48. package/dist/components/Library/TimePicker/TimePicker.demo.svelte +3 -10
  49. package/dist/components/Library/TokenSearchField/TokenSearchField.demo.svelte +3 -2
  50. package/dist/components/Library/VStack/VStack.svelte +4 -4
  51. package/dist/components/Library/VStack/VStack.svelte.d.ts +2 -1
  52. package/dist/components/Local/ColorStyleControls.svelte +0 -8
  53. package/dist/components/Local/ComponentGrid.svelte +3 -12
  54. package/dist/components/Local/HeroCard.svelte +1 -2
  55. package/dist/components/Local/LayoutStyleControls.svelte +33 -25
  56. package/dist/components/Local/StyleControls.svelte +1 -1
  57. package/dist/index.d.ts +2 -2
  58. package/dist/index.js +1 -1
  59. package/dist/style/index.css +2 -2
  60. package/dist/style/layout.d.ts +14 -20
  61. package/dist/style/layout.js +14 -40
  62. package/dist/style/surface.d.ts +1 -0
  63. package/dist/style/surface.js +10 -0
  64. package/dist/style.css +2 -53
  65. package/package.json +1 -1
@@ -10,25 +10,26 @@
10
10
  TooltipProps &
11
11
  Omit<HTMLInputAttributes, 'type' | 'class' | 'style' | 'checked'>;
12
12
 
13
- let { checked = $bindable(false), tooltip, disabled = false, ...restProps }: Props = $props();
13
+ let { checked = $bindable(false), tooltip, disabled = false, ...restProps }: Props &
14
+ Record<string, unknown> = $props();
14
15
 
15
16
  const extractedStyleProps = $derived.by(() => extractStyleProps(restProps));
16
17
  const styleProps = $derived(extractedStyleProps.styleProps);
17
- const props = $derived(extractedStyleProps.restProps);
18
+ const forwardedProps = $derived(extractedStyleProps.restProps);
18
19
  const rootStyle = $derived.by(() => surfaceStyle(styleProps, 'switch'));
19
20
  </script>
20
21
 
21
- <label
22
+ <span
22
23
  class="switch"
23
24
  style={rootStyle}
24
25
  data-disabled={disabled ? 'true' : 'false'}
25
26
  use:tooltipAction={tooltip}
26
27
  >
27
- <input bind:checked type="checkbox" {disabled} {...props} />
28
+ <input bind:checked type="checkbox" {disabled} {...forwardedProps} />
28
29
  <span class="switch-track" aria-hidden="true">
29
30
  <span class="switch-thumb"></span>
30
31
  </span>
31
- </label>
32
+ </span>
32
33
 
33
34
  <style>
34
35
  .switch {
@@ -4,6 +4,7 @@ import type { TooltipProps } from '../../../style/tooltip';
4
4
  type Props = {
5
5
  checked?: boolean;
6
6
  } & StyleProps & TooltipProps & Omit<HTMLInputAttributes, 'type' | 'class' | 'style' | 'checked'>;
7
- declare const Switch: import("svelte").Component<Props, {}, "checked">;
7
+ type $$ComponentProps = Props & Record<string, unknown>;
8
+ declare const Switch: import("svelte").Component<$$ComponentProps, {}, "checked">;
8
9
  type Switch = ReturnType<typeof Switch>;
9
10
  export default Switch;
@@ -6,6 +6,7 @@
6
6
  type Props = {
7
7
  key?: string;
8
8
  label: string;
9
+ header?: TableColumn<T>['header'];
9
10
  value?: keyof T | ((row: T) => unknown);
10
11
  cell?: TableColumn<T>['cell'];
11
12
  width?: number | string;
@@ -22,6 +23,7 @@
22
23
  let {
23
24
  key,
24
25
  label,
26
+ header,
25
27
  value,
26
28
  cell,
27
29
  width,
@@ -40,6 +42,7 @@
40
42
  const snapshot = (): TableColumn<T> => ({
41
43
  key,
42
44
  label,
45
+ header,
43
46
  value,
44
47
  cell,
45
48
  width,
@@ -3,6 +3,7 @@ declare function $$render<T extends Record<string, unknown>>(): {
3
3
  props: {
4
4
  key?: string;
5
5
  label: string;
6
+ header?: TableColumn<T>["header"];
6
7
  value?: keyof T | ((row: T) => unknown);
7
8
  cell?: TableColumn<T>["cell"];
8
9
  width?: number | string;
@@ -5,6 +5,12 @@
5
5
  owner: string;
6
6
  status: 'Active' | 'Paused' | 'Review';
7
7
  budget: number;
8
+ region: string;
9
+ phase: string;
10
+ priority: string;
11
+ launch: string;
12
+ risk: string;
13
+ updated: string;
8
14
  };
9
15
 
10
16
  export const demo = {
@@ -20,22 +26,214 @@
20
26
  import type { TableSortDescriptor } from './types';
21
27
 
22
28
  const rows: Project[] = [
23
- { id: 1, name: 'Atlas', owner: 'Mika', status: 'Active', budget: 18200 },
24
- { id: 2, name: 'Beacon', owner: 'Nia', status: 'Review', budget: 9400 },
25
- { id: 3, name: 'Canopy', owner: 'Tao', status: 'Paused', budget: 12650 },
26
- { id: 4, name: 'Drift', owner: 'Ari', status: 'Active', budget: 22100 },
27
- { id: 5, name: 'Ember', owner: 'Sana', status: 'Review', budget: 15840 },
28
- { id: 6, name: 'Fjord', owner: 'Leo', status: 'Active', budget: 27600 },
29
- { id: 7, name: 'Grove', owner: 'Ilya', status: 'Paused', budget: 7300 },
30
- { id: 8, name: 'Harbor', owner: 'Noor', status: 'Active', budget: 31450 },
31
- { id: 9, name: 'Ion', owner: 'Mika', status: 'Review', budget: 11900 },
32
- { id: 10, name: 'Juno', owner: 'Tao', status: 'Active', budget: 19875 },
33
- { id: 11, name: 'Keystone', owner: 'Ari', status: 'Paused', budget: 14620 },
34
- { id: 12, name: 'Lumen', owner: 'Nia', status: 'Review', budget: 24880 },
35
- { id: 13, name: 'Meridian', owner: 'Sana', status: 'Active', budget: 33750 },
36
- { id: 14, name: 'Nimbus', owner: 'Leo', status: 'Paused', budget: 6800 },
37
- { id: 15, name: 'Orchid', owner: 'Ilya', status: 'Active', budget: 17340 },
38
- { id: 16, name: 'Pulse', owner: 'Noor', status: 'Review', budget: 20410 }
29
+ {
30
+ id: 1,
31
+ name: 'Atlas',
32
+ owner: 'Mika',
33
+ status: 'Active',
34
+ budget: 18200,
35
+ region: 'North America',
36
+ phase: 'Discovery',
37
+ priority: 'High',
38
+ launch: 'Q2 2026',
39
+ risk: 'Low',
40
+ updated: 'Today'
41
+ },
42
+ {
43
+ id: 2,
44
+ name: 'Beacon',
45
+ owner: 'Nia',
46
+ status: 'Review',
47
+ budget: 9400,
48
+ region: 'Europe',
49
+ phase: 'Design',
50
+ priority: 'Medium',
51
+ launch: 'Q3 2026',
52
+ risk: 'Medium',
53
+ updated: 'Yesterday'
54
+ },
55
+ {
56
+ id: 3,
57
+ name: 'Canopy',
58
+ owner: 'Tao',
59
+ status: 'Paused',
60
+ budget: 12650,
61
+ region: 'Asia Pacific',
62
+ phase: 'Build',
63
+ priority: 'Low',
64
+ launch: 'Q4 2026',
65
+ risk: 'High',
66
+ updated: 'May 12'
67
+ },
68
+ {
69
+ id: 4,
70
+ name: 'Drift',
71
+ owner: 'Ari',
72
+ status: 'Active',
73
+ budget: 22100,
74
+ region: 'Latin America',
75
+ phase: 'Launch',
76
+ priority: 'High',
77
+ launch: 'Q1 2027',
78
+ risk: 'Low',
79
+ updated: 'May 10'
80
+ },
81
+ {
82
+ id: 5,
83
+ name: 'Ember',
84
+ owner: 'Sana',
85
+ status: 'Review',
86
+ budget: 15840,
87
+ region: 'Middle East',
88
+ phase: 'Validation',
89
+ priority: 'Medium',
90
+ launch: 'Q2 2027',
91
+ risk: 'Medium',
92
+ updated: 'May 8'
93
+ },
94
+ {
95
+ id: 6,
96
+ name: 'Fjord',
97
+ owner: 'Leo',
98
+ status: 'Active',
99
+ budget: 27600,
100
+ region: 'Nordics',
101
+ phase: 'Build',
102
+ priority: 'High',
103
+ launch: 'Q3 2027',
104
+ risk: 'Low',
105
+ updated: 'May 7'
106
+ },
107
+ {
108
+ id: 7,
109
+ name: 'Grove',
110
+ owner: 'Ilya',
111
+ status: 'Paused',
112
+ budget: 7300,
113
+ region: 'Africa',
114
+ phase: 'Planning',
115
+ priority: 'Low',
116
+ launch: 'Q4 2027',
117
+ risk: 'High',
118
+ updated: 'May 5'
119
+ },
120
+ {
121
+ id: 8,
122
+ name: 'Harbor',
123
+ owner: 'Noor',
124
+ status: 'Active',
125
+ budget: 31450,
126
+ region: 'Oceania',
127
+ phase: 'Scale',
128
+ priority: 'High',
129
+ launch: 'Q1 2028',
130
+ risk: 'Medium',
131
+ updated: 'May 3'
132
+ },
133
+ {
134
+ id: 9,
135
+ name: 'Ion',
136
+ owner: 'Mika',
137
+ status: 'Review',
138
+ budget: 11900,
139
+ region: 'North America',
140
+ phase: 'Research',
141
+ priority: 'Medium',
142
+ launch: 'Q2 2028',
143
+ risk: 'Low',
144
+ updated: 'May 1'
145
+ },
146
+ {
147
+ id: 10,
148
+ name: 'Juno',
149
+ owner: 'Tao',
150
+ status: 'Active',
151
+ budget: 19875,
152
+ region: 'Europe',
153
+ phase: 'Delivery',
154
+ priority: 'High',
155
+ launch: 'Q3 2028',
156
+ risk: 'Medium',
157
+ updated: 'Apr 29'
158
+ },
159
+ {
160
+ id: 11,
161
+ name: 'Keystone',
162
+ owner: 'Ari',
163
+ status: 'Paused',
164
+ budget: 14620,
165
+ region: 'Asia Pacific',
166
+ phase: 'Planning',
167
+ priority: 'Low',
168
+ launch: 'Q4 2028',
169
+ risk: 'High',
170
+ updated: 'Apr 27'
171
+ },
172
+ {
173
+ id: 12,
174
+ name: 'Lumen',
175
+ owner: 'Nia',
176
+ status: 'Review',
177
+ budget: 24880,
178
+ region: 'Latin America',
179
+ phase: 'Validation',
180
+ priority: 'Medium',
181
+ launch: 'Q1 2029',
182
+ risk: 'Low',
183
+ updated: 'Apr 24'
184
+ },
185
+ {
186
+ id: 13,
187
+ name: 'Meridian',
188
+ owner: 'Sana',
189
+ status: 'Active',
190
+ budget: 33750,
191
+ region: 'Middle East',
192
+ phase: 'Scale',
193
+ priority: 'High',
194
+ launch: 'Q2 2029',
195
+ risk: 'Medium',
196
+ updated: 'Apr 22'
197
+ },
198
+ {
199
+ id: 14,
200
+ name: 'Nimbus',
201
+ owner: 'Leo',
202
+ status: 'Paused',
203
+ budget: 6800,
204
+ region: 'Nordics',
205
+ phase: 'Discovery',
206
+ priority: 'Low',
207
+ launch: 'Q3 2029',
208
+ risk: 'High',
209
+ updated: 'Apr 20'
210
+ },
211
+ {
212
+ id: 15,
213
+ name: 'Orchid',
214
+ owner: 'Ilya',
215
+ status: 'Active',
216
+ budget: 17340,
217
+ region: 'Africa',
218
+ phase: 'Launch',
219
+ priority: 'Medium',
220
+ launch: 'Q4 2029',
221
+ risk: 'Low',
222
+ updated: 'Apr 18'
223
+ },
224
+ {
225
+ id: 16,
226
+ name: 'Pulse',
227
+ owner: 'Noor',
228
+ status: 'Review',
229
+ budget: 20410,
230
+ region: 'Oceania',
231
+ phase: 'Build',
232
+ priority: 'High',
233
+ launch: 'Q1 2030',
234
+ risk: 'Medium',
235
+ updated: 'Apr 16'
236
+ }
39
237
  ];
40
238
 
41
239
  let selection = $state<Set<number>>(new Set([1, 4]));
@@ -72,7 +270,7 @@
72
270
  })}
73
271
  {/snippet}
74
272
 
75
- <Table data={rows} bind:selection bind:sortOrder selectionMode="multiple">
273
+ <Table data={rows} bind:selection bind:sortOrder selectionMode="multiple" height="100%">
76
274
  <Table.Column label="Project" sortKey="name" sortable minWidth={160}>
77
275
  {#snippet cell(project: Project)}
78
276
  {@render projectCell(project)}
@@ -96,6 +294,13 @@
96
294
  {@render budgetCell(project)}
97
295
  {/snippet}
98
296
  </Table.Column>
297
+
298
+ <Table.Column label="Region" value="region" sortKey="region" sortable minWidth={150} />
299
+ <Table.Column label="Phase" value="phase" sortKey="phase" sortable minWidth={120} />
300
+ <Table.Column label="Priority" value="priority" sortKey="priority" sortable minWidth={112} />
301
+ <Table.Column label="Launch" value="launch" sortKey="launch" sortable minWidth={112} />
302
+ <Table.Column label="Risk" value="risk" sortKey="risk" sortable minWidth={104} />
303
+ <Table.Column label="Updated" value="updated" sortKey="updated" sortable minWidth={120} />
99
304
  </Table>
100
305
 
101
306
  <style>
@@ -54,6 +54,7 @@
54
54
  }: Props = $props();
55
55
 
56
56
  let tableSortOrder = $state<TableSortDescriptor<T>[]>(sortOrder);
57
+ let scrollOffsetX = $state(0);
57
58
  let dragSelection = $state<{
58
59
  active: boolean;
59
60
  pointerId: number;
@@ -88,15 +89,9 @@
88
89
  typeof value === 'number' ? `${value}px` : value;
89
90
 
90
91
  const tableShellStyle = $derived.by(() => {
91
- const hasExplicitHeight = layoutProps.height !== undefined || layoutProps.size !== undefined;
92
- const fallbackHeight = hasExplicitHeight ? undefined : (layoutProps.maxHeight ?? '100%');
93
-
94
92
  return [
95
93
  layoutStyle(layoutProps),
96
- rootStyle,
97
- layoutProps.height === undefined ? '' : `height: ${toCssSize(layoutProps.height)};`,
98
- layoutProps.maxHeight === undefined ? '' : `max-height: ${toCssSize(layoutProps.maxHeight)};`,
99
- fallbackHeight === undefined ? '' : `height: ${toCssSize(fallbackHeight)};`
94
+ rootStyle
100
95
  ]
101
96
  .filter(Boolean)
102
97
  .join(' ');
@@ -214,6 +209,18 @@
214
209
  (column, index) => !column.hidden && !hidden.has(columnKey(column, index))
215
210
  );
216
211
  });
212
+ const tableMinWidth = $derived.by(() => {
213
+ const widths = visibleColumns
214
+ .map((column) => toCssSize(column.width ?? column.minWidth))
215
+ .filter((width): width is string => Boolean(width));
216
+
217
+ if (widths.length === 0) return '100%';
218
+ return `max(100%, calc(${widths.join(' + ')}))`;
219
+ });
220
+ const tableWidthStyle = $derived(`width: ${tableMinWidth};`);
221
+ const headerStyle = $derived(
222
+ `${tableWidthStyle} transform: translate3d(${-scrollOffsetX}px, 0, 0);`
223
+ );
217
224
 
218
225
  const sortedRows = $derived.by(() => {
219
226
  if (tableSortOrder.length === 0) return data;
@@ -391,6 +398,10 @@
391
398
  if (selectionMode === 'multiple' || isInteractiveTarget(event.target)) return;
392
399
  updateSelection(key);
393
400
  };
401
+
402
+ const handleScroll = (geometry: { offset: { x: number } }) => {
403
+ scrollOffsetX = geometry.offset.x;
404
+ };
394
405
  </script>
395
406
 
396
407
  {#if children}
@@ -405,59 +416,78 @@
405
416
 
406
417
  <div class="table-shell" style={tableShellStyle} {...forwardedProps}>
407
418
  {#if columnHeaders === 'visible'}
408
- <table
409
- class="table-header-table table"
410
- role={selectionMode === 'none' ? undefined : 'grid'}
411
- aria-multiselectable={selectionMode === 'multiple' ? 'true' : undefined}
412
- >
413
- <thead class="table-header">
414
- <tr>
415
- {#each visibleColumns as column, index (columnKey(column, index))}
416
- <th
417
- class={`table-heading table-align-${column.alignment ?? 'leading'}`}
418
- colspan={headerSpan(column.colspan)}
419
- rowspan={headerSpan(column.rowspan)}
420
- style:min-width={toCssSize(column.minWidth)}
421
- style:width={toCssSize(column.width)}
422
- aria-sort={tableSortOrder[0]?.key === columnSortKey(column, index)
423
- ? tableSortOrder[0].direction === 'ascending'
424
- ? 'ascending'
425
- : 'descending'
426
- : undefined}
427
- >
428
- {#if column.sortable}
429
- {@const sortDirection = activeSortDirection(column, index)}
430
- <button
431
- type="button"
432
- class="table-sort-button"
433
- onclick={() => updateSort(column, index)}
434
- >
435
- <span>{column.label}</span>
436
- {#if sortDirection === 'ascending'}
437
- <ArrowUpIcon class="table-sort-icon" size={12} strokeWidth={2.25} />
438
- {:else if sortDirection === 'descending'}
439
- <ArrowDownIcon class="table-sort-icon" size={12} strokeWidth={2.25} />
419
+ <div class="table-header-frame">
420
+ <table
421
+ class="table-header-table table"
422
+ style={headerStyle}
423
+ role={selectionMode === 'none' ? undefined : 'grid'}
424
+ aria-multiselectable={selectionMode === 'multiple' ? 'true' : undefined}
425
+ >
426
+ <thead class="table-header">
427
+ <tr>
428
+ {#each visibleColumns as column, index (columnKey(column, index))}
429
+ <th
430
+ class={`table-heading table-align-${column.alignment ?? 'leading'}`}
431
+ colspan={headerSpan(column.colspan)}
432
+ rowspan={headerSpan(column.rowspan)}
433
+ style:min-width={toCssSize(column.minWidth)}
434
+ style:width={toCssSize(column.width)}
435
+ aria-sort={tableSortOrder[0]?.key === columnSortKey(column, index)
436
+ ? tableSortOrder[0].direction === 'ascending'
437
+ ? 'ascending'
438
+ : 'descending'
439
+ : undefined}
440
+ >
441
+ {#if column.sortable}
442
+ {@const sortDirection = activeSortDirection(column, index)}
443
+ <button
444
+ type="button"
445
+ class="table-sort-button"
446
+ onclick={() => updateSort(column, index)}
447
+ >
448
+ <span>
449
+ {#if column.header}
450
+ {@render column.header(column, index)}
451
+ {:else}
452
+ {column.label}
453
+ {/if}
454
+ </span>
455
+ {#if sortDirection === 'ascending'}
456
+ <ArrowUpIcon class="table-sort-icon" size={12} strokeWidth={2.25} />
457
+ {:else if sortDirection === 'descending'}
458
+ <ArrowDownIcon class="table-sort-icon" size={12} strokeWidth={2.25} />
459
+ {:else}
460
+ <ArrowUpDownIcon
461
+ class="table-sort-icon table-sort-icon-muted"
462
+ size={12}
463
+ strokeWidth={2.25}
464
+ />
465
+ {/if}
466
+ </button>
467
+ {:else}
468
+ {#if column.header}
469
+ {@render column.header(column, index)}
440
470
  {:else}
441
- <ArrowUpDownIcon
442
- class="table-sort-icon table-sort-icon-muted"
443
- size={12}
444
- strokeWidth={2.25}
445
- />
471
+ {column.label}
446
472
  {/if}
447
- </button>
448
- {:else}
449
- {column.label}
450
- {/if}
451
- </th>
452
- {/each}
453
- </tr>
454
- </thead>
455
- </table>
473
+ {/if}
474
+ </th>
475
+ {/each}
476
+ </tr>
477
+ </thead>
478
+ </table>
479
+ </div>
456
480
  {/if}
457
481
 
458
- <ScrollView axis="both" loader={bodyLoaderOptions} contentStyles={{ paddingX: 0, paddingY: 0 }}>
482
+ <ScrollView
483
+ axis="both"
484
+ loader={bodyLoaderOptions}
485
+ contentStyles={{ paddingX: 0, paddingY: 0 }}
486
+ onScroll={handleScroll}
487
+ >
459
488
  <table
460
489
  class="table-body-table table"
490
+ style={tableWidthStyle}
461
491
  role={selectionMode === 'none' ? undefined : 'grid'}
462
492
  aria-multiselectable={selectionMode === 'multiple' ? 'true' : undefined}
463
493
  >
@@ -512,8 +542,10 @@
512
542
  flex-direction: column;
513
543
  flex: 1 1 auto;
514
544
  align-self: stretch;
545
+ min-width: 0;
515
546
  min-height: 0;
516
547
  width: 100%;
548
+ max-width: 100%;
517
549
  overflow: hidden;
518
550
  border: 1px solid var(--sveltely-border-color);
519
551
  border-radius: var(--sveltely-border-radius);
@@ -524,7 +556,7 @@
524
556
 
525
557
  .table {
526
558
  width: 100%;
527
- min-width: max-content;
559
+ min-width: 100%;
528
560
  border-collapse: separate;
529
561
  border-spacing: 0;
530
562
  }
@@ -537,19 +569,28 @@
537
569
  );
538
570
  }
539
571
 
572
+ .table-header-frame {
573
+ width: 100%;
574
+ min-width: 0;
575
+ overflow: hidden;
576
+ border-bottom: 1px solid var(--sveltely-border-color);
577
+ }
578
+
540
579
  .table-header-table {
541
580
  flex: 0 0 auto;
542
- border-bottom: 1px solid var(--sveltely-border-color);
581
+ will-change: transform;
543
582
  }
544
583
 
545
- .table-header-table + :global(.scroll-view) {
584
+ .table-header-frame + :global(.scroll-view) {
546
585
  border-top-left-radius: 0;
547
586
  border-top-right-radius: 0;
548
587
  }
549
588
 
550
589
  .table-shell > :global(.scroll-view) {
551
590
  flex: 1 1 auto;
591
+ min-width: 0;
552
592
  min-height: 0;
593
+ max-width: 100%;
553
594
  }
554
595
 
555
596
  .table-heading,
@@ -1,7 +1,6 @@
1
1
  export { default as Column } from './Column.svelte';
2
2
  import { type Snippet } from 'svelte';
3
3
  import { type LoaderProps } from '../../../style/loader';
4
- import { type LayoutProps } from '../../../style/layout';
5
4
  import { type StyleProps } from '../../../style/surface';
6
5
  import type { TableColumn, TableColumnCustomization, TableColumnHeaderVisibility, TableSelection, TableSelectionMode, TableSortDescriptor } from './types';
7
6
  declare function $$render<T extends Record<string, unknown>>(): {
@@ -17,7 +16,7 @@ declare function $$render<T extends Record<string, unknown>>(): {
17
16
  emptyLabel?: string;
18
17
  onSortOrderChange?: (sortOrder: TableSortDescriptor<T>[]) => void;
19
18
  onSelectionChange?: (selection: TableSelection) => void;
20
- } & LayoutProps & StyleProps & LoaderProps & Record<string, unknown>;
19
+ } & import("../../../style/layout").FrameProps & import("../../../style/layout").StackProps & StyleProps & LoaderProps & Record<string, unknown>;
21
20
  exports: {};
22
21
  bindings: "selection" | "sortOrder" | "columnCustomization";
23
22
  slots: {};
@@ -18,6 +18,7 @@ export type TableColumnCustomization = {
18
18
  export type TableColumn<T> = {
19
19
  key?: string;
20
20
  label: string;
21
+ header?: Snippet<[column: TableColumn<T>, index: number]>;
21
22
  value?: keyof T | ((row: T) => unknown);
22
23
  cell?: Snippet<[row: T, index: number]>;
23
24
  width?: number | string;
@@ -6,9 +6,10 @@
6
6
  </script>
7
7
 
8
8
  <script lang="ts">
9
+ import VStack from '../VStack';
9
10
  import TextShimmer from './TextShimmer.svelte';
10
11
  </script>
11
12
 
12
- <div class="vstack gap-2">
13
+ <VStack gap={5}>
13
14
  <TextShimmer as="h2" text="Sveltely shimmer" />
14
- </div>
15
+ </VStack>
@@ -8,19 +8,12 @@
8
8
  </script>
9
9
 
10
10
  <script lang="ts">
11
+ import VStack from '../VStack';
11
12
  import TimePicker from './TimePicker.svelte';
12
13
 
13
14
  let value = $state<Date | null>(new Date());
14
15
  </script>
15
16
 
16
- <div class="time-picker-demo vstack gap-4">
17
+ <VStack width="100%" height="100%" gap={10}>
17
18
  <TimePicker bind:value />
18
- </div>
19
-
20
- <style>
21
- .time-picker-demo {
22
- width: 100%;
23
- height: 100%;
24
- min-height: 0;
25
- }
26
- </style>
19
+ </VStack>
@@ -7,15 +7,16 @@
7
7
  </script>
8
8
 
9
9
  <script lang="ts">
10
+ import VStack from '../VStack';
10
11
  import TokenSearchField from './TokenSearchField.svelte';
11
12
 
12
13
  let tokens = $state(['svelte', 'ui']);
13
14
  let value = $state('');
14
15
  </script>
15
16
 
16
- <div class="vstack w-full max-w-md gap-2">
17
+ <VStack width="100%" maxWidth="28rem" gap={5}>
17
18
  <TokenSearchField bind:tokens bind:value placeholder="Search keywords" />
18
19
  <p class="text-xs text-[var(--sveltely-text-secondary-color)]">
19
20
  Tokens: {tokens.join(', ') || 'empty'}
20
21
  </p>
21
- </div>
22
+ </VStack>