@x33025/sveltely 0.1.23 → 0.1.25

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 (107) hide show
  1. package/dist/actions/LoaderOverlay.svelte +10 -3
  2. package/dist/components/Library/Accordion/Accordion.demo.svelte +21 -0
  3. package/dist/components/Library/Accordion/Accordion.demo.svelte.d.ts +9 -0
  4. package/dist/components/Library/Accordion/Accordion.svelte +78 -0
  5. package/dist/components/Library/Accordion/Accordion.svelte.d.ts +14 -0
  6. package/dist/components/Library/Accordion/Content.svelte +57 -0
  7. package/dist/components/Library/Accordion/Content.svelte.d.ts +8 -0
  8. package/dist/components/Library/Accordion/Header.svelte +98 -0
  9. package/dist/components/Library/Accordion/Header.svelte.d.ts +10 -0
  10. package/dist/components/Library/Accordion/context.d.ts +9 -0
  11. package/dist/components/Library/Accordion/context.js +6 -0
  12. package/dist/components/Library/Accordion/index.d.ts +9 -0
  13. package/dist/components/Library/Accordion/index.js +7 -0
  14. package/dist/components/Library/AnimatedNumber/AnimatedNumber.demo.svelte +3 -2
  15. package/dist/components/Library/ArticleEditor/ArticleEditor.svelte +1 -2
  16. package/dist/components/Library/ArticleEditor/Blocks/Table.svelte +133 -172
  17. package/dist/components/Library/Checkbox/Checkbox.demo.svelte +5 -4
  18. package/dist/components/Library/Checkbox/Checkbox.svelte +6 -5
  19. package/dist/components/Library/Checkbox/Checkbox.svelte.d.ts +2 -1
  20. package/dist/components/Library/ChipInput/ChipInput.demo.svelte +3 -2
  21. package/dist/components/Library/Dropdown/Dropdown.demo.svelte +20 -15
  22. package/dist/components/Library/Floating/Floating.svelte +5 -6
  23. package/dist/components/Library/Grid/Grid.demo.svelte +58 -0
  24. package/dist/components/Library/Grid/Grid.demo.svelte.d.ts +25 -0
  25. package/dist/components/Library/Grid/Grid.svelte +128 -25
  26. package/dist/components/Library/Grid/Grid.svelte.d.ts +38 -9
  27. package/dist/components/Library/Grid/GridItem.svelte +18 -14
  28. package/dist/components/Library/Grid/GridItem.svelte.d.ts +2 -1
  29. package/dist/components/Library/HStack/HStack.svelte +4 -4
  30. package/dist/components/Library/HStack/HStack.svelte.d.ts +2 -1
  31. package/dist/components/Library/Image/Image.demo.svelte +3 -1
  32. package/dist/components/Library/Image/Image.demo.svelte.d.ts +2 -0
  33. package/dist/components/Library/ImageMask/ImageMask.demo.svelte +8 -6
  34. package/dist/components/Library/Label/Label.demo.svelte +5 -5
  35. package/dist/components/Library/Label/Label.svelte +10 -26
  36. package/dist/components/Library/NavigationStack/Link.svelte +1 -4
  37. package/dist/components/Library/Notifications/Notifications.demo.svelte +63 -0
  38. package/dist/components/Library/Notifications/Notifications.demo.svelte.d.ts +9 -0
  39. package/dist/components/Library/Notifications/Notifications.svelte +155 -0
  40. package/dist/components/Library/Notifications/Notifications.svelte.d.ts +35 -0
  41. package/dist/components/Library/Notifications/index.d.ts +2 -0
  42. package/dist/components/Library/Notifications/index.js +1 -0
  43. package/dist/components/Library/Notifications/types.d.ts +8 -0
  44. package/dist/components/Library/Notifications/types.js +1 -0
  45. package/dist/components/Library/NumberField/NumberField.svelte +25 -19
  46. package/dist/components/Library/Pagination/Pagination.demo.svelte +3 -2
  47. package/dist/components/Library/Pagination/Pagination.svelte +6 -18
  48. package/dist/components/Library/Popover/PopoverDebugOverlay.svelte +3 -3
  49. package/dist/components/Library/Portal/Content.svelte +20 -0
  50. package/dist/components/Library/Portal/Content.svelte.d.ts +10 -0
  51. package/dist/components/Library/Portal/Portal.svelte +4 -0
  52. package/dist/components/Library/Portal/Portal.svelte.d.ts +1 -0
  53. package/dist/components/Library/Portal/index.d.ts +1 -0
  54. package/dist/components/Library/Portal/index.js +1 -0
  55. package/dist/components/Library/ScrollView/ScrollView.svelte +88 -9
  56. package/dist/components/Library/ScrollView/ScrollView.svelte.d.ts +9 -2
  57. package/dist/components/Library/ScrollView/index.d.ts +1 -1
  58. package/dist/components/Library/SearchField/SearchField.demo.svelte +3 -2
  59. package/dist/components/Library/SearchField/SearchField.svelte +5 -5
  60. package/dist/components/Library/SearchField/SearchField.svelte.d.ts +2 -1
  61. package/dist/components/Library/SegmentedPicker/SegmentedPicker.demo.svelte +3 -2
  62. package/dist/components/Library/Sheet/Sheet.demo.svelte +3 -2
  63. package/dist/components/Library/Sheet/Sheet.svelte +3 -3
  64. package/dist/components/Library/Slider/Slider.demo.svelte +3 -2
  65. package/dist/components/Library/Spinner/Spinner.demo.svelte +3 -2
  66. package/dist/components/Library/Switch/Switch.demo.svelte +5 -4
  67. package/dist/components/Library/Switch/Switch.svelte +6 -5
  68. package/dist/components/Library/Switch/Switch.svelte.d.ts +2 -1
  69. package/dist/components/Library/Table/Column.svelte +3 -0
  70. package/dist/components/Library/Table/Column.svelte.d.ts +1 -0
  71. package/dist/components/Library/Table/Table.demo.svelte +230 -17
  72. package/dist/components/Library/Table/Table.svelte +322 -78
  73. package/dist/components/Library/Table/Table.svelte.d.ts +5 -0
  74. package/dist/components/Library/Table/types.d.ts +1 -0
  75. package/dist/components/Library/TextField/TextField.svelte +20 -14
  76. package/dist/components/Library/TextShimmer/TextShimmer.demo.svelte +3 -2
  77. package/dist/components/Library/TimePicker/TimePicker.demo.svelte +3 -10
  78. package/dist/components/Library/TokenSearchField/TokenSearchField.demo.svelte +3 -2
  79. package/dist/components/Library/VStack/VStack.svelte +4 -4
  80. package/dist/components/Library/VStack/VStack.svelte.d.ts +2 -1
  81. package/dist/components/Local/ColorStyleControls.svelte +25 -72
  82. package/dist/components/Local/ComponentGrid.svelte +99 -27
  83. package/dist/components/Local/ComponentGrid.svelte.d.ts +2 -1
  84. package/dist/components/Local/ComponentPage.svelte +74 -0
  85. package/dist/components/Local/ComponentPage.svelte.d.ts +13 -0
  86. package/dist/components/Local/HeroCard.svelte +10 -6
  87. package/dist/components/Local/LayoutStyleControls.svelte +33 -25
  88. package/dist/components/Local/StyleControls.svelte +1 -1
  89. package/dist/index.d.ts +8 -3
  90. package/dist/index.js +4 -1
  91. package/dist/style/index.css +3 -4
  92. package/dist/style/layout.d.ts +15 -36
  93. package/dist/style/layout.js +35 -83
  94. package/dist/style/surface.d.ts +1 -0
  95. package/dist/style/surface.js +10 -0
  96. package/dist/style.css +3 -51
  97. package/dist/viewport/geometry.d.ts +8 -0
  98. package/dist/viewport/geometry.js +43 -0
  99. package/dist/viewport/index.d.ts +4 -0
  100. package/dist/viewport/index.js +4 -0
  101. package/dist/viewport/layout.d.ts +4 -0
  102. package/dist/viewport/layout.js +138 -0
  103. package/dist/viewport/placement.d.ts +4 -0
  104. package/dist/viewport/placement.js +14 -0
  105. package/dist/viewport/types.d.ts +81 -0
  106. package/dist/viewport/types.js +1 -0
  107. package/package.json +1 -1
