runeforge 0.0.55 → 0.0.56

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 (54) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1342 -1342
  3. package/dist/components/Avatar.svelte +31 -31
  4. package/dist/components/IconRenderer.svelte +22 -22
  5. package/dist/components/Modal.svelte +75 -75
  6. package/dist/components/common/Header.svelte +40 -40
  7. package/dist/components/crud/EmbeddedField.svelte +175 -175
  8. package/dist/components/crud/Field.svelte +469 -376
  9. package/dist/components/crud/GenericCRUD.svelte +426 -426
  10. package/dist/components/crud/SearchInput.svelte +53 -53
  11. package/dist/components/crud/columns/Avatar.svelte +15 -15
  12. package/dist/components/crud/columns/Icon.svelte +8 -8
  13. package/dist/components/crud/views/Create.svelte +232 -232
  14. package/dist/components/crud/views/Read.svelte +124 -124
  15. package/dist/components/crud/views/Update.svelte +208 -208
  16. package/dist/components/crud/views/list/List.svelte +291 -291
  17. package/dist/components/crud/views/list/Modals.svelte +56 -56
  18. package/dist/components/crud/views/list/Table.svelte +176 -176
  19. package/dist/components/crud/views/list/Toolbar.svelte +341 -341
  20. package/dist/components/form/Button.svelte +27 -27
  21. package/dist/components/form/Label.svelte +37 -37
  22. package/dist/components/form/MultiSelect.svelte +248 -248
  23. package/dist/components/form/PasswordInput.svelte +68 -68
  24. package/dist/components/form/Required.svelte +1 -1
  25. package/dist/components/form/Select.svelte +209 -209
  26. package/dist/components/form/Tree.svelte +62 -62
  27. package/dist/components/form/TreeNode.svelte +66 -66
  28. package/dist/components/navigation/Breadcrumbs.svelte +111 -111
  29. package/dist/components/table/ColumnFilter.svelte +168 -168
  30. package/dist/components/table/PaginatedTable.svelte +536 -536
  31. package/dist/components/table/Paginator.svelte +113 -113
  32. package/dist/components/table/SortHeader.svelte +43 -43
  33. package/dist/components/table/TableBody.svelte +150 -150
  34. package/dist/components/table/TableHeader.svelte +88 -88
  35. package/dist/i18n/en.js +1 -0
  36. package/dist/i18n/es.js +1 -0
  37. package/dist/i18n/types.d.ts +1 -0
  38. package/dist/icons/defaults/Clear.svelte +6 -6
  39. package/dist/icons/defaults/Create.svelte +6 -6
  40. package/dist/icons/defaults/Delete.svelte +6 -6
  41. package/dist/icons/defaults/Download.svelte +7 -7
  42. package/dist/icons/defaults/Edit.svelte +7 -7
  43. package/dist/icons/defaults/Filter.svelte +6 -6
  44. package/dist/icons/defaults/FilterActive.svelte +6 -6
  45. package/dist/icons/defaults/Folder.svelte +6 -6
  46. package/dist/icons/defaults/Grip.svelte +7 -7
  47. package/dist/icons/defaults/Home.svelte +6 -6
  48. package/dist/icons/defaults/PasswordHide.svelte +9 -9
  49. package/dist/icons/defaults/PasswordShow.svelte +7 -7
  50. package/dist/icons/defaults/SortAsc.svelte +6 -6
  51. package/dist/icons/defaults/SortDesc.svelte +6 -6
  52. package/dist/icons/defaults/SortNone.svelte +6 -6
  53. package/dist/icons/defaults/View.svelte +7 -7
  54. package/package.json +1 -1
