@spaethtech/svelte-ui 0.1.10 → 0.3.1-dev.10.ff03a8d

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 (218) hide show
  1. package/.claude/skills/svelte-ui/SKILL.md +118 -0
  2. package/.claude/skills/themes/SKILL.md +303 -0
  3. package/CLAUDE.md +248 -0
  4. package/README.md +180 -42
  5. package/dist/components/Alert.svelte +119 -0
  6. package/dist/components/Alert.svelte.d.ts +29 -0
  7. package/dist/components/Badge/Badge.svelte +142 -69
  8. package/dist/components/Badge/Badge.svelte.d.ts +26 -6
  9. package/dist/components/Badge/index.d.ts +1 -1
  10. package/dist/components/Badge/index.js +1 -1
  11. package/dist/components/Banner.svelte +133 -0
  12. package/dist/components/Banner.svelte.d.ts +31 -0
  13. package/dist/components/Button.svelte +240 -0
  14. package/dist/components/Button.svelte.d.ts +33 -0
  15. package/dist/components/ButtonDropdown.svelte +145 -0
  16. package/dist/components/ButtonDropdown.svelte.d.ts +31 -0
  17. package/dist/components/Calendar.svelte +259 -0
  18. package/dist/components/Calendar.svelte.d.ts +27 -0
  19. package/dist/components/Card.svelte +79 -0
  20. package/dist/components/Card.svelte.d.ts +17 -0
  21. package/dist/components/CardBody.svelte +41 -0
  22. package/dist/components/CardBody.svelte.d.ts +17 -0
  23. package/dist/components/CardFooter.svelte +51 -0
  24. package/dist/components/CardFooter.svelte.d.ts +16 -0
  25. package/dist/components/CardHeader.svelte +51 -0
  26. package/dist/components/CardHeader.svelte.d.ts +16 -0
  27. package/dist/components/Checkbox.svelte +131 -0
  28. package/dist/components/Checkbox.svelte.d.ts +16 -0
  29. package/dist/components/ConfirmDialog.svelte +103 -0
  30. package/dist/components/ConfirmDialog.svelte.d.ts +33 -0
  31. package/dist/components/DataTable.svelte +518 -0
  32. package/dist/components/DataTable.svelte.d.ts +74 -0
  33. package/dist/components/DatePicker.svelte +312 -0
  34. package/dist/components/DatePicker.svelte.d.ts +32 -0
  35. package/dist/components/DateTimeInput.svelte +93 -0
  36. package/dist/components/DateTimeInput.svelte.d.ts +20 -0
  37. package/dist/components/Dialog.svelte +151 -0
  38. package/dist/components/Dialog.svelte.d.ts +30 -0
  39. package/dist/components/{EmailInput/EmailInput.svelte → EmailInput.svelte} +17 -8
  40. package/dist/components/EmailInput.svelte.d.ts +21 -0
  41. package/dist/components/Input.svelte +369 -0
  42. package/dist/components/Input.svelte.d.ts +35 -0
  43. package/dist/components/{List/List.svelte → List.svelte} +194 -133
  44. package/dist/components/{List/List.svelte.d.ts → List.svelte.d.ts} +9 -1
  45. package/dist/components/Menu.svelte +117 -0
  46. package/dist/components/Menu.svelte.d.ts +20 -0
  47. package/dist/components/NotesEditor.svelte +127 -0
  48. package/dist/components/NotesEditor.svelte.d.ts +17 -0
  49. package/dist/components/{NumberInput/NumberInput.svelte → NumberInput.svelte} +146 -105
  50. package/dist/components/{NumberInput/NumberInput.svelte.d.ts → NumberInput.svelte.d.ts} +11 -4
  51. package/dist/components/PasswordInput.svelte +52 -0
  52. package/dist/components/PasswordInput.svelte.d.ts +20 -0
  53. package/dist/components/Popup.svelte +140 -0
  54. package/dist/components/Popup.svelte.d.ts +31 -0
  55. package/dist/components/Query.svelte +284 -0
  56. package/dist/components/Query.svelte.d.ts +15 -0
  57. package/dist/components/{Rating/Rating.svelte → Rating.svelte} +19 -10
  58. package/dist/components/Rating.svelte.d.ts +13 -0
  59. package/dist/components/{SearchInput/SearchInput.svelte → SearchInput.svelte} +19 -8
  60. package/dist/components/{SearchInput/SearchInput.svelte.d.ts → SearchInput.svelte.d.ts} +9 -2
  61. package/dist/components/{Select/Select.svelte → Select.svelte} +48 -76
  62. package/dist/components/{Select/Select.svelte.d.ts → Select.svelte.d.ts} +11 -1
  63. package/dist/components/SideBarMenu/SideBarMenu.svelte +724 -0
  64. package/dist/components/SideBarMenu/SideBarMenu.svelte.d.ts +109 -0
  65. package/dist/components/SideBarMenu/index.d.ts +2 -0
  66. package/dist/components/SideBarMenu/index.js +1 -0
  67. package/dist/components/TabStrip/TabStrip.svelte +384 -0
  68. package/dist/components/TabStrip/TabStrip.svelte.d.ts +50 -0
  69. package/dist/components/TabStrip/index.d.ts +3 -0
  70. package/dist/components/TabStrip/index.js +2 -0
  71. package/dist/components/{TextArea/TextArea.svelte → TextArea.svelte} +143 -112
  72. package/dist/components/TextArea.svelte.d.ts +38 -0
  73. package/dist/components/ThemeSelector.svelte +81 -0
  74. package/dist/components/ThemeSelector.svelte.d.ts +10 -0
  75. package/dist/components/TimePicker.svelte +148 -0
  76. package/dist/components/TimePicker.svelte.d.ts +28 -0
  77. package/dist/components/TimeRangeInput.svelte +203 -0
  78. package/dist/components/TimeRangeInput.svelte.d.ts +29 -0
  79. package/dist/components/TimeSpinner.svelte +202 -0
  80. package/dist/components/TimeSpinner.svelte.d.ts +26 -0
  81. package/dist/components/Toast/Toaster.svelte +51 -0
  82. package/dist/components/Toast/Toaster.svelte.d.ts +12 -0
  83. package/dist/components/Toast/toast.svelte.d.ts +29 -0
  84. package/dist/components/Toast/toast.svelte.js +27 -0
  85. package/dist/components/Toggle.svelte +93 -0
  86. package/dist/components/Toggle.svelte.d.ts +15 -0
  87. package/dist/data/dataset.d.ts +42 -0
  88. package/dist/data/dataset.js +3 -0
  89. package/dist/data/index.d.ts +3 -0
  90. package/dist/data/index.js +3 -0
  91. package/dist/data/query/ast.d.ts +62 -0
  92. package/dist/data/query/ast.js +12 -0
  93. package/dist/data/query/index.d.ts +3 -0
  94. package/dist/data/query/index.js +3 -0
  95. package/dist/data/query/lexer.d.ts +33 -0
  96. package/dist/data/query/lexer.js +225 -0
  97. package/dist/data/query/parser.d.ts +11 -0
  98. package/dist/data/query/parser.js +252 -0
  99. package/dist/data/table/grid.svelte.d.ts +57 -0
  100. package/dist/data/table/grid.svelte.js +139 -0
  101. package/dist/data/table/index.d.ts +2 -0
  102. package/dist/data/table/index.js +2 -0
  103. package/dist/data/table/types.d.ts +79 -0
  104. package/dist/index.d.ts +49 -22
  105. package/dist/index.js +46 -21
  106. package/dist/positioning/anchored.d.ts +61 -0
  107. package/dist/positioning/anchored.js +122 -0
  108. package/dist/positioning/tooltip.d.ts +41 -0
  109. package/dist/positioning/tooltip.js +147 -0
  110. package/dist/theme.css +205 -0
  111. package/dist/types/breakpoints.d.ts +24 -0
  112. package/dist/types/breakpoints.js +13 -0
  113. package/dist/types/responsive.d.ts +32 -0
  114. package/dist/types/responsive.js +54 -0
  115. package/dist/types/sizes.d.ts +10 -3
  116. package/dist/types/time.d.ts +19 -0
  117. package/dist/types/time.js +10 -0
  118. package/dist/types/variants.d.ts +8 -1
  119. package/dist/types/variants.js +16 -1
  120. package/docs/components.md +255 -0
  121. package/docs/examples.md +323 -0
  122. package/docs/paradigm.md +240 -0
  123. package/docs/themes.md +170 -0
  124. package/docs/usage.md +450 -0
  125. package/package.json +97 -63
  126. package/dist/components/Button/Button.svelte +0 -172
  127. package/dist/components/Button/Button.svelte.d.ts +0 -32
  128. package/dist/components/Button/index.d.ts +0 -1
  129. package/dist/components/Button/index.js +0 -1
  130. package/dist/components/Dialog/Dialog.svelte +0 -101
  131. package/dist/components/Dialog/Dialog.svelte.d.ts +0 -18
  132. package/dist/components/Dialog/index.d.ts +0 -1
  133. package/dist/components/Dialog/index.js +0 -1
  134. package/dist/components/ElementManager/ElementManager.svelte +0 -397
  135. package/dist/components/ElementManager/ElementManager.svelte.d.ts +0 -43
  136. package/dist/components/ElementManager/index.d.ts +0 -1
  137. package/dist/components/ElementManager/index.js +0 -1
  138. package/dist/components/EmailInput/EmailInput.svelte.d.ts +0 -14
  139. package/dist/components/EmailInput/index.d.ts +0 -1
  140. package/dist/components/EmailInput/index.js +0 -1
  141. package/dist/components/Icon/Icon.svelte +0 -74
  142. package/dist/components/Icon/Icon.svelte.d.ts +0 -13
  143. package/dist/components/Icon/index.d.ts +0 -1
  144. package/dist/components/Icon/index.js +0 -1
  145. package/dist/components/Input/Input.svelte +0 -268
  146. package/dist/components/Input/Input.svelte.d.ts +0 -18
  147. package/dist/components/Input/index.d.ts +0 -1
  148. package/dist/components/Input/index.js +0 -1
  149. package/dist/components/List/index.d.ts +0 -1
  150. package/dist/components/List/index.js +0 -1
  151. package/dist/components/ListItem/ListItem.svelte +0 -175
  152. package/dist/components/ListItem/ListItem.svelte.d.ts +0 -24
  153. package/dist/components/ListItem/index.d.ts +0 -2
  154. package/dist/components/ListItem/index.js +0 -2
  155. package/dist/components/ListView/ListView.svelte +0 -463
  156. package/dist/components/ListView/ListView.svelte.d.ts +0 -37
  157. package/dist/components/ListView/index.d.ts +0 -2
  158. package/dist/components/ListView/index.js +0 -2
  159. package/dist/components/NodeGraph/BaseNode.d.ts +0 -57
  160. package/dist/components/NodeGraph/BaseNode.js +0 -30
  161. package/dist/components/NodeGraph/Edge.svelte +0 -60
  162. package/dist/components/NodeGraph/Edge.svelte.d.ts +0 -16
  163. package/dist/components/NodeGraph/ExpressionEvaluator.d.ts +0 -82
  164. package/dist/components/NodeGraph/ExpressionEvaluator.js +0 -152
  165. package/dist/components/NodeGraph/Node.svelte +0 -100
  166. package/dist/components/NodeGraph/Node.svelte.d.ts +0 -10
  167. package/dist/components/NodeGraph/NodeGraph.svelte +0 -52
  168. package/dist/components/NodeGraph/NodeGraph.svelte.d.ts +0 -14
  169. package/dist/components/NodeGraph/NodeInstance.svelte.d.ts +0 -80
  170. package/dist/components/NodeGraph/NodeInstance.svelte.js +0 -241
  171. package/dist/components/NodeGraph/NodePort.svelte +0 -75
  172. package/dist/components/NodeGraph/NodePort.svelte.d.ts +0 -11
  173. package/dist/components/NodeGraph/decorators.d.ts +0 -81
  174. package/dist/components/NodeGraph/decorators.js +0 -148
  175. package/dist/components/NodeGraph/index.d.ts +0 -9
  176. package/dist/components/NodeGraph/index.js +0 -9
  177. package/dist/components/NodeGraph/types.d.ts +0 -94
  178. package/dist/components/NodeGraph/types.js +0 -33
  179. package/dist/components/NotesEditor/NotesEditor.svelte +0 -203
  180. package/dist/components/NotesEditor/NotesEditor.svelte.d.ts +0 -9
  181. package/dist/components/NotesEditor/index.d.ts +0 -1
  182. package/dist/components/NotesEditor/index.js +0 -1
  183. package/dist/components/NumberInput/index.d.ts +0 -1
  184. package/dist/components/NumberInput/index.js +0 -1
  185. package/dist/components/PasswordInput/PasswordInput.svelte +0 -41
  186. package/dist/components/PasswordInput/PasswordInput.svelte.d.ts +0 -13
  187. package/dist/components/PasswordInput/index.d.ts +0 -1
  188. package/dist/components/PasswordInput/index.js +0 -1
  189. package/dist/components/Popup/index.d.ts +0 -1
  190. package/dist/components/Popup/index.js +0 -1
  191. package/dist/components/Rating/Rating.svelte.d.ts +0 -7
  192. package/dist/components/Rating/index.d.ts +0 -1
  193. package/dist/components/Rating/index.js +0 -1
  194. package/dist/components/ScrollView/ScrollView.svelte +0 -285
  195. package/dist/components/ScrollView/ScrollView.svelte.d.ts +0 -19
  196. package/dist/components/ScrollView/index.d.ts +0 -1
  197. package/dist/components/ScrollView/index.js +0 -1
  198. package/dist/components/SearchInput/index.d.ts +0 -1
  199. package/dist/components/SearchInput/index.js +0 -1
  200. package/dist/components/Select/index.d.ts +0 -1
  201. package/dist/components/Select/index.js +0 -1
  202. package/dist/components/TextArea/TextArea.svelte.d.ts +0 -19
  203. package/dist/components/TextArea/index.d.ts +0 -1
  204. package/dist/components/TextArea/index.js +0 -1
  205. package/dist/components/ThemeSelector/ThemeSelector.svelte +0 -64
  206. package/dist/components/ThemeSelector/ThemeSelector.svelte.d.ts +0 -3
  207. package/dist/components/ThemeSelector/index.d.ts +0 -1
  208. package/dist/components/ThemeSelector/index.js +0 -1
  209. package/dist/components/TooltipHandler/TooltipHandler.svelte +0 -593
  210. package/dist/components/TooltipHandler/TooltipHandler.svelte.d.ts +0 -10
  211. package/dist/components/TooltipHandler/index.d.ts +0 -1
  212. package/dist/components/TooltipHandler/index.js +0 -1
  213. package/dist/styles/sizes.d.ts +0 -78
  214. package/dist/styles/sizes.js +0 -120
  215. package/dist/styles/variants.d.ts +0 -106
  216. package/dist/styles/variants.js +0 -194
  217. package/dist/types/ManagerTypes.d.ts +0 -42
  218. /package/dist/{types/ManagerTypes.js → data/table/types.js} +0 -0
