@warkypublic/svelix 0.1.46 → 0.2.1

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 (129) hide show
  1. package/README.md +93 -33
  2. package/dist/components/BetterMenu/BetterMenu.svelte +21 -37
  3. package/dist/components/BetterMenu/BetterMenuAsyncButton.svelte +21 -31
  4. package/dist/components/BetterMenu/BetterMenuPreview.svelte +27 -29
  5. package/dist/components/BetterMenu/MenuRenderer.svelte +40 -51
  6. package/dist/components/Boxer/Boxer.svelte +492 -602
  7. package/dist/components/Boxer/BoxerTarget.svelte +6 -46
  8. package/dist/components/Boxer/BoxerTarget.svelte.d.ts +1 -0
  9. package/dist/components/Boxer/types.d.ts +0 -1
  10. package/dist/components/Button.svelte +19 -43
  11. package/dist/components/ButtonPreview.svelte +2 -11
  12. package/dist/components/CardGrid/CardGrid.svelte +489 -614
  13. package/dist/components/CardGrid/CardGrid.svelte.d.ts +4 -0
  14. package/dist/components/CardGrid/CardGridFilterPanel.svelte +111 -90
  15. package/dist/components/CardGrid/DefaultCard.svelte +86 -97
  16. package/dist/components/CardGrid/DefaultCard.svelte.d.ts +1 -0
  17. package/dist/components/CardGrid/ImageCardStory.svelte +87 -36
  18. package/dist/components/CardGrid/cardGrid.d.ts +24 -0
  19. package/dist/components/CardGrid/cardGrid.js +20 -0
  20. package/dist/components/ContentEditor/CollaboraInsertTextDemo.svelte +5 -10
  21. package/dist/components/ContentEditor/ContentEditor.svelte +24 -50
  22. package/dist/components/ContentEditor/subcomponents/AudioPlayer.svelte +17 -17
  23. package/dist/components/ContentEditor/subcomponents/CollaboraEditor.svelte +244 -309
  24. package/dist/components/ContentEditor/subcomponents/EmailViewer.svelte +2 -3
  25. package/dist/components/ContentEditor/subcomponents/ImageViewer.svelte +14 -15
  26. package/dist/components/ContentEditor/subcomponents/MarkdownViewer.svelte +74 -90
  27. package/dist/components/ContentEditor/subcomponents/MonacoEditor.svelte +75 -103
  28. package/dist/components/ContentEditor/subcomponents/Office365Editor.svelte +234 -297
  29. package/dist/components/ContentEditor/subcomponents/PdfViewer.svelte +14 -20
  30. package/dist/components/ContentEditor/subcomponents/TextEditor.svelte +122 -150
  31. package/dist/components/ContentEditor/subcomponents/UnknownFile.svelte +105 -126
  32. package/dist/components/ContentEditor/subcomponents/VideoPlayer.svelte +17 -17
  33. package/dist/components/ContentEditor/subcomponents/ZipViewer.svelte +2 -3
  34. package/dist/components/ErrorBoundary/ErrorBoundary.svelte +41 -58
  35. package/dist/components/ErrorBoundary/ErrorBoundaryPreview.svelte +8 -16
  36. package/dist/components/Former/Former.svelte +306 -424
  37. package/dist/components/Former/FormerButtonArea.svelte +17 -68
  38. package/dist/components/Former/FormerDrawer.svelte +16 -80
  39. package/dist/components/Former/FormerDrawerPreview.svelte +99 -89
  40. package/dist/components/Former/FormerModal.svelte +16 -74
  41. package/dist/components/Former/FormerModalPreview.svelte +99 -89
  42. package/dist/components/Former/FormerPreview.svelte +76 -78
  43. package/dist/components/Former/FormerRestApiPreview.svelte +55 -48
  44. package/dist/components/Former/formerOverlayHelpers.svelte.d.ts +11 -0
  45. package/dist/components/Former/formerOverlayHelpers.svelte.js +38 -0
  46. package/dist/components/Former/index.d.ts +1 -0
  47. package/dist/components/Former/index.js +1 -0
  48. package/dist/components/FormerControllers/ButtonCtrl.svelte +13 -49
  49. package/dist/components/FormerControllers/CtrlFieldShell.svelte +15 -0
  50. package/dist/components/FormerControllers/CtrlFieldShell.svelte.d.ts +12 -0
  51. package/dist/components/FormerControllers/DateTimeCtrl/DateTimeCtrl.svelte +285 -457
  52. package/dist/components/FormerControllers/DateTimeCtrl/DateTimeCtrlCalendar.svelte +95 -136
  53. package/dist/components/FormerControllers/DateTimeCtrl/DateTimeCtrlPickerPanel.svelte +3 -62
  54. package/dist/components/FormerControllers/DateTimeCtrl/DateTimeCtrlTimeFields.svelte +143 -217
  55. package/dist/components/FormerControllers/IconButtonCtrl.svelte +13 -47
  56. package/dist/components/FormerControllers/InlineWrapper.svelte +12 -41
  57. package/dist/components/FormerControllers/InlineWrapperPreview.svelte +4 -26
  58. package/dist/components/FormerControllers/NativeSelectCtrl.svelte +7 -39
  59. package/dist/components/FormerControllers/NumberInputCtrl.svelte +21 -43
  60. package/dist/components/FormerControllers/PasswordInputCtrl.svelte +8 -33
  61. package/dist/components/FormerControllers/SwitchCtrl.svelte +4 -20
  62. package/dist/components/FormerControllers/TextAreaCtrl.svelte +7 -34
  63. package/dist/components/FormerControllers/TextInputCtrl.svelte +7 -34
  64. package/dist/components/FormerControllers/ctrlLoading.svelte.d.ts +8 -0
  65. package/dist/components/FormerControllers/ctrlLoading.svelte.js +43 -0
  66. package/dist/components/FormerControllers/index.d.ts +2 -0
  67. package/dist/components/FormerControllers/index.js +2 -0
  68. package/dist/components/FormerControllers/utils.d.ts +1 -0
  69. package/dist/components/FormerControllers/utils.js +3 -0
  70. package/dist/components/GlobalStateStore/GlobalStateStoreProvider.svelte +73 -120
  71. package/dist/components/Gridler/components/Gridler.svelte +344 -442
  72. package/dist/components/Gridler/components/GridlerCanvas.svelte +720 -1115
  73. package/dist/components/Gridler/components/GridlerEditor.svelte +2 -15
  74. package/dist/components/Gridler/components/GridlerFull.svelte +521 -841
  75. package/dist/components/Gridler/components/GridlerFull.svelte.d.ts +1 -1
  76. package/dist/components/Gridler/components/GridlerFullWithFormerPreview.svelte +194 -147
  77. package/dist/components/Gridler/components/GridlerSearch.svelte +7 -16
  78. package/dist/components/Gridler/components/GridlerSearchToggle.svelte +7 -19
  79. package/dist/components/Gridler/types.d.ts +1 -1
  80. package/dist/components/Gridler/utils/serverPaging.d.ts +1 -0
  81. package/dist/components/Gridler/utils/serverPaging.js +7 -0
  82. package/dist/components/Icons/IconAdd.svelte +1 -3
  83. package/dist/components/Icons/IconAlertCircle.svelte +1 -3
  84. package/dist/components/Icons/IconAlertTriangle.svelte +1 -3
  85. package/dist/components/Icons/IconCamera.svelte +1 -3
  86. package/dist/components/Icons/IconClose.svelte +1 -3
  87. package/dist/components/Icons/IconEdit.svelte +1 -3
  88. package/dist/components/Icons/IconFilter.svelte +1 -3
  89. package/dist/components/Icons/IconSearch.svelte +1 -3
  90. package/dist/components/Icons/IconSort.svelte +1 -3
  91. package/dist/components/Icons/IconTrash.svelte +1 -3
  92. package/dist/components/Portal/Portal.svelte +14 -38
  93. package/dist/components/Screenshot/Screenshot.svelte +7 -13
  94. package/dist/components/Svark/Svark.svelte +680 -852
  95. package/dist/components/Svark/SvarkContextMenu.svelte +44 -63
  96. package/dist/components/Svark/SvarkInfiniteLoader.svelte +2 -6
  97. package/dist/components/Svark/SvarkPager.svelte +2 -28
  98. package/dist/components/Svark/SvarkSelectionDemo.svelte +4 -8
  99. package/dist/components/Svark/SvarkTopBar.svelte +9 -74
  100. package/dist/components/SvarkGrid/SvarkGrid.svelte +877 -1123
  101. package/dist/components/SvarkGrid/components/SvarkColumnFilterForm.svelte +45 -58
  102. package/dist/components/SvarkGrid/components/SvarkContextMenu.svelte +44 -63
  103. package/dist/components/SvarkGrid/components/SvarkHeaderFilterCell.svelte +41 -75
  104. package/dist/components/SvarkGrid/components/SvarkInfiniteLoader.svelte +2 -6
  105. package/dist/components/SvarkGrid/components/SvarkPager.svelte +2 -28
  106. package/dist/components/SvarkGrid/components/SvarkSearchPopover.svelte +8 -16
  107. package/dist/components/SvarkGrid/components/SvarkTopBar.svelte +6 -62
  108. package/dist/components/SvarkGrid/internal/SvarkGridView.svelte +345 -507
  109. package/dist/components/VTree/VTree.svelte +454 -431
  110. package/dist/components/VTree/VTree.utils.d.ts +23 -0
  111. package/dist/components/VTree/VTree.utils.js +73 -0
  112. package/dist/components/VTree/VTreeContextMenu.svelte +21 -33
  113. package/dist/components/VTree/VTreeControlledSelectionDemo.svelte +20 -0
  114. package/dist/components/VTree/VTreeControlledSelectionDemo.svelte.d.ts +18 -0
  115. package/dist/components/VTree/VTreeCustomizationDemo.svelte +23 -0
  116. package/dist/components/VTree/VTreeCustomizationDemo.svelte.d.ts +18 -0
  117. package/dist/components/VTree/VTreeEventsDemo.svelte +48 -58
  118. package/dist/components/VTree/VTreeInteractionDemo.svelte +29 -0
  119. package/dist/components/VTree/VTreeInteractionDemo.svelte.d.ts +18 -0
  120. package/dist/components/VTree/VTreeMultiSelectDemo.svelte +27 -0
  121. package/dist/components/VTree/VTreeMultiSelectDemo.svelte.d.ts +18 -0
  122. package/dist/components/VTree/VTreeRow.svelte +77 -115
  123. package/dist/components/VTree/VTreeRow.svelte.d.ts +34 -18
  124. package/dist/components/VTree/VTreeSearch.svelte +6 -13
  125. package/dist/components/VTree/VTreeVirtualViewport.svelte +54 -143
  126. package/dist/components/VTree/VTreeVirtualViewport.svelte.d.ts +35 -18
  127. package/dist/components/VTree/types.d.ts +39 -1
  128. package/llm/COMPONENT_GUIDE.md +25 -0
  129. package/package.json +51 -50
