@joewinke/jatui 0.39.0 → 0.41.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 (75) hide show
  1. package/CLAUDE.md +52 -5
  2. package/THIRD_PARTY_NOTICES.md +31 -0
  3. package/dist/actions/scrollEdge.d.ts +55 -0
  4. package/dist/actions/scrollEdge.js +144 -0
  5. package/dist/artifact-blocks/blocks/diagram/DiagramBlock.svelte.d.ts +1 -1
  6. package/dist/artifact-blocks/blocks/diagram/schema.d.ts +1 -1
  7. package/dist/components/AnimatedNumber.svelte +42 -1
  8. package/dist/components/AnimatedNumber.svelte.d.ts +7 -0
  9. package/dist/components/BottomSheet.svelte +7 -6
  10. package/dist/components/BottomSheet.svelte.d.ts +2 -0
  11. package/dist/components/CloseButton.svelte +75 -0
  12. package/dist/components/CloseButton.svelte.d.ts +29 -0
  13. package/dist/components/Drawer.svelte +10 -11
  14. package/dist/components/Drawer.svelte.d.ts +2 -8
  15. package/dist/components/IconButton.svelte +200 -0
  16. package/dist/components/IconButton.svelte.d.ts +46 -0
  17. package/dist/components/LinkButton.svelte +117 -0
  18. package/dist/components/LinkButton.svelte.d.ts +32 -0
  19. package/dist/components/MediaLightbox.svelte +2 -7
  20. package/dist/components/Modal.svelte +2 -10
  21. package/dist/components/PinInput.svelte +94 -31
  22. package/dist/components/PinInput.svelte.d.ts +4 -0
  23. package/dist/components/SegmentedControl.svelte +263 -0
  24. package/dist/components/SegmentedControl.svelte.d.ts +48 -0
  25. package/dist/components/TextArea.svelte +67 -5
  26. package/dist/components/TextArea.svelte.d.ts +4 -6
  27. package/dist/components/ThemeSelector.svelte +29 -9
  28. package/dist/components/ThemeSelector.svelte.d.ts +6 -0
  29. package/dist/components/ThemeToggle.svelte +28 -3
  30. package/dist/components/ThemeToggle.svelte.d.ts +9 -0
  31. package/dist/components/basic/Breadcrumb.svelte +226 -11
  32. package/dist/components/basic/Breadcrumb.svelte.d.ts +27 -1
  33. package/dist/components/basic/breadcrumbCollapse.d.ts +19 -0
  34. package/dist/components/basic/breadcrumbCollapse.js +12 -0
  35. package/dist/components/graph/GraphCanvas.svelte.d.ts +2 -2
  36. package/dist/components/settings/SettingsRow.svelte +177 -0
  37. package/dist/components/settings/SettingsRow.svelte.d.ts +32 -0
  38. package/dist/components/settings/SettingsSection.svelte +139 -0
  39. package/dist/components/settings/SettingsSection.svelte.d.ts +21 -0
  40. package/dist/components/stats/ActivityHeatmap.svelte +412 -0
  41. package/dist/components/stats/ActivityHeatmap.svelte.d.ts +72 -0
  42. package/dist/components/stats/BarList.svelte +262 -0
  43. package/dist/components/stats/BarList.svelte.d.ts +57 -0
  44. package/dist/components/stats/ChartCard.svelte +230 -0
  45. package/dist/components/stats/ChartCard.svelte.d.ts +63 -0
  46. package/dist/components/stats/StatCard.svelte +387 -0
  47. package/dist/components/stats/StatCard.svelte.d.ts +37 -0
  48. package/dist/components/stats/StatGroup.svelte +67 -0
  49. package/dist/components/stats/StatGroup.svelte.d.ts +14 -0
  50. package/dist/components/stats/heatmap.d.ts +76 -0
  51. package/dist/components/stats/heatmap.js +151 -0
  52. package/dist/components/tree/TreeView.svelte +680 -0
  53. package/dist/components/tree/TreeView.svelte.d.ts +123 -0
  54. package/dist/components/tree/flattenTree.d.ts +57 -0
  55. package/dist/components/tree/flattenTree.js +91 -0
  56. package/dist/components/tree/treeKeys.d.ts +46 -0
  57. package/dist/components/tree/treeKeys.js +80 -0
  58. package/dist/data/grid/cells.d.ts +40 -0
  59. package/dist/data/grid/cells.js +89 -0
  60. package/dist/data/grid/clipboard.d.ts +46 -0
  61. package/dist/data/grid/clipboard.js +131 -0
  62. package/dist/data/grid/edits.d.ts +148 -0
  63. package/dist/data/grid/edits.js +222 -0
  64. package/dist/data/grid/index.d.ts +12 -0
  65. package/dist/data/grid/index.js +12 -0
  66. package/dist/index.d.ts +36 -1
  67. package/dist/index.js +31 -1
  68. package/dist/styles/tokens.css +80 -1
  69. package/dist/utils/pinInput.d.ts +33 -0
  70. package/dist/utils/pinInput.js +63 -0
  71. package/dist/utils/textareaRows.d.ts +23 -0
  72. package/dist/utils/textareaRows.js +13 -0
  73. package/dist/utils/themeWipe.d.ts +36 -17
  74. package/dist/utils/themeWipe.js +145 -35
  75. package/package.json +5 -1
