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,62 +1,62 @@
1
- <script lang="ts">
2
- import type { SelectOption } from '../../types/attribute.js';
3
- import { buildChildrenByParent, collectDescendantIds } from '../crud/utils/tree.js';
4
- import TreeNode from './TreeNode.svelte';
5
-
6
- let {
7
- name,
8
- value = $bindable([]),
9
- options = [],
10
- disabled = false,
11
- columns = 1,
12
- defaultExpanded = true,
13
- }: {
14
- name?: string;
15
- value?: string[];
16
- options?: SelectOption[];
17
- disabled?: boolean;
18
- columns?: number;
19
- defaultExpanded?: boolean;
20
- } = $props();
21
-
22
- const childrenByParent = $derived(buildChildrenByParent(options));
23
- const selected = $derived(new Set(value));
24
- const roots = $derived(childrenByParent.get(null) ?? []);
25
-
26
- function toggle(nodeValue: string, checked: boolean) {
27
- const affected = [nodeValue, ...collectDescendantIds(nodeValue, childrenByParent)];
28
- if (checked) {
29
- value = [...new Set([...value, ...affected])];
30
- } else {
31
- const affectedSet = new Set(affected);
32
- value = value.filter((v) => !affectedSet.has(v));
33
- }
34
- }
35
- </script>
36
-
37
- <div
38
- class="overflow-y-auto rounded-box border border-base-300 p-2"
39
- style="max-height: var(--runeforge-tree-max-height, 24rem)"
40
- class:opacity-50={disabled}
41
- class:pointer-events-none={disabled}
42
- >
43
- {#if name}
44
- <input type="hidden" {name} value={JSON.stringify(value)} />
45
- {/if}
46
- {#if roots.length === 0}
47
- <p class="px-1 py-2 text-sm text-base-content/40">—</p>
48
- {/if}
49
- <div class:leaf-columns={columns > 1} style={`--columns: ${columns}`}>
50
- {#each roots as root (root.value)}
51
- <TreeNode node={root} {childrenByParent} {selected} onToggle={toggle} {disabled} depth={0} {columns} {defaultExpanded} />
52
- {/each}
53
- </div>
54
- </div>
55
-
56
- <style>
57
- @media (min-width: 1024px) {
58
- .leaf-columns {
59
- columns: var(--columns);
60
- }
61
- }
62
- </style>
1
+ <script lang="ts">
2
+ import type { SelectOption } from '../../types/attribute.js';
3
+ import { buildChildrenByParent, collectDescendantIds } from '../crud/utils/tree.js';
4
+ import TreeNode from './TreeNode.svelte';
5
+
6
+ let {
7
+ name,
8
+ value = $bindable([]),
9
+ options = [],
10
+ disabled = false,
11
+ columns = 1,
12
+ defaultExpanded = true,
13
+ }: {
14
+ name?: string;
15
+ value?: string[];
16
+ options?: SelectOption[];
17
+ disabled?: boolean;
18
+ columns?: number;
19
+ defaultExpanded?: boolean;
20
+ } = $props();
21
+
22
+ const childrenByParent = $derived(buildChildrenByParent(options));
23
+ const selected = $derived(new Set(value));
24
+ const roots = $derived(childrenByParent.get(null) ?? []);
25
+
26
+ function toggle(nodeValue: string, checked: boolean) {
27
+ const affected = [nodeValue, ...collectDescendantIds(nodeValue, childrenByParent)];
28
+ if (checked) {
29
+ value = [...new Set([...value, ...affected])];
30
+ } else {
31
+ const affectedSet = new Set(affected);
32
+ value = value.filter((v) => !affectedSet.has(v));
33
+ }
34
+ }
35
+ </script>
36
+
37
+ <div
38
+ class="overflow-y-auto rounded-box border border-base-300 p-2"
39
+ style="max-height: var(--runeforge-tree-max-height, 24rem)"
40
+ class:opacity-50={disabled}
41
+ class:pointer-events-none={disabled}
42
+ >
43
+ {#if name}
44
+ <input type="hidden" {name} value={JSON.stringify(value)} />
45
+ {/if}
46
+ {#if roots.length === 0}
47
+ <p class="px-1 py-2 text-sm text-base-content/40">—</p>
48
+ {/if}
49
+ <div class:leaf-columns={columns > 1} style={`--columns: ${columns}`}>
50
+ {#each roots as root (root.value)}
51
+ <TreeNode node={root} {childrenByParent} {selected} onToggle={toggle} {disabled} depth={0} {columns} {defaultExpanded} />
52
+ {/each}
53
+ </div>
54
+ </div>
55
+
56
+ <style>
57
+ @media (min-width: 1024px) {
58
+ .leaf-columns {
59
+ columns: var(--columns);
60
+ }
61
+ }
62
+ </style>
@@ -1,66 +1,66 @@
1
- <script lang="ts">
2
- import type { SelectOption } from '../../types/attribute.js';
3
- import TreeNode from './TreeNode.svelte';
4
-
5
- let {
6
- node,
7
- childrenByParent,
8
- selected,
9
- onToggle,
10
- disabled,
11
- depth,
12
- columns,
13
- defaultExpanded,
14
- }: {
15
- node: SelectOption;
16
- childrenByParent: Map<string | null, SelectOption[]>;
17
- selected: Set<string>;
18
- onToggle: (value: string, checked: boolean) => void;
19
- disabled: boolean;
20
- depth: number;
21
- columns: number;
22
- defaultExpanded: boolean;
23
- } = $props();
24
-
25
- let expanded = $state(defaultExpanded);
26
-
27
- const children = $derived(childrenByParent.get(node.value) ?? []);
28
- const hasChildren = $derived(children.length > 0);
29
- </script>
30
-
31
- <div class="flex flex-col" style={`--columns: ${columns}`}>
32
- <div
33
- class="flex w-full items-center gap-1 rounded py-1 pr-2 transition-colors hover:bg-base-200"
34
- style={`padding-left: ${depth * 1.25}rem`}
35
- >
36
- {#if hasChildren}
37
- <button
38
- type="button"
39
- class="btn btn-ghost btn-xs btn-circle"
40
- aria-label={expanded ? 'Collapse' : 'Expand'}
41
- onclick={() => (expanded = !expanded)}
42
- >
43
- <span class="inline-block text-xs transition-transform" class:rotate-90={expanded}>▸</span>
44
- </button>
45
- {:else}
46
- <span class="inline-block size-6"></span>
47
- {/if}
48
-
49
- <input
50
- type="checkbox"
51
- class="checkbox checkbox-sm"
52
- checked={selected.has(node.value)}
53
- {disabled}
54
- onchange={(e) => onToggle(node.value, (e.currentTarget as HTMLInputElement).checked)}
55
- aria-label={node.label}
56
- />
57
-
58
- <span>{node.label}</span>
59
- </div>
60
-
61
- {#if expanded && hasChildren}
62
- {#each children as child (child.value)}
63
- <TreeNode node={child} {childrenByParent} {selected} {onToggle} {disabled} depth={depth + 1} {columns} {defaultExpanded} />
64
- {/each}
65
- {/if}
66
- </div>
1
+ <script lang="ts">
2
+ import type { SelectOption } from '../../types/attribute.js';
3
+ import TreeNode from './TreeNode.svelte';
4
+
5
+ let {
6
+ node,
7
+ childrenByParent,
8
+ selected,
9
+ onToggle,
10
+ disabled,
11
+ depth,
12
+ columns,
13
+ defaultExpanded,
14
+ }: {
15
+ node: SelectOption;
16
+ childrenByParent: Map<string | null, SelectOption[]>;
17
+ selected: Set<string>;
18
+ onToggle: (value: string, checked: boolean) => void;
19
+ disabled: boolean;
20
+ depth: number;
21
+ columns: number;
22
+ defaultExpanded: boolean;
23
+ } = $props();
24
+
25
+ let expanded = $state(defaultExpanded);
26
+
27
+ const children = $derived(childrenByParent.get(node.value) ?? []);
28
+ const hasChildren = $derived(children.length > 0);
29
+ </script>
30
+
31
+ <div class="flex flex-col" style={`--columns: ${columns}`}>
32
+ <div
33
+ class="flex w-full items-center gap-1 rounded py-1 pr-2 transition-colors hover:bg-base-200"
34
+ style={`padding-left: ${depth * 1.25}rem`}
35
+ >
36
+ {#if hasChildren}
37
+ <button
38
+ type="button"
39
+ class="btn btn-ghost btn-xs btn-circle"
40
+ aria-label={expanded ? 'Collapse' : 'Expand'}
41
+ onclick={() => (expanded = !expanded)}
42
+ >
43
+ <span class="inline-block text-xs transition-transform" class:rotate-90={expanded}>▸</span>
44
+ </button>
45
+ {:else}
46
+ <span class="inline-block size-6"></span>
47
+ {/if}
48
+
49
+ <input
50
+ type="checkbox"
51
+ class="checkbox checkbox-sm"
52
+ checked={selected.has(node.value)}
53
+ {disabled}
54
+ onchange={(e) => onToggle(node.value, (e.currentTarget as HTMLInputElement).checked)}
55
+ aria-label={node.label}
56
+ />
57
+
58
+ <span>{node.label}</span>
59
+ </div>
60
+
61
+ {#if expanded && hasChildren}
62
+ {#each children as child (child.value)}
63
+ <TreeNode node={child} {childrenByParent} {selected} {onToggle} {disabled} depth={depth + 1} {columns} {defaultExpanded} />
64
+ {/each}
65
+ {/if}
66
+ </div>
@@ -1,111 +1,111 @@
1
- <script lang="ts">
2
- import { getIconSet } from '../../icons/context.js';
3
- import { defaultIconSet } from '../../icons/sets/default.js';
4
- import { getConfig } from '../../config/context.js';
5
- import type { BreadcrumbItem } from '../../types/breadcrumb.js';
6
-
7
- let {
8
- items = [],
9
- homeHref,
10
- }: {
11
- items?: BreadcrumbItem[];
12
- homeHref?: string;
13
- } = $props();
14
-
15
- const icons = $derived(getIconSet() ?? defaultIconSet);
16
-
17
- const home: BreadcrumbItem = $derived({
18
- label: 'Inicio',
19
- icon: icons.home,
20
- link: { href: homeHref ?? getConfig().homeHref ?? '/' },
21
- });
22
-
23
- const allItems = $derived([home, ...items]);
24
- </script>
25
-
26
- <div class="breadcrumbs">
27
- <ul>
28
- {#each allItems as item, i (i)}
29
- <li>
30
- {#if item.link !== undefined}
31
- <a class="inline-flex items-center gap-2" {...item.link}>
32
- {#if item.icon}
33
- {@const ItemIcon = item.icon}
34
- <ItemIcon />
35
- {/if}
36
- <span>{item.label}</span>
37
- </a>
38
- {:else}
39
- <span class="inline-flex items-center gap-2">
40
- {#if item.icon}
41
- {@const ItemIcon = item.icon}
42
- <ItemIcon />
43
- {/if}
44
- <span>{item.label}</span>
45
- </span>
46
- {/if}
47
- </li>
48
- {/each}
49
- </ul>
50
- </div>
51
-
52
- <style>
53
- div {
54
- font-size: var(--runeforge-breadcrumb-font-size, 0.875rem);
55
- }
56
-
57
- :global(.breadcrumbs svg) {
58
- width: var(--runeforge-breadcrumb-icon-size, 1rem);
59
- height: var(--runeforge-breadcrumb-icon-size, 1rem);
60
- flex-shrink: 0;
61
- }
62
-
63
- /*
64
- * DaisyUI breadcrumbs use @layer rules that Tailwind v4 doesn't propagate
65
- * from node_modules. These unlayered rules override that gap.
66
- */
67
- :global(.breadcrumbs > ul),
68
- :global(.breadcrumbs > ol),
69
- :global(.breadcrumbs > menu) {
70
- display: flex;
71
- align-items: center;
72
- white-space: nowrap;
73
- overflow-x: auto;
74
- }
75
-
76
- :global(.breadcrumbs > ul > li),
77
- :global(.breadcrumbs > ol > li),
78
- :global(.breadcrumbs > menu > li) {
79
- display: flex;
80
- align-items: center;
81
- }
82
-
83
- :global(.breadcrumbs > ul > li + li::before),
84
- :global(.breadcrumbs > ol > li + li::before),
85
- :global(.breadcrumbs > menu > li + li::before) {
86
- content: '';
87
- display: block;
88
- opacity: 0.4;
89
- border-top: 1px solid;
90
- border-right: 1px solid;
91
- width: 0.375rem;
92
- height: 0.375rem;
93
- margin-inline: 0.5rem 0.75rem;
94
- rotate: 45deg;
95
- }
96
-
97
- /*
98
- * Tailwind preflight sets svg { display: block }, which stacks icons above
99
- * labels when the <a>/<span> inline-flex class isn't generated from node_modules.
100
- */
101
- :global(.breadcrumbs > ul > li > a),
102
- :global(.breadcrumbs > ul > li > span),
103
- :global(.breadcrumbs > ol > li > a),
104
- :global(.breadcrumbs > ol > li > span),
105
- :global(.breadcrumbs > menu > li > a),
106
- :global(.breadcrumbs > menu > li > span) {
107
- display: inline-flex;
108
- align-items: center;
109
- gap: 0.5rem;
110
- }
111
- </style>
1
+ <script lang="ts">
2
+ import { getIconSet } from '../../icons/context.js';
3
+ import { defaultIconSet } from '../../icons/sets/default.js';
4
+ import { getConfig } from '../../config/context.js';
5
+ import type { BreadcrumbItem } from '../../types/breadcrumb.js';
6
+
7
+ let {
8
+ items = [],
9
+ homeHref,
10
+ }: {
11
+ items?: BreadcrumbItem[];
12
+ homeHref?: string;
13
+ } = $props();
14
+
15
+ const icons = $derived(getIconSet() ?? defaultIconSet);
16
+
17
+ const home: BreadcrumbItem = $derived({
18
+ label: 'Inicio',
19
+ icon: icons.home,
20
+ link: { href: homeHref ?? getConfig().homeHref ?? '/' },
21
+ });
22
+
23
+ const allItems = $derived([home, ...items]);
24
+ </script>
25
+
26
+ <div class="breadcrumbs">
27
+ <ul>
28
+ {#each allItems as item, i (i)}
29
+ <li>
30
+ {#if item.link !== undefined}
31
+ <a class="inline-flex items-center gap-2" {...item.link}>
32
+ {#if item.icon}
33
+ {@const ItemIcon = item.icon}
34
+ <ItemIcon />
35
+ {/if}
36
+ <span>{item.label}</span>
37
+ </a>
38
+ {:else}
39
+ <span class="inline-flex items-center gap-2">
40
+ {#if item.icon}
41
+ {@const ItemIcon = item.icon}
42
+ <ItemIcon />
43
+ {/if}
44
+ <span>{item.label}</span>
45
+ </span>
46
+ {/if}
47
+ </li>
48
+ {/each}
49
+ </ul>
50
+ </div>
51
+
52
+ <style>
53
+ div {
54
+ font-size: var(--runeforge-breadcrumb-font-size, 0.875rem);
55
+ }
56
+
57
+ :global(.breadcrumbs svg) {
58
+ width: var(--runeforge-breadcrumb-icon-size, 1rem);
59
+ height: var(--runeforge-breadcrumb-icon-size, 1rem);
60
+ flex-shrink: 0;
61
+ }
62
+
63
+ /*
64
+ * DaisyUI breadcrumbs use @layer rules that Tailwind v4 doesn't propagate
65
+ * from node_modules. These unlayered rules override that gap.
66
+ */
67
+ :global(.breadcrumbs > ul),
68
+ :global(.breadcrumbs > ol),
69
+ :global(.breadcrumbs > menu) {
70
+ display: flex;
71
+ align-items: center;
72
+ white-space: nowrap;
73
+ overflow-x: auto;
74
+ }
75
+
76
+ :global(.breadcrumbs > ul > li),
77
+ :global(.breadcrumbs > ol > li),
78
+ :global(.breadcrumbs > menu > li) {
79
+ display: flex;
80
+ align-items: center;
81
+ }
82
+
83
+ :global(.breadcrumbs > ul > li + li::before),
84
+ :global(.breadcrumbs > ol > li + li::before),
85
+ :global(.breadcrumbs > menu > li + li::before) {
86
+ content: '';
87
+ display: block;
88
+ opacity: 0.4;
89
+ border-top: 1px solid;
90
+ border-right: 1px solid;
91
+ width: 0.375rem;
92
+ height: 0.375rem;
93
+ margin-inline: 0.5rem 0.75rem;
94
+ rotate: 45deg;
95
+ }
96
+
97
+ /*
98
+ * Tailwind preflight sets svg { display: block }, which stacks icons above
99
+ * labels when the <a>/<span> inline-flex class isn't generated from node_modules.
100
+ */
101
+ :global(.breadcrumbs > ul > li > a),
102
+ :global(.breadcrumbs > ul > li > span),
103
+ :global(.breadcrumbs > ol > li > a),
104
+ :global(.breadcrumbs > ol > li > span),
105
+ :global(.breadcrumbs > menu > li > a),
106
+ :global(.breadcrumbs > menu > li > span) {
107
+ display: inline-flex;
108
+ align-items: center;
109
+ gap: 0.5rem;
110
+ }
111
+ </style>