runeforge 0.0.55 → 0.0.57

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 (61) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1355 -1342
  3. package/dist/components/Avatar.svelte +31 -31
  4. package/dist/components/IconRenderer.svelte +73 -22
  5. package/dist/components/IconRenderer.svelte.d.ts +2 -0
  6. package/dist/components/Modal.svelte +75 -75
  7. package/dist/components/common/Header.svelte +40 -40
  8. package/dist/components/crud/EmbeddedField.svelte +175 -175
  9. package/dist/components/crud/Field.svelte +469 -376
  10. package/dist/components/crud/GenericCRUD.svelte +426 -426
  11. package/dist/components/crud/SearchInput.svelte +53 -53
  12. package/dist/components/crud/columns/Avatar.svelte +15 -15
  13. package/dist/components/crud/columns/Icon.svelte +8 -8
  14. package/dist/components/crud/views/Create.svelte +232 -232
  15. package/dist/components/crud/views/Read.svelte +124 -124
  16. package/dist/components/crud/views/Update.svelte +208 -208
  17. package/dist/components/crud/views/list/List.svelte +291 -291
  18. package/dist/components/crud/views/list/Modals.svelte +56 -56
  19. package/dist/components/crud/views/list/Table.svelte +176 -176
  20. package/dist/components/crud/views/list/Toolbar.svelte +341 -341
  21. package/dist/components/form/Button.svelte +27 -27
  22. package/dist/components/form/Label.svelte +37 -37
  23. package/dist/components/form/MultiSelect.svelte +248 -248
  24. package/dist/components/form/PasswordInput.svelte +68 -68
  25. package/dist/components/form/Required.svelte +1 -1
  26. package/dist/components/form/Select.svelte +209 -209
  27. package/dist/components/form/Tree.svelte +62 -62
  28. package/dist/components/form/TreeNode.svelte +66 -66
  29. package/dist/components/navigation/Breadcrumbs.svelte +111 -111
  30. package/dist/components/table/ColumnFilter.svelte +168 -168
  31. package/dist/components/table/PaginatedTable.svelte +536 -536
  32. package/dist/components/table/Paginator.svelte +113 -113
  33. package/dist/components/table/SortHeader.svelte +43 -43
  34. package/dist/components/table/TableBody.svelte +150 -150
  35. package/dist/components/table/TableHeader.svelte +88 -88
  36. package/dist/i18n/en.js +1 -0
  37. package/dist/i18n/es.js +1 -0
  38. package/dist/i18n/types.d.ts +1 -0
  39. package/dist/icons/context.d.ts +5 -0
  40. package/dist/icons/context.js +10 -0
  41. package/dist/icons/defaults/Clear.svelte +6 -6
  42. package/dist/icons/defaults/Create.svelte +6 -6
  43. package/dist/icons/defaults/Delete.svelte +6 -6
  44. package/dist/icons/defaults/Download.svelte +7 -7
  45. package/dist/icons/defaults/Edit.svelte +7 -7
  46. package/dist/icons/defaults/Filter.svelte +6 -6
  47. package/dist/icons/defaults/FilterActive.svelte +6 -6
  48. package/dist/icons/defaults/Folder.svelte +6 -6
  49. package/dist/icons/defaults/Grip.svelte +7 -7
  50. package/dist/icons/defaults/Home.svelte +6 -6
  51. package/dist/icons/defaults/PasswordHide.svelte +9 -9
  52. package/dist/icons/defaults/PasswordShow.svelte +7 -7
  53. package/dist/icons/defaults/SortAsc.svelte +6 -6
  54. package/dist/icons/defaults/SortDesc.svelte +6 -6
  55. package/dist/icons/defaults/SortNone.svelte +6 -6
  56. package/dist/icons/defaults/View.svelte +7 -7
  57. package/dist/icons/sets/bootstrap.js +1 -4
  58. package/dist/icons/types.d.ts +0 -1
  59. package/dist/index.d.ts +1 -1
  60. package/dist/index.js +1 -1
  61. 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>