@marianmeres/stuic 1.126.0 → 2.0.0-next.3

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 (250) hide show
  1. package/README.md +2 -8
  2. package/dist/_shared.css +2 -0
  3. package/dist/actions/autogrow.svelte.d.ts +6 -0
  4. package/dist/actions/autogrow.svelte.js +19 -0
  5. package/dist/actions/highlight-dragover.svelte.d.ts +7 -0
  6. package/dist/actions/highlight-dragover.svelte.js +38 -0
  7. package/dist/actions/index.d.ts +7 -0
  8. package/dist/actions/index.js +7 -0
  9. package/dist/actions/on-submit-validity-check.svelte.d.ts +15 -0
  10. package/dist/actions/on-submit-validity-check.svelte.js +58 -0
  11. package/dist/actions/tooltip/index.css +34 -0
  12. package/dist/actions/tooltip/tooltip.svelte.d.ts +13 -0
  13. package/dist/actions/tooltip/tooltip.svelte.js +203 -0
  14. package/dist/actions/trim.svelte.d.ts +4 -0
  15. package/dist/actions/trim.svelte.js +17 -0
  16. package/dist/actions/{validate.d.ts → validate.svelte.d.ts} +8 -8
  17. package/dist/actions/validate.svelte.js +90 -0
  18. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +59 -385
  19. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +9 -101
  20. package/dist/components/AlertConfirmPrompt/Current.svelte +202 -0
  21. package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +22 -0
  22. package/dist/components/AlertConfirmPrompt/acp-icons.d.ts +7 -2
  23. package/dist/components/AlertConfirmPrompt/acp-icons.js +8 -8
  24. package/dist/components/AlertConfirmPrompt/alert-confirm-prompt-stack.svelte.d.ts +63 -0
  25. package/dist/components/AlertConfirmPrompt/alert-confirm-prompt-stack.svelte.js +144 -0
  26. package/dist/components/AlertConfirmPrompt/index.d.ts +2 -0
  27. package/dist/components/AlertConfirmPrompt/index.js +2 -0
  28. package/dist/components/AnimatedElipsis/AnimatedEllipsis.svelte +47 -0
  29. package/dist/components/AnimatedElipsis/AnimatedEllipsis.svelte.d.ts +7 -0
  30. package/dist/components/AnimatedElipsis/index.d.ts +1 -0
  31. package/dist/components/AnimatedElipsis/index.js +1 -0
  32. package/dist/components/AppShell/AppShell.svelte +188 -127
  33. package/dist/components/AppShell/AppShell.svelte.d.ts +62 -43
  34. package/dist/components/AppShell/index.d.ts +1 -0
  35. package/dist/components/AppShell/index.js +1 -0
  36. package/dist/components/Backdrop/Backdrop.svelte +149 -49
  37. package/dist/components/Backdrop/Backdrop.svelte.d.ts +22 -37
  38. package/dist/components/Backdrop/index.d.ts +1 -0
  39. package/dist/components/Backdrop/index.js +1 -0
  40. package/dist/components/Button/Button.svelte +122 -146
  41. package/dist/components/Button/Button.svelte.d.ts +22 -80
  42. package/dist/components/Button/index.css +16 -0
  43. package/dist/components/Button/index.d.ts +1 -0
  44. package/dist/components/Button/index.js +1 -0
  45. package/dist/components/ColResize/ColResize.svelte +0 -0
  46. package/dist/components/ColResize/ColResize.svelte.d.ts +26 -0
  47. package/dist/components/ColorScheme/{LocalColorScheme.svelte → ColorSchemeLocal.svelte} +2 -2
  48. package/dist/components/ColorScheme/ColorSchemeLocal.svelte.d.ts +26 -0
  49. package/dist/components/ColorScheme/{SystemAwareColorScheme.svelte → ColorSchemeSystemAware.svelte} +4 -4
  50. package/dist/components/ColorScheme/ColorSchemeSystemAware.svelte.d.ts +26 -0
  51. package/dist/components/ColorScheme/color-scheme.d.ts +26 -8
  52. package/dist/components/ColorScheme/color-scheme.js +40 -16
  53. package/dist/components/ColorScheme/index.d.ts +3 -0
  54. package/dist/components/ColorScheme/index.js +3 -0
  55. package/dist/components/DismissibleMessage/DismissibleMessage.svelte +76 -83
  56. package/dist/components/DismissibleMessage/DismissibleMessage.svelte.d.ts +16 -37
  57. package/dist/components/DismissibleMessage/index.css +13 -0
  58. package/dist/components/DismissibleMessage/index.d.ts +1 -0
  59. package/dist/components/DismissibleMessage/index.js +1 -0
  60. package/dist/components/Drawer/Drawer.svelte +155 -84
  61. package/dist/components/Drawer/Drawer.svelte.d.ts +24 -35
  62. package/dist/components/Drawer/index.d.ts +1 -0
  63. package/dist/components/Drawer/index.js +1 -0
  64. package/dist/components/HoverExpandableWidth/HoverExpandableWidth.svelte +150 -111
  65. package/dist/components/HoverExpandableWidth/HoverExpandableWidth.svelte.d.ts +16 -29
  66. package/dist/components/HoverExpandableWidth/index.d.ts +1 -0
  67. package/dist/components/HoverExpandableWidth/index.js +1 -0
  68. package/dist/components/Input/FieldCheckbox.svelte +174 -132
  69. package/dist/components/Input/FieldCheckbox.svelte.d.ts +28 -64
  70. package/dist/components/Input/FieldFile.svelte +166 -0
  71. package/dist/components/Input/FieldFile.svelte.d.ts +41 -0
  72. package/dist/components/Input/FieldInput.svelte +143 -0
  73. package/dist/components/Input/FieldInput.svelte.d.ts +41 -0
  74. package/dist/components/Input/FieldLikeButton.svelte +206 -0
  75. package/dist/components/Input/FieldLikeButton.svelte.d.ts +41 -0
  76. package/dist/components/Input/FieldOptions.svelte +646 -0
  77. package/dist/components/Input/FieldOptions.svelte.d.ts +58 -0
  78. package/dist/components/Input/FieldRadios.svelte +126 -77
  79. package/dist/components/Input/FieldRadios.svelte.d.ts +23 -61
  80. package/dist/components/Input/FieldSelect.svelte +160 -239
  81. package/dist/components/Input/FieldSelect.svelte.d.ts +40 -88
  82. package/dist/components/Input/FieldSwitch.svelte +132 -0
  83. package/dist/components/Input/FieldSwitch.svelte.d.ts +41 -0
  84. package/dist/components/Input/FieldTextarea.svelte +146 -0
  85. package/dist/components/Input/FieldTextarea.svelte.d.ts +44 -0
  86. package/dist/components/Input/Fieldset.svelte +21 -17
  87. package/dist/components/Input/Fieldset.svelte.d.ts +10 -27
  88. package/dist/components/Input/_internal/FieldRadioInternal.svelte +186 -0
  89. package/dist/components/Input/_internal/FieldRadioInternal.svelte.d.ts +30 -0
  90. package/dist/components/Input/_internal/InputWrap.svelte +216 -0
  91. package/dist/components/Input/_internal/InputWrap.svelte.d.ts +36 -0
  92. package/dist/components/Input/index.css +134 -0
  93. package/dist/components/Input/index.d.ts +11 -0
  94. package/dist/components/Input/index.js +11 -0
  95. package/dist/components/Input/types.d.ts +11 -0
  96. package/dist/components/KbdShortcut/KbdShortcut.svelte +89 -0
  97. package/dist/components/KbdShortcut/KbdShortcut.svelte.d.ts +17 -0
  98. package/dist/components/KbdShortcut/index.d.ts +1 -0
  99. package/dist/components/KbdShortcut/index.js +1 -0
  100. package/dist/components/Modal/Modal.svelte +127 -0
  101. package/dist/components/Modal/Modal.svelte.d.ts +32 -0
  102. package/dist/components/Modal/index.d.ts +1 -0
  103. package/dist/components/Modal/index.js +1 -0
  104. package/dist/components/ModalDialog/ModalDialog.svelte +137 -81
  105. package/dist/components/ModalDialog/ModalDialog.svelte.d.ts +17 -38
  106. package/dist/components/ModalDialog/index.d.ts +1 -0
  107. package/dist/components/ModalDialog/index.js +1 -0
  108. package/dist/components/Notifications/Notifications.svelte +259 -173
  109. package/dist/components/Notifications/Notifications.svelte.d.ts +32 -60
  110. package/dist/components/Notifications/index.css +12 -0
  111. package/dist/components/Notifications/index.d.ts +2 -0
  112. package/dist/components/Notifications/index.js +2 -0
  113. package/dist/components/Notifications/notifications-icons.d.ts +1 -1
  114. package/dist/components/Notifications/notifications-icons.js +4 -4
  115. package/dist/components/Notifications/notifications-stack.svelte.d.ts +89 -0
  116. package/dist/components/Notifications/notifications-stack.svelte.js +161 -0
  117. package/dist/components/Progress/Progress.svelte +26 -0
  118. package/dist/components/Progress/Progress.svelte.d.ts +10 -0
  119. package/dist/components/Progress/_internal/Bar.svelte +31 -0
  120. package/dist/components/Progress/_internal/Bar.svelte.d.ts +10 -0
  121. package/dist/components/Progress/_internal/Circle.svelte +10 -0
  122. package/dist/components/Progress/_internal/Circle.svelte.d.ts +7 -0
  123. package/dist/components/Progress/index.css +7 -0
  124. package/dist/components/Progress/index.d.ts +1 -0
  125. package/dist/components/Progress/index.js +1 -0
  126. package/dist/components/Spinner/Spinner.svelte +56 -41
  127. package/dist/components/Spinner/Spinner.svelte.d.ts +10 -22
  128. package/dist/components/Spinner/index.d.ts +1 -0
  129. package/dist/components/Spinner/index.js +1 -0
  130. package/dist/components/Switch/Switch.svelte +158 -118
  131. package/dist/components/Switch/Switch.svelte.d.ts +25 -66
  132. package/dist/components/Switch/SwitchButton.svelte +131 -0
  133. package/dist/components/Switch/SwitchButton.svelte.d.ts +21 -0
  134. package/dist/components/Switch/index.css +7 -0
  135. package/dist/components/Switch/index.d.ts +2 -0
  136. package/dist/components/Switch/index.js +2 -0
  137. package/dist/components/Thc/Thc.svelte +67 -10
  138. package/dist/components/Thc/Thc.svelte.d.ts +18 -22
  139. package/dist/components/Thc/index.d.ts +1 -0
  140. package/dist/components/Thc/index.js +1 -0
  141. package/dist/components/TwCheck/TwCheck.svelte +34 -0
  142. package/dist/components/TwCheck/TwCheck.svelte.d.ts +10 -0
  143. package/dist/components/TwCheck/index.css +5 -0
  144. package/dist/components/TwCheck/index.d.ts +1 -0
  145. package/dist/components/TwCheck/index.js +1 -0
  146. package/dist/components/X/X.svelte +12 -5
  147. package/dist/components/X/X.svelte.d.ts +6 -18
  148. package/dist/components/X/index.d.ts +1 -0
  149. package/dist/components/X/index.js +1 -0
  150. package/dist/index.css +26 -0
  151. package/dist/index.d.ts +21 -39
  152. package/dist/index.js +23 -54
  153. package/dist/types.d.ts +251 -2
  154. package/dist/types.js +248 -0
  155. package/dist/utils/breakpoint.svelte.d.ts +19 -0
  156. package/dist/utils/breakpoint.svelte.js +42 -0
  157. package/dist/utils/debounce.d.ts +13 -0
  158. package/dist/utils/debounce.js +22 -0
  159. package/dist/utils/device-pointer.svelte.d.ts +11 -0
  160. package/dist/utils/device-pointer.svelte.js +26 -0
  161. package/dist/utils/event-modifiers.d.ts +4 -0
  162. package/dist/utils/event-modifiers.js +29 -0
  163. package/dist/utils/get-id.d.ts +1 -1
  164. package/dist/utils/get-id.js +3 -1
  165. package/dist/utils/index.d.ts +21 -0
  166. package/dist/utils/index.js +21 -0
  167. package/dist/utils/is-browser.d.ts +1 -0
  168. package/dist/utils/is-browser.js +5 -0
  169. package/dist/utils/is-mac.d.ts +1 -0
  170. package/dist/utils/is-mac.js +11 -0
  171. package/dist/utils/maybe-json-parse.d.ts +1 -0
  172. package/dist/utils/maybe-json-parse.js +12 -0
  173. package/dist/utils/maybe-json-stringify.d.ts +1 -0
  174. package/dist/utils/maybe-json-stringify.js +11 -0
  175. package/dist/utils/move-array-item.d.ts +4 -0
  176. package/dist/utils/move-array-item.js +20 -0
  177. package/dist/utils/omit-pick.d.ts +2 -2
  178. package/dist/utils/omit-pick.js +10 -8
  179. package/dist/utils/paint.d.ts +18 -0
  180. package/dist/utils/paint.js +32 -0
  181. package/dist/utils/persistent-state.svelte.d.ts +23 -0
  182. package/dist/utils/persistent-state.svelte.js +48 -0
  183. package/dist/utils/prefers-reduced-motion.svelte.d.ts +2 -0
  184. package/dist/utils/prefers-reduced-motion.svelte.js +4 -0
  185. package/dist/utils/qsa.d.ts +1 -0
  186. package/dist/utils/qsa.js +3 -0
  187. package/dist/utils/sleep.d.ts +28 -0
  188. package/dist/utils/sleep.js +33 -0
  189. package/dist/utils/storage-abstraction.d.ts +35 -0
  190. package/dist/utils/storage-abstraction.js +136 -0
  191. package/dist/utils/str-hash.d.ts +7 -0
  192. package/dist/utils/str-hash.js +35 -0
  193. package/dist/utils/throttle.d.ts +1 -0
  194. package/dist/utils/throttle.js +47 -0
  195. package/dist/utils/to-integer.d.ts +1 -0
  196. package/dist/utils/to-integer.js +11 -0
  197. package/dist/utils/tr.d.ts +5 -0
  198. package/dist/utils/tr.js +13 -0
  199. package/dist/utils/tw-merge.d.ts +10 -0
  200. package/dist/utils/tw-merge.js +16 -0
  201. package/dist/utils/ucfirst.d.ts +1 -0
  202. package/dist/utils/ucfirst.js +6 -0
  203. package/package.json +66 -73
  204. package/dist/actions/autogrow.d.ts +0 -8
  205. package/dist/actions/autogrow.js +0 -22
  206. package/dist/actions/drag-drop.d.ts +0 -28
  207. package/dist/actions/drag-drop.js +0 -152
  208. package/dist/actions/on-outside.d.ts +0 -9
  209. package/dist/actions/on-outside.js +0 -27
  210. package/dist/actions/pre-submit-validity-check.d.ts +0 -3
  211. package/dist/actions/pre-submit-validity-check.js +0 -21
  212. package/dist/actions/tooltip/_make-visible.d.ts +0 -3
  213. package/dist/actions/tooltip/_make-visible.js +0 -25
  214. package/dist/actions/tooltip/_maybe-pick-safe-placement.d.ts +0 -3
  215. package/dist/actions/tooltip/_maybe-pick-safe-placement.js +0 -86
  216. package/dist/actions/tooltip/_set-position.d.ts +0 -2
  217. package/dist/actions/tooltip/_set-position.js +0 -125
  218. package/dist/actions/tooltip/tooltip.d.ts +0 -42
  219. package/dist/actions/tooltip/tooltip.js +0 -299
  220. package/dist/actions/trim.d.ts +0 -4
  221. package/dist/actions/trim.js +0 -18
  222. package/dist/actions/validate.js +0 -80
  223. package/dist/components/AlertConfirmPrompt/alert-confirm-prompt.d.ts +0 -58
  224. package/dist/components/AlertConfirmPrompt/alert-confirm-prompt.js +0 -141
  225. package/dist/components/ColorScheme/LocalColorScheme.svelte.d.ts +0 -25
  226. package/dist/components/ColorScheme/SystemAwareColorScheme.svelte.d.ts +0 -25
  227. package/dist/components/Input/Field.svelte +0 -315
  228. package/dist/components/Input/Field.svelte.d.ts +0 -102
  229. package/dist/components/Input/PinInput.svelte +0 -151
  230. package/dist/components/Input/PinInput.svelte.d.ts +0 -51
  231. package/dist/components/Input/XFieldRadioInternal.svelte +0 -143
  232. package/dist/components/Input/XFieldRadioInternal.svelte.d.ts +0 -45
  233. package/dist/components/Notifications/notifications.d.ts +0 -78
  234. package/dist/components/Notifications/notifications.js +0 -215
  235. package/dist/components/Popover/Popover.svelte +0 -24
  236. package/dist/components/Popover/Popover.svelte.d.ts +0 -22
  237. package/dist/components/Spinner/Spinner.v5.svelte +0 -114
  238. package/dist/components/Spinner/Spinner.v5.svelte.d.ts +0 -16
  239. package/dist/utils/calculate-alignment.d.ts +0 -68
  240. package/dist/utils/calculate-alignment.js +0 -183
  241. package/dist/utils/device-pointer.d.ts +0 -5
  242. package/dist/utils/device-pointer.js +0 -10
  243. package/dist/utils/prefers-reduced-motion.d.ts +0 -6
  244. package/dist/utils/prefers-reduced-motion.js +0 -26
  245. package/dist/utils/tw-merge2.d.ts +0 -3
  246. package/dist/utils/tw-merge2.js +0 -9
  247. package/dist/utils/tw-types.d.ts +0 -1
  248. package/dist/utils/window-size.d.ts +0 -22
  249. package/dist/utils/window-size.js +0 -35
  250. /package/dist/{utils/tw-types.js → components/Input/types.js} +0 -0
