@svadmin/lite 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +85 -9
  2. package/dist/components/LiteActivityFeed.svelte +98 -0
  3. package/dist/components/LiteActivityFeed.svelte.d.ts +19 -0
  4. package/dist/components/LiteApprovalActionCard.svelte +75 -0
  5. package/dist/components/LiteApprovalActionCard.svelte.d.ts +10 -0
  6. package/dist/components/LiteCanvasAnnotation.svelte +136 -0
  7. package/dist/components/LiteCanvasAnnotation.svelte.d.ts +16 -0
  8. package/dist/components/LiteColumnHeaderFilter.svelte +38 -0
  9. package/dist/components/LiteColumnHeaderFilter.svelte.d.ts +8 -0
  10. package/dist/components/LiteColumnSettings.svelte +82 -0
  11. package/dist/components/LiteColumnSettings.svelte.d.ts +15 -0
  12. package/dist/components/LiteDecisionTable.svelte +178 -0
  13. package/dist/components/LiteDecisionTable.svelte.d.ts +21 -0
  14. package/dist/components/LiteDraggableRowTable.svelte +70 -0
  15. package/dist/components/LiteDraggableRowTable.svelte.d.ts +14 -0
  16. package/dist/components/LiteDrawerForm.svelte +85 -0
  17. package/dist/components/LiteDrawerForm.svelte.d.ts +13 -0
  18. package/dist/components/LiteDynamicFormList.svelte +169 -0
  19. package/dist/components/LiteDynamicFormList.svelte.d.ts +45 -0
  20. package/dist/components/LiteEditableTable.svelte +84 -0
  21. package/dist/components/LiteEditableTable.svelte.d.ts +19 -0
  22. package/dist/components/LiteFilterBuilder.svelte +205 -0
  23. package/dist/components/LiteFilterBuilder.svelte.d.ts +19 -0
  24. package/dist/components/LiteGanttChart.svelte +144 -0
  25. package/dist/components/LiteGanttChart.svelte.d.ts +17 -0
  26. package/dist/components/LiteImageCropper.svelte +81 -0
  27. package/dist/components/LiteImageCropper.svelte.d.ts +9 -0
  28. package/dist/components/LiteImportWizard.svelte +99 -0
  29. package/dist/components/LiteImportWizard.svelte.d.ts +11 -0
  30. package/dist/components/LiteJsonSchemaForm.svelte +102 -0
  31. package/dist/components/LiteJsonSchemaForm.svelte.d.ts +10 -0
  32. package/dist/components/LiteKanbanBoard.svelte +169 -0
  33. package/dist/components/LiteKanbanBoard.svelte.d.ts +21 -0
  34. package/dist/components/LiteMasterDetailView.svelte +113 -0
  35. package/dist/components/LiteMasterDetailView.svelte.d.ts +11 -0
  36. package/dist/components/LiteMediaLibraryModal.svelte +110 -0
  37. package/dist/components/LiteMediaLibraryModal.svelte.d.ts +17 -0
  38. package/dist/components/LiteMentionsInput.svelte +98 -0
  39. package/dist/components/LiteMentionsInput.svelte.d.ts +19 -0
  40. package/dist/components/LiteModalForm.svelte +84 -0
  41. package/dist/components/LiteModalForm.svelte.d.ts +13 -0
  42. package/dist/components/LiteMultiTabKeepAlive.svelte +79 -0
  43. package/dist/components/LiteMultiTabKeepAlive.svelte.d.ts +15 -0
  44. package/dist/components/LiteOfflineSyncBanner.svelte +75 -0
  45. package/dist/components/LiteOfflineSyncBanner.svelte.d.ts +15 -0
  46. package/dist/components/LitePdfDocumentViewer.svelte +138 -0
  47. package/dist/components/LitePdfDocumentViewer.svelte.d.ts +17 -0
  48. package/dist/components/LitePivotTable.svelte +163 -0
  49. package/dist/components/LitePivotTable.svelte.d.ts +15 -0
  50. package/dist/components/LitePresenceAvatarGroup.svelte +52 -0
  51. package/dist/components/LitePresenceAvatarGroup.svelte.d.ts +12 -0
  52. package/dist/components/LitePrintableBill.svelte +119 -0
  53. package/dist/components/LitePrintableBill.svelte.d.ts +19 -0
  54. package/dist/components/LiteSensitiveDataMask.svelte +35 -0
  55. package/dist/components/LiteSensitiveDataMask.svelte.d.ts +7 -0
  56. package/dist/components/LiteShowField.svelte +22 -0
  57. package/dist/components/LiteSignaturePad.svelte +99 -0
  58. package/dist/components/LiteSignaturePad.svelte.d.ts +11 -0
  59. package/dist/components/LiteSplitPaneLayout.svelte +66 -0
  60. package/dist/components/LiteSplitPaneLayout.svelte.d.ts +9 -0
  61. package/dist/components/LiteSpreadsheetView.svelte +148 -0
  62. package/dist/components/LiteSpreadsheetView.svelte.d.ts +16 -0
  63. package/dist/components/LiteStepForm.svelte +144 -0
  64. package/dist/components/LiteStepForm.svelte.d.ts +18 -0
  65. package/dist/components/LiteTableSummary.svelte +93 -0
  66. package/dist/components/LiteTableSummary.svelte.d.ts +17 -0
  67. package/dist/components/LiteTransfer.svelte +185 -0
  68. package/dist/components/LiteTransfer.svelte.d.ts +18 -0
  69. package/dist/components/LiteTreeTable.svelte +85 -0
  70. package/dist/components/LiteTreeTable.svelte.d.ts +13 -0
  71. package/dist/components/LiteVersionDiffViewer.svelte +129 -0
  72. package/dist/components/LiteVersionDiffViewer.svelte.d.ts +10 -0
  73. package/dist/components/LiteVirtualTable.svelte +52 -0
  74. package/dist/components/LiteVirtualTable.svelte.d.ts +14 -0
  75. package/dist/components/LiteWatermark.svelte +35 -0
  76. package/dist/components/LiteWatermark.svelte.d.ts +11 -0
  77. package/dist/components/fields/LiteAvatarField.svelte +127 -0
  78. package/dist/components/fields/LiteAvatarField.svelte.d.ts +21 -0
  79. package/dist/components/fields/LiteCascader.svelte +119 -0
  80. package/dist/components/fields/LiteCascader.svelte.d.ts +24 -0
  81. package/dist/components/fields/LiteCodeField.svelte +71 -0
  82. package/dist/components/fields/LiteCodeField.svelte.d.ts +16 -0
  83. package/dist/components/fields/LiteCopyField.svelte +74 -0
  84. package/dist/components/fields/LiteCopyField.svelte.d.ts +18 -0
  85. package/dist/components/fields/LiteCurrencyField.svelte +126 -0
  86. package/dist/components/fields/LiteCurrencyField.svelte.d.ts +21 -0
  87. package/dist/components/fields/LiteDateRangeField.svelte +147 -0
  88. package/dist/components/fields/LiteDateRangeField.svelte.d.ts +26 -0
  89. package/dist/components/fields/LitePercentField.svelte +124 -0
  90. package/dist/components/fields/LitePercentField.svelte.d.ts +17 -0
  91. package/dist/components/fields/LitePhoneField.svelte +81 -0
  92. package/dist/components/fields/LitePhoneField.svelte.d.ts +17 -0
  93. package/dist/components/fields/LiteRatingField.svelte +105 -0
  94. package/dist/components/fields/LiteRatingField.svelte.d.ts +16 -0
  95. package/dist/components/fields/LiteTreeSelect.svelte +143 -0
  96. package/dist/components/fields/LiteTreeSelect.svelte.d.ts +23 -0
  97. package/dist/components/fields/index.d.ts +12 -0
  98. package/dist/components/fields/index.js +10 -0
  99. package/dist/components/pages/LiteListPage.svelte +14 -12
  100. package/dist/index.d.ts +40 -0
  101. package/dist/index.js +37 -0
  102. package/dist/lite.css +205 -0
  103. package/dist/schema-generator.js +15 -4
  104. package/package.json +4 -3
