@warkypublic/svelix 0.1.38 → 0.1.40

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 (46) hide show
  1. package/dist/components/BetterMenu/BetterMenuAsyncButton.svelte +41 -24
  2. package/dist/components/BetterMenu/BetterMenuAsyncButton.svelte.d.ts +1 -1
  3. package/dist/components/BetterMenu/types.d.ts +2 -1
  4. package/dist/components/ContentEditor/subcomponents/AudioPlayer.svelte +2 -3
  5. package/dist/components/ContentEditor/subcomponents/ImageViewer.svelte +2 -3
  6. package/dist/components/ContentEditor/subcomponents/VideoPlayer.svelte +2 -3
  7. package/dist/components/Former/FormerButtonArea.svelte +3 -2
  8. package/dist/components/Former/FormerDrawer.svelte +130 -124
  9. package/dist/components/Former/FormerDrawer.svelte.d.ts +1 -1
  10. package/dist/components/FormerControllers/InlineWrapper.svelte +4 -34
  11. package/dist/components/Gridler/components/GridlerFull.svelte +6 -20
  12. package/dist/components/Gridler/components/GridlerFullWithFormerPreview.svelte +340 -0
  13. package/dist/components/Gridler/components/GridlerFullWithFormerPreview.svelte.d.ts +3 -0
  14. package/dist/components/Gridler/components/GridlerSearch.svelte +2 -4
  15. package/dist/components/Gridler/components/GridlerSearchToggle.svelte +2 -4
  16. package/dist/components/Gridler/types.d.ts +1 -0
  17. package/dist/components/Icons/IconAdd.svelte +8 -0
  18. package/dist/components/Icons/IconAdd.svelte.d.ts +7 -0
  19. package/dist/components/Icons/IconAlertCircle.svelte +9 -0
  20. package/dist/components/Icons/IconAlertCircle.svelte.d.ts +7 -0
  21. package/dist/components/Icons/IconAlertTriangle.svelte +9 -0
  22. package/dist/components/Icons/IconAlertTriangle.svelte.d.ts +7 -0
  23. package/dist/components/Icons/IconCamera.svelte +8 -0
  24. package/dist/components/Icons/IconCamera.svelte.d.ts +7 -0
  25. package/dist/components/Icons/IconClose.svelte +7 -0
  26. package/dist/components/Icons/IconClose.svelte.d.ts +7 -0
  27. package/dist/components/Icons/IconEdit.svelte +8 -0
  28. package/dist/components/Icons/IconEdit.svelte.d.ts +7 -0
  29. package/dist/components/Icons/IconFilter.svelte +7 -0
  30. package/dist/components/Icons/IconFilter.svelte.d.ts +7 -0
  31. package/dist/components/Icons/IconSearch.svelte +8 -0
  32. package/dist/components/Icons/IconSearch.svelte.d.ts +7 -0
  33. package/dist/components/Icons/IconSort.svelte +11 -0
  34. package/dist/components/Icons/IconSort.svelte.d.ts +8 -0
  35. package/dist/components/Icons/IconTrash.svelte +10 -0
  36. package/dist/components/Icons/IconTrash.svelte.d.ts +7 -0
  37. package/dist/components/Icons/index.d.ts +11 -0
  38. package/dist/components/Icons/index.js +11 -0
  39. package/dist/components/Icons/strings.d.ts +11 -0
  40. package/dist/components/Icons/strings.js +15 -0
  41. package/dist/components/Screenshot/Screenshot.svelte +2 -15
  42. package/dist/components/SvarkGrid/components/SvarkHeaderFilterCell.svelte +4 -13
  43. package/dist/components/index.d.ts +1 -0
  44. package/dist/components/index.js +1 -0
  45. package/llm/README.md +93 -0
  46. package/package.json +19 -20