@@ -53,8 +53,12 @@ interface Props {
53
53
  onLoadError?: (error: string) => void;
54
54
  class?: string;
55
55
  toolbarEnd?: Snippet;
56
+ animate?: boolean;
57
+ density?: 'compact' | 'default' | 'comfortable' | 'spacious';
58
+ expand?: 'none' | 'medium' | 'large';
56
59
  }
57
60
  declare const CardGrid: import("svelte").Component<Props, {
61
+ selectItem: (uniqueIDValue: string) => boolean;
58
62
  refresh: () => void;
59
63
  }, "loading" | "total">;
60
64
  type CardGrid = ReturnType<typeof CardGrid>;
@@ -1,96 +1,117 @@
1
- <script lang="ts">
2
- import type { CardGridColumn } from './cardGrid.js';
3
- import type { GridColumnFilters } from '../Types/generic_grid.js';
4
-
5
- interface Props {
6
- columns: CardGridColumn[];
7
- filters: GridColumnFilters;
8
- onApply: (filters: GridColumnFilters) => void;
9
- onCancel: () => void;
10
- }
11
-
12
- const { columns, filters, onApply, onCancel }: Props = $props();
13
-
14
- type Op = NonNullable<GridColumnFilters[string]['op']>;
15
-
16
- const ALL_OPERATORS: { value: Op; label: string }[] = [
17
- { value: 'contains', label: 'Contains' },
18
- { value: 'equals', label: 'Equals' },
19
- { value: 'notEquals', label: 'Not equals' },
20
- { value: 'startsWith', label: 'Starts with' },
21
- { value: 'endsWith', label: 'Ends with' },
22
- { value: 'greaterThan', label: '>' },
23
- { value: 'greaterThanOrEqual', label: '>=' },
24
- { value: 'lessThan', label: '<' },
25
- { value: 'lessThanOrEqual', label: '<=' },
26
- { value: 'between', label: 'Between' },
27
- { value: 'notBetween', label: 'Not between' },
28
- { value: 'in', label: 'In (comma-sep)' },
29
- { value: 'notIn', label: 'Not in' },
30
- { value: 'isNull', label: 'Is empty' },
31
- { value: 'isNotNull', label: 'Is not empty' },
32
- ];
33
-
34
- const filterableColumns = $derived(columns.filter((c) => !c.disableFilter));
35
-
36
- interface FilterRow {
37
- colId: string;
38
- op: Op;
39
- value: string;
40
- value2: string;
1
+ <script lang="ts">const { columns, filters, onApply, onCancel } = $props();
2
+ const ALL_OPERATORS = [
3
+ {
4
+ value: "contains",
5
+ label: "Contains"
6
+ },
7
+ {
8
+ value: "equals",
9
+ label: "Equals"
10
+ },
11
+ {
12
+ value: "notEquals",
13
+ label: "Not equals"
14
+ },
15
+ {
16
+ value: "startsWith",
17
+ label: "Starts with"
18
+ },
19
+ {
20
+ value: "endsWith",
21
+ label: "Ends with"
22
+ },
23
+ {
24
+ value: "greaterThan",
25
+ label: ">"
26
+ },
27
+ {
28
+ value: "greaterThanOrEqual",
29
+ label: ">="
30
+ },
31
+ {
32
+ value: "lessThan",
33
+ label: "<"
34
+ },
35
+ {
36
+ value: "lessThanOrEqual",
37
+ label: "<="
38
+ },
39
+ {
40
+ value: "between",
41
+ label: "Between"
42
+ },
43
+ {
44
+ value: "notBetween",
45
+ label: "Not between"
46
+ },
47
+ {
48
+ value: "in",
49
+ label: "In (comma-sep)"
50
+ },
51
+ {
52
+ value: "notIn",
53
+ label: "Not in"
54
+ },
55
+ {
56
+ value: "isNull",
57
+ label: "Is empty"
58
+ },
59
+ {
60
+ value: "isNotNull",
61
+ label: "Is not empty"
41
62
  }
42
-
43
- function filtersToRows(f: GridColumnFilters): FilterRow[] {
44
- return Object.entries(f).map(([colId, entry]) => ({
45
- colId,
46
- op: entry.op ?? 'contains',
47
- value: entry.value ?? '',
48
- value2: entry.value2 ?? '',
49
- }));
50
- }
51
-
52
- let rows = $state<FilterRow[]>([]);
53
-
54
- $effect(() => {
55
- rows = filtersToRows(filters);
56
- });
57
-
58
- function addRow() {
59
- const firstCol = filterableColumns[0];
60
- if (!firstCol) return;
61
- rows = [...rows, { colId: firstCol.id, op: 'contains', value: '', value2: '' }];
62
- }
63
-
64
- function removeRow(index: number) {
65
- rows = rows.filter((_, i) => i !== index);
66
- }
67
-
68
- function apply() {
69
- const next: GridColumnFilters = {};
70
- for (const row of rows) {
71
- if (!row.colId) continue;
72
- const needsValue = row.op !== 'isNull' && row.op !== 'isNotNull';
73
- if (needsValue && !row.value) continue;
74
- const col = columns.find((c) => c.id === row.colId);
75
- const entry: GridColumnFilters[string] = {
76
- value: row.value,
77
- op: row.op,
78
- ...(col?.dataKey ? { dataKey: col.dataKey } : {}),
79
- };
80
- if ((row.op === 'between' || row.op === 'notBetween') && row.value2) {
81
- entry.value2 = row.value2;
82
- }
83
- next[row.colId] = entry;
63
+ ];
64
+ const filterableColumns = $derived(columns.filter((c) => !c.disableFilter));
65
+ function filtersToRows(f) {
66
+ return Object.entries(f).map(([colId, entry]) => ({
67
+ colId,
68
+ op: entry.op ?? "contains",
69
+ value: entry.value ?? "",
70
+ value2: entry.value2 ?? ""
71
+ }));
72
+ }
73
+ let rows = $state([]);
74
+ $effect(() => {
75
+ rows = filtersToRows(filters);
76
+ });
77
+ function addRow() {
78
+ const firstCol = filterableColumns[0];
79
+ if (!firstCol) return;
80
+ rows = [...rows, {
81
+ colId: firstCol.id,
82
+ op: "contains",
83
+ value: "",
84
+ value2: ""
85
+ }];
86
+ }
87
+ function removeRow(index) {
88
+ rows = rows.filter((_, i) => i !== index);
89
+ }
90
+ function apply() {
91
+ const next = {};
92
+ for (const row of rows) {
93
+ if (!row.colId) continue;
94
+ const needsValue = row.op !== "isNull" && row.op !== "isNotNull";
95
+ if (needsValue && !row.value) continue;
96
+ const col = columns.find((c) => c.id === row.colId);
97
+ const entry = {
98
+ value: row.value,
99
+ op: row.op,
100
+ ...col?.dataKey ? { dataKey: col.dataKey } : {}
101
+ };
102
+ if ((row.op === "between" || row.op === "notBetween") && row.value2) {
103
+ entry.value2 = row.value2;
84
104
  }
85
- onApply(next);
86
- }
87
-
88
- function clear() {
89
- onApply({});
105
+ next[row.colId] = entry;
90
106
  }
91
-
92
- const needsValue = (op: Op) => op !== 'isNull' && op !== 'isNotNull';
93
- const needsValue2 = (op: Op) => op === 'between' || op === 'notBetween';
107
+ onApply(next);
108
+ }
109
+ function clear() {
110
+ onApply({});
111
+ }
112
+ const needsValue = (op) => op !== "isNull" && op !== "isNotNull";
113
+ const needsValue2 = (op) => op === "between" || op === "notBetween";
114
+ export {};
94
115
  </script>
95
116
 
96
117
  <div class="fp-panel">
@@ -1,106 +1,90 @@
1
- <script lang="ts">
2
- import type { CardGridColumn } from './cardGrid.js';
3
-
4
- interface Props {
5
- record: Record<string, unknown>;
6
- columns: CardGridColumn[];
7
- selected: boolean;
8
- focused: boolean;
1
+ <script lang="ts">const { record, columns, selected, focused, expanded } = $props();
2
+ // First column title, second → subtitle, rest → detail rows
3
+ const titleCol = $derived(columns[0]);
4
+ const subtitleCol = $derived(columns.length > 1 ? columns[1] : undefined);
5
+ const detailCols = $derived(columns.slice(subtitleCol ? 2 : 1));
6
+ function getVal(key, row) {
7
+ const parts = key.split(".");
8
+ let val = row;
9
+ for (const part of parts) {
10
+ if (val == null || typeof val !== "object") return undefined;
11
+ val = val[part];
9
12
  }
10
-
11
- const { record, columns, selected, focused }: Props = $props();
12
-
13
- // First column title, second subtitle, rest → detail rows
14
- const titleCol = $derived(columns[0]);
15
- const subtitleCol = $derived(columns.length > 1 ? columns[1] : undefined);
16
- const detailCols = $derived(columns.slice(subtitleCol ? 2 : 1));
17
-
18
- function getVal(key: string, row: Record<string, unknown>): unknown {
19
- const parts = key.split('.');
20
- let val: unknown = row;
21
- for (const part of parts) {
22
- if (val == null || typeof val !== 'object') return undefined;
23
- val = (val as Record<string, unknown>)[part];
13
+ return val;
14
+ }
15
+ function formatVal(val, col) {
16
+ if (val == null || val === "") return "—";
17
+ switch (col.format) {
18
+ case "currency": {
19
+ const n = Number(val);
20
+ if (!isNaN(n)) return new Intl.NumberFormat(undefined, {
21
+ style: "currency",
22
+ currency: "ZAR",
23
+ maximumFractionDigits: 0
24
+ }).format(n);
25
+ break;
24
26
  }
25
- return val;
26
- }
27
-
28
- function formatVal(val: unknown, col: CardGridColumn): string {
29
- if (val == null || val === '') return '—';
30
- switch (col.format) {
31
- case 'currency': {
32
- const n = Number(val);
33
- if (!isNaN(n))
34
- return new Intl.NumberFormat(undefined, {
35
- style: 'currency',
36
- currency: 'ZAR',
37
- maximumFractionDigits: 0,
38
- }).format(n);
39
- break;
40
- }
41
- case 'number': {
42
- const n = Number(val);
43
- if (!isNaN(n)) return n.toLocaleString();
44
- break;
45
- }
46
- case 'percentage': {
47
- const n = Number(val);
48
- if (!isNaN(n)) return `${(n * 100).toFixed(1)}%`;
49
- break;
50
- }
51
- case 'date': {
52
- const d = val instanceof Date ? val : new Date(String(val));
53
- if (!isNaN(d.getTime())) return d.toLocaleDateString();
54
- break;
55
- }
56
- case 'datetime': {
57
- const d = val instanceof Date ? val : new Date(String(val));
58
- if (!isNaN(d.getTime())) return d.toLocaleString();
59
- break;
60
- }
27
+ case "number": {
28
+ const n = Number(val);
29
+ if (!isNaN(n)) return n.toLocaleString();
30
+ break;
31
+ }
32
+ case "percentage": {
33
+ const n = Number(val);
34
+ if (!isNaN(n)) return `${(n * 100).toFixed(1)}%`;
35
+ break;
36
+ }
37
+ case "date": {
38
+ const d = val instanceof Date ? val : new Date(String(val));
39
+ if (!isNaN(d.getTime())) return d.toLocaleDateString();
40
+ break;
41
+ }
42
+ case "datetime": {
43
+ const d = val instanceof Date ? val : new Date(String(val));
44
+ if (!isNaN(d.getTime())) return d.toLocaleString();
45
+ break;
61
46
  }
62
- return String(val);
63
- }
64
-
65
- // Status chip logic — keyed on common English status words
66
- const STATUS_MAP: Record<string, 'success' | 'warning' | 'error' | 'neutral'> = {
67
- active: 'success',
68
- enabled: 'success',
69
- approved: 'success',
70
- confirmed: 'success',
71
- completed: 'success',
72
- done: 'success',
73
- live: 'success',
74
- pending: 'warning',
75
- review: 'warning',
76
- draft: 'warning',
77
- in_progress: 'warning',
78
- processing: 'warning',
79
- queued: 'warning',
80
- inactive: 'error',
81
- disabled: 'error',
82
- cancelled: 'error',
83
- rejected: 'error',
84
- failed: 'error',
85
- error: 'error',
86
- blocked: 'error',
87
- archived: 'neutral',
88
- closed: 'neutral',
89
- deprecated: 'neutral',
90
- };
91
-
92
- function isStatusCol(col: CardGridColumn): boolean {
93
- const id = col.id.toLowerCase();
94
- return id.includes('status') || id.includes('state') || id === 'type';
95
- }
96
-
97
- function statusVariant(val: unknown): 'success' | 'warning' | 'error' | 'neutral' | null {
98
- if (val == null) return null;
99
- return STATUS_MAP[String(val).toLowerCase().replace(/[\s-]/g, '_')] ?? null;
100
47
  }
48
+ return String(val);
49
+ }
50
+ // Status chip logic — keyed on common English status words
51
+ const STATUS_MAP = {
52
+ active: "success",
53
+ enabled: "success",
54
+ approved: "success",
55
+ confirmed: "success",
56
+ completed: "success",
57
+ done: "success",
58
+ live: "success",
59
+ pending: "warning",
60
+ review: "warning",
61
+ draft: "warning",
62
+ in_progress: "warning",
63
+ processing: "warning",
64
+ queued: "warning",
65
+ inactive: "error",
66
+ disabled: "error",
67
+ cancelled: "error",
68
+ rejected: "error",
69
+ failed: "error",
70
+ error: "error",
71
+ blocked: "error",
72
+ archived: "neutral",
73
+ closed: "neutral",
74
+ deprecated: "neutral"
75
+ };
76
+ function isStatusCol(col) {
77
+ const id = col.id.toLowerCase();
78
+ return id.includes("status") || id.includes("state") || id === "type";
79
+ }
80
+ function statusVariant(val) {
81
+ if (val == null) return null;
82
+ return STATUS_MAP[String(val).toLowerCase().replace(/[\s-]/g, "_")] ?? null;
83
+ }
84
+ export {};
101
85
  </script>
102
86
 
103
- <article class="dc-card" class:dc-selected={selected} class:dc-focused={focused}>
87
+ <article class="dc-card" class:dc-selected={selected} class:dc-focused={focused} class:dc-expanded={expanded}>
104
88
  <!-- Header -->
105
89
  {#if titleCol}
106
90
  {@const titleKey = titleCol.dataKey ?? titleCol.id}
@@ -148,6 +132,11 @@
148
132
  flex-direction: column;
149
133
  }
150
134
 
135
+ /* Expanded mode — merges front + back columns */
136
+ .dc-expanded {
137
+ --cg-colspan: span 2;
138
+ }
139
+
151
140
  /* ── Header ───────────────────────────────────────────────────────── */
152
141
 
153
142
  .dc-header {
@@ -4,6 +4,7 @@ interface Props {
4
4
  columns: CardGridColumn[];
5
5
  selected: boolean;
6
6
  focused: boolean;
7
+ expanded?: boolean;
7
8
  }
8
9
  declare const DefaultCard: import("svelte").Component<Props, {}, "">;
9
10
  type DefaultCard = ReturnType<typeof DefaultCard>;
@@ -1,39 +1,90 @@
1
- <script lang="ts">
2
- import CardGrid from './CardGrid.svelte';
3
- import type { CardGridColumn, CardSortOption } from './cardGrid.js';
4
-
5
- const columns: CardGridColumn[] = [
6
- { id: 'id', title: 'ID', disableSearch: true, disableFilter: true },
7
- { id: 'title', title: 'Title' },
8
- { id: 'photographer', title: 'Photographer' },
9
- { id: 'category', title: 'Category' },
10
- { id: 'likes', title: 'Likes', format: 'number' },
11
- { id: 'views', title: 'Views', format: 'number' },
12
- ];
13
-
14
- const sortOptions: CardSortOption[] = [
15
- { columnId: 'title', label: 'Title' },
16
- { columnId: 'photographer', label: 'Photographer' },
17
- { columnId: 'likes', label: 'Likes' },
18
- ];
19
-
20
- const CATEGORIES = ['Architecture', 'Nature', 'People', 'Travel', 'Abstract', 'Animals'];
21
- const PHOTOGRAPHERS = ['Alice Monroe', 'Ben Carter', 'Cara Lee', 'Daniel Park', 'Emma Rios', 'Felix Braun'];
22
- const TITLES = [
23
- 'Golden Hour', 'Morning Mist', 'Urban Jungle', 'Still Waters', 'First Light',
24
- 'Hidden Path', 'City Pulse', 'Wild Plains', 'Quiet Corner', 'Storm Front',
25
- 'Desert Bloom', 'Arctic Echo', 'Neon Drift', 'Forest Floor', 'Tidal Wave',
26
- ];
27
-
28
- const data = Array.from({ length: 60 }, (_, i) => ({
29
- id: i + 1,
30
- title: `${TITLES[i % TITLES.length]} ${Math.floor(i / TITLES.length) || ''}`.trim(),
31
- photographer: PHOTOGRAPHERS[i % PHOTOGRAPHERS.length],
32
- category: CATEGORIES[i % CATEGORIES.length],
33
- likes: Math.floor(Math.random() * 4800 + 200),
34
- views: Math.floor(Math.random() * 48000 + 2000),
35
- imageUrl: `https://picsum.photos/seed/${i + 1}/400/260`,
36
- }));
1
+ <script lang="ts">import CardGrid from "./CardGrid.svelte";
2
+ const columns = [
3
+ {
4
+ id: "id",
5
+ title: "ID",
6
+ disableSearch: true,
7
+ disableFilter: true
8
+ },
9
+ {
10
+ id: "title",
11
+ title: "Title"
12
+ },
13
+ {
14
+ id: "photographer",
15
+ title: "Photographer"
16
+ },
17
+ {
18
+ id: "category",
19
+ title: "Category"
20
+ },
21
+ {
22
+ id: "likes",
23
+ title: "Likes",
24
+ format: "number"
25
+ },
26
+ {
27
+ id: "views",
28
+ title: "Views",
29
+ format: "number"
30
+ }
31
+ ];
32
+ const sortOptions = [
33
+ {
34
+ columnId: "title",
35
+ label: "Title"
36
+ },
37
+ {
38
+ columnId: "photographer",
39
+ label: "Photographer"
40
+ },
41
+ {
42
+ columnId: "likes",
43
+ label: "Likes"
44
+ }
45
+ ];
46
+ const CATEGORIES = [
47
+ "Architecture",
48
+ "Nature",
49
+ "People",
50
+ "Travel",
51
+ "Abstract",
52
+ "Animals"
53
+ ];
54
+ const PHOTOGRAPHERS = [
55
+ "Alice Monroe",
56
+ "Ben Carter",
57
+ "Cara Lee",
58
+ "Daniel Park",
59
+ "Emma Rios",
60
+ "Felix Braun"
61
+ ];
62
+ const TITLES = [
63
+ "Golden Hour",
64
+ "Morning Mist",
65
+ "Urban Jungle",
66
+ "Still Waters",
67
+ "First Light",
68
+ "Hidden Path",
69
+ "City Pulse",
70
+ "Wild Plains",
71
+ "Quiet Corner",
72
+ "Storm Front",
73
+ "Desert Bloom",
74
+ "Arctic Echo",
75
+ "Neon Drift",
76
+ "Forest Floor",
77
+ "Tidal Wave"
78
+ ];
79
+ const data = Array.from({ length: 60 }, (_, i) => ({
80
+ id: i + 1,
81
+ title: `${TITLES[i % TITLES.length]} ${Math.floor(i / TITLES.length) || ""}`.trim(),
82
+ photographer: PHOTOGRAPHERS[i % PHOTOGRAPHERS.length],
83
+ category: CATEGORIES[i % CATEGORIES.length],
84
+ likes: Math.floor(Math.random() * 4800 + 200),
85
+ views: Math.floor(Math.random() * 48e3 + 2e3),
86
+ imageUrl: `https://picsum.photos/seed/${i + 1}/400/260`
87
+ }));
37
88
  </script>
38
89
 
39
90
  <!-- cardMaxFrontColumns=3 splits: front=[id,title,photographer], back=[category,likes,views] -->
@@ -31,3 +31,27 @@ export declare function rangeSelect(allItems: Record<string, unknown>[], anchorI
31
31
  export declare function isItemSelected(selectedItems: Record<string, unknown>[], item: Record<string, unknown>, uniqueID: string): boolean;
32
32
  /** Compute how many cards fit in a row given container width, min card width, and gap. */
33
33
  export declare function computeColumnsInRow(containerWidth: number, cardMinWidth: number, gap: number): number;
34
+ /** Density mode for the card grid. */
35
+ export type CardGridDensity = 'compact' | 'default' | 'comfortable';
36
+ /** Expand mode for the card grid. */
37
+ export type CardGridExpand = 'none' | 'medium' | 'large';
38
+ /** Extended props interface including animation, density and expand controls. */
39
+ export interface CardGridAnimationProps {
40
+ /** Enable staggered entry/exit animations on cards (default true). */
41
+ animate?: boolean;
42
+ /** Duration of card entrance transitions in ms (default 200). */
43
+ animateDuration?: number;
44
+ }
45
+ /** Extended props interface including animation, density and expand controls. */
46
+ export interface CardGridDensityProps {
47
+ /** Density mode: compact(default), comfortable. Overrides cardMinWidth/gap when set. */
48
+ density?: CardGridDensity;
49
+ /** Expand mode: none, medium, large. Controls how much space each card occupies. */
50
+ expand?: CardGridExpand;
51
+ }
52
+ /** Build virtual rows from flat displayData, packing columnsInRow items per row. */
53
+ export declare function buildVirtualRows(displayData: Record<string, unknown>[], columnsInRow: number): Record<string, unknown>[][];
54
+ /** Match a search string against any hotfield column value. */
55
+ export declare function typeaheadMatch(searchValue: string, item: Record<string, unknown>, hotfields?: string[]): boolean;
56
+ export interface ExtendedCardGridProps extends CardGridAnimationProps, CardGridDensityProps {
57
+ }
@@ -19,3 +19,23 @@ export function isItemSelected(selectedItems, item, uniqueID) {
19
19
  export function computeColumnsInRow(containerWidth, cardMinWidth, gap) {
20
20
  return Math.max(1, Math.floor((containerWidth + gap) / (cardMinWidth + gap)));
21
21
  }
22
+ /** Build virtual rows from flat displayData, packing columnsInRow items per row. */
23
+ export function buildVirtualRows(displayData, columnsInRow) {
24
+ const cols = Math.max(1, columnsInRow);
25
+ const rows = [];
26
+ for (let i = 0; i < displayData.length; i += cols) {
27
+ rows.push(displayData.slice(i, i + cols));
28
+ }
29
+ return rows;
30
+ }
31
+ /** Match a search string against any hotfield column value. */
32
+ export function typeaheadMatch(searchValue, item, hotfields) {
33
+ if (!searchValue)
34
+ return true;
35
+ const lower = searchValue.toLowerCase();
36
+ if (hotfields && hotfields.length > 0) {
37
+ return Object.entries(item).some(([k, v]) => hotfields.some((f) => k === f || k.endsWith(`.${f}`)) &&
38
+ String(v ?? '').toLowerCase().includes(lower));
39
+ }
40
+ return Object.values(item).some((v) => String(v ?? '').toLowerCase().includes(lower));
41
+ }
@@ -1,13 +1,8 @@
1
- <script lang="ts">
2
- import type { ContentEditorProps } from "./types.js";
3
- import ContentEditor from "./ContentEditor.svelte";
4
-
5
- let { value, filename, wopiUrl, discoverUrl, adminKey, userid, username }: ContentEditorProps =
6
- $props();
7
-
8
- let insertText = $state<((text: string) => void) | undefined>();
9
- let insertHtml = $state<((html: string) => void) | undefined>();
10
- let inputText = $state("Hello from Storybook!");
1
+ <script lang="ts">import ContentEditor from "./ContentEditor.svelte";
2
+ let { value, filename, wopiUrl, discoverUrl, adminKey, userid, username } = $props();
3
+ let insertText = $state();
4
+ let insertHtml = $state();
5
+ let inputText = $state("Hello from Storybook!");
11
6
  </script>
12
7
 
13
8
  <div style="display:flex;flex-direction:column;height:100vh;">