@@ -0,0 +1,178 @@
1
+ <script lang="ts">
2
+ export interface DecisionColumn {
3
+ key: string;
4
+ label: string;
5
+ type: 'condition' | 'action';
6
+ }
7
+
8
+ export interface DecisionRule {
9
+ id: string;
10
+ description?: string;
11
+ values: Record<string, string>;
12
+ }
13
+
14
+ interface Props {
15
+ title?: string;
16
+ columns?: DecisionColumn[];
17
+ rules?: DecisionRule[];
18
+ hitPolicy?: string;
19
+ formAction?: string;
20
+ class?: string;
21
+ }
22
+
23
+ let {
24
+ title = 'Decision Table Matrix',
25
+ columns = [
26
+ { key: 'tier', label: 'Tier', type: 'condition' },
27
+ { key: 'discount', label: 'Discount', type: 'action' },
28
+ ],
29
+ rules = [
30
+ { id: 'r1', description: 'VIP', values: { tier: 'VIP', discount: '20%' } },
31
+ { id: 'r2', description: 'Standard', values: { tier: 'Standard', discount: '10%' } },
32
+ ],
33
+ hitPolicy = 'FIRST',
34
+ formAction = '',
35
+ class: className = '',
36
+ }: Props = $props();
37
+
38
+ const conditionCols = $derived(columns.filter((c) => c.type === 'condition'));
39
+ const actionCols = $derived(columns.filter((c) => c.type === 'action'));
40
+ </script>
41
+
42
+ <div class="sv-lite-decision-container {className}">
43
+ <div class="sv-lite-decision-header">
44
+ <strong>{title}</strong>
45
+ <span class="sv-lite-hit-policy">[Policy: {hitPolicy}]</span>
46
+ </div>
47
+
48
+ <form method="POST" action={formAction}>
49
+ <table class="sv-lite-decision-table">
50
+ <thead>
51
+ <tr>
52
+ <th rowspan="2" class="sv-lite-th-idx">#</th>
53
+ <th colspan={conditionCols.length} class="sv-lite-th-cond">Conditions (IF)</th>
54
+ <th colspan={actionCols.length} class="sv-lite-th-act">Actions (THEN)</th>
55
+ </tr>
56
+ <tr>
57
+ {#each conditionCols as col (col.key)}
58
+ <th class="sv-lite-th-sub">{col.label}</th>
59
+ {/each}
60
+ {#each actionCols as col (col.key)}
61
+ <th class="sv-lite-th-sub">{col.label}</th>
62
+ {/each}
63
+ </tr>
64
+ </thead>
65
+ <tbody>
66
+ {#each rules as rule, idx (rule.id)}
67
+ <tr>
68
+ <td class="sv-lite-td-idx">{idx + 1}</td>
69
+ {#each conditionCols as col (col.key)}
70
+ <td>
71
+ <input
72
+ type="text"
73
+ name={`rule_${rule.id}_${col.key}`}
74
+ value={rule.values[col.key] ?? ''}
75
+ class="sv-lite-rule-input"
76
+ />
77
+ </td>
78
+ {/each}
79
+ {#each actionCols as col (col.key)}
80
+ <td>
81
+ <input
82
+ type="text"
83
+ name={`rule_${rule.id}_${col.key}`}
84
+ value={rule.values[col.key] ?? ''}
85
+ class="sv-lite-rule-input sv-lite-act-input"
86
+ />
87
+ </td>
88
+ {/each}
89
+ </tr>
90
+ {/each}
91
+ </tbody>
92
+ </table>
93
+
94
+ {#if formAction}
95
+ <div class="sv-lite-decision-actions">
96
+ <button type="submit" class="sv-lite-save-btn">Save Rules</button>
97
+ </div>
98
+ {/if}
99
+ </form>
100
+ </div>
101
+
102
+ <style>
103
+ .sv-lite-decision-container {
104
+ display: block;
105
+ border: 1px solid #e2e8f0;
106
+ border-radius: 6px;
107
+ padding: 12px;
108
+ background-color: #ffffff;
109
+ font-size: 12px;
110
+ overflow-x: auto;
111
+ }
112
+ .sv-lite-decision-header {
113
+ margin-bottom: 10px;
114
+ font-size: 13px;
115
+ color: #0f172a;
116
+ }
117
+ .sv-lite-hit-policy {
118
+ font-size: 10px;
119
+ color: #64748b;
120
+ margin-left: 6px;
121
+ }
122
+ .sv-lite-decision-table {
123
+ width: 100%;
124
+ border-collapse: collapse;
125
+ font-family: monospace;
126
+ }
127
+ .sv-lite-decision-table th, .sv-lite-decision-table td {
128
+ border: 1px solid #cbd5e1;
129
+ padding: 4px 6px;
130
+ }
131
+ .sv-lite-th-idx, .sv-lite-td-idx {
132
+ background-color: #f1f5f9;
133
+ text-align: center;
134
+ width: 28px;
135
+ font-size: 10px;
136
+ }
137
+ .sv-lite-th-cond {
138
+ background-color: #e0e7ff;
139
+ color: #3730a3;
140
+ text-align: center;
141
+ font-weight: bold;
142
+ }
143
+ .sv-lite-th-act {
144
+ background-color: #dcfce7;
145
+ color: #166534;
146
+ text-align: center;
147
+ font-weight: bold;
148
+ }
149
+ .sv-lite-th-sub {
150
+ background-color: #f8fafc;
151
+ color: #475569;
152
+ font-weight: 600;
153
+ }
154
+ .sv-lite-rule-input {
155
+ width: 100%;
156
+ border: 1px solid #cbd5e1;
157
+ padding: 3px;
158
+ font-size: 11px;
159
+ box-sizing: border-box;
160
+ }
161
+ .sv-lite-act-input {
162
+ font-weight: bold;
163
+ color: #4338ca;
164
+ }
165
+ .sv-lite-decision-actions {
166
+ margin-top: 10px;
167
+ text-align: right;
168
+ }
169
+ .sv-lite-save-btn {
170
+ padding: 5px 12px;
171
+ background-color: #4f46e5;
172
+ color: #ffffff;
173
+ border: none;
174
+ border-radius: 3px;
175
+ font-size: 11px;
176
+ cursor: pointer;
177
+ }
178
+ </style>
@@ -0,0 +1,21 @@
1
+ export interface DecisionColumn {
2
+ key: string;
3
+ label: string;
4
+ type: 'condition' | 'action';
5
+ }
6
+ export interface DecisionRule {
7
+ id: string;
8
+ description?: string;
9
+ values: Record<string, string>;
10
+ }
11
+ interface Props {
12
+ title?: string;
13
+ columns?: DecisionColumn[];
14
+ rules?: DecisionRule[];
15
+ hitPolicy?: string;
16
+ formAction?: string;
17
+ class?: string;
18
+ }
19
+ declare const LiteDecisionTable: import("svelte").Component<Props, {}, "">;
20
+ type LiteDecisionTable = ReturnType<typeof LiteDecisionTable>;
21
+ export default LiteDecisionTable;
@@ -0,0 +1,70 @@
1
+ <script lang="ts">
2
+ interface LiteDraggableColumn {
3
+ key: string;
4
+ label: string;
5
+ }
6
+
7
+ interface Props {
8
+ columns: LiteDraggableColumn[];
9
+ items?: Record<string, unknown>[];
10
+ action?: string;
11
+ method?: 'get' | 'post' | 'dialog' | 'GET' | 'POST' | 'DIALOG' | null;
12
+ rowKey?: string;
13
+ }
14
+
15
+ let {
16
+ columns,
17
+ items = [],
18
+ action = '',
19
+ method = 'POST',
20
+ rowKey = 'id',
21
+ }: Props = $props();
22
+ </script>
23
+
24
+ <div class="lite-sortable-table-card">
25
+ <form {action} {method}>
26
+ <table class="lite-table">
27
+ <thead>
28
+ <tr>
29
+ <th style="width: 70px;">Order</th>
30
+ {#each columns as col (col.key)}
31
+ <th>{col.label}</th>
32
+ {/each}
33
+ </tr>
34
+ </thead>
35
+ <tbody>
36
+ {#each items as item, index (item[rowKey] ?? index)}
37
+ <tr>
38
+ <td>
39
+ <input type="number" name="order_{item[rowKey] ?? index}" value={index + 1} class="lite-input" style="width: 55px;" />
40
+ </td>
41
+ {#each columns as col (col.key)}
42
+ <td>{item[col.key] ?? '—'}</td>
43
+ {/each}
44
+ </tr>
45
+ {/each}
46
+ </tbody>
47
+ </table>
48
+
49
+ <div class="lite-sortable-actions">
50
+ <button type="submit" class="lite-btn lite-btn-primary lite-btn-sm">
51
+ Update Order
52
+ </button>
53
+ </div>
54
+ </form>
55
+ </div>
56
+
57
+ <style>
58
+ .lite-sortable-table-card {
59
+ background: #ffffff;
60
+ border: 1px solid #cbd5e1;
61
+ border-radius: 6px;
62
+ padding: 12px;
63
+ margin-bottom: 16px;
64
+ }
65
+ .lite-sortable-actions {
66
+ margin-top: 12px;
67
+ display: flex;
68
+ justify-content: flex-end;
69
+ }
70
+ </style>
@@ -0,0 +1,14 @@
1
+ interface LiteDraggableColumn {
2
+ key: string;
3
+ label: string;
4
+ }
5
+ interface Props {
6
+ columns: LiteDraggableColumn[];
7
+ items?: Record<string, unknown>[];
8
+ action?: string;
9
+ method?: 'get' | 'post' | 'dialog' | 'GET' | 'POST' | 'DIALOG' | null;
10
+ rowKey?: string;
11
+ }
12
+ declare const LiteDraggableRowTable: import("svelte").Component<Props, {}, "">;
13
+ type LiteDraggableRowTable = ReturnType<typeof LiteDraggableRowTable>;
14
+ export default LiteDraggableRowTable;
@@ -0,0 +1,85 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ title: string;
6
+ description?: string;
7
+ action?: string;
8
+ method?: "get" | "post" | "dialog" | "GET" | "POST" | "DIALOG" | null;
9
+ submitText?: string;
10
+ cancelText?: string;
11
+ children?: Snippet;
12
+ }
13
+
14
+ let {
15
+ title,
16
+ description,
17
+ action = '',
18
+ method = 'POST',
19
+ submitText = 'Save',
20
+ cancelText = 'Cancel',
21
+ children,
22
+ }: Props = $props();
23
+ </script>
24
+
25
+ <div class="lite-drawer-card">
26
+ <div class="lite-drawer-header">
27
+ <h3 class="lite-drawer-title">{title}</h3>
28
+ {#if description}
29
+ <p class="lite-drawer-desc">{description}</p>
30
+ {/if}
31
+ </div>
32
+
33
+ <form {action} {method} class="lite-drawer-form">
34
+ <div class="lite-drawer-body">
35
+ {#if children}
36
+ {@render children()}
37
+ {/if}
38
+ </div>
39
+
40
+ <div class="lite-drawer-footer">
41
+ <button type="button" class="lite-btn lite-btn-outline lite-btn-sm" onclick={() => history.back()}>
42
+ {cancelText}
43
+ </button>
44
+ <button type="submit" class="lite-btn lite-btn-primary lite-btn-sm" style="margin-left: 8px;">
45
+ {submitText}
46
+ </button>
47
+ </div>
48
+ </form>
49
+ </div>
50
+
51
+ <style>
52
+ .lite-drawer-card {
53
+ padding: 16px;
54
+ background: #f8fafc;
55
+ border: 1px solid #cbd5e1;
56
+ border-left: 4px solid #3b82f6;
57
+ border-radius: 4px;
58
+ margin-bottom: 16px;
59
+ }
60
+ .lite-drawer-header {
61
+ padding-bottom: 10px;
62
+ border-bottom: 1px solid #e2e8f0;
63
+ margin-bottom: 12px;
64
+ }
65
+ .lite-drawer-title {
66
+ margin: 0;
67
+ font-size: 14px;
68
+ color: #1e293b;
69
+ }
70
+ .lite-drawer-desc {
71
+ margin: 4px 0 0 0;
72
+ font-size: 12px;
73
+ color: #64748b;
74
+ }
75
+ .lite-drawer-body {
76
+ margin-bottom: 16px;
77
+ font-size: 13px;
78
+ }
79
+ .lite-drawer-footer {
80
+ display: flex;
81
+ justify-content: flex-end;
82
+ padding-top: 12px;
83
+ border-top: 1px solid #e2e8f0;
84
+ }
85
+ </style>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ title: string;
4
+ description?: string;
5
+ action?: string;
6
+ method?: "get" | "post" | "dialog" | "GET" | "POST" | "DIALOG" | null;
7
+ submitText?: string;
8
+ cancelText?: string;
9
+ children?: Snippet;
10
+ }
11
+ declare const LiteDrawerForm: import("svelte").Component<Props, {}, "">;
12
+ type LiteDrawerForm = ReturnType<typeof LiteDrawerForm>;
13
+ export default LiteDrawerForm;
@@ -0,0 +1,169 @@
1
+ <script lang="ts" generics="T = Record<string, unknown>">
2
+ import type { Snippet } from 'svelte';
3
+ import { t } from '@svadmin/core/i18n';
4
+
5
+ interface Props {
6
+ items?: T[];
7
+ name?: string;
8
+ label?: string;
9
+ description?: string;
10
+ addButtonLabel?: string;
11
+ minItems?: number;
12
+ maxItems?: number;
13
+ defaultItem?: T | (() => T);
14
+ disabled?: boolean;
15
+ emptyText?: string;
16
+ children?: Snippet<[{
17
+ item: T;
18
+ index: number;
19
+ isFirst: boolean;
20
+ isLast: boolean;
21
+ }]>;
22
+ headerExtra?: Snippet<[{ count: number }]>;
23
+ }
24
+
25
+ let {
26
+ items = [],
27
+ name = 'items',
28
+ label,
29
+ description,
30
+ addButtonLabel = '+ Add Item',
31
+ minItems = 0,
32
+ maxItems = Infinity,
33
+ disabled = false,
34
+ emptyText = 'No items yet',
35
+ children,
36
+ headerExtra,
37
+ }: Props = $props();
38
+
39
+ const renderedItems = $derived(items.length > 0 ? items : (minItems > 0 ? Array(minItems).fill({}) as T[] : []));
40
+ </script>
41
+
42
+ <div class="lite-dynamic-form-list lite-form-group">
43
+ <div class="lite-dynamic-header">
44
+ <div>
45
+ {#if label}
46
+ <span class="lite-label">{label}</span>
47
+ {/if}
48
+ {#if description}
49
+ <p class="lite-help-text">{description}</p>
50
+ {/if}
51
+ </div>
52
+ <div class="lite-dynamic-actions">
53
+ {#if headerExtra}
54
+ {@render headerExtra({ count: renderedItems.length })}
55
+ {/if}
56
+ <span class="lite-badge">{renderedItems.length} {t('common.items') || 'items'}</span>
57
+ </div>
58
+ </div>
59
+
60
+ {#if renderedItems.length === 0}
61
+ <div class="lite-empty-box">
62
+ <p>{emptyText}</p>
63
+ </div>
64
+ {:else}
65
+ <div class="lite-dynamic-items">
66
+ {#each renderedItems as item, idx (idx)}
67
+ <div class="lite-dynamic-item-card">
68
+ <div class="lite-dynamic-item-header">
69
+ <span class="lite-badge lite-badge-indigo">#{idx + 1}</span>
70
+ <div class="lite-dynamic-item-tools">
71
+ {#if idx > 0}
72
+ <button type="submit" name="_action" value="move_up_{name}_{idx}" class="lite-btn lite-btn-sm" {disabled} title="Move Up">↑</button>
73
+ {/if}
74
+ {#if idx < renderedItems.length - 1}
75
+ <button type="submit" name="_action" value="move_down_{name}_{idx}" class="lite-btn lite-btn-sm" {disabled} title="Move Down">↓</button>
76
+ {/if}
77
+ {#if renderedItems.length > minItems}
78
+ <button type="submit" name="_action" value="remove_{name}_{idx}" class="lite-btn lite-btn-sm lite-btn-danger" {disabled} title="Remove">✕</button>
79
+ {/if}
80
+ </div>
81
+ </div>
82
+ <div class="lite-dynamic-item-body">
83
+ {#if children}
84
+ {@render children({
85
+ item,
86
+ index: idx,
87
+ isFirst: idx === 0,
88
+ isLast: idx === renderedItems.length - 1,
89
+ })}
90
+ {:else}
91
+ <div class="lite-form-row">
92
+ {#each Object.entries((item as Record<string, unknown>) ?? {}) as [k, v] (k)}
93
+ <div class="lite-form-group" style="flex: 1; min-width: 140px;">
94
+ <label class="lite-label" for="{name}_{idx}_{k}">{k}</label>
95
+ <input
96
+ type="text"
97
+ id="{name}_{idx}_{k}"
98
+ name="{name}[{idx}][{k}]"
99
+ value={String(v ?? '')}
100
+ class="lite-input"
101
+ {disabled}
102
+ />
103
+ </div>
104
+ {/each}
105
+ </div>
106
+ {/if}
107
+ </div>
108
+ </div>
109
+ {/each}
110
+ </div>
111
+ {/if}
112
+
113
+ {#if renderedItems.length < maxItems && !disabled}
114
+ <div style="margin-top: 10px;">
115
+ <button type="submit" name="_action" value="add_{name}" class="lite-btn">
116
+ {addButtonLabel}
117
+ </button>
118
+ </div>
119
+ {/if}
120
+ </div>
121
+
122
+ <style>
123
+ .lite-dynamic-form-list {
124
+ border: 1px solid #e2e8f0;
125
+ border-radius: 6px;
126
+ padding: 14px;
127
+ background-color: #fafafa;
128
+ margin-bottom: 16px;
129
+ }
130
+ .lite-dynamic-header {
131
+ display: flex;
132
+ justify-content: space-between;
133
+ align-items: center;
134
+ margin-bottom: 12px;
135
+ }
136
+ .lite-dynamic-items {
137
+ display: flex;
138
+ flex-direction: column;
139
+ }
140
+ .lite-dynamic-item-card {
141
+ background: #ffffff;
142
+ border: 1px solid #e2e8f0;
143
+ border-radius: 4px;
144
+ padding: 12px;
145
+ margin-bottom: 10px;
146
+ }
147
+ .lite-dynamic-item-header {
148
+ display: flex;
149
+ justify-content: space-between;
150
+ align-items: center;
151
+ margin-bottom: 8px;
152
+ border-bottom: 1px dashed #e2e8f0;
153
+ padding-bottom: 6px;
154
+ }
155
+ .lite-dynamic-item-tools {
156
+ display: flex;
157
+ }
158
+ .lite-dynamic-item-tools button {
159
+ margin-left: 4px;
160
+ }
161
+ .lite-empty-box {
162
+ text-align: center;
163
+ padding: 24px 12px;
164
+ color: #64748b;
165
+ background: #ffffff;
166
+ border: 1px dashed #cbd5e1;
167
+ border-radius: 4px;
168
+ }
169
+ </style>
@@ -0,0 +1,45 @@
1
+ import type { Snippet } from 'svelte';
2
+ declare function $$render<T = Record<string, unknown>>(): {
3
+ props: {
4
+ items?: T[];
5
+ name?: string;
6
+ label?: string;
7
+ description?: string;
8
+ addButtonLabel?: string;
9
+ minItems?: number;
10
+ maxItems?: number;
11
+ defaultItem?: T | (() => T);
12
+ disabled?: boolean;
13
+ emptyText?: string;
14
+ children?: Snippet<[{
15
+ item: T;
16
+ index: number;
17
+ isFirst: boolean;
18
+ isLast: boolean;
19
+ }]>;
20
+ headerExtra?: Snippet<[{
21
+ count: number;
22
+ }]>;
23
+ };
24
+ exports: {};
25
+ bindings: "";
26
+ slots: {};
27
+ events: {};
28
+ };
29
+ declare class __sveltets_Render<T = Record<string, unknown>> {
30
+ props(): ReturnType<typeof $$render<T>>['props'];
31
+ events(): ReturnType<typeof $$render<T>>['events'];
32
+ slots(): ReturnType<typeof $$render<T>>['slots'];
33
+ bindings(): "";
34
+ exports(): {};
35
+ }
36
+ interface $$IsomorphicComponent {
37
+ new <T = Record<string, unknown>>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
38
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
39
+ } & ReturnType<__sveltets_Render<T>['exports']>;
40
+ <T = Record<string, unknown>>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
41
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
42
+ }
43
+ declare const LiteDynamicFormList: $$IsomorphicComponent;
44
+ type LiteDynamicFormList<T = Record<string, unknown>> = InstanceType<typeof LiteDynamicFormList<T>>;
45
+ export default LiteDynamicFormList;
@@ -0,0 +1,84 @@
1
+ <script lang="ts">
2
+ interface LiteEditableTableColumn {
3
+ key: string;
4
+ label: string;
5
+ type?: 'text' | 'number' | 'select' | 'boolean' | 'date';
6
+ options?: Array<{ label: string; value: string | number }>;
7
+ }
8
+
9
+ interface Props {
10
+ columns: LiteEditableTableColumn[];
11
+ data?: Record<string, unknown>[];
12
+ action?: string;
13
+ method?: 'get' | 'post' | 'dialog' | 'GET' | 'POST' | 'DIALOG' | null;
14
+ rowKey?: string;
15
+ }
16
+
17
+ let {
18
+ columns,
19
+ data = [],
20
+ action = '',
21
+ method = 'POST',
22
+ rowKey = 'id',
23
+ }: Props = $props();
24
+ </script>
25
+
26
+ <div class="lite-editable-table-card">
27
+ <form {action} {method}>
28
+ <table class="lite-table">
29
+ <thead>
30
+ <tr>
31
+ {#each columns as col (col.key)}
32
+ <th>{col.label}</th>
33
+ {/each}
34
+ </tr>
35
+ </thead>
36
+ <tbody>
37
+ {#each data as row, rowIndex (row[rowKey] ?? rowIndex)}
38
+ <tr>
39
+ {#each columns as col (col.key)}
40
+ <td>
41
+ {#if col.type === 'select' && col.options}
42
+ <select name="{col.key}_{rowIndex}" class="lite-select">
43
+ {#each col.options as opt (opt.value)}
44
+ <option value={String(opt.value)} selected={String(row[col.key]) === String(opt.value)}>
45
+ {opt.label}
46
+ </option>
47
+ {/each}
48
+ </select>
49
+ {:else if col.type === 'boolean'}
50
+ <input type="checkbox" name="{col.key}_{rowIndex}" checked={Boolean(row[col.key])} />
51
+ {:else if col.type === 'number'}
52
+ <input type="number" name="{col.key}_{rowIndex}" value={Number(row[col.key] ?? 0)} class="lite-input" />
53
+ {:else}
54
+ <input type="text" name="{col.key}_{rowIndex}" value={String(row[col.key] ?? '')} class="lite-input" />
55
+ {/if}
56
+ </td>
57
+ {/each}
58
+ </tr>
59
+ {/each}
60
+ </tbody>
61
+ </table>
62
+
63
+ <div class="lite-editable-actions">
64
+ <button type="submit" class="lite-btn lite-btn-primary lite-btn-sm">
65
+ Save All Changes
66
+ </button>
67
+ </div>
68
+ </form>
69
+ </div>
70
+
71
+ <style>
72
+ .lite-editable-table-card {
73
+ background: #ffffff;
74
+ border: 1px solid #cbd5e1;
75
+ border-radius: 6px;
76
+ padding: 12px;
77
+ margin-bottom: 16px;
78
+ }
79
+ .lite-editable-actions {
80
+ margin-top: 12px;
81
+ display: flex;
82
+ justify-content: flex-end;
83
+ }
84
+ </style>