@@ -1,7 +1,19 @@
1
1
  <script lang="ts">
2
2
  import { Plus, Trash2 } from '@lucide/svelte';
3
+ import Grid from '../../Grid';
4
+ import HStack from '../../HStack';
5
+ import Spacer from '../../Spacer';
6
+ import SveltelyTable from '../../Table';
7
+ import { Column as TableColumn } from '../../Table';
8
+ import VStack from '../../VStack';
3
9
  import type { BlockDraft } from '../types.js';
4
10
 
11
+ type EditorTableRow = {
12
+ id: string;
13
+ rowIndex: number;
14
+ cells: string[];
15
+ };
16
+
5
17
  let { block, onUpdateHeader, onUpdateCell, onAddColumn, onAddRow, onRemoveColumn, onRemoveRow } =
6
18
  $props<{
7
19
  block: BlockDraft;
@@ -17,6 +29,14 @@
17
29
  Math.max((block.columns ?? []).length, block.rows?.[0]?.length ?? 0, 1)
18
30
  );
19
31
  const rowCount = $derived(Math.max((block.rows ?? []).length, 1));
32
+ const columnIndexes = $derived(Array.from({ length: columnCount }, (_, index) => index));
33
+ const tableRows = $derived<EditorTableRow[]>(
34
+ Array.from({ length: rowCount }, (_, rowIndex) => ({
35
+ id: `${block.id}-${rowIndex}`,
36
+ rowIndex,
37
+ cells: block.rows?.[rowIndex] ?? []
38
+ }))
39
+ );
20
40
 