@@ -1,56 +1,56 @@
1
- <script lang="ts" generics="T extends object = Record<string, unknown>">
2
- import Button from '../../../form/Button.svelte';
3
- import Modal from '../../../Modal.svelte';
4
- import type { CustomBulkAction } from '../../../../types/crud.js';
5
- import { getStrings } from '../../../../i18n/context.js';
6
-
7
- const strings = getStrings();
8
-
9
- let {
10
- deleteLabel = '',
11
- pendingDeletion = null as T[] | null,
12
- pendingBulkAction = null as { action: CustomBulkAction<T>; items: T[] } | null,
13
- onCancelDeletion,
14
- onConfirmDeletion,
15
- onCancelBulkAction,
16
- onConfirmBulkAction
17
- }: {
18
- deleteLabel?: string;
19
- pendingDeletion?: T[] | null;
20
- pendingBulkAction?: { action: CustomBulkAction<T>; items: T[] } | null;
21
- onCancelDeletion?: () => void;
22
- onConfirmDeletion?: () => void;
23
- onCancelBulkAction?: () => void;
24
- onConfirmBulkAction?: () => void;
25
- } = $props();
26
- </script>
27
-
28
- {#if pendingDeletion !== null}
29
- <Modal title={deleteLabel} onClose={onCancelDeletion}>
30
- <p>{strings.deleteConfirm(pendingDeletion.length, deleteLabel)}</p>
31
- <div class="flex justify-end gap-2 mt-4">
32
- <Button variant="ghost" onclick={onCancelDeletion}>
33
- {strings.cancel}
34
- </Button>
35
- <Button variant="error" onclick={onConfirmDeletion}>
36
- {strings.confirm}
37
- </Button>
38
- </div>
39
- </Modal>
40
- {/if}
41
-
42
- {#if pendingBulkAction !== null}
43
- {@const pendingActionLabel =
44
- pendingBulkAction.action.label ?? pendingBulkAction.action.tooltip ?? strings.actions}
45
- <Modal title={pendingActionLabel} onClose={onCancelBulkAction}>
46
- <p>{strings.deleteConfirm(pendingBulkAction.items.length, pendingActionLabel)}</p>
47
- <div class="flex justify-end gap-2 mt-4">
48
- <Button variant="ghost" onclick={onCancelBulkAction}>
49
- {strings.cancel}
50
- </Button>
51
- <Button variant={pendingBulkAction.action.variant ?? 'primary'} onclick={onConfirmBulkAction}>
52
- {strings.confirm}
53
- </Button>
54
- </div>
55
- </Modal>
56
- {/if}
1
+ <script lang="ts" generics="T extends object = Record<string, unknown>">
2
+ import Button from '../../../form/Button.svelte';
3
+ import Modal from '../../../Modal.svelte';
4
+ import type { CustomBulkAction } from '../../../../types/crud.js';
5
+ import { getStrings } from '../../../../i18n/context.js';
6
+
7
+ const strings = getStrings();
8
+
9
+ let {
10
+ deleteLabel = '',
11
+ pendingDeletion = null as T[] | null,
12
+ pendingBulkAction = null as { action: CustomBulkAction<T>; items: T[] } | null,
13
+ onCancelDeletion,
14
+ onConfirmDeletion,
15
+ onCancelBulkAction,
16
+ onConfirmBulkAction
17
+ }: {
18
+ deleteLabel?: string;
19
+ pendingDeletion?: T[] | null;
20
+ pendingBulkAction?: { action: CustomBulkAction<T>; items: T[] } | null;
21
+ onCancelDeletion?: () => void;
22
+ onConfirmDeletion?: () => void;
23
+ onCancelBulkAction?: () => void;
24
+ onConfirmBulkAction?: () => void;
25
+ } = $props();
26
+ </script>
27
+
28
+ {#if pendingDeletion !== null}
29
+ <Modal title={deleteLabel} onClose={onCancelDeletion}>
30
+ <p>{strings.deleteConfirm(pendingDeletion.length, deleteLabel)}</p>
31
+ <div class="flex justify-end gap-2 mt-4">
32
+ <Button variant="ghost" onclick={onCancelDeletion}>
33
+ {strings.cancel}
34
+ </Button>
35
+ <Button variant="error" onclick={onConfirmDeletion}>
36
+ {strings.confirm}
37
+ </Button>
38
+ </div>
39
+ </Modal>
40
+ {/if}
41
+
42
+ {#if pendingBulkAction !== null}
43
+ {@const pendingActionLabel =
44
+ pendingBulkAction.action.label ?? pendingBulkAction.action.tooltip ?? strings.actions}
45
+ <Modal title={pendingActionLabel} onClose={onCancelBulkAction}>
46
+ <p>{strings.deleteConfirm(pendingBulkAction.items.length, pendingActionLabel)}</p>
47
+ <div class="flex justify-end gap-2 mt-4">
48
+ <Button variant="ghost" onclick={onCancelBulkAction}>
49
+ {strings.cancel}
50
+ </Button>
51
+ <Button variant={pendingBulkAction.action.variant ?? 'primary'} onclick={onConfirmBulkAction}>
52
+ {strings.confirm}
53
+ </Button>
54
+ </div>
55
+ </Modal>
56
+ {/if}
@@ -1,176 +1,176 @@
1
- <script lang="ts" generics="T extends object = Record<string, unknown>">
2
- import { SvelteSet } from 'svelte/reactivity';
3
- import Button from '../../../form/Button.svelte';
4
- import PaginatedTable from '../../../table/PaginatedTable.svelte';
5
- import { getIconSet } from '../../../../icons/context.js';
6
- import { defaultIconSet } from '../../../../icons/sets/default.js';
7
- import type {
8
- ColumnDefinition,
9
- CustomAction,
10
- ReorderConfiguration,
11
- RowAction
12
- } from '../../../../types/crud.js';
13
- import type {
14
- FilterSnapshot,
15
- ServerPagination,
16
- SortDirection,
17
- TableQuery
18
- } from '../../../../types/table.js';
19
-
20
- const icons = $derived(getIconSet() ?? defaultIconSet);
21
-
22
- let {
23
- data = [] as T[],
24
- columns = [] as ColumnDefinition<T>[],
25
- pageSize = 10,
26
- selectable = true,
27
- selected = $bindable(new SvelteSet<number>()),
28
- pagination = undefined as ServerPagination | undefined,
29
- initialSort = undefined as { column: string; direction: SortDirection } | undefined,
30
- initialFilters = undefined as Partial<FilterSnapshot> | undefined,
31
- onPaginationChange = undefined as ((query: TableQuery) => void) | undefined,
32
- visibleRows = $bindable<T[]>([]),
33
- query = $bindable<TableQuery | undefined>(undefined),
34
- customActions = [] as CustomAction<T>[],
35
- allowRead = true,
36
- allowUpdate = true,
37
- allowDelete = true,
38
- readLabel = '',
39
- updateLabel = '',
40
- deleteLabel = '',
41
- reorder = undefined as ReorderConfiguration<T> | undefined,
42
- onView,
43
- onEdit,
44
- onAction,
45
- onRequestDeletion,
46
- onReorder
47
- }: {
48
- data?: T[];
49
- columns?: ColumnDefinition<T>[];
50
- pageSize?: number;
51
- selectable?: boolean;
52
- selected?: SvelteSet<number>;
53
- pagination?: ServerPagination;
54
- initialSort?: { column: string; direction: SortDirection };
55
- initialFilters?: Partial<FilterSnapshot>;
56
- onPaginationChange?: (query: TableQuery) => void;
57
- visibleRows?: T[];
58
- query?: TableQuery;
59
- customActions?: CustomAction<T>[];
60
- allowRead?: boolean;
61
- allowUpdate?: boolean;
62
- allowDelete?: boolean;
63
- readLabel?: string;
64
- updateLabel?: string;
65
- deleteLabel?: string;
66
- /** Drag-to-reorder configuration — see `ReorderConfiguration`. Ignored
67
- * in server-pagination mode (`pagination` set). */
68
- reorder?: ReorderConfiguration<T>;
69
- onView?: (item: T) => void;
70
- onEdit?: (item: T) => void;
71
- onAction?: (action: CustomAction<T>, item: T) => void;
72
- onRequestDeletion?: (item: T) => void;
73
- /** Fires with the complete reordered row list after a drag; the caller
74
- * (the list orchestrator) owns persisting it. */
75
- onReorder?: (rows: T[]) => void;
76
- } = $props();
77
-
78
- const reorderActive = $derived(!!reorder && reorder.enabled !== false && !pagination);
79
-
80
- const showRowActions = $derived(
81
- allowRead || allowUpdate || allowDelete || customActions.length > 0
82
- );
83
-
84
- const rowActions = $derived<RowAction<T>[]>([
85
- ...customActions.map((action) => ({
86
- label: action.label,
87
- icon: action.icon,
88
- toggle: action.toggle,
89
- class: action.class,
90
- condition: action.condition,
91
- run: (item: T) => onAction?.(action, item)
92
- })),
93
- ...(allowRead
94
- ? [{ label: readLabel, icon: icons.view, run: (item: T) => onView?.(item) }]
95
- : []),
96
- ...(allowUpdate
97
- ? [{ label: updateLabel, icon: icons.edit, run: (item: T) => onEdit?.(item) }]
98
- : []),
99
- ...(allowDelete
100
- ? [
101
- {
102
- label: deleteLabel,
103
- icon: icons.delete,
104
- class: 'text-error',
105
- run: (item: T) => onRequestDeletion?.(item)
106
- }
107
- ]
108
- : [])
109
- ]);
110
- </script>
111
-
112
- {#snippet actionsCell(item: T)}
113
- <div class="flex justify-end items-center gap-1">
114
- {#each rowActions as action (action.label)}
115
- {#if action.condition?.(item) ?? true}
116
- {@const resolvedClass =
117
- typeof action.class === 'function' ? action.class(item) : action.class}
118
- {#if action.toggle}
119
- <input
120
- type="checkbox"
121
- class={['toggle toggle-sm', resolvedClass]}
122
- title={action.label}
123
- aria-label={action.label}
124
- checked={action.toggle(item)}
125
- onclick={(e) => {
126
- e.preventDefault();
127
- e.stopPropagation();
128
- action.run(item);
129
- }}
130
- />
131
- {:else}
132
- {@const Icon = action.icon}
133
- <Button
134
- variant="ghost"
135
- class={['btn-xs', resolvedClass]}
136
- title={action.label}
137
- aria-label={action.label}
138
- onclick={(e) => {
139
- e.stopPropagation();
140
- action.run(item);
141
- }}
142
- >
143
- <Icon class="size-4" />
144
- </Button>
145
- {/if}
146
- {/if}
147
- {/each}
148
- </div>
149
- {/snippet}
150
-
151
- <div class="table-wrapper">
152
- <PaginatedTable
153
- {data}
154
- {columns}
155
- {pageSize}
156
- {selectable}
157
- bind:selected
158
- rowActions={showRowActions ? actionsCell : undefined}
159
- {pagination}
160
- {initialSort}
161
- {initialFilters}
162
- {onPaginationChange}
163
- bind:visibleRows
164
- bind:query
165
- reorder={reorderActive ? reorder : undefined}
166
- {onReorder}
167
- />
168
- </div>
169
-
170
- <style>
171
- .table-wrapper {
172
- width: 100%;
173
- max-width: var(--runeforge-crud-max-width);
174
- margin-inline: auto;
175
- }
176
- </style>
1
+ <script lang="ts" generics="T extends object = Record<string, unknown>">
2
+ import { SvelteSet } from 'svelte/reactivity';
3
+ import Button from '../../../form/Button.svelte';
4
+ import PaginatedTable from '../../../table/PaginatedTable.svelte';
5
+ import { getIconSet } from '../../../../icons/context.js';
6
+ import { defaultIconSet } from '../../../../icons/sets/default.js';
7
+ import type {
8
+ ColumnDefinition,
9
+ CustomAction,
10
+ ReorderConfiguration,
11
+ RowAction
12
+ } from '../../../../types/crud.js';
13
+ import type {
14
+ FilterSnapshot,
15
+ ServerPagination,
16
+ SortDirection,
17
+ TableQuery
18
+ } from '../../../../types/table.js';
19
+
20
+ const icons = $derived(getIconSet() ?? defaultIconSet);
21
+
22
+ let {
23
+ data = [] as T[],
24
+ columns = [] as ColumnDefinition<T>[],
25
+ pageSize = 10,
26
+ selectable = true,
27
+ selected = $bindable(new SvelteSet<number>()),
28
+ pagination = undefined as ServerPagination | undefined,
29
+ initialSort = undefined as { column: string; direction: SortDirection } | undefined,
30
+ initialFilters = undefined as Partial<FilterSnapshot> | undefined,
31
+ onPaginationChange = undefined as ((query: TableQuery) => void) | undefined,
32
+ visibleRows = $bindable<T[]>([]),
33
+ query = $bindable<TableQuery | undefined>(undefined),
34
+ customActions = [] as CustomAction<T>[],
35
+ allowRead = true,
36
+ allowUpdate = true,
37
+ allowDelete = true,
38
+ readLabel = '',
39
+ updateLabel = '',
40
+ deleteLabel = '',
41
+ reorder = undefined as ReorderConfiguration<T> | undefined,
42
+ onView,
43
+ onEdit,
44
+ onAction,
45
+ onRequestDeletion,
46
+ onReorder
47
+ }: {
48
+ data?: T[];
49
+ columns?: ColumnDefinition<T>[];
50
+ pageSize?: number;
51
+ selectable?: boolean;
52
+ selected?: SvelteSet<number>;
53
+ pagination?: ServerPagination;
54
+ initialSort?: { column: string; direction: SortDirection };
55
+ initialFilters?: Partial<FilterSnapshot>;
56
+ onPaginationChange?: (query: TableQuery) => void;
57
+ visibleRows?: T[];
58
+ query?: TableQuery;
59
+ customActions?: CustomAction<T>[];
60
+ allowRead?: boolean;
61
+ allowUpdate?: boolean;
62
+ allowDelete?: boolean;
63
+ readLabel?: string;
64
+ updateLabel?: string;
65
+ deleteLabel?: string;
66
+ /** Drag-to-reorder configuration — see `ReorderConfiguration`. Ignored
67
+ * in server-pagination mode (`pagination` set). */
68
+ reorder?: ReorderConfiguration<T>;
69
+ onView?: (item: T) => void;
70
+ onEdit?: (item: T) => void;
71
+ onAction?: (action: CustomAction<T>, item: T) => void;
72
+ onRequestDeletion?: (item: T) => void;
73
+ /** Fires with the complete reordered row list after a drag; the caller
74
+ * (the list orchestrator) owns persisting it. */
75
+ onReorder?: (rows: T[]) => void;
76
+ } = $props();
77
+
78
+ const reorderActive = $derived(!!reorder && reorder.enabled !== false && !pagination);
79
+
80
+ const showRowActions = $derived(
81
+ allowRead || allowUpdate || allowDelete || customActions.length > 0
82
+ );
83
+
84
+ const rowActions = $derived<RowAction<T>[]>([
85
+ ...customActions.map((action) => ({
86
+ label: action.label,
87
+ icon: action.icon,
88
+ toggle: action.toggle,
89
+ class: action.class,
90
+ condition: action.condition,
91
+ run: (item: T) => onAction?.(action, item)
92
+ })),
93
+ ...(allowRead
94
+ ? [{ label: readLabel, icon: icons.view, run: (item: T) => onView?.(item) }]
95
+ : []),
96
+ ...(allowUpdate
97
+ ? [{ label: updateLabel, icon: icons.edit, run: (item: T) => onEdit?.(item) }]
98
+ : []),
99
+ ...(allowDelete
100
+ ? [
101
+ {
102
+ label: deleteLabel,
103
+ icon: icons.delete,
104
+ class: 'text-error',
105
+ run: (item: T) => onRequestDeletion?.(item)
106
+ }
107
+ ]
108
+ : [])
109
+ ]);
110
+ </script>
111
+
112
+ {#snippet actionsCell(item: T)}
113
+ <div class="flex justify-end items-center gap-1">
114
+ {#each rowActions as action (action.label)}
115
+ {#if action.condition?.(item) ?? true}
116
+ {@const resolvedClass =
117
+ typeof action.class === 'function' ? action.class(item) : action.class}
118
+ {#if action.toggle}
119
+ <input
120
+ type="checkbox"
121
+ class={['toggle toggle-sm', resolvedClass]}
122
+ title={action.label}
123
+ aria-label={action.label}
124
+ checked={action.toggle(item)}
125
+ onclick={(e) => {
126
+ e.preventDefault();
127
+ e.stopPropagation();
128
+ action.run(item);
129
+ }}
130
+ />
131
+ {:else}
132
+ {@const Icon = action.icon}
133
+ <Button
134
+ variant="ghost"
135
+ class={['btn-xs', resolvedClass]}
136
+ title={action.label}
137
+ aria-label={action.label}
138
+ onclick={(e) => {
139
+ e.stopPropagation();
140
+ action.run(item);
141
+ }}
142
+ >
143
+ <Icon class="size-4" />
144
+ </Button>
145
+ {/if}
146
+ {/if}
147
+ {/each}
148
+ </div>
149
+ {/snippet}
150
+
151
+ <div class="table-wrapper">
152
+ <PaginatedTable
153
+ {data}
154
+ {columns}
155
+ {pageSize}
156
+ {selectable}
157
+ bind:selected
158
+ rowActions={showRowActions ? actionsCell : undefined}
159
+ {pagination}
160
+ {initialSort}
161
+ {initialFilters}
162
+ {onPaginationChange}
163
+ bind:visibleRows
164
+ bind:query
165
+ reorder={reorderActive ? reorder : undefined}
166
+ {onReorder}
167
+ />
168
+ </div>
169
+
170
+ <style>
171
+ .table-wrapper {
172
+ width: 100%;
173
+ max-width: var(--runeforge-crud-max-width);
174
+ margin-inline: auto;
175
+ }
176
+ </style>