@@ -0,0 +1,177 @@
1
+ <!--
2
+ SettingsRow: label + description on the start side, the control on the
3
+ end side (jatui-6kitr). Stacks when its container is narrow. The row wires
4
+ ids: pass `for` (your control's id) or let it generate one and put
5
+ `ctx.id` on your control; `ctx.descriptionId` goes on aria-describedby.
6
+
7
+ <SettingsRow label="Email digests" description="One summary a day">
8
+ {#snippet control(ctx)}
9
+ <Switch id={ctx.id} aria-describedby={ctx.descriptionId} bind:checked />
10
+ {/snippet}
11
+ </SettingsRow>
12
+ -->
13
+ <script lang="ts" module>
14
+ export interface SettingsRowContext {
15
+ /** Id to put on the control (the label points at it). */
16
+ id: string;
17
+ labelId: string;
18
+ /** Undefined when there is no description. */
19
+ descriptionId: string | undefined;
20
+ }
21
+ </script>
22
+
23
+ <script lang="ts">
24
+ import type { Snippet } from 'svelte';
25
+
26
+ interface Props {
27
+ label: string;
28
+ description?: string;
29
+ /** Id of the control the label is for. Default: generated, passed as `ctx.id`. */
30
+ for?: string;
31
+ /** 'inline' (default) puts the control beside the text; 'stacked' always below. */
32
+ layout?: 'inline' | 'stacked';
33
+ /** Unsaved-change dot. */
34
+ dirty?: boolean;
35
+ disabled?: boolean;
36
+ /** Validation / warning text under the description. */
37
+ error?: string;
38
+ /** Anchor id for deep links. */
39
+ id?: string;
40
+ control?: Snippet<[SettingsRowContext]>;
41
+ /** Extra content under the row (an expanded sub-form). */
42
+ children?: Snippet;
43
+ /** Custom label content (badge, icon). It becomes the accessible name, so include the text. */
44
+ labelContent?: Snippet;
45
+ class?: string;
46
+ }
47
+
48
+ let {
49
+ label,
50
+ description,
51
+ for: forId,
52
+ layout = 'inline',
53
+ dirty = false,
54
+ disabled = false,
55
+ error,
56
+ id,
57
+ control,
58
+ children,
59
+ labelContent,
60
+ class: className = ''
61
+ }: Props = $props();
62
+
63
+ const uid = $props.id();
64
+ const ctx = $derived<SettingsRowContext>({
65
+ id: forId ?? `${uid}-control`,
66
+ labelId: `${uid}-label`,
67
+ descriptionId: description || error ? `${uid}-desc` : undefined
68
+ });
69
+ </script>
70
+
71
+ <div
72
+ {id}
73
+ class="jatui-settings-row srow-{layout} {className}"
74
+ class:is-disabled={disabled}
75
+ class:has-error={!!error}
76
+ >
77
+ <div class="srow-main">
78
+ <div class="srow-text">
79
+ <label class="srow-label" id={ctx.labelId} for={ctx.id}>
80
+ {#if labelContent}{@render labelContent()}{:else}{label}{/if}
81
+ {#if dirty}
82
+ <span class="srow-dirty" aria-hidden="true"></span><span class="sr-only">(unsaved)</span>
83
+ {/if}
84
+ </label>
85
+ {#if description || error}
86
+ <p class="srow-desc" id={ctx.descriptionId}>
87
+ {#if description}<span>{description}</span>{/if}
88
+ {#if error}<span class="srow-error" role="alert">{error}</span>{/if}
89
+ </p>
90
+ {/if}
91
+ </div>
92
+ {#if control}
93
+ <div class="srow-control">{@render control(ctx)}</div>
94
+ {/if}
95
+ </div>
96
+ {#if children}
97
+ <div class="srow-extra">{@render children()}</div>
98
+ {/if}
99
+ </div>
100
+
101
+ <style>
102
+ .jatui-settings-row {
103
+ display: flex;
104
+ flex-direction: column;
105
+ gap: var(--jatui-space-base, 8px);
106
+ min-height: 3.25rem;
107
+ padding-block: var(--jatui-space-lg, 12px);
108
+ justify-content: center;
109
+ }
110
+ .srow-main {
111
+ display: flex;
112
+ align-items: center;
113
+ justify-content: space-between;
114
+ gap: var(--jatui-space-xl, 16px);
115
+ }
116
+ .srow-stacked .srow-main {
117
+ flex-direction: column;
118
+ align-items: stretch;
119
+ gap: var(--jatui-space-base, 8px);
120
+ }
121
+ @container (max-width: 28rem) {
122
+ .srow-main {
123
+ flex-direction: column;
124
+ align-items: stretch;
125
+ gap: var(--jatui-space-base, 8px);
126
+ }
127
+ }
128
+ .srow-text {
129
+ display: flex;
130
+ flex-direction: column;
131
+ gap: 2px;
132
+ min-width: 0;
133
+ flex: 1 1 auto;
134
+ }
135
+ .srow-label {
136
+ display: inline-flex;
137
+ align-items: center;
138
+ gap: var(--jatui-space-md, 6px);
139
+ font-size: 0.875rem;
140
+ font-weight: 500;
141
+ color: var(--color-base-content);
142
+ }
143
+ .srow-dirty {
144
+ width: 0.4375rem;
145
+ height: 0.4375rem;
146
+ border-radius: 9999px;
147
+ background: var(--color-warning);
148
+ }
149
+ .srow-desc {
150
+ display: flex;
151
+ flex-direction: column;
152
+ gap: 2px;
153
+ margin: 0;
154
+ font-size: 0.8125rem;
155
+ color: color-mix(in oklch, var(--color-base-content) 60%, transparent);
156
+ }
157
+ .srow-error {
158
+ color: var(--color-error);
159
+ }
160
+ .srow-control {
161
+ display: flex;
162
+ align-items: center;
163
+ justify-content: flex-end;
164
+ gap: var(--jatui-space-base, 8px);
165
+ flex: none;
166
+ max-width: 100%;
167
+ }
168
+ .srow-stacked .srow-control {
169
+ justify-content: flex-start;
170
+ }
171
+ .is-disabled .srow-text {
172
+ opacity: 0.55;
173
+ }
174
+ .srow-extra {
175
+ min-width: 0;
176
+ }
177
+ </style>
@@ -0,0 +1,32 @@
1
+ export interface SettingsRowContext {
2
+ /** Id to put on the control (the label points at it). */
3
+ id: string;
4
+ labelId: string;
5
+ /** Undefined when there is no description. */
6
+ descriptionId: string | undefined;
7
+ }
8
+ import type { Snippet } from 'svelte';
9
+ interface Props {
10
+ label: string;
11
+ description?: string;
12
+ /** Id of the control the label is for. Default: generated, passed as `ctx.id`. */
13
+ for?: string;
14
+ /** 'inline' (default) puts the control beside the text; 'stacked' always below. */
15
+ layout?: 'inline' | 'stacked';
16
+ /** Unsaved-change dot. */
17
+ dirty?: boolean;
18
+ disabled?: boolean;
19
+ /** Validation / warning text under the description. */
20
+ error?: string;
21
+ /** Anchor id for deep links. */
22
+ id?: string;
23
+ control?: Snippet<[SettingsRowContext]>;
24
+ /** Extra content under the row (an expanded sub-form). */
25
+ children?: Snippet;
26
+ /** Custom label content (badge, icon). It becomes the accessible name, so include the text. */
27
+ labelContent?: Snippet;
28
+ class?: string;
29
+ }
30
+ declare const SettingsRow: import("svelte").Component<Props, {}, "">;
31
+ type SettingsRow = ReturnType<typeof SettingsRow>;
32
+ export default SettingsRow;
@@ -0,0 +1,139 @@
1
+ <!--
2
+ SettingsSection: a titled group of SettingsRows (jatui-6kitr). Rows inside
3
+ get hairline dividers. Give it an `id` + use it with SectionNav for long
4
+ settings pages; `dirty` shows the same amber dot SectionNav uses.
5
+ Row recipe after BoardUI's settings rows (MIT, © 2026 Mertcan Dundar
6
+ Esmergul); the modal shell was intentionally not taken.
7
+ -->
8
+ <script lang="ts">
9
+ import type { Snippet } from 'svelte';
10
+
11
+ interface Props {
12
+ title?: string;
13
+ description?: string;
14
+ /** Anchor id (SectionNav target). */
15
+ id?: string;
16
+ /** 'card' (default) frames the rows; 'plain' is flush. */
17
+ variant?: 'card' | 'plain';
18
+ headingLevel?: 2 | 3 | 4;
19
+ /** Unsaved-changes dot beside the title. */
20
+ dirty?: boolean;
21
+ /** Header controls (Reset, Save…). */
22
+ actions?: Snippet;
23
+ /** Footer under the rows (save bar, help link). */
24
+ footer?: Snippet;
25
+ children: Snippet;
26
+ class?: string;
27
+ }
28
+
29
+ let {
30
+ title,
31
+ description,
32
+ id,
33
+ variant = 'card',
34
+ headingLevel = 2,
35
+ dirty = false,
36
+ actions,
37
+ footer,
38
+ children,
39
+ class: className = ''
40
+ }: Props = $props();
41
+
42
+ const uid = $props.id();
43
+ </script>
44
+
45
+ <section
46
+ {id}
47
+ class="jatui-settings-section ss-{variant} {className}"
48
+ aria-labelledby={title ? `${uid}-title` : undefined}
49
+ aria-describedby={description ? `${uid}-desc` : undefined}
50
+ >
51
+ {#if title || description || actions}
52
+ <header class="ss-head">
53
+ <div class="ss-titles">
54
+ {#if title}
55
+ <svelte:element this={`h${headingLevel}`} class="ss-title" id="{uid}-title">
56
+ {title}
57
+ {#if dirty}
58
+ <span class="ss-dirty" aria-hidden="true"></span><span class="sr-only">(unsaved changes)</span>
59
+ {/if}
60
+ </svelte:element>
61
+ {/if}
62
+ {#if description}<p class="ss-desc" id="{uid}-desc">{description}</p>{/if}
63
+ </div>
64
+ {#if actions}<div class="ss-actions">{@render actions()}</div>{/if}
65
+ </header>
66
+ {/if}
67
+ <div class="ss-rows">
68
+ {@render children()}
69
+ </div>
70
+ {#if footer}<div class="ss-footer">{@render footer()}</div>{/if}
71
+ </section>
72
+
73
+ <style>
74
+ .jatui-settings-section {
75
+ display: flex;
76
+ flex-direction: column;
77
+ gap: var(--jatui-space-base, 8px);
78
+ min-width: 0;
79
+ scroll-margin-top: var(--jatui-space-xl, 16px);
80
+ }
81
+ .ss-head {
82
+ display: flex;
83
+ align-items: flex-end;
84
+ justify-content: space-between;
85
+ gap: var(--jatui-space-lg, 12px);
86
+ padding: 0 var(--jatui-space-xs, 2px);
87
+ }
88
+ .ss-titles {
89
+ min-width: 0;
90
+ }
91
+ .ss-title {
92
+ display: inline-flex;
93
+ align-items: center;
94
+ gap: var(--jatui-space-md, 6px);
95
+ margin: 0;
96
+ font-size: 0.9375rem;
97
+ font-weight: 600;
98
+ color: var(--color-base-content);
99
+ }
100
+ .ss-dirty {
101
+ width: 0.5rem;
102
+ height: 0.5rem;
103
+ border-radius: 9999px;
104
+ background: var(--color-warning);
105
+ }
106
+ .ss-desc {
107
+ margin: 2px 0 0;
108
+ font-size: 0.8125rem;
109
+ color: color-mix(in oklch, var(--color-base-content) 60%, transparent);
110
+ }
111
+ .ss-actions {
112
+ display: flex;
113
+ align-items: center;
114
+ gap: var(--jatui-space-base, 8px);
115
+ flex: none;
116
+ }
117
+ .ss-rows {
118
+ display: flex;
119
+ flex-direction: column;
120
+ container-type: inline-size;
121
+ }
122
+ .ss-card .ss-rows {
123
+ border: var(--jatui-border-w, 1px) solid color-mix(in oklch, var(--color-base-content) 10%, transparent);
124
+ border-radius: var(--jatui-radius-box, 0.5rem);
125
+ background: var(--color-base-100);
126
+ }
127
+ /* Hairline between rows. */
128
+ .ss-rows > :global(.jatui-settings-row + .jatui-settings-row) {
129
+ border-top: var(--jatui-border-w, 1px) solid color-mix(in oklch, var(--color-base-content) 8%, transparent);
130
+ }
131
+ .ss-card .ss-rows > :global(.jatui-settings-row) {
132
+ padding-inline: var(--jatui-space-xl, 16px);
133
+ }
134
+ .ss-footer {
135
+ display: flex;
136
+ justify-content: flex-end;
137
+ gap: var(--jatui-space-base, 8px);
138
+ }
139
+ </style>
@@ -0,0 +1,21 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ title?: string;
4
+ description?: string;
5
+ /** Anchor id (SectionNav target). */
6
+ id?: string;
7
+ /** 'card' (default) frames the rows; 'plain' is flush. */
8
+ variant?: 'card' | 'plain';
9
+ headingLevel?: 2 | 3 | 4;
10
+ /** Unsaved-changes dot beside the title. */
11
+ dirty?: boolean;
12
+ /** Header controls (Reset, Save…). */
13
+ actions?: Snippet;
14
+ /** Footer under the rows (save bar, help link). */
15
+ footer?: Snippet;
16
+ children: Snippet;
17
+ class?: string;
18
+ }
19
+ declare const SettingsSection: import("svelte").Component<Props, {}, "">;
20
+ type SettingsSection = ReturnType<typeof SettingsSection>;
21
+ export default SettingsSection;