21
41
  const columnHasContent = (columnIndex: number) =>
22
42
  Boolean(block.columns?.[columnIndex]?.trim()) ||
@@ -48,227 +68,168 @@
48
68
  };
49
69
  </script>
50
70
 
51
- <div class="article-block-table-shell">
52
- <div class="article-block-table-scroll">
53
- <table class="article-block-table">
54
- {#if (block.columns ?? []).length > 0}
55
- <thead class="article-block-table-head">
56
- <tr>
57
- {#each block.columns ?? [] as column, columnIndex}
58
- <th class="article-block-table-header">
59
- <input
60
- class="article-block-table-header-input"
61
- value={column}
62
- oninput={(event) =>
63
- onUpdateHeader(
64
- block.id,
65
- columnIndex,
66
- (event.currentTarget as HTMLInputElement).value
67
- )}
68
- />
69
- <button
70
- type="button"
71
- aria-label="Remove column"
72
- disabled={columnCount <= 1}
73
- class="article-block-table-remove-column"
74
- onclick={() => removeColumn(columnIndex)}
75
- >
76
- <Trash2 size={14} />
77
- </button>
78
- </th>
79
- {/each}
80
- </tr>
81
- </thead>
82
- {/if}
83
- <tbody>
84
- {#each block.rows ?? [] as row, rowIndex}
85
- <tr class="article-block-table-row">
86
- {#each row as cell, cellIndex}
87
- <td class="article-block-table-cell">
88
- <textarea
89
- rows="2"
90
- class="article-block-table-cell-input"
91
- value={cell}
92
- oninput={(event) =>
93
- onUpdateCell(
94
- block.id,
95
- rowIndex,
96
- cellIndex,
97
- (event.currentTarget as HTMLTextAreaElement).value
98
- )}
99
- ></textarea>
100
- </td>
101
- {/each}
102
- <td class="article-block-table-row-control">
71
+ <VStack width="100%" gap={0}>
72
+ <Grid columns="minmax(0, 1fr) 2.25rem" gap={0}>
73
+ <SveltelyTable data={tableRows} borderRadius={0} emptyLabel="No rows">
74
+ {#each columnIndexes as columnIndex (columnIndex)}
75
+ <TableColumn
76
+ key={`column-${columnIndex}`}
77
+ label={block.columns?.[columnIndex] || `Column ${columnIndex + 1}`}
78
+ minWidth={180}
79
+ >
80
+ {#snippet header()}
81
+ <HStack width="100%" gap={5}>
82
+ <input
83
+ class="article-block-table-header-input"
84
+ value={block.columns?.[columnIndex] ?? ''}
85
+ aria-label={`Column ${columnIndex + 1} header`}
86
+ oninput={(event) =>
87
+ onUpdateHeader(
88
+ block.id,
89
+ columnIndex,
90
+ (event.currentTarget as HTMLInputElement).value
91
+ )}
92
+ />
93
+ <Spacer />
103
94
  <button
104
95
  type="button"
105
- aria-label="Remove row"
106
- disabled={rowCount <= 1}
107
- class="article-block-table-remove-row"
108
- onclick={() => removeRow(rowIndex)}
96
+ aria-label="Remove column"
97
+ disabled={columnCount <= 1}
98
+ class="article-block-table-remove"
99
+ onclick={() => removeColumn(columnIndex)}
109
100
  >
110
101
  <Trash2 size={14} />
111
102
  </button>
112
- </td>
113
- </tr>
114
- {/each}
115
- </tbody>
116
- </table>
117
- </div>
118
- <button
119
- type="button"
120
- aria-label="Add column"
121
- class="article-block-table-add-column"
122
- onclick={() => onAddColumn(block.id)}
123
- >
124
- <Plus size={16} />
125
- </button>
126
- <button
127
- type="button"
128
- aria-label="Add row"
129
- class="article-block-table-add-row"
130
- onclick={() => onAddRow(block.id)}
131
- >
132
- <Plus size={16} />
133
- </button>
134
- <div class="article-block-table-corner"></div>
135
- </div>
103
+ </HStack>
104
+ {/snippet}
105
+
106
+ {#snippet cell(row: EditorTableRow)}
107
+ <textarea
108
+ rows="2"
109
+ class="article-block-table-cell-input"
110
+ value={row.cells[columnIndex] ?? ''}
111
+ aria-label={`Row ${row.rowIndex + 1}, column ${columnIndex + 1}`}
112
+ oninput={(event) =>
113
+ onUpdateCell(
114
+ block.id,
115
+ row.rowIndex,
116
+ columnIndex,
117
+ (event.currentTarget as HTMLTextAreaElement).value
118
+ )}
119
+ ></textarea>
120
+ {/snippet}
121
+ </TableColumn>
122
+ {/each}
123
+
124
+ <TableColumn key="row-actions" label="" width={44} minWidth={44} alignment="center">
125
+ {#snippet cell(row: EditorTableRow)}
126
+ <button
127
+ type="button"
128
+ aria-label="Remove row"
129
+ disabled={rowCount <= 1}
130
+ class="article-block-table-remove"
131
+ onclick={() => removeRow(row.rowIndex)}
132
+ >
133
+ <Trash2 size={14} />
134
+ </button>
135
+ {/snippet}
136
+ </TableColumn>
137
+ </SveltelyTable>
138
+
139
+ <button
140
+ type="button"
141
+ aria-label="Add column"
142
+ class="article-block-table-add article-block-table-add-column"
143
+ onclick={() => onAddColumn(block.id)}
144
+ >
145
+ <Plus size={16} />
146
+ </button>
147
+ </Grid>
148
+
149
+ <Grid columns="minmax(0, 1fr) 2.25rem" gap={0}>
150
+ <button
151
+ type="button"
152
+ aria-label="Add row"
153
+ class="article-block-table-add article-block-table-add-row"
154
+ onclick={() => onAddRow(block.id)}
155
+ >
156
+ <Plus size={16} />
157
+ </button>
158
+ <div class="article-block-table-corner"></div>
159
+ </Grid>
160
+ </VStack>
136
161
 
137
162
  <style>
138
- .article-block-table-shell {
139
- display: grid;
140
- grid-template-columns: minmax(0, 1fr) 2.25rem;
141
- grid-template-rows: auto 2.25rem;
142
- }
143
-
144
- .article-block-table-scroll {
145
- overflow-x: auto;
146
- border: 1px solid rgba(0, 0, 0, 0.08);
147
- }
148
-
149
- .article-block-table {
150
- min-width: 100%;
151
- border-collapse: collapse;
152
- text-align: left;
153
- font-size: 0.875rem;
154
- }
155
-
156
- .article-block-table-head {
157
- background: #fafaf9;
158
- }
159
-
160
- .article-block-table-header {
161
- position: relative;
162
- border-bottom: 1px solid rgba(0, 0, 0, 0.08);
163
- padding: 0.75rem;
164
- }
165
-
166
- .article-block-table-header-input {
163
+ .article-block-table-header-input,
164
+ .article-block-table-cell-input {
167
165
  width: 100%;
166
+ min-width: 0;
168
167
  border: 0;
169
168
  background: transparent;
170
- padding-right: 2rem;
171
- font-weight: 600;
169
+ color: inherit;
172
170
  outline: none;
173
171
  }
174
172
 
175
- .article-block-table-row {
176
- border-top: 1px solid rgba(0, 0, 0, 0.08);
177
- }
178
-
179
- .article-block-table-cell {
180
- padding: 0.75rem;
181
- vertical-align: top;
173
+ .article-block-table-header-input {
174
+ font-weight: 600;
182
175
  }
183
176
 
184
177
  .article-block-table-cell-input {
185
- width: 100%;
186
178
  resize: none;
187
- border: 0;
188
- background: transparent;
189
- outline: none;
190
179
  }
191
180
 
192
- .article-block-table-row-control {
193
- width: 2.25rem;
194
- padding: 0.5rem 0.25rem;
195
- vertical-align: middle;
196
- }
197
-
198
- .article-block-table-remove-column,
199
- .article-block-table-remove-row,
200
- .article-block-table-add-column,
201
- .article-block-table-add-row {
202
- display: flex;
181
+ .article-block-table-remove,
182
+ .article-block-table-add {
183
+ display: inline-flex;
203
184
  align-items: center;
204
185
  justify-content: center;
205
186
  border: 0;
206
187
  background: transparent;
207
- color: #a1a1aa;
188
+ color: var(--sveltely-text-tertiary-color);
208
189
  transition:
209
190
  background-color 150ms,
210
191
  color 150ms,
211
192
  opacity 150ms;
212
193
  }
213
194
 
214
- .article-block-table-remove-column {
215
- position: absolute;
216
- top: 50%;
217
- right: 0.5rem;
218
- width: 1.5rem;
219
- height: 1.5rem;
220
- transform: translateY(-50%);
221
- opacity: 0;
222
- }
223
-
224
- .article-block-table-remove-row {
195
+ .article-block-table-remove {
225
196
  width: 1.75rem;
226
197
  height: 1.75rem;
227
- opacity: 0;
198
+ flex: 0 0 1.75rem;
228
199
  }
229
200
 
230
- .article-block-table-header:hover .article-block-table-remove-column,
231
- .article-block-table-remove-column:focus,
232
- .article-block-table-row:hover .article-block-table-remove-row,
233
- .article-block-table-remove-row:focus {
234
- opacity: 1;
201
+ .article-block-table-remove:hover,
202
+ .article-block-table-add:hover {
203
+ background: var(--sveltely-control-inactive-color);
204
+ color: var(--sveltely-text-primary-color);
235
205
  }
236
206
 
237
- .article-block-table-remove-column:hover,
238
- .article-block-table-remove-row:hover {
239
- background: #fef2f2;
240
- color: #dc2626;
241
- }
242
-
243
- .article-block-table-remove-column:disabled,
244
- .article-block-table-remove-row:disabled {
207
+ .article-block-table-remove:disabled {
245
208
  pointer-events: none;
246
- opacity: 0;
209
+ opacity: 0.25;
247
210
  }
248
211
 
249
- .article-block-table-add-column,
250
- .article-block-table-add-row {
251
- border-color: rgba(0, 0, 0, 0.08);
212
+ .article-block-table-add {
213
+ border-color: var(--sveltely-border-color);
252
214
  border-style: solid;
253
215
  }
254
216
 
255
217
  .article-block-table-add-column {
218
+ width: 2.25rem;
256
219
  border-width: 1px 1px 1px 0;
257
220
  }
258
221
 
259
222
  .article-block-table-add-row {
223
+ height: 2.25rem;
224
+ flex: 1 1 auto;
260
225
  border-width: 0 1px 1px 1px;
261
226
  }
262
227
 
263
- .article-block-table-add-column:hover,
264
- .article-block-table-add-row:hover {
265
- background: #f5f5f4;
266
- color: #3f3f46;
267
- }
268
-
269
228
  .article-block-table-corner {
270
- border-right: 1px solid rgba(0, 0, 0, 0.08);
271
- border-bottom: 1px solid rgba(0, 0, 0, 0.08);
272
- background: rgba(250, 250, 249, 0.5);
229
+ width: 2.25rem;
230
+ height: 2.25rem;
231
+ border-right: 1px solid var(--sveltely-border-color);
232
+ border-bottom: 1px solid var(--sveltely-border-color);
233
+ background: color-mix(in oklab, var(--sveltely-background-color) 94%, var(--sveltely-border-color));
273
234
  }
274
235
  </style>
@@ -8,16 +8,17 @@
8
8
  <script lang="ts">
9
9
  import Checkbox from './Checkbox.svelte';
10
10
  import Label from '../Label';
11
+ import VStack from '../VStack';
11
12
 
12
13
  let notificationsEnabled = $state(true);
13
14
  let weeklySummaryEnabled = $state(false);
14
15
  </script>
15
16
 
16
- <div class="vstack gap-3">
17
- <Label label="Enable notifications" orientation="leading" width="fit">
17
+ <VStack gap={7.5}>
18
+ <Label label="Enable notifications" orientation="leading">
18
19
  <Checkbox bind:checked={notificationsEnabled} />
19
20
  </Label>
20
- <Label label="Send weekly summary" orientation="leading" width="fit">
21
+ <Label label="Send weekly summary" orientation="leading">
21
22
  <Checkbox bind:checked={weeklySummaryEnabled} />
22
23
  </Label>
23
- </div>
24
+ </VStack>
@@ -11,25 +11,26 @@
11
11
  TooltipProps &
12
12
  Omit<HTMLInputAttributes, 'type' | 'class' | 'style' | 'checked'>;
13
13
 
14
- let { checked = $bindable(false), tooltip, disabled = false, ...restProps }: Props = $props();
14
+ let { checked = $bindable(false), tooltip, disabled = false, ...restProps }: Props &
15
+ Record<string, unknown> = $props();
15
16
 
16
17
  const extractedStyleProps = $derived.by(() => extractStyleProps(restProps));
17
18
  const styleProps = $derived(extractedStyleProps.styleProps);
18
- const props = $derived(extractedStyleProps.restProps);
19
+ const forwardedProps = $derived(extractedStyleProps.restProps);
19
20
  const rootStyle = $derived.by(() => surfaceStyle(styleProps, 'checkbox'));
20
21
  </script>
21
22
 
22
- <label
23
+ <span
23
24
  class="checkbox"
24
25
  style={rootStyle}
25
26
  data-disabled={disabled ? 'true' : 'false'}
26
27
  use:tooltipAction={tooltip}
27
28
  >
28
- <input bind:checked type="checkbox" {disabled} {...props} />
29
+ <input bind:checked type="checkbox" {disabled} {...forwardedProps} />
29
30
  <span class="checkbox-mark" aria-hidden="true">
30
31
  <CheckIcon class="checkbox-icon" />
31
32
  </span>
32
- </label>
33
+ </span>
33
34
 
34
35
  <style>
35
36
  .checkbox {
@@ -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 Checkbox: import("svelte").Component<Props, {}, "checked">;
7
+ type $$ComponentProps = Props & Record<string, unknown>;
8
+ declare const Checkbox: import("svelte").Component<$$ComponentProps, {}, "checked">;
8
9
  type Checkbox = ReturnType<typeof Checkbox>;
9
10
  export default Checkbox;
@@ -6,12 +6,13 @@
6
6
  </script>
7
7
 
8
8
  <script lang="ts">
9
+ import VStack from '../VStack';
9
10
  import ChipInput from './ChipInput.svelte';
10
11
 
11
12
  let tags = $state(['svelte', 'ui', 'search']);
12
13
  </script>
13
14
 
14
- <div class="vstack w-full max-w-sm gap-2">
15
+ <VStack width="24rem" gap={5}>
15
16
  <ChipInput bind:tags />
16
17
  <p class="text-xs text-[var(--sveltely-text-secondary-color)]">Tags: {tags.join(', ')}</p>
17
- </div>
18
+ </VStack>
@@ -8,8 +8,11 @@
8
8
 
9
9
  <script lang="ts">
10
10
  import { CheckIcon, PlusIcon, UserRoundXIcon } from '@lucide/svelte';
11
+ import Grid from '../Grid';
12
+ import HStack from '../HStack';
11
13
  import SearchField from '../SearchField';
12
14
  import ScrollView, { type ScrollGeometry } from '../ScrollView';
15
+ import VStack from '../VStack';
13
16
  import Dropdown from './index';
14
17
 
15
18
  type Website = {
@@ -87,8 +90,8 @@
87
90
  });
88
91
  </script>
89
92
 
90
- <div class="grid w-full gap-4 md:grid-cols-2">
91
- <div class="vstack gap-2">
93
+ <Grid columns="repeat(auto-fit, minmax(min(100%, 18rem), 1fr))" gap={10}>
94
+ <VStack gap={5}>
92
95
  <p class="text-sm font-medium text-[var(--sveltely-text-primary-color)]">Default trigger</p>
93
96
  <Dropdown bind:value={status} placeholder="Choose status" selectedLabel={selectedStatusLabel}>
94
97
  <Dropdown.Section label="Publishing">
@@ -106,9 +109,9 @@
106
109
  <p class="text-xs text-[var(--sveltely-text-secondary-color)]">
107
110
  Selected: {selectedStatusLabel ?? 'none'}
108
111
  </p>
109
- </div>
112
+ </VStack>
110
113
 
111
- <div class="vstack gap-2">
114
+ <VStack gap={5}>
112
115
  <p class="text-sm font-medium text-[var(--sveltely-text-primary-color)]">
113
116
  Custom trigger and rich rows
114
117
  </p>
@@ -120,7 +123,7 @@
120
123
  {#snippet trigger()}
121
124
  <Dropdown.Trigger>
122
125
  {#if selectedWebsite}
123
- <span class="hstack min-w-0 items-center gap-2">
126
+ <HStack gap={5}>
124
127
  <span class="truncate text-[var(--sveltely-text-primary-color)]"
125
128
  >{selectedWebsite.name}</span
126
129
  >
@@ -129,7 +132,7 @@
129
132
  {selectedWebsite.domain}
130
133
  </span>
131
134
  {/if}
132
- </span>
135
+ </HStack>
133
136
  {:else}
134
137
  <span class="text-[var(--sveltely-text-secondary-color)]">Select website</span>
135
138
  {/if}
@@ -152,25 +155,25 @@
152
155
  No websites found.
153
156
  </div>
154
157
  {:else}
155
- <div class="h-36">
158
+ <VStack height={9}>
156
159
  <ScrollView
157
160
  contentStyles={{ paddingX: 0, paddingY: 0 }}
158
161
  borderRadius={5}
159
162
  background="white"
160
163
  onScroll={handleWebsiteScroll}
161
164
  >
162
- <div class="vstack gap-1">
165
+ <VStack gap={2.5}>
163
166
  {#each visibleWebsites as website (website.id)}
164
167
  <Dropdown.Item value={website.id}>
165
168
  {#snippet children({ selected })}
166
- <div class="vstack min-w-0 gap-0.5">
169
+ <VStack gap={1.25}>
167
170
  <span class="truncate">{website.name}</span>
168
171
  {#if website.domain}
169
172
  <span class="truncate text-xs text-[var(--sveltely-text-secondary-color)]"
170
173
  >{website.domain}</span
171
174
  >
172
175
  {/if}
173
- </div>
176
+ </VStack>
174
177
  {#if selected}
175
178
  <CheckIcon
176
179
  size={14}
@@ -180,12 +183,14 @@
180
183
  {/snippet}
181
184
  </Dropdown.Item>
182
185
  {/each}
183
- </div>
186
+ </VStack>
184
187
  </ScrollView>
185
- </div>
188
+ </VStack>
186
189
  {/if}
187
190
  </Dropdown.Section>
188
191
  </Dropdown>
189
- <p class="text-xs text-[var(--sveltely-text-secondary-color)]">Actions clicked: {actionCount}</p>
190
- </div>
191
- </div>
192
+ <p class="text-xs text-[var(--sveltely-text-secondary-color)]">
193
+ Actions clicked: {actionCount}
194
+ </p>
195
+ </VStack>
196
+ </Grid>
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { tick, onDestroy } from 'svelte';
3
3
  import type { Snippet } from 'svelte';
4
- import { portalContent } from '../../../actions/portal';
4
+ import { Content as PortalContent } from '../Portal';
5
5
  import { autoAlignForViewport, computePosition, type Anchor } from '../../../utils/positioning';
6
6
  import {
7
7
  hasOpenChild,
@@ -385,9 +385,8 @@
385
385
  {@render trigger({ useTrigger, open, toggle, openPanel, closePanel })}
386
386
 
387
387
  {#if open}
388
- <div
389
- use:portalContent
390
- bind:this={panelEl}
388
+ <PortalContent
389
+ bind:element={panelEl}
391
390
  class={panelClass}
392
391
  style={resolvedPanelStyle}
393
392
  data-floating
@@ -395,11 +394,11 @@
395
394
  data-floating-parent-id={parentFloatingId ?? ''}
396
395
  role={panelRole}
397
396
  aria-modal={panelAriaModal}
398
- tabindex="-1"
397
+ tabindex={-1}
399
398
  >
400
399
  <div bind:this={contentEl} class={contentClass} style={contentStyle}>
401
400
  {@render children()}
402
401
  </div>
403
- </div>
402
+ </PortalContent>
404
403
  {/if}
405
404
  </div>
@@ -0,0 +1,58 @@
1
+ <script module lang="ts">
2
+ type Tile = {
3
+ id: number;
4
+ title: string;
5
+ tone: string;
6
+ };
7
+
8
+ export const demo = {
9
+ name: 'Grid',
10
+ description: 'Virtualized fixed-size grid powered by the viewport layout engine.',
11
+ columnSpan: 2,
12
+ rowSpan: 2
13
+ };
14
+ </script>
15
+
16
+ <script lang="ts">
17
+ import Grid from './index';
18
+
19
+ const tones = ['#2563eb', '#16a34a', '#d97706', '#db2777'];
20
+ const tiles: Tile[] = Array.from({ length: 400 }, (_, index) => ({
21
+ id: index + 1,
22
+ title: `Tile ${index + 1}`,
23
+ tone: tones[index % tones.length]
24
+ }));
25
+ </script>
26
+
27
+ {#snippet tile(item: Tile)}
28
+ <div class="grid-demo-tile" style:--grid-demo-tone={item.tone}>
29
+ <span>{item.title}</span>
30
+ </div>
31
+ {/snippet}
32
+
33
+ <Grid
34
+ items={tiles}
35
+ item={tile}
36
+ columns={4}
37
+ columnWidth={120}
38
+ rowHeight={84}
39
+ columnGap={8}
40
+ rowGap={8}
41
+ overscan={96}
42
+ height="100%"
43
+ />
44
+
45
+ <style>
46
+ .grid-demo-tile {
47
+ display: flex;
48
+ align-items: center;
49
+ height: 100%;
50
+ border: 1px solid color-mix(in oklab, var(--grid-demo-tone) 24%, transparent);
51
+ border-radius: var(--sveltely-border-radius-nested);
52
+ background: color-mix(in oklab, var(--grid-demo-tone) 10%, var(--sveltely-background-color));
53
+ padding: 0.75rem;
54
+ color: var(--sveltely-text-primary-color);
55
+ font-size: 0.85rem;
56
+ font-weight: 600;
57
+ }
58
+ </style>
@@ -0,0 +1,25 @@
1
+ export declare const demo: {
2
+ name: string;
3
+ description: string;
4
+ columnSpan: number;
5
+ rowSpan: number;
6
+ };
7
+ import Grid from './index';
8
+ 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> {
9
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
10
+ $$bindings?: Bindings;
11
+ } & Exports;
12
+ (internal: unknown, props: {
13
+ $$events?: Events;
14
+ $$slots?: Slots;
15
+ }): Exports & {
16
+ $set?: any;
17
+ $on?: any;
18
+ };
19
+ z_$$bindings?: Bindings;
20
+ }
21
+ declare const Grid: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
22
+ [evt: string]: CustomEvent<any>;
23
+ }, {}, {}, string>;
24
+ type Grid = InstanceType<typeof Grid>;
25
+ export default Grid;