@@ -0,0 +1,340 @@
1
+ <script lang="ts">
2
+ import GridlerFull from './GridlerFull.svelte';
3
+ import FormerDrawer from '../../Former/FormerDrawer.svelte';
4
+ import TextInputCtrl from '../../FormerControllers/TextInputCtrl.svelte';
5
+ import NumberInputCtrl from '../../FormerControllers/NumberInputCtrl.svelte';
6
+ import NativeSelectCtrl from '../../FormerControllers/NativeSelectCtrl.svelte';
7
+ import type { FormRequestType } from '../../Former/types';
8
+ import type { GridlerContextMenuItem } from '../types';
9
+ import IconEdit from '../../Icons/IconEdit.svelte';
10
+ import IconTrash from '../../Icons/IconTrash.svelte';
11
+ import { iconAddSvg, iconEditSvg, iconTrashSvg } from '../../Icons/strings';
12
+
13
+ interface EmployeeRow {
14
+ id: number;
15
+ name: string;
16
+ email: string;
17
+ department: string;
18
+ salary: number;
19
+ status: string;
20
+ }
21
+
22
+ const DEPARTMENTS = ['Engineering', 'Marketing', 'Sales', 'HR', 'Finance', 'Operations'];
23
+ const STATUSES = ['Active', 'Pending', 'Inactive'];
24
+ const FIRST = ['Alice', 'Bob', 'Carol', 'David', 'Eve', 'Frank', 'Grace', 'Henry'];
25
+ const LAST = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia'];
26
+
27
+ function makeRow(i: number): EmployeeRow {
28
+ const first = FIRST[i % FIRST.length];
29
+ const last = LAST[Math.floor(i / FIRST.length) % LAST.length];
30
+ return {
31
+ id: i + 1,
32
+ name: `${first} ${last}`,
33
+ email: `${first.toLowerCase()}.${last.toLowerCase()}@example.com`,
34
+ department: DEPARTMENTS[i % DEPARTMENTS.length],
35
+ salary: 40000 + (i % 60) * 1000,
36
+ status: STATUSES[i % STATUSES.length],
37
+ };
38
+ }
39
+
40
+ const columns = [
41
+ { id: 'id', title: 'ID', width: 70 },
42
+ { id: 'name', title: 'Name', width: 180 },
43
+ { id: 'email', title: 'Email', width: 220 },
44
+ { id: 'department', title: 'Department', width: 150 },
45
+ { id: 'salary', title: 'Salary', width: 110 },
46
+ { id: 'status', title: 'Status', width: 110 },
47
+ ];
48
+
49
+ const departmentOptions = DEPARTMENTS.map((d) => ({ label: d, value: d }));
50
+ const statusOptions = STATUSES.map((s) => ({ label: s, value: s }));
51
+
52
+ let nextId = 51;
53
+ let rows = $state<Record<string, unknown>[]>(
54
+ Array.from({ length: 50 }, (_, i) => makeRow(i) as unknown as Record<string, unknown>),
55
+ );
56
+
57
+ // ── Drawer state ─────────────────────────────────────────────────────────────
58
+
59
+ let drawerOpen = $state(false);
60
+ let formMode = $state<FormRequestType>('update');
61
+ let formValues = $state<EmployeeRow | undefined>(undefined);
62
+ let lastSaved = $state<EmployeeRow | undefined>(undefined);
63
+
64
+ function openForm(mode: FormRequestType, row?: EmployeeRow) {
65
+ formMode = mode;
66
+ formValues = row ? { ...row } : { id: 0, name: '', email: '', department: '', salary: 50000, status: 'Active' };
67
+ drawerOpen = true;
68
+ }
69
+
70
+ const drawerTitle = $derived(
71
+ formMode === 'insert' ? 'Add Employee' : formMode === 'delete' ? 'Delete Employee' : 'Edit Employee',
72
+ );
73
+
74
+ // ── Selection tracking ────────────────────────────────────────────────────────
75
+
76
+ let selectedItems = $state<Record<string, unknown>[]>([]);
77
+
78
+ function firstSelected(): EmployeeRow | undefined {
79
+ const item = selectedItems[0];
80
+ return item ? (item as unknown as EmployeeRow) : undefined;
81
+ }
82
+
83
+ // ── Burger menu items ─────────────────────────────────────────────────────────
84
+
85
+ const menuItems: GridlerContextMenuItem[] = [
86
+ { id: 'add', label: 'Add', icon: iconAddSvg, kind: 'item', onselect: () => openForm('insert') },
87
+ { id: 'sep1', label: '', kind: 'separator' },
88
+ {
89
+ id: 'edit',
90
+ label: 'Edit Selected',
91
+ icon: iconEditSvg,
92
+ kind: 'item',
93
+ onselect: () => {
94
+ const row = firstSelected();
95
+ if (row) openForm('update', row);
96
+ },
97
+ },
98
+ {
99
+ id: 'delete',
100
+ label: 'Delete Selected',
101
+ icon: iconTrashSvg,
102
+ kind: 'item',
103
+ onselect: () => {
104
+ const row = firstSelected();
105
+ if (row) openForm('delete', row);
106
+ },
107
+ },
108
+ ];
109
+
110
+ // ── Context menu (right-click on row) ─────────────────────────────────────────
111
+
112
+ let ctxVisible = $state(false);
113
+ let ctxX = $state(0);
114
+ let ctxY = $state(0);
115
+ let ctxRow = $state<EmployeeRow | undefined>(undefined);
116
+ let wrapperEl = $state<HTMLElement | null>(null);
117
+ let lastMousePos = { x: 0, y: 0 };
118
+
119
+ // Capture phase fires before the canvas handler, so lastMousePos is fresh when
120
+ // onRowContextMenu calls showContextMenu.
121
+ $effect(() => {
122
+ if (!wrapperEl) return;
123
+ const handler = (e: MouseEvent) => { lastMousePos = { x: e.clientX, y: e.clientY }; };
124
+ wrapperEl.addEventListener('contextmenu', handler, true);
125
+ return () => wrapperEl?.removeEventListener('contextmenu', handler, true);
126
+ });
127
+
128
+ function showContextMenu(rowData: Record<string, unknown> | undefined) {
129
+ if (!rowData) return;
130
+ ctxRow = rowData as unknown as EmployeeRow;
131
+ ctxX = lastMousePos.x;
132
+ ctxY = lastMousePos.y;
133
+ ctxVisible = true;
134
+
135
+ const close = () => {
136
+ ctxVisible = false;
137
+ document.removeEventListener('click', close, true);
138
+ document.removeEventListener('keydown', closeOnEsc, true);
139
+ };
140
+ const closeOnEsc = (e: KeyboardEvent) => {
141
+ if (e.key === 'Escape') close();
142
+ };
143
+ setTimeout(() => {
144
+ document.addEventListener('click', close, true);
145
+ document.addEventListener('keydown', closeOnEsc, true);
146
+ }, 0);
147
+ }
148
+ </script>
149
+
150
+ <div class="p-4 space-y-2" bind:this={wrapperEl}>
151
+ <p class="text-sm text-surface-600-300-token">
152
+ Double-click a row to edit · Right-click for context menu · Use ☰ for Add / Edit / Delete
153
+ </p>
154
+
155
+ <GridlerFull
156
+ {columns}
157
+ data={rows}
158
+ height={480}
159
+ uniqueID="id"
160
+ rowMarkers="number"
161
+ {menuItems}
162
+ onRowDblClick={(_row, rowData) => rowData && openForm('update', rowData as unknown as EmployeeRow)}
163
+ onRowContextMenu={(_row, rowData) => showContextMenu(rowData)}
164
+ onSelectedItemsChange={(items) => (selectedItems = items)}
165
+ />
166
+
167
+ <!-- Context menu popup -->
168
+ {#if ctxVisible}
169
+ <div
170
+ role="menu"
171
+ class="ctx-menu"
172
+ style="left:{ctxX}px;top:{ctxY}px;"
173
+ >
174
+ <button
175
+ role="menuitem"
176
+ class="ctx-item"
177
+ onclick={() => { ctxVisible = false; openForm('update', ctxRow); }}
178
+ >
179
+ <IconEdit size={15} />
180
+ Edit
181
+ </button>
182
+ <button
183
+ role="menuitem"
184
+ class="ctx-item ctx-item--danger"
185
+ onclick={() => { ctxVisible = false; openForm('delete', ctxRow); }}
186
+ >
187
+ <IconTrash size={15} />
188
+ Delete
189
+ </button>
190
+ </div>
191
+ {/if}
192
+
193
+ <FormerDrawer
194
+ bind:opened={drawerOpen}
195
+ bind:values={formValues}
196
+ request={formMode}
197
+ uniqueKeyField="id"
198
+ layout={{ title: drawerTitle, buttonArea: 'bottom' }}
199
+ onAPICall={async (_mode, _req, data) => {
200
+ await new Promise((r) => setTimeout(r, 400));
201
+ return data as EmployeeRow;
202
+ }}
203
+ afterSave={(data) => {
204
+ const saved = data as EmployeeRow;
205
+ lastSaved = saved;
206
+ if (formMode === 'insert') {
207
+ saved.id = nextId++;
208
+ rows = [...rows, saved as unknown as Record<string, unknown>];
209
+ } else if (formMode === 'delete') {
210
+ rows = rows.filter((r) => r['id'] !== saved.id);
211
+ } else {
212
+ const rec = saved as unknown as Record<string, unknown>;
213
+ rows = rows.map((r) => (r['id'] === saved.id ? { ...rec } : r));
214
+ }
215
+ }}
216
+ onClose={() => { drawerOpen = false; }}
217
+ >
218
+ {#snippet children(state)}
219
+ {@const isReadonly = state.request === 'delete'}
220
+ <div class="p-6 space-y-4">
221
+ <TextInputCtrl
222
+ label="Name"
223
+ name="name"
224
+ value={state.values?.name ?? ''}
225
+ required
226
+ disabled={isReadonly}
227
+ onchange={(v) => state.setState('values', { ...state.values, name: v })}
228
+ />
229
+ <TextInputCtrl
230
+ label="Email"
231
+ name="email"
232
+ type="email"
233
+ value={state.values?.email ?? ''}
234
+ required
235
+ disabled={isReadonly}
236
+ onchange={(v) => state.setState('values', { ...state.values, email: v })}
237
+ />
238
+ <div class="grid grid-cols-2 gap-4">
239
+ <NativeSelectCtrl
240
+ label="Department"
241
+ name="department"
242
+ value={state.values?.department ?? ''}
243
+ options={departmentOptions}
244
+ disabled={isReadonly}
245
+ onchange={(v) => state.setState('values', { ...state.values, department: v })}
246
+ />
247
+ <NativeSelectCtrl
248
+ label="Status"
249
+ name="status"
250
+ value={state.values?.status ?? ''}
251
+ options={statusOptions}
252
+ disabled={isReadonly}
253
+ onchange={(v) => state.setState('values', { ...state.values, status: v })}
254
+ />
255
+ </div>
256
+ <NumberInputCtrl
257
+ label="Salary"
258
+ name="salary"
259
+ value={state.values?.salary}
260
+ min={0}
261
+ disabled={isReadonly}
262
+ onchange={(v) => state.setState('values', { ...state.values, salary: v })}
263
+ />
264
+ </div>
265
+ {/snippet}
266
+ </FormerDrawer>
267
+
268
+ {#if lastSaved}
269
+ <div class="card p-4">
270
+ <p class="font-semibold text-sm mb-2">Last saved:</p>
271
+ <pre class="text-xs overflow-auto">{JSON.stringify(lastSaved, null, 2)}</pre>
272
+ </div>
273
+ {/if}
274
+ </div>
275
+
276
+ <style>
277
+ .ctx-menu {
278
+ position: fixed;
279
+ z-index: 9999;
280
+ min-width: 160px;
281
+ background: #fff;
282
+ border: 1px solid #e2e8f0;
283
+ border-radius: 8px;
284
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.06);
285
+ padding: 4px;
286
+ font-family: system-ui, sans-serif;
287
+ font-size: 13px;
288
+ }
289
+
290
+ :global(.dark) .ctx-menu {
291
+ background: #1e293b;
292
+ border-color: #334155;
293
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
294
+ }
295
+
296
+ .ctx-item {
297
+ display: flex;
298
+ align-items: center;
299
+ gap: 9px;
300
+ width: 100%;
301
+ padding: 7px 10px;
302
+ background: none;
303
+ border: none;
304
+ border-radius: 5px;
305
+ text-align: left;
306
+ cursor: pointer;
307
+ color: #1e293b;
308
+ font-size: inherit;
309
+ font-family: inherit;
310
+ transition: background 120ms;
311
+ }
312
+
313
+ :global(.dark) .ctx-item {
314
+ color: #e2e8f0;
315
+ }
316
+
317
+ .ctx-item:hover {
318
+ background: #f1f5f9;
319
+ }
320
+
321
+ :global(.dark) .ctx-item:hover {
322
+ background: #334155;
323
+ }
324
+
325
+ .ctx-item--danger {
326
+ color: #dc2626;
327
+ }
328
+
329
+ :global(.dark) .ctx-item--danger {
330
+ color: #f87171;
331
+ }
332
+
333
+ .ctx-item--danger:hover {
334
+ background: #fef2f2;
335
+ }
336
+
337
+ :global(.dark) .ctx-item--danger:hover {
338
+ background: #450a0a;
339
+ }
340
+ </style>
@@ -0,0 +1,3 @@
1
+ declare const GridlerFullWithFormerPreview: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type GridlerFullWithFormerPreview = ReturnType<typeof GridlerFullWithFormerPreview>;
3
+ export default GridlerFullWithFormerPreview;
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  // @ts-nocheck
3
+ import IconClose from '../../Icons/IconClose.svelte';
3
4
  interface Props {
4
5
  value: string;
5
6
  onValueChange: (v: string) => void;
@@ -35,10 +36,7 @@
35
36
  aria-label="Clear search"
36
37
  onclick={() => { onValueChange(''); inputRef?.focus(); }}
37
38
  >
38
- <svg width="10" height="10" viewBox="0 0 10 10" fill="none">
39
- <line x1="1" y1="1" x2="9" y2="9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
40
- <line x1="9" y1="1" x2="1" y2="9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
41
- </svg>
39
+ <IconClose size={10} />
42
40
  </button>
43
41
  {/if}
44
42
  </div>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import GridlerSearch from './GridlerSearch.svelte';
3
+ import IconSearch from '../../Icons/IconSearch.svelte';
3
4
 
4
5
  interface Props {
5
6
  show: boolean;
@@ -19,10 +20,7 @@
19
20
  aria-label={show ? "Close search" : "Open search"}
20
21
  onclick={onToggle}
21
22
  >
22
- <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
23
- <circle cx="5.5" cy="5.5" r="4" stroke="currentColor" stroke-width="1.5" />
24
- <line x1="9" y1="9" x2="13" y2="13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
25
- </svg>
23
+ <IconSearch size={14} />
26
24
  </button>
27
25
 
28
26
  {#if show}
@@ -152,6 +152,7 @@ export interface GridlerContextMenuItem {
152
152
  id: string;
153
153
  label: string;
154
154
  disabled?: boolean;
155
+ icon?: string;
155
156
  /** Use 'separator' to render a divider line. */
156
157
  kind?: 'item' | 'separator';
157
158
  onselect?: () => void;
@@ -0,0 +1,8 @@
1
+ <script lang="ts">
2
+ interface Props { size?: number; class?: string; }
3
+ const { size = 16, class: cls = '' }: Props = $props();
4
+ </script>
5
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class={cls} aria-hidden="true">
6
+ <circle cx="12" cy="12" r="9"/>
7
+ <path d="M12 8v8M8 12h8"/>
8
+ </svg>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ size?: number;
3
+ class?: string;
4
+ }
5
+ declare const IconAdd: import("svelte").Component<Props, {}, "">;
6
+ type IconAdd = ReturnType<typeof IconAdd>;
7
+ export default IconAdd;
@@ -0,0 +1,9 @@
1
+ <script lang="ts">
2
+ interface Props { size?: number; class?: string; }
3
+ const { size = 16, class: cls = '' }: Props = $props();
4
+ </script>
5
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class={cls} aria-hidden="true">
6
+ <circle cx="12" cy="12" r="10"/>
7
+ <line x1="12" y1="8" x2="12" y2="12"/>
8
+ <line x1="12" y1="16" x2="12.01" y2="16"/>
9
+ </svg>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ size?: number;
3
+ class?: string;
4
+ }
5
+ declare const IconAlertCircle: import("svelte").Component<Props, {}, "">;
6
+ type IconAlertCircle = ReturnType<typeof IconAlertCircle>;
7
+ export default IconAlertCircle;
@@ -0,0 +1,9 @@
1
+ <script lang="ts">
2
+ interface Props { size?: number; class?: string; }
3
+ const { size = 16, class: cls = '' }: Props = $props();
4
+ </script>
5
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class={cls} aria-hidden="true">
6
+ <path d="m10.29 3.86-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.71-3.14l-8-14a2 2 0 0 0-3.42 0z"/>
7
+ <line x1="12" y1="9" x2="12" y2="13"/>
8
+ <line x1="12" y1="17" x2="12.01" y2="17"/>
9
+ </svg>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ size?: number;
3
+ class?: string;
4
+ }
5
+ declare const IconAlertTriangle: import("svelte").Component<Props, {}, "">;
6
+ type IconAlertTriangle = ReturnType<typeof IconAlertTriangle>;
7
+ export default IconAlertTriangle;
@@ -0,0 +1,8 @@
1
+ <script lang="ts">
2
+ interface Props { size?: number; class?: string; }
3
+ const { size = 16, class: cls = '' }: Props = $props();
4
+ </script>
5
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class={cls} aria-hidden="true">
6
+ <path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/>
7
+ <circle cx="12" cy="13" r="3"/>
8
+ </svg>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ size?: number;
3
+ class?: string;
4
+ }
5
+ declare const IconCamera: import("svelte").Component<Props, {}, "">;
6
+ type IconCamera = ReturnType<typeof IconCamera>;
7
+ export default IconCamera;
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ interface Props { size?: number; class?: string; }
3
+ const { size = 16, class: cls = '' }: Props = $props();
4
+ </script>
5
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class={cls} aria-hidden="true">
6
+ <path d="M18 6 6 18M6 6l12 12"/>
7
+ </svg>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ size?: number;
3
+ class?: string;
4
+ }
5
+ declare const IconClose: import("svelte").Component<Props, {}, "">;
6
+ type IconClose = ReturnType<typeof IconClose>;
7
+ export default IconClose;
@@ -0,0 +1,8 @@
1
+ <script lang="ts">
2
+ interface Props { size?: number; class?: string; }
3
+ const { size = 16, class: cls = '' }: Props = $props();
4
+ </script>
5
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class={cls} aria-hidden="true">
6
+ <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
7
+ <path d="m18.5 2.5 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
8
+ </svg>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ size?: number;
3
+ class?: string;
4
+ }
5
+ declare const IconEdit: import("svelte").Component<Props, {}, "">;
6
+ type IconEdit = ReturnType<typeof IconEdit>;
7
+ export default IconEdit;
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ interface Props { size?: number; class?: string; }
3
+ const { size = 16, class: cls = '' }: Props = $props();
4
+ </script>
5
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor" class={cls} aria-hidden="true">
6
+ <path d="M3 5a1 1 0 0 1 1-1h16a1 1 0 0 1 .8 1.6L14 13.5V19a1 1 0 0 1-1.45.9l-3-1.5A1 1 0 0 1 9 17.5v-4L3.2 5.6A1 1 0 0 1 3 5Z"/>
7
+ </svg>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ size?: number;
3
+ class?: string;
4
+ }
5
+ declare const IconFilter: import("svelte").Component<Props, {}, "">;
6
+ type IconFilter = ReturnType<typeof IconFilter>;
7
+ export default IconFilter;
@@ -0,0 +1,8 @@
1
+ <script lang="ts">
2
+ interface Props { size?: number; class?: string; }
3
+ const { size = 16, class: cls = '' }: Props = $props();
4
+ </script>
5
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class={cls} aria-hidden="true">
6
+ <circle cx="11" cy="11" r="7"/>
7
+ <path d="m21 21-4.35-4.35"/>
8
+ </svg>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ size?: number;
3
+ class?: string;
4
+ }
5
+ declare const IconSearch: import("svelte").Component<Props, {}, "">;
6
+ type IconSearch = ReturnType<typeof IconSearch>;
7
+ export default IconSearch;
@@ -0,0 +1,11 @@
1
+ <script lang="ts">
2
+ interface Props { direction: 'asc' | 'desc'; size?: number; class?: string; }
3
+ const { direction, size = 16, class: cls = '' }: Props = $props();
4
+ </script>
5
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor" class={cls} aria-hidden="true">
6
+ {#if direction === 'asc'}
7
+ <path d="M7 14l5-5 5 5H7z"/>
8
+ {:else}
9
+ <path d="M7 10l5 5 5-5H7z"/>
10
+ {/if}
11
+ </svg>
@@ -0,0 +1,8 @@
1
+ interface Props {
2
+ direction: 'asc' | 'desc';
3
+ size?: number;
4
+ class?: string;
5
+ }
6
+ declare const IconSort: import("svelte").Component<Props, {}, "">;
7
+ type IconSort = ReturnType<typeof IconSort>;
8
+ export default IconSort;
@@ -0,0 +1,10 @@
1
+ <script lang="ts">
2
+ interface Props { size?: number; class?: string; }
3
+ const { size = 16, class: cls = '' }: Props = $props();
4
+ </script>
5
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class={cls} aria-hidden="true">
6
+ <path d="M3 6h18"/>
7
+ <path d="M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/>
8
+ <path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>
9
+ <path d="M10 11v6M14 11v6"/>
10
+ </svg>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ size?: number;
3
+ class?: string;
4
+ }
5
+ declare const IconTrash: import("svelte").Component<Props, {}, "">;
6
+ type IconTrash = ReturnType<typeof IconTrash>;
7
+ export default IconTrash;
@@ -0,0 +1,11 @@
1
+ export { default as IconAdd } from './IconAdd.svelte';
2
+ export { default as IconAlertCircle } from './IconAlertCircle.svelte';
3
+ export { default as IconAlertTriangle } from './IconAlertTriangle.svelte';
4
+ export { default as IconCamera } from './IconCamera.svelte';
5
+ export { default as IconClose } from './IconClose.svelte';
6
+ export { default as IconEdit } from './IconEdit.svelte';
7
+ export { default as IconFilter } from './IconFilter.svelte';
8
+ export { default as IconSearch } from './IconSearch.svelte';
9
+ export { default as IconSort } from './IconSort.svelte';
10
+ export { default as IconTrash } from './IconTrash.svelte';
11
+ export * from './strings';
@@ -0,0 +1,11 @@
1
+ export { default as IconAdd } from './IconAdd.svelte';
2
+ export { default as IconAlertCircle } from './IconAlertCircle.svelte';
3
+ export { default as IconAlertTriangle } from './IconAlertTriangle.svelte';
4
+ export { default as IconCamera } from './IconCamera.svelte';
5
+ export { default as IconClose } from './IconClose.svelte';
6
+ export { default as IconEdit } from './IconEdit.svelte';
7
+ export { default as IconFilter } from './IconFilter.svelte';
8
+ export { default as IconSearch } from './IconSearch.svelte';
9
+ export { default as IconSort } from './IconSort.svelte';
10
+ export { default as IconTrash } from './IconTrash.svelte';
11
+ export * from './strings';
@@ -0,0 +1,11 @@
1
+ export declare const iconAddSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M12 8v8M8 12h8\"/></svg>";
2
+ export declare const iconEditSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"m18.5 2.5 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>";
3
+ export declare const iconTrashSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"M3 6h18\"/><path d=\"M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/></svg>";
4
+ export declare const iconSearchSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0\" aria-hidden=\"true\"><circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m21 21-4.35-4.35\"/></svg>";
5
+ export declare const iconCloseSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"M18 6 6 18M6 6l12 12\"/></svg>";
6
+ export declare const iconAlertCircleSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/></svg>";
7
+ export declare const iconAlertTriangleSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"m10.29 3.86-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.71-3.14l-8-14a2 2 0 0 0-3.42 0z\"/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"/><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"/></svg>";
8
+ export declare const iconFilterSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"M3 5a1 1 0 0 1 1-1h16a1 1 0 0 1 .8 1.6L14 13.5V19a1 1 0 0 1-1.45.9l-3-1.5A1 1 0 0 1 9 17.5v-4L3.2 5.6A1 1 0 0 1 3 5Z\"/></svg>";
9
+ export declare const iconCameraSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\"/><circle cx=\"12\" cy=\"13\" r=\"3\"/></svg>";
10
+ export declare const iconSortAscSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"M7 14l5-5 5 5H7z\"/></svg>";
11
+ export declare const iconSortDescSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"M7 10l5 5 5-5H7z\"/></svg>";
@@ -0,0 +1,15 @@
1
+ // SVG HTML strings for use with {@html} or the `icon?: string` prop on menu items.
2
+ // Each string renders at 16×16 px and inherits colour via currentColor.
3
+ const S = `width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0" aria-hidden="true"`;
4
+ const F = `width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="flex-shrink:0" aria-hidden="true"`;
5
+ export const iconAddSvg = `<svg ${S}><circle cx="12" cy="12" r="9"/><path d="M12 8v8M8 12h8"/></svg>`;
6
+ export const iconEditSvg = `<svg ${S}><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="m18.5 2.5 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>`;
7
+ export const iconTrashSvg = `<svg ${S}><path d="M3 6h18"/><path d="M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/></svg>`;
8
+ export const iconSearchSvg = `<svg ${S}><circle cx="11" cy="11" r="7"/><path d="m21 21-4.35-4.35"/></svg>`;
9
+ export const iconCloseSvg = `<svg ${S}><path d="M18 6 6 18M6 6l12 12"/></svg>`;
10
+ export const iconAlertCircleSvg = `<svg ${S}><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>`;
11
+ export const iconAlertTriangleSvg = `<svg ${S}><path d="m10.29 3.86-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.71-3.14l-8-14a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>`;
12
+ export const iconFilterSvg = `<svg ${F}><path d="M3 5a1 1 0 0 1 1-1h16a1 1 0 0 1 .8 1.6L14 13.5V19a1 1 0 0 1-1.45.9l-3-1.5A1 1 0 0 1 9 17.5v-4L3.2 5.6A1 1 0 0 1 3 5Z"/></svg>`;
13
+ export const iconCameraSvg = `<svg ${S}><path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/></svg>`;
14
+ export const iconSortAscSvg = `<svg ${F}><path d="M7 14l5-5 5 5H7z"/></svg>`;
15
+ export const iconSortDescSvg = `<svg ${F}><path d="M7 10l5 5 5-5H7z"/></svg>`;