@@ -1,203 +0,0 @@
1
- <script lang="ts">
2
- let {
3
- notes = $bindable(""),
4
- placeholder = "Add your notes...",
5
- onSave,
6
- className = ""
7
- }: {
8
- notes: string | undefined;
9
- placeholder?: string;
10
- onSave: (notes: string) => Promise<void>;
11
- className?: string;
12
- } = $props();
13
-
14
- // State management
15
- let saveState = $state<'idle' | 'typing' | 'saving' | 'saved' | 'error'>('idle');
16
- let saveTimeout: ReturnType<typeof setTimeout>;
17
- let lastSavedNotes = $state(notes || '');
18
-
19
- // Auto-save effect - runs when notes change
20
- $effect(() => {
21
- const currentNotes = notes || '';
22
-
23
- if (currentNotes !== lastSavedNotes && saveState !== 'saving') {
24
- saveState = 'typing';
25
-
26
- // Clear existing timeout
27
- clearTimeout(saveTimeout);
28
-
29
- // Set new timeout for auto-save
30
- saveTimeout = setTimeout(async () => {
31
- await handleSave();
32
- }, 1000); // Save after 1 second of no typing
33
- }
34
- });
35
-
36
- // Textarea reference for initial sizing
37
- let textareaElement: HTMLTextAreaElement;
38
-
39
- // Initial sizing effect - runs after component mounts
40
- $effect(() => {
41
- if (textareaElement && notes) {
42
- // Use setTimeout to ensure DOM is fully rendered
43
- setTimeout(() => {
44
- resizeTextarea(textareaElement);
45
- }, 0);
46
- }
47
- });
48
-
49
- // Ctrl+S listener for manual save
50
- $effect(() => {
51
- async function handleKeyDown(event: KeyboardEvent) {
52
- // Check if Ctrl+S (or Cmd+S on Mac) is pressed and textarea is focused
53
- if ((event.ctrlKey || event.metaKey) && event.key === 's' &&
54
- textareaElement && document.activeElement === textareaElement) {
55
- event.preventDefault();
56
- event.stopPropagation();
57
-
58
-
59
- // Clear any pending auto-save timeout and save immediately
60
- clearTimeout(saveTimeout);
61
- await handleSave();
62
- }
63
- }
64
-
65
- // Add listener to document
66
- document.addEventListener('keydown', handleKeyDown);
67
-
68
- // Cleanup function
69
- return () => {
70
- document.removeEventListener('keydown', handleKeyDown);
71
- };
72
- });
73
-
74
- async function handleSave() {
75
- const currentNotes = notes || '';
76
-
77
- if (currentNotes === lastSavedNotes) {
78
- // Show brief "No changes" feedback for manual save attempts
79
- saveState = 'saved';
80
- setTimeout(() => {
81
- if (saveState === 'saved') {
82
- saveState = 'idle';
83
- }
84
- }, 1000);
85
- return;
86
- }
87
-
88
- saveState = 'saving';
89
-
90
- try {
91
- await onSave(currentNotes);
92
- lastSavedNotes = currentNotes;
93
- saveState = 'saved';
94
-
95
- // Clear "saved" status after 2 seconds
96
- setTimeout(() => {
97
- if (saveState === 'saved') {
98
- saveState = 'idle';
99
- }
100
- }, 2000);
101
- } catch (error) {
102
- console.error('Failed to save notes:', error);
103
- saveState = 'error';
104
-
105
- // Clear error status after 3 seconds
106
- setTimeout(() => {
107
- if (saveState === 'error') {
108
- saveState = 'idle';
109
- }
110
- }, 3000);
111
- }
112
- }
113
-
114
- // Shared function to resize textarea
115
- function resizeTextarea(target: HTMLTextAreaElement) {
116
- // Get computed styles to calculate exact line height
117
- const computedStyle = window.getComputedStyle(target);
118
- const lineHeight = parseInt(computedStyle.lineHeight);
119
- const paddingTop = parseInt(computedStyle.paddingTop);
120
- const paddingBottom = parseInt(computedStyle.paddingBottom);
121
- const borderTop = parseInt(computedStyle.borderTopWidth);
122
- const borderBottom = parseInt(computedStyle.borderBottomWidth);
123
-
124
- // Calculate heights based on actual lines
125
- const minLines = 3;
126
- const maxLines = 15;
127
- const minHeight = (lineHeight * minLines) + paddingTop + paddingBottom + borderTop + borderBottom;
128
- const maxHeight = (lineHeight * maxLines) + paddingTop + paddingBottom + borderTop + borderBottom;
129
-
130
- // Reset height to measure content
131
- target.style.height = 'auto';
132
-
133
- // Set height based on content, capped at max
134
- const contentHeight = target.scrollHeight;
135
- const newHeight = Math.min(Math.max(contentHeight, minHeight), maxHeight);
136
- target.style.height = newHeight + 'px';
137
-
138
- // Only show scrollbar when content actually exceeds max height
139
- if (contentHeight > maxHeight) {
140
- target.style.overflowY = 'auto';
141
- } else {
142
- target.style.overflowY = 'hidden';
143
- }
144
- }
145
-
146
- function handleInput(event: Event) {
147
- const target = event.target as HTMLTextAreaElement;
148
- resizeTextarea(target);
149
- }
150
-
151
-
152
- // Get status text and styling - simplified approach
153
- let statusText = $state('');
154
- let statusClass = $state('');
155
-
156
- $effect(() => {
157
- switch (saveState) {
158
- case 'typing':
159
- statusText = 'Typing...';
160
- statusClass = 'text-gray-500';
161
- break;
162
- case 'saving':
163
- statusText = 'Saving...';
164
- statusClass = 'text-blue-500';
165
- break;
166
- case 'saved':
167
- statusText = 'Saved';
168
- statusClass = 'text-green-600';
169
- break;
170
- case 'error':
171
- statusText = 'Save failed';
172
- statusClass = 'text-red-500';
173
- break;
174
- default:
175
- statusText = '';
176
- statusClass = '';
177
- }
178
- });
179
- </script>
180
-
181
- <div class={className}>
182
- <!-- Header with Notes label and status -->
183
- <div class="flex items-center justify-between mb-2">
184
- <label for="notes-textarea" class="block text-sm font-medium [color:var(--color-text)]">
185
- Notes
186
- </label>
187
- <span class="text-xs {statusClass} min-h-[16px]">
188
- {statusText}
189
- </span>
190
- </div>
191
-
192
- <!-- Textarea -->
193
- <textarea
194
- id="notes-textarea"
195
- bind:this={textareaElement}
196
- bind:value={notes}
197
- {placeholder}
198
- class="w-full px-3 py-2 bg-transparent [color:var(--color-text)] [border-color:var(--color-secondary)] border-2 rounded-md focus:outline-none hover:[border-color:color-mix(in_srgb,var(--color-secondary)_80%,black)] focus:[border-color:color-mix(in_srgb,var(--color-secondary)_90%,black)] focus:[outline:2px_solid_color-mix(in_srgb,currentColor_70%,transparent)] focus:[outline-offset:0px] resize-none min-h-[80px] overflow-hidden"
199
- rows="3"
200
- oninput={handleInput}
201
- ></textarea>
202
-
203
- </div>
@@ -1,9 +0,0 @@
1
- type $$ComponentProps = {
2
- notes: string | undefined;
3
- placeholder?: string;
4
- onSave: (notes: string) => Promise<void>;
5
- className?: string;
6
- };
7
- declare const NotesEditor: import("svelte").Component<$$ComponentProps, {}, "notes">;
8
- type NotesEditor = ReturnType<typeof NotesEditor>;
9
- export default NotesEditor;
@@ -1 +0,0 @@
1
- export { default } from './NotesEditor.svelte';
@@ -1 +0,0 @@
1
- export { default } from './NotesEditor.svelte';
@@ -1 +0,0 @@
1
- export { default } from './NumberInput.svelte';
@@ -1 +0,0 @@
1
- export { default } from './NumberInput.svelte';
@@ -1,41 +0,0 @@
1
- <script lang="ts">
2
- import Input from '../Input/Input.svelte';
3
- import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
4
- import type { HTMLInputAttributes } from 'svelte/elements';
5
-
6
- interface Props extends Omit<HTMLInputAttributes, 'type'> {
7
- value: string;
8
- class?: string;
9
- inputClass?: string;
10
- validate?: (value: string) => boolean | string;
11
- valid?: boolean;
12
- touched?: boolean;
13
- element?: HTMLInputElement;
14
- }
15
-
16
- let {
17
- value = $bindable(),
18
- valid = $bindable(true),
19
- touched = $bindable(false),
20
- element = $bindable(),
21
- ...restProps
22
- }: Props = $props();
23
-
24
- let showPassword = $state(false);
25
-
26
- function toggleVisibility() {
27
- showPassword = !showPassword;
28
- }
29
- </script>
30
-
31
- <Input
32
- bind:value
33
- bind:valid
34
- bind:touched
35
- bind:element
36
- type={showPassword ? 'text' : 'password'}
37
- icon={showPassword ? faEye : faEyeSlash}
38
- iconClickable={true}
39
- onIconClick={toggleVisibility}
40
- {...restProps}
41
- />
@@ -1,13 +0,0 @@
1
- import type { HTMLInputAttributes } from 'svelte/elements';
2
- interface Props extends Omit<HTMLInputAttributes, 'type'> {
3
- value: string;
4
- class?: string;
5
- inputClass?: string;
6
- validate?: (value: string) => boolean | string;
7
- valid?: boolean;
8
- touched?: boolean;
9
- element?: HTMLInputElement;
10
- }
11
- declare const PasswordInput: import("svelte").Component<Props, {}, "element" | "value" | "valid" | "touched">;
12
- type PasswordInput = ReturnType<typeof PasswordInput>;
13
- export default PasswordInput;
@@ -1 +0,0 @@
1
- export { default } from './PasswordInput.svelte';
@@ -1 +0,0 @@
1
- export { default } from './PasswordInput.svelte';
@@ -1 +0,0 @@
1
- export { default } from './Popup.svelte';
@@ -1 +0,0 @@
1
- export { default } from './Popup.svelte';
@@ -1,7 +0,0 @@
1
- export type RatingProps = {
2
- average: number;
3
- count: number;
4
- };
5
- declare const Rating: import("svelte").Component<RatingProps, {}, "">;
6
- type Rating = ReturnType<typeof Rating>;
7
- export default Rating;
@@ -1 +0,0 @@
1
- export { default } from './Rating.svelte';
@@ -1 +0,0 @@
1
- export { default } from './Rating.svelte';
@@ -1,285 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from "svelte";
3
- import type { HTMLAttributes } from "svelte/elements";
4
-
5
- interface Props extends HTMLAttributes<HTMLDivElement> {
6
- showScrollbar?: boolean;
7
- scrollbarWidth?: number;
8
- class?: string;
9
- disabled?: boolean;
10
- children: Snippet;
11
- view?: HTMLDivElement;
12
- onScroll?: (data: {
13
- scrollTop: number;
14
- thumbTop: number;
15
- scrollHeight: number;
16
- clientHeight: number;
17
- }) => void;
18
- }
19
-
20
- let {
21
- showScrollbar = true,
22
- scrollbarWidth = 6,
23
- class: className = "",
24
- style = "",
25
- disabled = false,
26
- children,
27
- view = $bindable(),
28
- onScroll,
29
- ...restProps
30
- }: Props = $props();
31
-
32
- let isDragging = $state(false);
33
- let dragStartY = $state(0);
34
- let dragStartScrollTop = $state(0);
35
- let scrollTop = $state(0);
36
- let previousScrollTop = $state(0);
37
- let scrollHeight = $state(0);
38
- let clientHeight = $state(0);
39
- let isScrolling = $state(false);
40
- let isHovering = $state(false);
41
- let scrollTimeout = $state<ReturnType<typeof setTimeout>>();
42
-
43
- // Inset from edges (0.25rem = 4px)
44
- const inset = 4;
45
-
46
- // Generate unique ID for aria-controls if not provided
47
- const scrollableId =
48
- restProps.id ?? `scrollview-${Math.random().toString(36).substr(2, 9)}`;
49
-
50
- // Split classes: height/sizing/border/rounded classes go to wrapper, everything else to view
51
- const wrapperClasses = $derived(
52
- className
53
- .match(
54
- /\b(h-|min-h-|max-h-|flex-\d|flex-grow|flex-shrink|flex-none|flex-auto|basis-|border|rounded)\S*/g,
55
- )
56
- ?.join(" ") || "",
57
- );
58
- const viewClasses = $derived(
59
- className
60
- .split(/\s+/)
61
- .filter((cls) => cls && !wrapperClasses.includes(cls))
62
- .join(" "),
63
- );
64
-
65
- // Initialize dimensions when view is mounted
66
- $effect(() => {
67
- if (view) {
68
- scrollTop = view.scrollTop;
69
- scrollHeight = view.scrollHeight;
70
- clientHeight = view.clientHeight;
71
-
72
- // Fire initial callback if provided
73
- if (onScroll) {
74
- onScroll({ scrollTop, thumbTop, scrollHeight, clientHeight });
75
- }
76
- }
77
- });
78
-
79
- // Calculate thumb height based on view dimensions
80
- const thumbHeight = $derived.by(() => {
81
- if (scrollHeight === 0 || clientHeight === 0) return 20;
82
- const visibleRatio = clientHeight / scrollHeight;
83
- return Math.max(
84
- 20,
85
- Math.min(clientHeight - inset * 2, visibleRatio * clientHeight),
86
- );
87
- });
88
-
89
- // Calculate thumb position based on scroll position
90
- const thumbTop = $derived.by(() => {
91
- if (scrollHeight === 0 || clientHeight === 0) return inset;
92
- const maxScrollTop = scrollHeight - clientHeight;
93
- if (maxScrollTop <= 0) return inset;
94
- const scrollRatio = scrollTop / maxScrollTop;
95
- const trackHeight = clientHeight - thumbHeight - inset * 2;
96
- return inset + scrollRatio * trackHeight;
97
- });
98
-
99
- // Check if scrollbar is needed
100
- const needsScrollbar = $derived(
101
- showScrollbar &&
102
- !disabled &&
103
- scrollHeight > 0 &&
104
- clientHeight > 0 &&
105
- scrollHeight > clientHeight,
106
- );
107
-
108
- // Calculate scroll percentage for aria-valuenow
109
- const scrollPercentage = $derived(() => {
110
- if (!view) return 0;
111
- const maxScrollTop = view.scrollHeight - view.clientHeight;
112
- if (maxScrollTop <= 0) return 0;
113
- return Math.round((scrollTop / maxScrollTop) * 100);
114
- });
115
-
116
- // Calculate opacity based on state
117
- const thumbOpacity = $derived(isScrolling || isHovering ? "80%" : "30%");
118
-
119
- // Handle scrollbar thumb mouse down
120
- function handleThumbMouseDown(event: MouseEvent) {
121
- if (!view) return;
122
- event.preventDefault();
123
- isDragging = true;
124
- dragStartY = event.clientY;
125
- dragStartScrollTop = view.scrollTop;
126
-
127
- document.addEventListener("mousemove", handleThumbMouseMove);
128
- document.addEventListener("mouseup", handleThumbMouseUp);
129
- }
130
-
131
- // Handle scrollbar thumb mouse move
132
- function handleThumbMouseMove(event: MouseEvent) {
133
- if (!isDragging || !view) return;
134
-
135
- const deltaY = event.clientY - dragStartY;
136
- const scrollRatio = deltaY / (view.clientHeight - thumbHeight);
137
- const maxScrollTop = view.scrollHeight - view.clientHeight;
138
-
139
- view.scrollTop = Math.max(
140
- 0,
141
- Math.min(
142
- maxScrollTop,
143
- dragStartScrollTop + scrollRatio * maxScrollTop,
144
- ),
145
- );
146
- }
147
-
148
- // Handle scrollbar thumb mouse up
149
- function handleThumbMouseUp() {
150
- isDragging = false;
151
- document.removeEventListener("mousemove", handleThumbMouseMove);
152
- document.removeEventListener("mouseup", handleThumbMouseUp);
153
- }
154
-
155
- // Handle keyboard events - prevent scroll chaining while preserving smooth scrolling
156
- function handleKeyDown(event: KeyboardEvent) {
157
- if (disabled) return;
158
-
159
- // Only handle if this ScrollView has focus (not a child element)
160
- if (event.target !== view) return;
161
-
162
- // Check for scroll keys
163
- const scrollKeys = [
164
- "ArrowDown",
165
- "ArrowUp",
166
- "PageDown",
167
- "PageUp",
168
- "Home",
169
- "End",
170
- " ",
171
- ];
172
- if (!scrollKeys.includes(event.key)) return;
173
-
174
- if (!view) return;
175
-
176
- // ALWAYS prevent default and stop propagation to have full control
177
- event.preventDefault();
178
- event.stopPropagation();
179
-
180
- // Calculate scroll amount based on key
181
- const {
182
- clientHeight: currentClientHeight,
183
- scrollTop: currentScrollTop,
184
- scrollHeight: currentScrollHeight,
185
- } = view;
186
- let scrollAmount = 0;
187
-
188
- if (event.key === "ArrowDown") scrollAmount = 40;
189
- else if (event.key === "ArrowUp") scrollAmount = -40;
190
- else if (event.key === "PageDown")
191
- scrollAmount = currentClientHeight * 0.9;
192
- else if (event.key === "PageUp")
193
- scrollAmount = -currentClientHeight * 0.9;
194
- else if (event.key === " ")
195
- scrollAmount = event.shiftKey
196
- ? -currentClientHeight * 0.9
197
- : currentClientHeight * 0.9;
198
- else if (event.key === "Home") scrollAmount = -currentScrollTop;
199
- else if (event.key === "End")
200
- scrollAmount =
201
- currentScrollHeight - currentClientHeight - currentScrollTop;
202
-
203
- // Apply scroll instantly (smooth behavior feels laggy with keyboard)
204
- view.scrollBy({ top: scrollAmount, behavior: "auto" });
205
- }
206
-
207
- // Handle scroll and update state
208
- function handleScroll() {
209
- if (!view) return;
210
-
211
- // Update scroll state
212
- previousScrollTop = scrollTop;
213
- scrollTop = view.scrollTop;
214
- scrollHeight = view.scrollHeight;
215
- clientHeight = view.clientHeight;
216
-
217
- // Show scrollbar during scrolling
218
- isScrolling = true;
219
-
220
- // Clear previous timeout
221
- if (scrollTimeout) {
222
- clearTimeout(scrollTimeout);
223
- }
224
-
225
- // Hide scrollbar after scrolling stops (500ms delay)
226
- scrollTimeout = setTimeout(() => {
227
- isScrolling = false;
228
- }, 500);
229
-
230
- // Fire onScroll callback
231
- if (onScroll) {
232
- onScroll({ scrollTop, thumbTop, scrollHeight, clientHeight });
233
- }
234
- }
235
- </script>
236
-
237
- <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
238
- <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
239
- <div
240
- class="relative overflow-hidden p-0 flex-1 min-h-8 {wrapperClasses}"
241
- {style}
242
- {...restProps}
243
- >
244
- <div
245
- bind:this={view}
246
- id={scrollableId}
247
- class="scrollview absolute inset-0 {disabled
248
- ? 'overflow-y-hidden'
249
- : 'overflow-y-auto'} overflow-x-hidden [scrollbar-width:none] [-ms-overflow-style:none] [overscroll-behavior:contain] {viewClasses} {disabled
250
- ? '[background-color:color-mix(in_srgb,var(--color-text)_5%,transparent)] cursor-not-allowed'
251
- : '[background-color:var(--color-background)]'} focus-visible:[outline:2px_solid_var(--color-primary)] focus-visible:[outline-offset:0px]"
252
- onscroll={handleScroll}
253
- onkeydown={handleKeyDown}
254
- onmouseenter={() => (isHovering = true)}
255
- onmouseleave={() => (isHovering = false)}
256
- tabindex={disabled ? -1 : 0}
257
- role="region"
258
- aria-label="Scrollable content"
259
- >
260
- {@render children()}
261
- </div>
262
-
263
- <!-- Custom scrollbar thumb -->
264
- {#if needsScrollbar}
265
- <div
266
- class="absolute rounded cursor-pointer pointer-events-auto z-10"
267
- style="top: {thumbTop}px; right: {inset}px; height: {thumbHeight}px; width: {scrollbarWidth}px; background-color: color-mix(in srgb, var(--color-primary) {thumbOpacity}, transparent);"
268
- onmousedown={handleThumbMouseDown}
269
- role="scrollbar"
270
- aria-controls={scrollableId}
271
- aria-orientation="vertical"
272
- aria-valuenow={scrollPercentage()}
273
- aria-valuemin="0"
274
- aria-valuemax="100"
275
- tabindex="-1"
276
- aria-label="Scroll thumb"
277
- ></div>
278
- {/if}
279
- </div>
280
-
281
- <style>
282
- .scrollview::-webkit-scrollbar {
283
- display: none;
284
- }
285
- </style>
@@ -1,19 +0,0 @@
1
- import type { Snippet } from "svelte";
2
- import type { HTMLAttributes } from "svelte/elements";
3
- interface Props extends HTMLAttributes<HTMLDivElement> {
4
- showScrollbar?: boolean;
5
- scrollbarWidth?: number;
6
- class?: string;
7
- disabled?: boolean;
8
- children: Snippet;
9
- view?: HTMLDivElement;
10
- onScroll?: (data: {
11
- scrollTop: number;
12
- thumbTop: number;
13
- scrollHeight: number;
14
- clientHeight: number;
15
- }) => void;
16
- }
17
- declare const ScrollView: import("svelte").Component<Props, {}, "view">;
18
- type ScrollView = ReturnType<typeof ScrollView>;
19
- export default ScrollView;
@@ -1 +0,0 @@
1
- export { default } from './ScrollView.svelte';
@@ -1 +0,0 @@
1
- export { default } from './ScrollView.svelte';
@@ -1 +0,0 @@
1
- export { default } from './SearchInput.svelte';
@@ -1 +0,0 @@
1
- export { default } from './SearchInput.svelte';
@@ -1 +0,0 @@
1
- export { default } from './Select.svelte';
@@ -1 +0,0 @@
1
- export { default } from './Select.svelte';
@@ -1,19 +0,0 @@
1
- import type { HTMLTextareaAttributes } from "svelte/elements";
2
- interface Props extends HTMLTextareaAttributes {
3
- value?: string;
4
- lines?: string[];
5
- class?: string;
6
- textareaClass?: string;
7
- validate?: (value: string) => boolean | string;
8
- valid?: boolean;
9
- touched?: boolean;
10
- element?: HTMLTextAreaElement;
11
- minRows?: number;
12
- maxRows?: number;
13
- lineHeightRem?: number;
14
- required?: boolean;
15
- allowCopy?: boolean;
16
- }
17
- declare const TextArea: import("svelte").Component<Props, {}, "element" | "value" | "valid" | "touched" | "lines" | "allowCopy">;
18
- type TextArea = ReturnType<typeof TextArea>;
19
- export default TextArea;
@@ -1 +0,0 @@
1
- export { default } from './TextArea.svelte';
@@ -1 +0,0 @@
1
- export { default } from './TextArea.svelte';