@marianmeres/stuic 1.126.0 → 2.0.0-next.2
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.
- package/README.md +2 -8
- package/dist/_shared.css +2 -0
- package/dist/actions/autogrow.svelte.d.ts +6 -0
- package/dist/actions/autogrow.svelte.js +19 -0
- package/dist/actions/highlight-dragover.svelte.d.ts +7 -0
- package/dist/actions/highlight-dragover.svelte.js +38 -0
- package/dist/actions/index.d.ts +7 -0
- package/dist/actions/index.js +7 -0
- package/dist/actions/on-submit-validity-check.svelte.d.ts +15 -0
- package/dist/actions/on-submit-validity-check.svelte.js +58 -0
- package/dist/actions/tooltip/index.css +34 -0
- package/dist/actions/tooltip/tooltip.svelte.d.ts +13 -0
- package/dist/actions/tooltip/tooltip.svelte.js +203 -0
- package/dist/actions/trim.svelte.d.ts +4 -0
- package/dist/actions/trim.svelte.js +17 -0
- package/dist/actions/{validate.d.ts → validate.svelte.d.ts} +8 -8
- package/dist/actions/validate.svelte.js +90 -0
- package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +59 -385
- package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +9 -101
- package/dist/components/AlertConfirmPrompt/Current.svelte +202 -0
- package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +22 -0
- package/dist/components/AlertConfirmPrompt/acp-icons.d.ts +7 -2
- package/dist/components/AlertConfirmPrompt/acp-icons.js +8 -8
- package/dist/components/AlertConfirmPrompt/alert-confirm-prompt-stack.svelte.d.ts +63 -0
- package/dist/components/AlertConfirmPrompt/alert-confirm-prompt-stack.svelte.js +144 -0
- package/dist/components/AlertConfirmPrompt/index.d.ts +2 -0
- package/dist/components/AlertConfirmPrompt/index.js +2 -0
- package/dist/components/AnimatedElipsis/AnimatedEllipsis.svelte +47 -0
- package/dist/components/AnimatedElipsis/AnimatedEllipsis.svelte.d.ts +7 -0
- package/dist/components/AnimatedElipsis/index.d.ts +1 -0
- package/dist/components/AnimatedElipsis/index.js +1 -0
- package/dist/components/AppShell/AppShell.svelte +188 -127
- package/dist/components/AppShell/AppShell.svelte.d.ts +62 -43
- package/dist/components/AppShell/index.d.ts +1 -0
- package/dist/components/AppShell/index.js +1 -0
- package/dist/components/Backdrop/Backdrop.svelte +149 -49
- package/dist/components/Backdrop/Backdrop.svelte.d.ts +22 -37
- package/dist/components/Backdrop/index.d.ts +1 -0
- package/dist/components/Backdrop/index.js +1 -0
- package/dist/components/Button/Button.svelte +122 -146
- package/dist/components/Button/Button.svelte.d.ts +22 -80
- package/dist/components/Button/index.css +16 -0
- package/dist/components/Button/index.d.ts +1 -0
- package/dist/components/Button/index.js +1 -0
- package/dist/components/ColResize/ColResize.svelte +0 -0
- package/dist/components/ColResize/ColResize.svelte.d.ts +26 -0
- package/dist/components/ColorScheme/{LocalColorScheme.svelte → ColorSchemeLocal.svelte} +2 -2
- package/dist/components/ColorScheme/ColorSchemeLocal.svelte.d.ts +26 -0
- package/dist/components/ColorScheme/{SystemAwareColorScheme.svelte → ColorSchemeSystemAware.svelte} +4 -4
- package/dist/components/ColorScheme/ColorSchemeSystemAware.svelte.d.ts +26 -0
- package/dist/components/ColorScheme/color-scheme.d.ts +26 -8
- package/dist/components/ColorScheme/color-scheme.js +40 -16
- package/dist/components/ColorScheme/index.d.ts +3 -0
- package/dist/components/ColorScheme/index.js +3 -0
- package/dist/components/DismissibleMessage/DismissibleMessage.svelte +76 -83
- package/dist/components/DismissibleMessage/DismissibleMessage.svelte.d.ts +16 -37
- package/dist/components/DismissibleMessage/index.css +13 -0
- package/dist/components/DismissibleMessage/index.d.ts +1 -0
- package/dist/components/DismissibleMessage/index.js +1 -0
- package/dist/components/Drawer/Drawer.svelte +155 -84
- package/dist/components/Drawer/Drawer.svelte.d.ts +24 -35
- package/dist/components/Drawer/index.d.ts +1 -0
- package/dist/components/Drawer/index.js +1 -0
- package/dist/components/HoverExpandableWidth/HoverExpandableWidth.svelte +150 -111
- package/dist/components/HoverExpandableWidth/HoverExpandableWidth.svelte.d.ts +16 -29
- package/dist/components/HoverExpandableWidth/index.d.ts +1 -0
- package/dist/components/HoverExpandableWidth/index.js +1 -0
- package/dist/components/Input/FieldCheckbox.svelte +174 -132
- package/dist/components/Input/FieldCheckbox.svelte.d.ts +28 -64
- package/dist/components/Input/FieldFile.svelte +166 -0
- package/dist/components/Input/FieldFile.svelte.d.ts +41 -0
- package/dist/components/Input/FieldInput.svelte +143 -0
- package/dist/components/Input/FieldInput.svelte.d.ts +41 -0
- package/dist/components/Input/FieldLikeButton.svelte +206 -0
- package/dist/components/Input/FieldLikeButton.svelte.d.ts +41 -0
- package/dist/components/Input/FieldOptions.svelte +646 -0
- package/dist/components/Input/FieldOptions.svelte.d.ts +58 -0
- package/dist/components/Input/FieldRadios.svelte +126 -77
- package/dist/components/Input/FieldRadios.svelte.d.ts +23 -61
- package/dist/components/Input/FieldSelect.svelte +160 -239
- package/dist/components/Input/FieldSelect.svelte.d.ts +40 -88
- package/dist/components/Input/FieldSwitch.svelte +132 -0
- package/dist/components/Input/FieldSwitch.svelte.d.ts +41 -0
- package/dist/components/Input/FieldTextarea.svelte +146 -0
- package/dist/components/Input/FieldTextarea.svelte.d.ts +44 -0
- package/dist/components/Input/Fieldset.svelte +21 -17
- package/dist/components/Input/Fieldset.svelte.d.ts +10 -27
- package/dist/components/Input/_internal/FieldRadioInternal.svelte +186 -0
- package/dist/components/Input/_internal/FieldRadioInternal.svelte.d.ts +30 -0
- package/dist/components/Input/_internal/InputWrap.svelte +216 -0
- package/dist/components/Input/_internal/InputWrap.svelte.d.ts +36 -0
- package/dist/components/Input/index.css +134 -0
- package/dist/components/Input/index.d.ts +11 -0
- package/dist/components/Input/index.js +11 -0
- package/dist/components/Input/types.d.ts +11 -0
- package/dist/components/KbdShortcut/KbdShortcut.svelte +89 -0
- package/dist/components/KbdShortcut/KbdShortcut.svelte.d.ts +17 -0
- package/dist/components/KbdShortcut/index.d.ts +1 -0
- package/dist/components/KbdShortcut/index.js +1 -0
- package/dist/components/Modal/Modal.svelte +127 -0
- package/dist/components/Modal/Modal.svelte.d.ts +32 -0
- package/dist/components/Modal/index.d.ts +1 -0
- package/dist/components/Modal/index.js +1 -0
- package/dist/components/ModalDialog/ModalDialog.svelte +137 -81
- package/dist/components/ModalDialog/ModalDialog.svelte.d.ts +17 -38
- package/dist/components/ModalDialog/index.d.ts +1 -0
- package/dist/components/ModalDialog/index.js +1 -0
- package/dist/components/Notifications/Notifications.svelte +259 -173
- package/dist/components/Notifications/Notifications.svelte.d.ts +32 -60
- package/dist/components/Notifications/index.css +12 -0
- package/dist/components/Notifications/index.d.ts +2 -0
- package/dist/components/Notifications/index.js +2 -0
- package/dist/components/Notifications/notifications-icons.d.ts +1 -1
- package/dist/components/Notifications/notifications-icons.js +4 -4
- package/dist/components/Notifications/notifications-stack.svelte.d.ts +89 -0
- package/dist/components/Notifications/notifications-stack.svelte.js +161 -0
- package/dist/components/Progress/Progress.svelte +26 -0
- package/dist/components/Progress/Progress.svelte.d.ts +10 -0
- package/dist/components/Progress/_internal/Bar.svelte +31 -0
- package/dist/components/Progress/_internal/Bar.svelte.d.ts +10 -0
- package/dist/components/Progress/_internal/Circle.svelte +10 -0
- package/dist/components/Progress/_internal/Circle.svelte.d.ts +7 -0
- package/dist/components/Progress/index.css +7 -0
- package/dist/components/Progress/index.d.ts +1 -0
- package/dist/components/Progress/index.js +1 -0
- package/dist/components/Spinner/Spinner.svelte +56 -41
- package/dist/components/Spinner/Spinner.svelte.d.ts +10 -22
- package/dist/components/Spinner/index.d.ts +1 -0
- package/dist/components/Spinner/index.js +1 -0
- package/dist/components/Switch/Switch.svelte +158 -118
- package/dist/components/Switch/Switch.svelte.d.ts +25 -66
- package/dist/components/Switch/SwitchButton.svelte +131 -0
- package/dist/components/Switch/SwitchButton.svelte.d.ts +21 -0
- package/dist/components/Switch/index.css +7 -0
- package/dist/components/Switch/index.d.ts +2 -0
- package/dist/components/Switch/index.js +2 -0
- package/dist/components/Thc/Thc.svelte +67 -10
- package/dist/components/Thc/Thc.svelte.d.ts +18 -22
- package/dist/components/Thc/index.d.ts +1 -0
- package/dist/components/Thc/index.js +1 -0
- package/dist/components/TwCheck/TwCheck.svelte +34 -0
- package/dist/components/TwCheck/TwCheck.svelte.d.ts +10 -0
- package/dist/components/TwCheck/index.css +5 -0
- package/dist/components/TwCheck/index.d.ts +1 -0
- package/dist/components/TwCheck/index.js +1 -0
- package/dist/components/X/X.svelte +12 -5
- package/dist/components/X/X.svelte.d.ts +6 -18
- package/dist/components/X/index.d.ts +1 -0
- package/dist/components/X/index.js +1 -0
- package/dist/index.css +26 -0
- package/dist/index.d.ts +21 -39
- package/dist/index.js +23 -54
- package/dist/types.d.ts +251 -2
- package/dist/types.js +248 -0
- package/dist/utils/breakpoint.svelte.d.ts +19 -0
- package/dist/utils/breakpoint.svelte.js +42 -0
- package/dist/utils/debounce.d.ts +13 -0
- package/dist/utils/debounce.js +22 -0
- package/dist/utils/device-pointer.svelte.d.ts +11 -0
- package/dist/utils/device-pointer.svelte.js +26 -0
- package/dist/utils/event-modifiers.d.ts +4 -0
- package/dist/utils/event-modifiers.js +29 -0
- package/dist/utils/get-id.d.ts +1 -1
- package/dist/utils/get-id.js +3 -1
- package/dist/utils/index.d.ts +21 -0
- package/dist/utils/index.js +21 -0
- package/dist/utils/is-browser.d.ts +1 -0
- package/dist/utils/is-browser.js +5 -0
- package/dist/utils/is-mac.d.ts +1 -0
- package/dist/utils/is-mac.js +11 -0
- package/dist/utils/maybe-json-parse.d.ts +1 -0
- package/dist/utils/maybe-json-parse.js +12 -0
- package/dist/utils/maybe-json-stringify.d.ts +1 -0
- package/dist/utils/maybe-json-stringify.js +11 -0
- package/dist/utils/move-array-item.d.ts +4 -0
- package/dist/utils/move-array-item.js +20 -0
- package/dist/utils/omit-pick.d.ts +2 -2
- package/dist/utils/omit-pick.js +10 -8
- package/dist/utils/paint.d.ts +18 -0
- package/dist/utils/paint.js +32 -0
- package/dist/utils/persistent-state.svelte.d.ts +23 -0
- package/dist/utils/persistent-state.svelte.js +48 -0
- package/dist/utils/prefers-reduced-motion.svelte.d.ts +2 -0
- package/dist/utils/prefers-reduced-motion.svelte.js +4 -0
- package/dist/utils/qsa.d.ts +1 -0
- package/dist/utils/qsa.js +3 -0
- package/dist/utils/sleep.d.ts +28 -0
- package/dist/utils/sleep.js +33 -0
- package/dist/utils/storage-abstraction.d.ts +35 -0
- package/dist/utils/storage-abstraction.js +136 -0
- package/dist/utils/str-hash.d.ts +7 -0
- package/dist/utils/str-hash.js +35 -0
- package/dist/utils/throttle.d.ts +1 -0
- package/dist/utils/throttle.js +47 -0
- package/dist/utils/to-integer.d.ts +1 -0
- package/dist/utils/to-integer.js +11 -0
- package/dist/utils/tr.d.ts +5 -0
- package/dist/utils/tr.js +13 -0
- package/dist/utils/tw-merge.d.ts +10 -0
- package/dist/utils/tw-merge.js +16 -0
- package/dist/utils/ucfirst.d.ts +1 -0
- package/dist/utils/ucfirst.js +6 -0
- package/package.json +66 -73
- package/dist/actions/autogrow.d.ts +0 -8
- package/dist/actions/autogrow.js +0 -22
- package/dist/actions/autoscroll.d.ts +0 -21
- package/dist/actions/autoscroll.js +0 -60
- package/dist/actions/drag-drop.d.ts +0 -28
- package/dist/actions/drag-drop.js +0 -152
- package/dist/actions/on-outside.d.ts +0 -9
- package/dist/actions/on-outside.js +0 -27
- package/dist/actions/pre-submit-validity-check.d.ts +0 -3
- package/dist/actions/pre-submit-validity-check.js +0 -21
- package/dist/actions/tooltip/_make-visible.d.ts +0 -3
- package/dist/actions/tooltip/_make-visible.js +0 -25
- package/dist/actions/tooltip/_maybe-pick-safe-placement.d.ts +0 -3
- package/dist/actions/tooltip/_maybe-pick-safe-placement.js +0 -86
- package/dist/actions/tooltip/_set-position.d.ts +0 -2
- package/dist/actions/tooltip/_set-position.js +0 -125
- package/dist/actions/tooltip/tooltip.d.ts +0 -42
- package/dist/actions/tooltip/tooltip.js +0 -299
- package/dist/actions/trim.d.ts +0 -4
- package/dist/actions/trim.js +0 -18
- package/dist/actions/validate.js +0 -80
- package/dist/components/AlertConfirmPrompt/alert-confirm-prompt.d.ts +0 -58
- package/dist/components/AlertConfirmPrompt/alert-confirm-prompt.js +0 -141
- package/dist/components/ColorScheme/LocalColorScheme.svelte.d.ts +0 -25
- package/dist/components/ColorScheme/SystemAwareColorScheme.svelte.d.ts +0 -25
- package/dist/components/Input/Field.svelte +0 -315
- package/dist/components/Input/Field.svelte.d.ts +0 -102
- package/dist/components/Input/PinInput.svelte +0 -151
- package/dist/components/Input/PinInput.svelte.d.ts +0 -51
- package/dist/components/Input/XFieldRadioInternal.svelte +0 -143
- package/dist/components/Input/XFieldRadioInternal.svelte.d.ts +0 -45
- package/dist/components/Notifications/notifications.d.ts +0 -78
- package/dist/components/Notifications/notifications.js +0 -215
- package/dist/components/Popover/Popover.svelte +0 -24
- package/dist/components/Popover/Popover.svelte.d.ts +0 -22
- package/dist/components/Spinner/Spinner.v5.svelte +0 -114
- package/dist/components/Spinner/Spinner.v5.svelte.d.ts +0 -16
- package/dist/utils/calculate-alignment.d.ts +0 -68
- package/dist/utils/calculate-alignment.js +0 -183
- package/dist/utils/device-pointer.d.ts +0 -5
- package/dist/utils/device-pointer.js +0 -10
- package/dist/utils/prefers-reduced-motion.d.ts +0 -6
- package/dist/utils/prefers-reduced-motion.js +0 -26
- package/dist/utils/tw-merge2.d.ts +0 -3
- package/dist/utils/tw-merge2.js +0 -9
- package/dist/utils/tw-types.d.ts +0 -1
- package/dist/utils/window-size.d.ts +0 -22
- package/dist/utils/window-size.js +0 -35
- /package/dist/{utils/tw-types.js → components/Input/types.js} +0 -0
package/README.md
CHANGED
|
@@ -2,14 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
*S*velte *T*ailwind _UI_ *C*omponents.
|
|
4
4
|
|
|
5
|
-
OPINIONATED, UNSTABLE
|
|
5
|
+
OPINIONATED, UNSTABLE AND IN PROGRESS...
|
|
6
6
|
|
|
7
7
|
Ongoing effort to build reusable Svelte UI primitives as I need them, inspired by many
|
|
8
|
-
other libs,
|
|
8
|
+
other libs -- cherry-picked, combined, adjusted and tweaked to my personal preference and needs.
|
|
9
9
|
|
|
10
|
-
- https://www.skeleton.dev/
|
|
11
|
-
- https://flowbite-svelte.com/
|
|
12
|
-
- https://captaincodeman.github.io/svelte-headlessui/
|
|
13
|
-
- https://www.svelteui.org/
|
|
14
|
-
|
|
15
|
-
Cherry-picked, combined, adjusted and tweaked to my personal preference and needs.
|
package/dist/_shared.css
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function autogrow(el, fn) {
|
|
2
|
+
$effect(() => {
|
|
3
|
+
let { enabled = true, max = 250, immediate = true } = fn?.() || {};
|
|
4
|
+
function set_height(e) {
|
|
5
|
+
if (enabled) {
|
|
6
|
+
el.style.height = "auto"; // Reset height to auto to correctly calculate scrollHeight
|
|
7
|
+
el.style.height = Math.min(el.scrollHeight, max) + "px";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
if (immediate)
|
|
11
|
+
set_height(null);
|
|
12
|
+
el.addEventListener("input", set_height);
|
|
13
|
+
el.addEventListener("blur", set_height);
|
|
14
|
+
return () => {
|
|
15
|
+
el.removeEventListener("input", set_height);
|
|
16
|
+
el.removeEventListener("blur", set_height);
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Will just add classes to el when being dragged over
|
|
3
|
+
*/
|
|
4
|
+
export function highlightDragover(el, fn) {
|
|
5
|
+
// function handle_drop(e: DragEvent) {
|
|
6
|
+
// const files = e?.dataTransfer?.files;
|
|
7
|
+
// // Update the file input with the dropped files
|
|
8
|
+
// el.files = files || null;
|
|
9
|
+
// // Trigger change event for any listeners
|
|
10
|
+
// el.dispatchEvent(new Event("change"));
|
|
11
|
+
// }
|
|
12
|
+
function prevent(e) {
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
e.stopPropagation();
|
|
15
|
+
}
|
|
16
|
+
const HIGH = ["dragenter", "dragover"];
|
|
17
|
+
const UNHIGH = ["dragleave", "drop"];
|
|
18
|
+
// const ALL = [...HIGH, ...UNHIGH];
|
|
19
|
+
$effect(() => {
|
|
20
|
+
let { classes = ["dragover"], enabled = true } = fn?.() || {};
|
|
21
|
+
if (!enabled)
|
|
22
|
+
return;
|
|
23
|
+
if (!Array.isArray(classes))
|
|
24
|
+
classes = [classes];
|
|
25
|
+
const highlight = () => el.classList.add(...classes);
|
|
26
|
+
const unhighlight = () => el.classList.remove(...classes);
|
|
27
|
+
// ALL.forEach((name: any) => el.addEventListener(name, prevent, false));
|
|
28
|
+
HIGH.forEach((name) => el.addEventListener(name, highlight, false));
|
|
29
|
+
UNHIGH.forEach((name) => el.addEventListener(name, unhighlight, false));
|
|
30
|
+
// el.addEventListener("drop", handle_drop, false);
|
|
31
|
+
return () => {
|
|
32
|
+
// ALL.forEach((name: any) => el.removeEventListener(name, prevent));
|
|
33
|
+
HIGH.forEach((name) => el.removeEventListener(name, highlight));
|
|
34
|
+
UNHIGH.forEach((name) => el.removeEventListener(name, unhighlight));
|
|
35
|
+
// el.removeEventListener("drop", handle_drop);
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./autogrow.svelte.js";
|
|
2
|
+
export * from "./focus-trap.js";
|
|
3
|
+
export * from "./highlight-dragover.svelte.js";
|
|
4
|
+
export * from "./on-submit-validity-check.svelte.js";
|
|
5
|
+
export * from "./tooltip/tooltip.svelte.js";
|
|
6
|
+
export * from "./trim.svelte.js";
|
|
7
|
+
export * from "./validate.svelte.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./autogrow.svelte.js";
|
|
2
|
+
export * from "./focus-trap.js";
|
|
3
|
+
export * from "./highlight-dragover.svelte.js";
|
|
4
|
+
export * from "./on-submit-validity-check.svelte.js";
|
|
5
|
+
export * from "./tooltip/tooltip.svelte.js";
|
|
6
|
+
export * from "./trim.svelte.js";
|
|
7
|
+
export * from "./validate.svelte.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The problem: custom validity checks via `validate` action are registered on
|
|
3
|
+
* "input" or "change" events. When a form is submitted without touching those custom
|
|
4
|
+
* validated elements, those will not be validity-checked...
|
|
5
|
+
* I'm not able to come up with better solution than to manually trigger events which will
|
|
6
|
+
* then trigger the custom validation... (utilizing the `requestSubmit` seems like
|
|
7
|
+
* a right direction, but that still is not good)
|
|
8
|
+
*
|
|
9
|
+
* Still, smells like a hack...
|
|
10
|
+
*/
|
|
11
|
+
export declare function onSubmitValidityCheck(node: HTMLFormElement): void;
|
|
12
|
+
export declare namespace onSubmitValidityCheck {
|
|
13
|
+
var SUBMIT_VALID_EVENT_NAME: string;
|
|
14
|
+
var SUBMIT_INVALID_EVENT_NAME: string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const SUBMIT_VALID_EVENT_NAME = "submit_valid";
|
|
2
|
+
const SUBMIT_INVALID_EVENT_NAME = "submit_invalid";
|
|
3
|
+
/**
|
|
4
|
+
* The problem: custom validity checks via `validate` action are registered on
|
|
5
|
+
* "input" or "change" events. When a form is submitted without touching those custom
|
|
6
|
+
* validated elements, those will not be validity-checked...
|
|
7
|
+
* I'm not able to come up with better solution than to manually trigger events which will
|
|
8
|
+
* then trigger the custom validation... (utilizing the `requestSubmit` seems like
|
|
9
|
+
* a right direction, but that still is not good)
|
|
10
|
+
*
|
|
11
|
+
* Still, smells like a hack...
|
|
12
|
+
*/
|
|
13
|
+
export function onSubmitValidityCheck(node) {
|
|
14
|
+
const onSubmit = (e) => {
|
|
15
|
+
e.preventDefault();
|
|
16
|
+
// this will disable all other onsubmit listeners...
|
|
17
|
+
e.stopImmediatePropagation();
|
|
18
|
+
let invalid = [];
|
|
19
|
+
for (let i = 0; i < node.elements?.length; i++) {
|
|
20
|
+
let el = node.elements[i];
|
|
21
|
+
if (typeof el.checkValidity === "function") {
|
|
22
|
+
// hm... radios are tricky, as triggering change automatically checks the last
|
|
23
|
+
// input (last radio input), which is not desired
|
|
24
|
+
if (el.type === "radio")
|
|
25
|
+
continue;
|
|
26
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
27
|
+
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
28
|
+
// typeof el.checkValidity === "function" && !el.checkValidity();
|
|
29
|
+
// NOTE: el.checkValidity() returns true for hidden inputs event if they are invalid!
|
|
30
|
+
// if (!el.checkValidity()) {
|
|
31
|
+
if (!el.validity.valid) {
|
|
32
|
+
invalid.push(el);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// none invalid
|
|
37
|
+
if (!invalid.length) {
|
|
38
|
+
node.dispatchEvent(new CustomEvent(SUBMIT_VALID_EVENT_NAME, {
|
|
39
|
+
bubbles: true,
|
|
40
|
+
detail: { formData: new FormData(node) },
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
node.dispatchEvent(new CustomEvent(SUBMIT_INVALID_EVENT_NAME, {
|
|
45
|
+
bubbles: true,
|
|
46
|
+
detail: { invalid },
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
$effect(() => {
|
|
51
|
+
node.addEventListener("submit", onSubmit, true);
|
|
52
|
+
return () => {
|
|
53
|
+
node.removeEventListener("submit", onSubmit, true);
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
onSubmitValidityCheck.SUBMIT_VALID_EVENT_NAME = SUBMIT_VALID_EVENT_NAME;
|
|
58
|
+
onSubmitValidityCheck.SUBMIT_INVALID_EVENT_NAME = SUBMIT_INVALID_EVENT_NAME;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* prettier-ignore */
|
|
2
|
+
@theme inline {
|
|
3
|
+
/* style props will not work as with regular components, because tooltips are created outside of the anchor dom tree */
|
|
4
|
+
--color-tooltip-bg: var(--color-tooltip-bg, var(--color-neutral-800));
|
|
5
|
+
--color-tooltip-bg-dark: var(--color-tooltip-bg-dark, var(--color-neutral-300));
|
|
6
|
+
--color-tooltip-text: var(--color-tooltip-text, var(--color-white));
|
|
7
|
+
--color-tooltip-text-dark: var(--color-tooltip-text-dark, var(--color-black));
|
|
8
|
+
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.stuic-tooltip {
|
|
12
|
+
position: fixed;
|
|
13
|
+
display: none;
|
|
14
|
+
opacity: 0;
|
|
15
|
+
transition-property: opacity;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@supports (anchor-name: --anchor) {
|
|
19
|
+
.stuic-tooltip {
|
|
20
|
+
position-area: top span-right;
|
|
21
|
+
position-try-fallbacks:
|
|
22
|
+
flip-inline,
|
|
23
|
+
flip-block,
|
|
24
|
+
flip-block flip-inline;
|
|
25
|
+
|
|
26
|
+
&.tt-block {
|
|
27
|
+
display: block;
|
|
28
|
+
opacity: 0;
|
|
29
|
+
&.tt-visible {
|
|
30
|
+
opacity: 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import "./index.css";
|
|
2
|
+
export declare function isTooltipSupported(): boolean;
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
export declare function tooltip(anchorEl: HTMLElement, fn?: () => {
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
content?: string | null;
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
class?: string;
|
|
11
|
+
onShow?: CallableFunction;
|
|
12
|
+
onHide?: CallableFunction;
|
|
13
|
+
}): void;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { twMerge } from "../../utils/tw-merge.js";
|
|
2
|
+
//
|
|
3
|
+
import "./index.css";
|
|
4
|
+
const TIMEOUT = 200;
|
|
5
|
+
const TRANSITION = 200;
|
|
6
|
+
export function isTooltipSupported() {
|
|
7
|
+
return (CSS.supports("anchor-name", "--anchor") &&
|
|
8
|
+
CSS.supports("position-area", "top") &&
|
|
9
|
+
CSS.supports("position-try", "top") &&
|
|
10
|
+
CSS.supports("position-try-fallbacks", "top"));
|
|
11
|
+
}
|
|
12
|
+
//
|
|
13
|
+
// let _initialized = false;
|
|
14
|
+
// function global_init_once() {
|
|
15
|
+
// if (!is_tooltip_supported()) {
|
|
16
|
+
// console.warn("Tooltips not supported...");
|
|
17
|
+
// return false;
|
|
18
|
+
// }
|
|
19
|
+
// if (!_initialized) {
|
|
20
|
+
// _initialized = true;
|
|
21
|
+
// // const sheet = new CSSStyleSheet();
|
|
22
|
+
// // sheet.replaceSync(`
|
|
23
|
+
// // .stuic-tooltip {
|
|
24
|
+
// // position: fixed;
|
|
25
|
+
// // display: none;
|
|
26
|
+
// // opacity: 0;
|
|
27
|
+
// // transition-property: opacity;
|
|
28
|
+
// // transition-duration: ${TRANSITION}ms;
|
|
29
|
+
// // }
|
|
30
|
+
// // @supports (anchor-name: --anchor) {
|
|
31
|
+
// // .stuic-tooltip {
|
|
32
|
+
// // position-area: top span-right;
|
|
33
|
+
// // position-try-fallbacks: flip-inline, flip-block, flip-block flip-inline;
|
|
34
|
+
// // }
|
|
35
|
+
// // .stuic-tooltip.tt-block {
|
|
36
|
+
// // display: block;
|
|
37
|
+
// // opacity: 0;
|
|
38
|
+
// // }
|
|
39
|
+
// // .stuic-tooltip.tt-block.tt-visible {
|
|
40
|
+
// // display: block;
|
|
41
|
+
// // opacity: 1;
|
|
42
|
+
// // }
|
|
43
|
+
// // }
|
|
44
|
+
// // `);
|
|
45
|
+
// // document.adoptedStyleSheets = [sheet];
|
|
46
|
+
// }
|
|
47
|
+
// return true;
|
|
48
|
+
// }
|
|
49
|
+
const _classTooltip = `
|
|
50
|
+
bg-tooltip-bg dark:bg-tooltip-bg-dark text-tooltip-text dark:text-tooltip-text-dark
|
|
51
|
+
text-xs tracking-tight rounded my-1
|
|
52
|
+
px-2.5 py-1.5
|
|
53
|
+
max-w-64
|
|
54
|
+
z-50
|
|
55
|
+
`;
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
*/
|
|
59
|
+
export function tooltip(anchorEl, fn) {
|
|
60
|
+
// the node has been mounted in the DOM
|
|
61
|
+
if (!isTooltipSupported())
|
|
62
|
+
return;
|
|
63
|
+
//
|
|
64
|
+
let tooltipEl;
|
|
65
|
+
let hide_timer = null;
|
|
66
|
+
let show_timer = null;
|
|
67
|
+
let do_debug = false;
|
|
68
|
+
let on_show = null;
|
|
69
|
+
let on_hide = null;
|
|
70
|
+
let content = null;
|
|
71
|
+
let classTooltip = null;
|
|
72
|
+
let enabled = true;
|
|
73
|
+
//
|
|
74
|
+
const rnd = Math.random().toString(36).slice(2);
|
|
75
|
+
const id = `tooltip-${rnd}`;
|
|
76
|
+
const anchorName = `--anchor-${rnd}`;
|
|
77
|
+
// node once init
|
|
78
|
+
anchorEl.style.cssText += `anchor-name: ${anchorName};`;
|
|
79
|
+
anchorEl.setAttribute("aria-describedby", id);
|
|
80
|
+
anchorEl.setAttribute("aria-expanded", "false");
|
|
81
|
+
const debug = (...args) => {
|
|
82
|
+
do_debug && console.debug("[tooltip]", rnd, ...args);
|
|
83
|
+
};
|
|
84
|
+
function ensure_tooltip() {
|
|
85
|
+
debug("ensure_tooltip()", content, classTooltip);
|
|
86
|
+
if (!content)
|
|
87
|
+
return false;
|
|
88
|
+
// lazy factory init
|
|
89
|
+
if (!tooltipEl) {
|
|
90
|
+
debug("creating element...");
|
|
91
|
+
tooltipEl = document.createElement("div");
|
|
92
|
+
tooltipEl.setAttribute("id", id);
|
|
93
|
+
tooltipEl.setAttribute("role", "tooltip");
|
|
94
|
+
tooltipEl.style.cssText += `position-anchor: ${anchorName}; transition-duration: ${TRANSITION}ms;`;
|
|
95
|
+
tooltipEl.classList.add(...twMerge("stuic-tooltip", _classTooltip).split(/\s/));
|
|
96
|
+
document.body.appendChild(tooltipEl);
|
|
97
|
+
//
|
|
98
|
+
tooltipEl.addEventListener("mouseover", schedule_show);
|
|
99
|
+
tooltipEl.addEventListener("mouseout", schedule_hide);
|
|
100
|
+
}
|
|
101
|
+
// re/set based on params
|
|
102
|
+
set_content();
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
function set_content() {
|
|
106
|
+
if (tooltipEl) {
|
|
107
|
+
debug("set_content()", classTooltip, content);
|
|
108
|
+
if (classTooltip) {
|
|
109
|
+
let old = tooltipEl.className;
|
|
110
|
+
tooltipEl.className = ""; // reset
|
|
111
|
+
tooltipEl.classList.add(...twMerge(old, classTooltip).split(/\s/));
|
|
112
|
+
}
|
|
113
|
+
tooltipEl.textContent = "";
|
|
114
|
+
tooltipEl.innerHTML = `${content}`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function clear_show() {
|
|
118
|
+
clearTimeout(show_timer);
|
|
119
|
+
show_timer = null;
|
|
120
|
+
}
|
|
121
|
+
function clear_hide() {
|
|
122
|
+
clearTimeout(hide_timer);
|
|
123
|
+
hide_timer = null;
|
|
124
|
+
}
|
|
125
|
+
function clear_both() {
|
|
126
|
+
clear_show();
|
|
127
|
+
clear_hide();
|
|
128
|
+
}
|
|
129
|
+
function schedule_show() {
|
|
130
|
+
debug("schedule_show()", enabled);
|
|
131
|
+
clear_both();
|
|
132
|
+
if (!enabled || !ensure_tooltip())
|
|
133
|
+
return;
|
|
134
|
+
show_timer = setTimeout(() => {
|
|
135
|
+
if (!hide_timer) {
|
|
136
|
+
debug("show...");
|
|
137
|
+
clear_show();
|
|
138
|
+
anchorEl.setAttribute("aria-expanded", "true");
|
|
139
|
+
//
|
|
140
|
+
tooltipEl.classList.add("tt-block");
|
|
141
|
+
setTimeout(() => {
|
|
142
|
+
tooltipEl.classList.add("tt-visible");
|
|
143
|
+
on_show?.();
|
|
144
|
+
}, TRANSITION);
|
|
145
|
+
// waitForTwoRepaints().then(() => {
|
|
146
|
+
// tooltipEl.classList.add("tt-visible");
|
|
147
|
+
// this approach is nicer, but I have a suspicion of the event handlers not being destroyed properly (maybe just a hot-reload issues...)
|
|
148
|
+
// waitForTransitionEnd(tooltipEl).then(() => on_show?.());
|
|
149
|
+
// });
|
|
150
|
+
}
|
|
151
|
+
}, TIMEOUT);
|
|
152
|
+
}
|
|
153
|
+
function schedule_hide() {
|
|
154
|
+
debug("scheduleHide()", enabled);
|
|
155
|
+
clear_both();
|
|
156
|
+
// legit - maybe there was no content available...
|
|
157
|
+
if (!tooltipEl)
|
|
158
|
+
return false;
|
|
159
|
+
hide_timer = setTimeout(() => {
|
|
160
|
+
debug("hide...");
|
|
161
|
+
clear_hide();
|
|
162
|
+
anchorEl.setAttribute("aria-expanded", "false");
|
|
163
|
+
tooltipEl.classList.remove("tt-visible");
|
|
164
|
+
setTimeout(() => {
|
|
165
|
+
tooltipEl.classList.remove("tt-block");
|
|
166
|
+
on_hide?.();
|
|
167
|
+
}, TRANSITION);
|
|
168
|
+
// this approach is nicer, but I have a suspicion of the event handlers not being destroyed properly (maybe just a hot-reload issues...)
|
|
169
|
+
// waitForTransitionEnd(tooltipEl).then(() => {
|
|
170
|
+
// tooltipEl.classList.remove("tt-block");
|
|
171
|
+
// on_hide?.();
|
|
172
|
+
// });
|
|
173
|
+
}, TIMEOUT);
|
|
174
|
+
}
|
|
175
|
+
// "reactive" params re/set
|
|
176
|
+
$effect(() => {
|
|
177
|
+
let { enabled: _enabled, content: _content, debug: debugParam, class: _classTooltip, onShow, onHide, } = fn?.() || {};
|
|
178
|
+
// re/assign new params
|
|
179
|
+
do_debug = !!debugParam;
|
|
180
|
+
on_show = onShow;
|
|
181
|
+
on_hide = onHide;
|
|
182
|
+
content = _content ||= anchorEl.getAttribute("aria-label");
|
|
183
|
+
classTooltip = _classTooltip;
|
|
184
|
+
enabled = _enabled ?? true;
|
|
185
|
+
// this will be effective here only if currently in open state, otherwise noop
|
|
186
|
+
set_content();
|
|
187
|
+
// do not return cleanups here - we want the tooltipEl to persist params change
|
|
188
|
+
});
|
|
189
|
+
// add/remove listeners effect ("non-reactive")
|
|
190
|
+
$effect(() => {
|
|
191
|
+
anchorEl.addEventListener("mouseover", schedule_show);
|
|
192
|
+
anchorEl.addEventListener("mouseout", schedule_hide);
|
|
193
|
+
return () => {
|
|
194
|
+
anchorEl.removeEventListener("mouseover", schedule_show);
|
|
195
|
+
anchorEl.removeEventListener("mouseout", schedule_hide);
|
|
196
|
+
// might not have been initialized
|
|
197
|
+
tooltipEl?.removeEventListener("mouseover", schedule_show);
|
|
198
|
+
tooltipEl?.removeEventListener("mouseout", schedule_hide);
|
|
199
|
+
tooltipEl?.remove();
|
|
200
|
+
clear_both();
|
|
201
|
+
};
|
|
202
|
+
});
|
|
203
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function trim(el, fn) {
|
|
2
|
+
// the node has been mounted in the DOM
|
|
3
|
+
$effect(() => {
|
|
4
|
+
// setup goes here
|
|
5
|
+
let { enabled, setValue } = fn?.() || { enabled: true };
|
|
6
|
+
function trim(e) {
|
|
7
|
+
if (enabled && typeof el.value === "string") {
|
|
8
|
+
el.value = el.value.trim();
|
|
9
|
+
setValue?.(el.value);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
el.addEventListener("change", trim);
|
|
13
|
+
return () => {
|
|
14
|
+
el.removeEventListener("change", trim);
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
}
|
|
@@ -5,18 +5,18 @@ export interface ValidationResult {
|
|
|
5
5
|
message: string;
|
|
6
6
|
}
|
|
7
7
|
type ReasonTranslate = (reason: keyof ValidityStateFlags, value: any, fallback: string) => string;
|
|
8
|
+
/** */
|
|
8
9
|
export interface ValidateOptions {
|
|
10
|
+
enabled?: boolean;
|
|
9
11
|
context?: Record<string, any>;
|
|
10
12
|
customValidator?: (value: any, context: Record<string, any> | undefined, el: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement) => string | undefined;
|
|
11
|
-
on?:
|
|
13
|
+
on?: "input" | "change";
|
|
12
14
|
setValidationResult?: (res: ValidationResult) => void;
|
|
13
15
|
t?: false | ReasonTranslate;
|
|
14
16
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
t: null;
|
|
21
|
-
};
|
|
17
|
+
/** Main action api */
|
|
18
|
+
export declare function validate(el: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement, fn?: () => boolean | ValidateOptions): void;
|
|
19
|
+
export declare namespace validate {
|
|
20
|
+
var t: null;
|
|
21
|
+
}
|
|
22
22
|
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { tick } from "svelte";
|
|
2
|
+
import { waitForNextRepaint, waitForTwoRepaints } from "../utils/paint.js";
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
const KNOWN_REASONS = [
|
|
7
|
+
"badInput",
|
|
8
|
+
"customError",
|
|
9
|
+
"patternMismatch",
|
|
10
|
+
"rangeOverflow",
|
|
11
|
+
"rangeUnderflow",
|
|
12
|
+
"stepMismatch",
|
|
13
|
+
"tooLong",
|
|
14
|
+
"tooShort",
|
|
15
|
+
"typeMismatch",
|
|
16
|
+
"valueMissing",
|
|
17
|
+
];
|
|
18
|
+
/** Main action api */
|
|
19
|
+
export function validate(el, fn) {
|
|
20
|
+
$effect(() => {
|
|
21
|
+
//
|
|
22
|
+
let fnResult = fn?.() ?? {};
|
|
23
|
+
let { enabled, context, customValidator, on = "change", setValidationResult, t, } = typeof fnResult === "boolean" ? { enabled: !!fnResult } : fnResult;
|
|
24
|
+
//
|
|
25
|
+
const _t = (reason, value, fallback) => {
|
|
26
|
+
// explicit false
|
|
27
|
+
if (!reason || t === false) {
|
|
28
|
+
return fallback;
|
|
29
|
+
}
|
|
30
|
+
// local t (if any)
|
|
31
|
+
else if (typeof t === "function") {
|
|
32
|
+
return t(reason, value, fallback);
|
|
33
|
+
}
|
|
34
|
+
// global t (if any)
|
|
35
|
+
else if (typeof validate.t === "function") {
|
|
36
|
+
return validate.t(reason, value, fallback);
|
|
37
|
+
}
|
|
38
|
+
return fallback;
|
|
39
|
+
};
|
|
40
|
+
const _doValidate = () => {
|
|
41
|
+
if (!enabled)
|
|
42
|
+
return;
|
|
43
|
+
el.checkValidity();
|
|
44
|
+
if (typeof customValidator === "function") {
|
|
45
|
+
el.setCustomValidity(customValidator(el.value, context, el) || "");
|
|
46
|
+
}
|
|
47
|
+
// this triggers the bubble, which is not what we want
|
|
48
|
+
// el.reportValidity();
|
|
49
|
+
const validityState = el.validity;
|
|
50
|
+
const reasons = KNOWN_REASONS.reduce((m, k) => {
|
|
51
|
+
if (validityState[k])
|
|
52
|
+
m.push(k);
|
|
53
|
+
return m;
|
|
54
|
+
}, []);
|
|
55
|
+
// console.log(1111, validityState, el);
|
|
56
|
+
// hm... Uncaught Svelte error: state_unsafe_mutation...
|
|
57
|
+
// the `tick` await helps, but I'm not really sure I understand the internals...
|
|
58
|
+
tick().then(() => {
|
|
59
|
+
setValidationResult?.({
|
|
60
|
+
validity: validityState,
|
|
61
|
+
reasons,
|
|
62
|
+
valid: validityState?.valid,
|
|
63
|
+
// use translate fn for first reason (if fn provided and allowed),
|
|
64
|
+
// otherwise fallback to native msg
|
|
65
|
+
message: _t(reasons?.[0], el.value, el.validationMessage ||
|
|
66
|
+
// PROBLEM: hidden inputs do not report validationMessage-s even
|
|
67
|
+
// if correctly reported as invalid. So all we can do, is
|
|
68
|
+
// put anything generically reasonable here...
|
|
69
|
+
"This field contains invalid data. Please review and try again."),
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
el.addEventListener(on, _doValidate);
|
|
74
|
+
//
|
|
75
|
+
let _touchCount = 0;
|
|
76
|
+
const onFocus = (e) => _touchCount++;
|
|
77
|
+
el.addEventListener("focus", onFocus);
|
|
78
|
+
// also validate on first blur
|
|
79
|
+
const onBlur = (e) => _touchCount === 1 && _doValidate();
|
|
80
|
+
el.addEventListener("blur", onBlur);
|
|
81
|
+
return () => {
|
|
82
|
+
el.removeEventListener(on, _doValidate);
|
|
83
|
+
el.removeEventListener("focus", onFocus);
|
|
84
|
+
el.removeEventListener("blur", onBlur);
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
// ReasonTranslate
|
|
89
|
+
const t = null;
|
|
90
|
+
validate.t = t;
|