@@ -0,0 +1,216 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { slide } from "svelte/transition";
4
+ import type { ValidationResult } from "../../../actions/validate.svelte.js";
5
+ import { twMerge } from "../../../utils/tw-merge.js";
6
+ import Thc, { isTHCNotEmpty, type THC } from "../../Thc/Thc.svelte";
7
+
8
+ type SnippetWithId = Snippet<[{ id: string }]>;
9
+
10
+ interface Props {
11
+ id: string;
12
+ size?: "sm" | "md" | "lg" | string;
13
+ class?: string;
14
+ label?: SnippetWithId | THC;
15
+ labelAfter?: SnippetWithId | THC;
16
+ inputBefore?: SnippetWithId | THC;
17
+ children: Snippet;
18
+ inputAfter?: SnippetWithId | THC;
19
+ inputBelow?: SnippetWithId | THC;
20
+ description?: SnippetWithId | THC;
21
+ below?: SnippetWithId | THC;
22
+ required?: boolean;
23
+ disabled?: boolean;
24
+ validation?: ValidationResult | undefined;
25
+ //
26
+ labelLeft?: boolean;
27
+ labelLeftWidth?: "normal" | "wide";
28
+ labelLeftBreakpoint?: number;
29
+ //
30
+ classLabel?: string;
31
+ classLabelBox?: string;
32
+ classInputBox?: string;
33
+ classInputBoxWrap?: string;
34
+ classDescBox?: string;
35
+ classBelowBox?: string;
36
+ classValidationBox?: string;
37
+ style?: string;
38
+ }
39
+ let {
40
+ id,
41
+ size = "md",
42
+ class: classProp,
43
+ label,
44
+ labelAfter,
45
+ inputBefore,
46
+ children,
47
+ inputAfter,
48
+ inputBelow,
49
+ description,
50
+ below,
51
+ required = false,
52
+ disabled = false,
53
+ validation,
54
+ //
55
+ labelLeft = false,
56
+ labelLeftWidth = "normal",
57
+ labelLeftBreakpoint = 480,
58
+ //
59
+ classLabel,
60
+ classLabelBox,
61
+ classInputBox,
62
+ classInputBoxWrap,
63
+ classDescBox,
64
+ classBelowBox,
65
+ classValidationBox,
66
+ style,
67
+ }: Props = $props();
68
+
69
+ let invalid = $derived(validation && !validation?.valid);
70
+
71
+ let width = $state<number>(0);
72
+
73
+ $effect(() => {
74
+ // a non-zero breakpoint has priority
75
+ if (labelLeftBreakpoint) {
76
+ labelLeft = !(width && width < labelLeftBreakpoint);
77
+ }
78
+ });
79
+
80
+ let _classCommon = $derived(
81
+ [invalid && "invalid", disabled && "disabled", required && "required", size]
82
+ .filter(Boolean)
83
+ .join(" ")
84
+ );
85
+
86
+ let hasLabel = $derived(isTHCNotEmpty(label) || typeof label === "function");
87
+
88
+ const _preset = {
89
+ label: {
90
+ size: {
91
+ sm: "text-sm",
92
+ lg: "font-semibold",
93
+ } as any,
94
+ },
95
+ inputBox: {
96
+ size: {
97
+ sm: "text-sm",
98
+ } as any,
99
+ },
100
+ };
101
+ </script>
102
+
103
+ {#snippet snippetOrThc({ id, value }: { id: string; value?: SnippetWithId | THC })}
104
+ {#if typeof value === "function"}
105
+ {@render value({ id })}
106
+ {:else if value}
107
+ <Thc thc={value} forceAsHtml />
108
+ {/if}
109
+ {/snippet}
110
+
111
+ <div
112
+ class={twMerge(
113
+ "stuic-input",
114
+ _classCommon,
115
+ "mb-8 grid",
116
+ hasLabel && labelLeft && labelLeftWidth === "normal" && "width-normal grid-cols-4",
117
+ hasLabel && labelLeft && labelLeftWidth === "wide" && "width-wide grid-cols-3",
118
+ classProp
119
+ )}
120
+ bind:clientWidth={width}
121
+ {style}
122
+ >
123
+ <div
124
+ class={twMerge(
125
+ "label-box",
126
+ _classCommon,
127
+ "flex",
128
+ labelLeft ? "left items-start mt-2" : "items-end",
129
+ classLabelBox
130
+ )}
131
+ >
132
+ {#if label}
133
+ <label
134
+ for={id}
135
+ class={twMerge(
136
+ "block",
137
+ _classCommon,
138
+ "flex-1 px-2 mb-1 text-base",
139
+ required && "after:content-['*'] after:opacity-40 after:pl-1",
140
+ _preset.label.size[size],
141
+ classLabel
142
+ )}
143
+ >
144
+ {@render snippetOrThc({ id, value: label })}
145
+ </label>
146
+ {/if}
147
+
148
+ {@render snippetOrThc({ id, value: labelAfter })}
149
+ </div>
150
+
151
+ <div
152
+ class={twMerge(
153
+ "input-box",
154
+ _classCommon,
155
+ hasLabel && labelLeft && labelLeftWidth === "normal" && "col-span-3",
156
+ hasLabel && labelLeft && labelLeftWidth === "wide" && "col-span-2",
157
+ classInputBox
158
+ )}
159
+ >
160
+ <div
161
+ class={twMerge(
162
+ "input-wrap",
163
+ _classCommon,
164
+ `rounded-md border border-neutral-300 dark:border-neutral-600
165
+ bg-neutral-100 dark:bg-neutral-700
166
+ focus-within:border-input-accent focus-within:dark:border-input-accent-dark
167
+ focus-within:ring-input-accent/20 focus-within:dark:ring-input-accent-dark/20
168
+ focus-within:ring-4`,
169
+ invalid && "border-input-accent dark:border-input-accent-dark",
170
+ disabled && "cursor-not-allowed opacity-50",
171
+ _preset.inputBox.size[size],
172
+ classInputBoxWrap
173
+ )}
174
+ >
175
+ <div class="flex">
176
+ {@render snippetOrThc({ id, value: inputBefore })}
177
+ {@render children()}
178
+ {@render snippetOrThc({ id, value: inputAfter })}
179
+ </div>
180
+ {@render snippetOrThc({ id, value: inputBelow })}
181
+ </div>
182
+
183
+ {#if validation && !validation?.valid}
184
+ <div
185
+ transition:slide={{ duration: 150 }}
186
+ class={twMerge(
187
+ "validation-box",
188
+ _classCommon,
189
+ "my-1 text-xs px-2 text-input-accent dark:text-input-accent-dark",
190
+ classValidationBox
191
+ )}
192
+ >
193
+ {@html validation.message}
194
+ </div>
195
+ {/if}
196
+
197
+ {#if description}
198
+ <div
199
+ class={twMerge(
200
+ "desc-box",
201
+ _classCommon,
202
+ "mx-2 mt-1 text-sm opacity-50",
203
+ classDescBox
204
+ )}
205
+ >
206
+ {@render snippetOrThc({ id, value: description })}
207
+ </div>
208
+ {/if}
209
+
210
+ {#if below}
211
+ <div class={twMerge("below-box", _classCommon, "mx-2 my-1", classBelowBox)}>
212
+ {@render snippetOrThc({ id, value: below })}
213
+ </div>
214
+ {/if}
215
+ </div>
216
+ </div>
@@ -0,0 +1,36 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { ValidationResult } from "../../../actions/validate.svelte.js";
3
+ import { type THC } from "../../Thc/Thc.svelte";
4
+ type SnippetWithId = Snippet<[{
5
+ id: string;
6
+ }]>;
7
+ interface Props {
8
+ id: string;
9
+ size?: "sm" | "md" | "lg" | string;
10
+ class?: string;
11
+ label?: SnippetWithId | THC;
12
+ labelAfter?: SnippetWithId | THC;
13
+ inputBefore?: SnippetWithId | THC;
14
+ children: Snippet;
15
+ inputAfter?: SnippetWithId | THC;
16
+ inputBelow?: SnippetWithId | THC;
17
+ description?: SnippetWithId | THC;
18
+ below?: SnippetWithId | THC;
19
+ required?: boolean;
20
+ disabled?: boolean;
21
+ validation?: ValidationResult | undefined;
22
+ labelLeft?: boolean;
23
+ labelLeftWidth?: "normal" | "wide";
24
+ labelLeftBreakpoint?: number;
25
+ classLabel?: string;
26
+ classLabelBox?: string;
27
+ classInputBox?: string;
28
+ classInputBoxWrap?: string;
29
+ classDescBox?: string;
30
+ classBelowBox?: string;
31
+ classValidationBox?: string;
32
+ style?: string;
33
+ }
34
+ declare const InputWrap: import("svelte").Component<Props, {}, "">;
35
+ type InputWrap = ReturnType<typeof InputWrap>;
36
+ export default InputWrap;
@@ -0,0 +1,134 @@
1
+ @import "../../_shared.css";
2
+ @plugin '@tailwindcss/forms';
3
+
4
+ /* prettier-ignore */
5
+ @theme inline {
6
+ --color-input-accent: var(--color-input-accent, var(--color-red-600));
7
+ --color-input-accent-dark: var(--color-input-accent-dark, var(--color-red-400));
8
+ }
9
+
10
+ .stuic-input {
11
+ .form-input {
12
+ @apply rounded-md border-0 w-full flex-1
13
+ text-base placeholder:text-base
14
+ bg-transparent
15
+ tracking-tight
16
+ focus:outline-0 focus-visible:ring-0
17
+ placeholder:tracking-tight
18
+ placeholder:text-neutral-950/35 dark:placeholder:text-neutral-50/35
19
+ text-neutral-950 dark:text-neutral-50;
20
+ &.sm {
21
+ @apply text-sm placeholder:text-sm;
22
+ }
23
+ &.lg {
24
+ @apply text-lg placeholder:text-lg;
25
+ }
26
+ }
27
+
28
+ select.form-input {
29
+ @apply pr-8;
30
+ }
31
+
32
+ textarea {
33
+ scrollbar-width: thin;
34
+ }
35
+
36
+ /* https://danielstern.ca/range.css/ */
37
+ input[type="range"] {
38
+ --thumb-width: 18px;
39
+ --thumb-height: 18px;
40
+ --thumb-border-radius: 100%;
41
+ --track-border-radius: 18px;
42
+ --track-height: 4px;
43
+ --track-bg: #808080;
44
+
45
+ width: 100%;
46
+ /* margin: 7px 0; */
47
+ margin: calc((var(--thumb-height) - var(--track-height)) / 2) 0;
48
+ background-color: transparent;
49
+ appearance: none;
50
+
51
+ &:focus {
52
+ @apply ring-0 outline-0 border-0;
53
+ }
54
+ &::-webkit-slider-runnable-track {
55
+ /* background: var(--track-bg); */
56
+ border: 0;
57
+ border-radius: var(--track-border-radius);
58
+ width: 100%;
59
+ height: var(--track-height);
60
+ cursor: pointer;
61
+ @apply bg-neutral-300 dark:bg-neutral-600;
62
+ }
63
+ &::-webkit-slider-thumb {
64
+ /* margin-top: -7px; */
65
+ margin-top: calc(-1 * (var(--thumb-height) - var(--track-height)) / 2);
66
+ width: var(--thumb-width);
67
+ height: var(--thumb-height);
68
+ border: 0;
69
+ border-radius: var(--thumb-border-radius);
70
+ cursor: pointer;
71
+ -webkit-appearance: none;
72
+ @apply bg-input-accent dark:bg-input-accent-dark;
73
+ }
74
+ &:focus::-webkit-slider-runnable-track {
75
+ /* background: var(--track-bg); */
76
+ @apply bg-neutral-300 dark:bg-neutral-600;
77
+ }
78
+ &::-moz-range-track {
79
+ /* background: var(--track-bg); */
80
+ border: 0;
81
+ border-radius: var(--track-border-radius);
82
+ width: 100%;
83
+ height: var(--track-height);
84
+ cursor: pointer;
85
+ @apply bg-neutral-300 dark:bg-neutral-600;
86
+ }
87
+ &::-moz-range-thumb {
88
+ width: var(--thumb-width);
89
+ height: var(--thumb-height);
90
+ border: 0;
91
+ border-radius: var(--thumb-border-radius);
92
+ cursor: pointer;
93
+ @apply bg-input-accent dark:bg-input-accent-dark;
94
+ }
95
+ &::-ms-track {
96
+ background: transparent;
97
+ border-color: transparent;
98
+ border-width: calc((var(--thumb-height) - var(--track-height)) / 2) 0;
99
+ color: transparent;
100
+ width: 100%;
101
+ height: var(--track-height);
102
+ cursor: pointer;
103
+ }
104
+ &::-ms-fill-lower {
105
+ /* background: var(--track-bg); */
106
+ border: 0;
107
+ border-radius: var(--thumb-border-radius);
108
+ @apply bg-neutral-300 dark:bg-neutral-600;
109
+ }
110
+ &::-ms-fill-upper {
111
+ /* background: var(--track-bg); */
112
+ border: 0;
113
+ border-radius: var(--thumb-border-radius);
114
+ @apply bg-neutral-300 dark:bg-neutral-600;
115
+ }
116
+ &::-ms-thumb {
117
+ width: var(--thumb-width);
118
+ height: var(--thumb-height);
119
+ border: 0;
120
+ border-radius: var(--thumb-border-radius);
121
+ cursor: pointer;
122
+ margin-top: 0px;
123
+ @apply bg-input-accent dark:bg-input-accent-dark;
124
+ }
125
+ &:focus::-ms-fill-lower {
126
+ /* background: var(--track-bg); */
127
+ @apply bg-neutral-300 dark:bg-neutral-600;
128
+ }
129
+ &:focus::-ms-fill-upper {
130
+ /* background: var(--track-bg); */
131
+ @apply bg-neutral-300 dark:bg-neutral-600;
132
+ }
133
+ }
134
+ }
@@ -0,0 +1,11 @@
1
+ export * from "./types.js";
2
+ export { default as FieldCheckbox } from "./FieldCheckbox.svelte";
3
+ export { default as FieldFile } from "./FieldFile.svelte";
4
+ export { default as FieldInput } from "./FieldInput.svelte";
5
+ export { default as FieldLikeButton } from "./FieldLikeButton.svelte";
6
+ export { default as FieldOptions } from "./FieldOptions.svelte";
7
+ export { default as FieldRadios } from "./FieldRadios.svelte";
8
+ export { default as FieldSelect } from "./FieldSelect.svelte";
9
+ export { default as Fieldset } from "./Fieldset.svelte";
10
+ export { default as FieldSwitch } from "./FieldSwitch.svelte";
11
+ export { default as FieldTextarea } from "./FieldTextarea.svelte";
@@ -0,0 +1,11 @@
1
+ export * from "./types.js";
2
+ export { default as FieldCheckbox } from "./FieldCheckbox.svelte";
3
+ export { default as FieldFile } from "./FieldFile.svelte";
4
+ export { default as FieldInput } from "./FieldInput.svelte";
5
+ export { default as FieldLikeButton } from "./FieldLikeButton.svelte";
6
+ export { default as FieldOptions } from "./FieldOptions.svelte";
7
+ export { default as FieldRadios } from "./FieldRadios.svelte";
8
+ export { default as FieldSelect } from "./FieldSelect.svelte";
9
+ export { default as Fieldset } from "./Fieldset.svelte";
10
+ export { default as FieldSwitch } from "./FieldSwitch.svelte";
11
+ export { default as FieldTextarea } from "./FieldTextarea.svelte";
@@ -0,0 +1,11 @@
1
+ import type { THC } from "../Thc/Thc.svelte";
2
+ export interface FieldSelectOption {
3
+ label: string;
4
+ value?: string;
5
+ optgroup?: string;
6
+ }
7
+ export interface FieldRadiosOption {
8
+ label: string;
9
+ value?: string;
10
+ description?: THC;
11
+ }
@@ -0,0 +1,89 @@
1
+ <script lang="ts" module>
2
+ type KnownMeta = "cmd" | "opt" | "shift" | "ctrl" | "alt" | "win" | "meta";
3
+
4
+ // just the base ones...
5
+ // Windows Ctrl → macOS Command (⌘)
6
+ // Windows Alt → macOS Option (⌥)
7
+ // Windows Shift → macOS Shift (⇧)
8
+
9
+ export const macToOther: Partial<Record<KnownMeta, KnownMeta>> = {
10
+ cmd: "win",
11
+ };
12
+
13
+ export const otherToMac: Partial<Record<KnownMeta, KnownMeta>> = {
14
+ win: "cmd",
15
+ };
16
+
17
+ export const macSymbol: Partial<Record<KnownMeta, string>> = {
18
+ meta: "⌘",
19
+ cmd: "⌘",
20
+ shift: "⇧",
21
+ ctrl: "⌃",
22
+ alt: "⌥",
23
+ };
24
+
25
+ export const otherSymbol: Partial<Record<KnownMeta, string>> = {
26
+ meta: "⊞",
27
+ win: "⊞",
28
+ shift: "⇧",
29
+ };
30
+ </script>
31
+
32
+ <script lang="ts">
33
+ import { isMac } from "../../utils/is-mac.js";
34
+ import { twMerge } from "../../utils/tw-merge.js";
35
+ import { ucfirst } from "../../utils/ucfirst.js";
36
+
37
+ /**
38
+ * This needs more thoughts... now just quick-n-dirty...
39
+ */
40
+
41
+ interface Props {
42
+ class?: string;
43
+ metas?: KnownMeta[];
44
+ keys: string;
45
+ forcedOs?: "mac" | "win" | "linux";
46
+ }
47
+
48
+ let { class: classProp, metas, keys, forcedOs }: Props = $props();
49
+
50
+ function wrap(s: string, mac: boolean) {
51
+ const cls = ["pr-0.5 font-mono tracking-tight"];
52
+ const sym = mac ? macSymbol[s as KnownMeta] : otherSymbol[s as KnownMeta];
53
+ if (sym) {
54
+ s = sym;
55
+ cls.push("font-sans pr-0");
56
+ }
57
+ const _class = twMerge(...cls);
58
+ return `<span class="${_class}">${ucfirst(s)}</span>`;
59
+ }
60
+
61
+ async function get_meta_key() {
62
+ if (!metas?.length) return "";
63
+ const mac = forcedOs ? forcedOs === "mac" : await isMac();
64
+ const replace = mac ? otherToMac : macToOther;
65
+ const kk = (metas || []).map((m) => wrap(replace[m] ?? m, mac));
66
+ const _unique = uniq(kk);
67
+ if (_unique.length !== kk.length) {
68
+ console.warn(
69
+ `Some meta keys (${metas.join(", ")}) were mapped as duplicates for this OS (${mac ? "MacOS" : "not MacOS"})`
70
+ );
71
+ }
72
+ return _unique.join("");
73
+ }
74
+
75
+ function uniq(s: string[]) {
76
+ return [...new Set(s)];
77
+ }
78
+ </script>
79
+
80
+ <kbd
81
+ class={twMerge(
82
+ "text-xs leading-0 space-x-0.5 rounded px-1 py-0 outline outline-neutral-400",
83
+ classProp
84
+ )}
85
+ >
86
+ {#await get_meta_key() then metaKey}
87
+ <span class="font-sans">{@html metaKey}</span><span>{keys}</span>
88
+ {/await}
89
+ </kbd>
@@ -0,0 +1,17 @@
1
+ type KnownMeta = "cmd" | "opt" | "shift" | "ctrl" | "alt" | "win" | "meta";
2
+ export declare const macToOther: Partial<Record<KnownMeta, KnownMeta>>;
3
+ export declare const otherToMac: Partial<Record<KnownMeta, KnownMeta>>;
4
+ export declare const macSymbol: Partial<Record<KnownMeta, string>>;
5
+ export declare const otherSymbol: Partial<Record<KnownMeta, string>>;
6
+ /**
7
+ * This needs more thoughts... now just quick-n-dirty...
8
+ */
9
+ interface Props {
10
+ class?: string;
11
+ metas?: KnownMeta[];
12
+ keys: string;
13
+ forcedOs?: "mac" | "win" | "linux";
14
+ }
15
+ declare const KbdShortcut: import("svelte").Component<Props, {}, "">;
16
+ type KbdShortcut = ReturnType<typeof KbdShortcut>;
17
+ export default KbdShortcut;
@@ -0,0 +1 @@
1
+ export { default as KbdShortcut } from "./KbdShortcut.svelte";
@@ -0,0 +1 @@
1
+ export { default as KbdShortcut } from "./KbdShortcut.svelte";
@@ -0,0 +1,127 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import Backdrop from "../Backdrop/Backdrop.svelte";
4
+ import { type FocusTrapOptions } from "../../actions/focus-trap.js";
5
+ import { prefersReducedMotion } from "../../utils/prefers-reduced-motion.svelte.js";
6
+ import { twMerge } from "../../utils/tw-merge.js";
7
+
8
+ const prefersReduced = prefersReducedMotion();
9
+
10
+ interface Props {
11
+ visible?: boolean;
12
+ children: Snippet;
13
+ header?: Snippet;
14
+ footer?: Snippet;
15
+ classBackdrop?: string;
16
+ classInner?: string;
17
+ class?: string;
18
+ classHeader?: string;
19
+ classMain?: string;
20
+ classFooter?: string;
21
+
22
+ labelledby?: string;
23
+ describedby?: string;
24
+ transitionDuration?: number;
25
+ elBackdrop?: HTMLDivElement;
26
+ el?: HTMLDivElement;
27
+ focusTrap?: boolean | FocusTrapOptions;
28
+ onEscape?: undefined | (() => void);
29
+
30
+ noScrollLock?: boolean;
31
+ }
32
+
33
+ let {
34
+ visible = $bindable(false),
35
+ children,
36
+ header,
37
+ footer,
38
+ classBackdrop,
39
+ classInner,
40
+ class: classProp,
41
+ classHeader,
42
+ classMain,
43
+ classFooter,
44
+ labelledby,
45
+ describedby,
46
+ transitionDuration = 100,
47
+ // transitionEnabled = true,
48
+ elBackdrop = $bindable(),
49
+ el = $bindable(),
50
+ focusTrap = true,
51
+ onEscape,
52
+ noScrollLock = false,
53
+ }: Props = $props();
54
+
55
+ let backdrop: Backdrop = $state()!;
56
+
57
+ export function close() {
58
+ backdrop.close();
59
+ }
60
+
61
+ export function open(openerOrEvent?: null | HTMLElement | MouseEvent) {
62
+ backdrop.open(openerOrEvent);
63
+ }
64
+
65
+ export function setOpener(opener?: null | HTMLElement) {
66
+ backdrop.setOpener(opener);
67
+ }
68
+
69
+ export function visibility() {
70
+ return backdrop.visibility();
71
+ }
72
+ </script>
73
+
74
+ <Backdrop
75
+ bind:this={backdrop}
76
+ bind:el={elBackdrop}
77
+ bind:visible
78
+ class={twMerge(
79
+ "justify-center items-center bg-black/25 p-2 sm:p-4 md:p-[10vh] transition-all",
80
+ classBackdrop
81
+ )}
82
+ {focusTrap}
83
+ fadeOutDuration={transitionDuration}
84
+ {onEscape}
85
+ {noScrollLock}
86
+ >
87
+ <div
88
+ bind:this={el}
89
+ role="dialog"
90
+ aria-modal="true"
91
+ aria-labelledby={labelledby}
92
+ aria-describedby={describedby}
93
+ class={twMerge(
94
+ "overflow-x-hidden overflow-y-hidden w-full h-full max-w-3xl",
95
+ // "overflow-y-auto w-full h-full max-w-3xl max-h-[66vh] border",
96
+ classInner
97
+ )}
98
+ >
99
+ <div
100
+ class={twMerge(
101
+ "bg-white dark:bg-neutral-800 rounded-md flex flex-col overflow-hidden",
102
+ "w-full max-h-full md:max-h-2/3",
103
+ classProp
104
+ )}
105
+ >
106
+ {#if header}
107
+ <div class={twMerge("header", classHeader)}>
108
+ {@render header()}
109
+ </div>
110
+ {/if}
111
+ <div class={twMerge("main overflow-auto flex-1", classMain)}>
112
+ {@render children()}
113
+ </div>
114
+ {#if footer}
115
+ <div class={twMerge("footer", classFooter)}>
116
+ {@render footer()}
117
+ </div>
118
+ {/if}
119
+ </div>
120
+ </div>
121
+ </Backdrop>
122
+
123
+ <style>
124
+ .main {
125
+ scrollbar-width: thin;
126
+ }
127
+ </style>
@@ -0,0 +1,32 @@
1
+ import type { Snippet } from "svelte";
2
+ import { type FocusTrapOptions } from "../../actions/focus-trap.js";
3
+ interface Props {
4
+ visible?: boolean;
5
+ children: Snippet;
6
+ header?: Snippet;
7
+ footer?: Snippet;
8
+ classBackdrop?: string;
9
+ classInner?: string;
10
+ class?: string;
11
+ classHeader?: string;
12
+ classMain?: string;
13
+ classFooter?: string;
14
+ labelledby?: string;
15
+ describedby?: string;
16
+ transitionDuration?: number;
17
+ elBackdrop?: HTMLDivElement;
18
+ el?: HTMLDivElement;
19
+ focusTrap?: boolean | FocusTrapOptions;
20
+ onEscape?: undefined | (() => void);
21
+ noScrollLock?: boolean;
22
+ }
23
+ declare const Modal: import("svelte").Component<Props, {
24
+ close: () => void;
25
+ open: (openerOrEvent?: null | HTMLElement | MouseEvent) => void;
26
+ setOpener: (opener?: null | HTMLElement) => void;
27
+ visibility: () => {
28
+ readonly visible: boolean;
29
+ };
30
+ }, "el" | "visible" | "elBackdrop">;
31
+ type Modal = ReturnType<typeof Modal>;
32
+ export default Modal;
@@ -0,0 +1 @@
1
+ export { default as Modal } from "./Modal.svelte";
@@ -0,0 +1 @@
1
+ export { default as Modal } from "./Modal.svelte";