@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.
- 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/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
|
@@ -0,0 +1,646 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export interface Option {
|
|
3
|
+
label: string;
|
|
4
|
+
value: any;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// i18n ready
|
|
8
|
+
function t_default(k: string) {
|
|
9
|
+
const m: Record<string, string> = {
|
|
10
|
+
field_req_att: "This field requires attention. Please review and try again.",
|
|
11
|
+
cardinality_of: "of",
|
|
12
|
+
cardinality_selected: "selected",
|
|
13
|
+
submit: "Submit",
|
|
14
|
+
select_all: "Select all",
|
|
15
|
+
clear_all: "Clear all",
|
|
16
|
+
search_placeholder: "Type to search...",
|
|
17
|
+
cardinality_full: "Max selection reached",
|
|
18
|
+
select_from_list: "Please select from the list",
|
|
19
|
+
x_close: "Clear input or close [esc]",
|
|
20
|
+
unknown_allowed: "Select from the list or type and submit any value",
|
|
21
|
+
unknown_not_allowed: "Select values from the list only",
|
|
22
|
+
};
|
|
23
|
+
return m[k] ?? k;
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<script lang="ts">
|
|
28
|
+
import { createClog } from "@marianmeres/clog";
|
|
29
|
+
import { iconBsSearch } from "@marianmeres/icons-fns/bootstrap/iconBsSearch.js";
|
|
30
|
+
import { iconLucideCheck } from "@marianmeres/icons-fns/lucide/iconLucideCheck.js";
|
|
31
|
+
import { iconLucideCircle } from "@marianmeres/icons-fns/lucide/iconLucideCircle.js";
|
|
32
|
+
import { iconLucideSquare } from "@marianmeres/icons-fns/lucide/iconLucideSquare.js";
|
|
33
|
+
import { ItemCollection, type Item } from "@marianmeres/item-collection";
|
|
34
|
+
import { Debounced, watch } from "runed";
|
|
35
|
+
import { type Snippet } from "svelte";
|
|
36
|
+
import { tooltip } from "../../actions/index.js";
|
|
37
|
+
import { type ValidateOptions } from "../../actions/validate.svelte.js";
|
|
38
|
+
import { getId } from "../../utils/get-id.js";
|
|
39
|
+
import { maybeJsonParse } from "../../utils/maybe-json-parse.js";
|
|
40
|
+
import { waitForNextRepaint } from "../../utils/paint.js";
|
|
41
|
+
import { qsa } from "../../utils/qsa.js";
|
|
42
|
+
import { strHash } from "../../utils/str-hash.js";
|
|
43
|
+
import { twMerge } from "../../utils/tw-merge.js";
|
|
44
|
+
import Button from "../Button/Button.svelte";
|
|
45
|
+
import Modal from "../Modal/Modal.svelte";
|
|
46
|
+
import { NotificationsStack } from "../Notifications/index.js";
|
|
47
|
+
import Spinner from "../Spinner/Spinner.svelte";
|
|
48
|
+
import type { THC } from "../Thc/Thc.svelte";
|
|
49
|
+
import X from "../X/X.svelte";
|
|
50
|
+
import InputWrap from "./_internal/InputWrap.svelte";
|
|
51
|
+
import FieldLikeButton from "./FieldLikeButton.svelte";
|
|
52
|
+
|
|
53
|
+
const clog = createClog("FieldOptions");
|
|
54
|
+
|
|
55
|
+
const iconCheckboxEmpty = iconLucideSquare;
|
|
56
|
+
const iconCheckboxCheck = iconLucideCheck;
|
|
57
|
+
|
|
58
|
+
const iconRadioEmpty = iconLucideCircle;
|
|
59
|
+
const iconRadioCheck = iconLucideCheck;
|
|
60
|
+
|
|
61
|
+
type SnippetWithId = Snippet<[{ id: string }]>;
|
|
62
|
+
|
|
63
|
+
interface Props extends Record<string, any> {
|
|
64
|
+
input?: HTMLInputElement;
|
|
65
|
+
value: string;
|
|
66
|
+
label?: SnippetWithId | THC;
|
|
67
|
+
type?: string;
|
|
68
|
+
description?: SnippetWithId | THC;
|
|
69
|
+
class?: string;
|
|
70
|
+
id?: string;
|
|
71
|
+
tabindex?: number; // tooShort
|
|
72
|
+
renderSize?: "sm" | "md" | "lg" | string;
|
|
73
|
+
useTrim?: boolean;
|
|
74
|
+
//
|
|
75
|
+
required?: boolean;
|
|
76
|
+
disabled?: boolean;
|
|
77
|
+
//
|
|
78
|
+
validate?: boolean | Omit<ValidateOptions, "setValidationResult">;
|
|
79
|
+
// wrap snippets
|
|
80
|
+
labelAfter?: SnippetWithId | THC;
|
|
81
|
+
below?: SnippetWithId | THC;
|
|
82
|
+
//
|
|
83
|
+
labelLeft?: boolean;
|
|
84
|
+
labelLeftWidth?: "normal" | "wide";
|
|
85
|
+
labelLeftBreakpoint?: number;
|
|
86
|
+
//
|
|
87
|
+
classInput?: string;
|
|
88
|
+
classLabel?: string;
|
|
89
|
+
classLabelBox?: string;
|
|
90
|
+
classInputBox?: string;
|
|
91
|
+
classInputBoxWrap?: string;
|
|
92
|
+
classDescBox?: string;
|
|
93
|
+
classBelowBox?: string;
|
|
94
|
+
//
|
|
95
|
+
classOption?: string;
|
|
96
|
+
classOptionActive?: string;
|
|
97
|
+
//
|
|
98
|
+
classModalField?: string;
|
|
99
|
+
noScrollLock?: boolean;
|
|
100
|
+
//
|
|
101
|
+
style?: string;
|
|
102
|
+
t?: (key: string) => string;
|
|
103
|
+
//
|
|
104
|
+
renderValue?: (strigifiedItems: string) => string;
|
|
105
|
+
getOptions: (s: string, current: Item[]) => Promise<Item[]>;
|
|
106
|
+
notifications?: NotificationsStack;
|
|
107
|
+
// -1 no limit
|
|
108
|
+
// +n max selected limit
|
|
109
|
+
cardinality?: number;
|
|
110
|
+
renderOptionLabel?: (item: Item) => string;
|
|
111
|
+
// whether to allow adding unknown options
|
|
112
|
+
allowUnknown?: boolean;
|
|
113
|
+
showIcons?: boolean;
|
|
114
|
+
searchPlaceholder?: string;
|
|
115
|
+
name: string;
|
|
116
|
+
itemIdPropName?: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let {
|
|
120
|
+
input = $bindable(),
|
|
121
|
+
value = $bindable(), //
|
|
122
|
+
label = "",
|
|
123
|
+
id = getId(),
|
|
124
|
+
type = "text",
|
|
125
|
+
tabindex = 0,
|
|
126
|
+
description,
|
|
127
|
+
class: classProp,
|
|
128
|
+
renderSize = "md",
|
|
129
|
+
useTrim = true,
|
|
130
|
+
//
|
|
131
|
+
required = false,
|
|
132
|
+
disabled = false,
|
|
133
|
+
//
|
|
134
|
+
validate,
|
|
135
|
+
//
|
|
136
|
+
labelAfter,
|
|
137
|
+
below,
|
|
138
|
+
//
|
|
139
|
+
labelLeft = false,
|
|
140
|
+
labelLeftWidth = "normal",
|
|
141
|
+
labelLeftBreakpoint = 480,
|
|
142
|
+
//
|
|
143
|
+
classInput,
|
|
144
|
+
classLabel,
|
|
145
|
+
classLabelBox,
|
|
146
|
+
classInputBox,
|
|
147
|
+
classInputBoxWrap,
|
|
148
|
+
classDescBox,
|
|
149
|
+
classBelowBox,
|
|
150
|
+
//
|
|
151
|
+
classOption,
|
|
152
|
+
classOptionActive,
|
|
153
|
+
//
|
|
154
|
+
style,
|
|
155
|
+
//
|
|
156
|
+
classModalField,
|
|
157
|
+
noScrollLock = false,
|
|
158
|
+
t = t_default,
|
|
159
|
+
//
|
|
160
|
+
renderValue,
|
|
161
|
+
getOptions,
|
|
162
|
+
notifications,
|
|
163
|
+
cardinality: _cardinality = Infinity,
|
|
164
|
+
renderOptionLabel,
|
|
165
|
+
allowUnknown = false,
|
|
166
|
+
showIcons = true,
|
|
167
|
+
searchPlaceholder,
|
|
168
|
+
name,
|
|
169
|
+
itemIdPropName = "id",
|
|
170
|
+
...rest
|
|
171
|
+
}: Props = $props();
|
|
172
|
+
|
|
173
|
+
let modal: Modal = $state()!;
|
|
174
|
+
let innerValue = $state("");
|
|
175
|
+
let isFetching = $state(false);
|
|
176
|
+
let cardinality = $derived(_cardinality === -1 ? Infinity : _cardinality);
|
|
177
|
+
let isMultiple = $derived(cardinality > 1);
|
|
178
|
+
|
|
179
|
+
//
|
|
180
|
+
let wrappedValidate: Omit<ValidateOptions, "setValidationResult"> = $derived({
|
|
181
|
+
enabled: true,
|
|
182
|
+
customValidator(value: any, context: Record<string, any> | undefined, el: any) {
|
|
183
|
+
// NOTE: the below error message code will be ignored, so it's just cosmetics.
|
|
184
|
+
// This, built-in JSON array validator cannot be bypassed. Strictly expecting array.
|
|
185
|
+
let selected = [];
|
|
186
|
+
try {
|
|
187
|
+
selected = JSON.parse(value);
|
|
188
|
+
if (!Array.isArray(selected)) return "typeMismatch";
|
|
189
|
+
} catch (e) {
|
|
190
|
+
return "typeMismatch";
|
|
191
|
+
}
|
|
192
|
+
// cardinality check
|
|
193
|
+
if (selected.length > cardinality) return "rangeOverflow";
|
|
194
|
+
|
|
195
|
+
// continue with provided validator
|
|
196
|
+
return (validate as any)?.customValidator?.(value, context, el) || "";
|
|
197
|
+
},
|
|
198
|
+
t(reason: keyof ValidityStateFlags, value: any, fallback: string) {
|
|
199
|
+
// Unfortunately, for hidden, everything is a `customError` reason. So, we must generalize...
|
|
200
|
+
return t("field_req_att");
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
function _renderOptionLabel(item: Item): string {
|
|
205
|
+
return renderOptionLabel?.(item) || `${item[itemIdPropName]}`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function sortFn(a: Item, b: Item) {
|
|
209
|
+
return _renderOptionLabel(a).localeCompare(_renderOptionLabel(b), undefined, {
|
|
210
|
+
sensitivity: "base",
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// let's have two distinct collections for the job, they are independent on each other
|
|
215
|
+
// first, the all available options
|
|
216
|
+
const _optionsColl = new ItemCollection([], {
|
|
217
|
+
allowNextPrevCycle: false,
|
|
218
|
+
sortFn,
|
|
219
|
+
idPropName: itemIdPropName,
|
|
220
|
+
searchable: { getContent: (item) => _renderOptionLabel(item) },
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// second, the selected ones
|
|
224
|
+
const _selectedColl = new ItemCollection([], {
|
|
225
|
+
cardinality,
|
|
226
|
+
sortFn,
|
|
227
|
+
idPropName: itemIdPropName,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// now, create the reactive, subscribed variants
|
|
231
|
+
let options = $derived($_optionsColl);
|
|
232
|
+
let selected = $derived($_selectedColl);
|
|
233
|
+
// $inspect("options", options);
|
|
234
|
+
// $inspect("selected", selected);
|
|
235
|
+
|
|
236
|
+
let activeEl: HTMLButtonElement | undefined = $state();
|
|
237
|
+
let optionsBox: HTMLUListElement | undefined = $state();
|
|
238
|
+
let modalEl: HTMLDivElement | undefined = $state();
|
|
239
|
+
|
|
240
|
+
// set value on open
|
|
241
|
+
watch(
|
|
242
|
+
() => modal.visibility().visible,
|
|
243
|
+
(isVisible, wasVisible) => {
|
|
244
|
+
// modal was just opened
|
|
245
|
+
if (!wasVisible && isVisible) {
|
|
246
|
+
_selectedColl.clear().addMany(maybeJsonParse(value));
|
|
247
|
+
// IMPORTANT: focus first selected so it scrolls into view on open
|
|
248
|
+
if (_selectedColl.size) {
|
|
249
|
+
waitForNextRepaint().then(() => {
|
|
250
|
+
_optionsColl.setActive(_selectedColl.items[0]);
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
// scroll the active option into view
|
|
258
|
+
$effect(() => {
|
|
259
|
+
if (modal.visibility().visible && options.active?.[itemIdPropName]) {
|
|
260
|
+
activeEl = qsa(`#${btnId(options.active[itemIdPropName])}`, optionsBox)[0] as any;
|
|
261
|
+
activeEl?.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
262
|
+
activeEl?.focus();
|
|
263
|
+
} else {
|
|
264
|
+
activeEl = undefined;
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// suggest options as a typeahead feature
|
|
269
|
+
const debounced = new Debounced(() => innerValue, 150);
|
|
270
|
+
watch(
|
|
271
|
+
[() => modal.visibility().visible, () => debounced.current],
|
|
272
|
+
([isVisible, currVal]) => {
|
|
273
|
+
if (!isVisible) return;
|
|
274
|
+
isFetching = true;
|
|
275
|
+
getOptions(currVal, selected.items)
|
|
276
|
+
.then((res) => {
|
|
277
|
+
// always update the existing with recent server data
|
|
278
|
+
_selectedColl.patchMany(res);
|
|
279
|
+
// continue normally, with (server) provided options...
|
|
280
|
+
_optionsColl.clear().addMany(res);
|
|
281
|
+
})
|
|
282
|
+
.catch((e) => {
|
|
283
|
+
console.error(e);
|
|
284
|
+
notifications?.error(`${e}`);
|
|
285
|
+
})
|
|
286
|
+
.finally(() => (isFetching = false));
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
// internal DRY
|
|
291
|
+
function btnId(id: string | number, prefix = "btn-") {
|
|
292
|
+
return prefix + strHash(`${id}`.repeat(3));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// this will set the outer bound value (always string) and close modal... further process is left on the consumer
|
|
296
|
+
function submit() {
|
|
297
|
+
// clog("modal submit", $state.snapshot(selected.items));
|
|
298
|
+
value = JSON.stringify(selected.items);
|
|
299
|
+
innerValue = "";
|
|
300
|
+
_optionsColl.clear();
|
|
301
|
+
modal.close();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// clears, closes, submits nothing
|
|
305
|
+
function escape() {
|
|
306
|
+
innerValue = "";
|
|
307
|
+
_optionsColl.clear();
|
|
308
|
+
modal?.close();
|
|
309
|
+
}
|
|
310
|
+
</script>
|
|
311
|
+
|
|
312
|
+
<!-- this must be on window as we're catching any typing anywhere -->
|
|
313
|
+
<svelte:window
|
|
314
|
+
onkeydown={(e) => {
|
|
315
|
+
if (modal.visibility().visible) {
|
|
316
|
+
// arrow navigation
|
|
317
|
+
if (["ArrowDown", "ArrowUp"].includes(e.key)) {
|
|
318
|
+
e.preventDefault();
|
|
319
|
+
|
|
320
|
+
if (e.key === "ArrowUp") {
|
|
321
|
+
e.metaKey ? _optionsColl.setActiveFirst() : _optionsColl.setActivePrevious();
|
|
322
|
+
} else if (e.key === "ArrowDown") {
|
|
323
|
+
e.metaKey ? _optionsColl.setActiveLast() : _optionsColl.setActiveNext();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// common UI convention: radios are selected by arrows
|
|
327
|
+
if (!isMultiple && _optionsColl.active) {
|
|
328
|
+
_selectedColl.clear().add(_optionsColl.active!);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
// everything else (except controls) "forward" as an input search
|
|
332
|
+
else if (!["Tab", " ", "Enter"].includes(e.key)) {
|
|
333
|
+
input?.focus();
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}}
|
|
337
|
+
/>
|
|
338
|
+
|
|
339
|
+
<!-- must wrap both -->
|
|
340
|
+
<div>
|
|
341
|
+
<FieldLikeButton
|
|
342
|
+
bind:value
|
|
343
|
+
{name}
|
|
344
|
+
class={classProp}
|
|
345
|
+
{label}
|
|
346
|
+
{description}
|
|
347
|
+
{labelLeft}
|
|
348
|
+
{labelAfter}
|
|
349
|
+
{below}
|
|
350
|
+
{labelLeftWidth}
|
|
351
|
+
{labelLeftBreakpoint}
|
|
352
|
+
{classLabel}
|
|
353
|
+
{classLabelBox}
|
|
354
|
+
{classInputBox}
|
|
355
|
+
{classInputBoxWrap}
|
|
356
|
+
{classDescBox}
|
|
357
|
+
{classBelowBox}
|
|
358
|
+
{style}
|
|
359
|
+
validate={wrappedValidate}
|
|
360
|
+
{required}
|
|
361
|
+
{disabled}
|
|
362
|
+
renderValue={(v) => {
|
|
363
|
+
if (typeof renderValue === "function") return renderValue(v);
|
|
364
|
+
// console.log(123123, "renderValue", v);
|
|
365
|
+
// prettier-ignore
|
|
366
|
+
try {
|
|
367
|
+
// defensive
|
|
368
|
+
if (!v) v = "[]";
|
|
369
|
+
|
|
370
|
+
const limit = 5;
|
|
371
|
+
let vals: any[] = JSON.parse(v);
|
|
372
|
+
if (!Array.isArray(vals)) throw new Error('Expecting value to be an array');
|
|
373
|
+
const origLength = vals.length;
|
|
374
|
+
let extra = '';
|
|
375
|
+
if (vals.length > limit) {
|
|
376
|
+
vals = vals.slice(0, limit);
|
|
377
|
+
extra = `, ... <span class="text-sm opacity-50">(+${(origLength - limit)})</span>`;
|
|
378
|
+
}
|
|
379
|
+
return vals.map(_renderOptionLabel).join(", ") + extra;
|
|
380
|
+
} catch (e) {
|
|
381
|
+
clog.warn(e);
|
|
382
|
+
return `${e}`; // either invalid json or not array...
|
|
383
|
+
}
|
|
384
|
+
}}
|
|
385
|
+
onclick={modal?.open}
|
|
386
|
+
/>
|
|
387
|
+
|
|
388
|
+
<Modal
|
|
389
|
+
bind:this={modal}
|
|
390
|
+
onEscape={escape}
|
|
391
|
+
class="bg-transparent dark:bg-transparent"
|
|
392
|
+
classInner="max-w-2xl"
|
|
393
|
+
bind:el={modalEl}
|
|
394
|
+
{noScrollLock}
|
|
395
|
+
>
|
|
396
|
+
<InputWrap
|
|
397
|
+
size={renderSize}
|
|
398
|
+
class={twMerge("m-4 mb-12 shadow-xl", classModalField)}
|
|
399
|
+
classInputBoxWrap={twMerge(
|
|
400
|
+
// always look like focused
|
|
401
|
+
`border border-input-accent dark:border-input-accent-dark`,
|
|
402
|
+
`ring-input-accent/20 dark:ring-input-accent-dark/20 ring-4`
|
|
403
|
+
)}
|
|
404
|
+
{id}
|
|
405
|
+
{required}
|
|
406
|
+
>
|
|
407
|
+
<input
|
|
408
|
+
bind:value={innerValue}
|
|
409
|
+
bind:this={input}
|
|
410
|
+
{type}
|
|
411
|
+
{id}
|
|
412
|
+
class={twMerge("form-input", renderSize, classInput)}
|
|
413
|
+
tabindex={1}
|
|
414
|
+
{required}
|
|
415
|
+
{disabled}
|
|
416
|
+
placeholder={searchPlaceholder ?? t("search_placeholder")}
|
|
417
|
+
onkeydown={(e) => {
|
|
418
|
+
if (e.key === "Enter") {
|
|
419
|
+
e.preventDefault();
|
|
420
|
+
|
|
421
|
+
if (innerValue) {
|
|
422
|
+
// doing label search, taking first result
|
|
423
|
+
let found = _optionsColl.search(innerValue)?.[0];
|
|
424
|
+
if (!found) {
|
|
425
|
+
if (!allowUnknown) {
|
|
426
|
+
return notifications?.error(t("select_from_list"), { ttl: 1000 });
|
|
427
|
+
}
|
|
428
|
+
found = { [itemIdPropName]: innerValue };
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (!isMultiple) _selectedColl.clear();
|
|
432
|
+
|
|
433
|
+
// actual selection addon
|
|
434
|
+
_selectedColl.add(found);
|
|
435
|
+
|
|
436
|
+
// we might have added a new one, so add it to options as well
|
|
437
|
+
// (will be noop if already exists)...
|
|
438
|
+
if (allowUnknown) {
|
|
439
|
+
_optionsColl.add(found);
|
|
440
|
+
_optionsColl.setActive(found);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// maybe submit
|
|
444
|
+
if (_selectedColl.isFull) submit();
|
|
445
|
+
}
|
|
446
|
+
// enter on empty input always submits
|
|
447
|
+
else {
|
|
448
|
+
submit();
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}}
|
|
452
|
+
autocomplete="off"
|
|
453
|
+
name={`rand-${Math.random().toString(36).slice(2)}`}
|
|
454
|
+
{...rest}
|
|
455
|
+
/>
|
|
456
|
+
|
|
457
|
+
{#snippet inputBelow()}
|
|
458
|
+
<div class="h-full border-t p-2 border-black/20">
|
|
459
|
+
<div class="text-sm -mt-1 flex items-center">
|
|
460
|
+
{#if isMultiple}
|
|
461
|
+
<button
|
|
462
|
+
type="button"
|
|
463
|
+
onclick={() => _selectedColl.addMany(options.items)}
|
|
464
|
+
class={twMerge(
|
|
465
|
+
"control flex items-center p-1 m-1 text-xs opacity-75 underline rounded",
|
|
466
|
+
"hover:opacity-100 focus-visible:outline-neutral-400 focus-visible:opacity-100"
|
|
467
|
+
)}
|
|
468
|
+
tabindex={4}
|
|
469
|
+
>
|
|
470
|
+
{@html t("select_all")}
|
|
471
|
+
</button>
|
|
472
|
+
{/if}
|
|
473
|
+
<button
|
|
474
|
+
type="button"
|
|
475
|
+
onclick={() => {
|
|
476
|
+
_selectedColl.clear();
|
|
477
|
+
input?.focus();
|
|
478
|
+
}}
|
|
479
|
+
class={twMerge(
|
|
480
|
+
"control flex items-center p-1 m-1 text-xs opacity-75 underline rounded",
|
|
481
|
+
"hover:opacity-100 focus-visible:outline-neutral-400 focus-visible:opacity-100"
|
|
482
|
+
)}
|
|
483
|
+
class:opacity-20={!selected.items.length}
|
|
484
|
+
tabindex={5}
|
|
485
|
+
disabled={!selected.items.length}
|
|
486
|
+
>
|
|
487
|
+
{@html t("clear_all")}
|
|
488
|
+
</button>
|
|
489
|
+
|
|
490
|
+
<span class="p-1 m-1 text-xs"> </span>
|
|
491
|
+
<span class="flex-1 block justify-end opacity-50 text-right text-xs p-1 pr-2">
|
|
492
|
+
{selected.items.length}
|
|
493
|
+
{#if cardinality > 0 && cardinality < Infinity}
|
|
494
|
+
{@html t("cardinality_of")} {cardinality}
|
|
495
|
+
{/if}
|
|
496
|
+
{@html t("cardinality_selected")}
|
|
497
|
+
</span>
|
|
498
|
+
</div>
|
|
499
|
+
|
|
500
|
+
<!-- {#if options.items.length} -->
|
|
501
|
+
<ul
|
|
502
|
+
class={twMerge(
|
|
503
|
+
"options block h-[250px] max-h-[250px] overflow-y-auto overflow-x-hidden space-y-1"
|
|
504
|
+
)}
|
|
505
|
+
bind:this={optionsBox}
|
|
506
|
+
tabindex="-1"
|
|
507
|
+
>
|
|
508
|
+
{#if isFetching && !options.items.length}
|
|
509
|
+
<div class="p-4 opacity-50">
|
|
510
|
+
<Spinner class="w-4" />
|
|
511
|
+
</div>
|
|
512
|
+
{/if}
|
|
513
|
+
{#each options.items as item}
|
|
514
|
+
{@const active = item[itemIdPropName] === options.active?.[itemIdPropName]}
|
|
515
|
+
{@const isSelected =
|
|
516
|
+
selected.items && _selectedColl.exists(item[itemIdPropName])}
|
|
517
|
+
<li class:active class="px-2">
|
|
518
|
+
<button
|
|
519
|
+
type="button"
|
|
520
|
+
id={btnId(item[itemIdPropName])}
|
|
521
|
+
onclick={() => {
|
|
522
|
+
if (isMultiple) {
|
|
523
|
+
if (selected.isFull && !_selectedColl.exists(item)) {
|
|
524
|
+
return notifications?.error(t("cardinality_full"), {
|
|
525
|
+
ttl: 1000,
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
_selectedColl.toggleAdd(item);
|
|
529
|
+
} else {
|
|
530
|
+
_selectedColl.clear();
|
|
531
|
+
_selectedColl.add(item);
|
|
532
|
+
submit();
|
|
533
|
+
}
|
|
534
|
+
}}
|
|
535
|
+
class:active
|
|
536
|
+
class:selected={isSelected}
|
|
537
|
+
class={twMerge(
|
|
538
|
+
"no-focus-visible",
|
|
539
|
+
"w-full text-left rounded-md py-2 px-2.5 flex items-center space-x-2",
|
|
540
|
+
"text-ellipsis border border-transparent",
|
|
541
|
+
"focus:outline-0 focus:border-neutral-400 dark:focus:border-neutral-500",
|
|
542
|
+
"focus-visible:outline-0 focus-visible:ring-0",
|
|
543
|
+
"hover:border-neutral-400 dark:hover:border-neutral-500",
|
|
544
|
+
isSelected && "bg-neutral-200 dark:bg-neutral-800",
|
|
545
|
+
classOption,
|
|
546
|
+
// active && "border-neutral-400",
|
|
547
|
+
active && classOptionActive
|
|
548
|
+
)}
|
|
549
|
+
tabindex="-1"
|
|
550
|
+
role="checkbox"
|
|
551
|
+
aria-checked={isSelected}
|
|
552
|
+
>
|
|
553
|
+
{#if showIcons}
|
|
554
|
+
<span class={isSelected ? "opacity-100" : "opacity-25"}>
|
|
555
|
+
{#if isMultiple}
|
|
556
|
+
{#if isSelected}
|
|
557
|
+
{@html iconCheckboxCheck()}
|
|
558
|
+
{:else}
|
|
559
|
+
{@html iconCheckboxEmpty()}
|
|
560
|
+
{/if}
|
|
561
|
+
{:else if isSelected}
|
|
562
|
+
{@html iconRadioCheck()}
|
|
563
|
+
{:else}
|
|
564
|
+
{@html iconRadioEmpty()}
|
|
565
|
+
{/if}
|
|
566
|
+
</span>
|
|
567
|
+
{/if}
|
|
568
|
+
<span>{_renderOptionLabel(item)}</span>
|
|
569
|
+
</button>
|
|
570
|
+
</li>
|
|
571
|
+
{/each}
|
|
572
|
+
</ul>
|
|
573
|
+
<!-- {/if} -->
|
|
574
|
+
<div class="p-2 flex items-end justify-between">
|
|
575
|
+
<div class="text-xs opacity-50">
|
|
576
|
+
<!-- Use arrows to navigate. Spacebar and Enter to select and/or submit. -->
|
|
577
|
+
{#if allowUnknown}
|
|
578
|
+
{@html t("unknown_allowed")}
|
|
579
|
+
{:else}
|
|
580
|
+
{@html t("unknown_not_allowed")}
|
|
581
|
+
{/if}
|
|
582
|
+
</div>
|
|
583
|
+
<div>
|
|
584
|
+
<Button
|
|
585
|
+
class="control"
|
|
586
|
+
type="button"
|
|
587
|
+
variant="primary"
|
|
588
|
+
onclick={(e) => {
|
|
589
|
+
e.preventDefault();
|
|
590
|
+
submit();
|
|
591
|
+
}}
|
|
592
|
+
tabindex={3}
|
|
593
|
+
>
|
|
594
|
+
{@html t("submit")}
|
|
595
|
+
</Button>
|
|
596
|
+
</div>
|
|
597
|
+
</div>
|
|
598
|
+
</div>
|
|
599
|
+
{/snippet}
|
|
600
|
+
|
|
601
|
+
{#snippet inputAfter()}
|
|
602
|
+
<div class="flex pl-2 items-center justify-center opacity-50">
|
|
603
|
+
{#if isFetching}
|
|
604
|
+
<Spinner class="w-4" />
|
|
605
|
+
{/if}
|
|
606
|
+
</div>
|
|
607
|
+
<div class="flex pl-2 pr-1 items-center justify-center">
|
|
608
|
+
<button
|
|
609
|
+
type="button"
|
|
610
|
+
class={twMerge(
|
|
611
|
+
"opacity-50 rounded",
|
|
612
|
+
"hover:opacity-100 hover:bg-neutral-200 dark:hover:bg-neutral-800",
|
|
613
|
+
"focus-visible:opacity-100 focus-visible:outline-0",
|
|
614
|
+
" focus-visible:bg-neutral-200 dark:focus-visible:bg-neutral-800"
|
|
615
|
+
)}
|
|
616
|
+
use:tooltip
|
|
617
|
+
aria-label={t("x_close")}
|
|
618
|
+
onclick={(e) => {
|
|
619
|
+
e.preventDefault();
|
|
620
|
+
if (innerValue.trim() == "") {
|
|
621
|
+
return escape();
|
|
622
|
+
}
|
|
623
|
+
innerValue = "";
|
|
624
|
+
input?.focus();
|
|
625
|
+
}}
|
|
626
|
+
tabindex={2}
|
|
627
|
+
>
|
|
628
|
+
<X class="m-2 size-4 " />
|
|
629
|
+
</button>
|
|
630
|
+
</div>
|
|
631
|
+
{/snippet}
|
|
632
|
+
|
|
633
|
+
{#snippet inputBefore()}
|
|
634
|
+
<div class="flex flex-col items-center justify-center pl-3 opacity-50">
|
|
635
|
+
{@html iconBsSearch({ size: 14 })}
|
|
636
|
+
</div>
|
|
637
|
+
{/snippet}
|
|
638
|
+
</InputWrap>
|
|
639
|
+
</Modal>
|
|
640
|
+
</div>
|
|
641
|
+
|
|
642
|
+
<style>
|
|
643
|
+
ul.options {
|
|
644
|
+
scrollbar-width: thin;
|
|
645
|
+
}
|
|
646
|
+
</style>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export interface Option {
|
|
2
|
+
label: string;
|
|
3
|
+
value: any;
|
|
4
|
+
}
|
|
5
|
+
import { type Item } from "@marianmeres/item-collection";
|
|
6
|
+
import { type Snippet } from "svelte";
|
|
7
|
+
import { type ValidateOptions } from "../../actions/validate.svelte.js";
|
|
8
|
+
import { NotificationsStack } from "../Notifications/index.js";
|
|
9
|
+
import type { THC } from "../Thc/Thc.svelte";
|
|
10
|
+
type SnippetWithId = Snippet<[{
|
|
11
|
+
id: string;
|
|
12
|
+
}]>;
|
|
13
|
+
interface Props extends Record<string, any> {
|
|
14
|
+
input?: HTMLInputElement;
|
|
15
|
+
value: string;
|
|
16
|
+
label?: SnippetWithId | THC;
|
|
17
|
+
type?: string;
|
|
18
|
+
description?: SnippetWithId | THC;
|
|
19
|
+
class?: string;
|
|
20
|
+
id?: string;
|
|
21
|
+
tabindex?: number;
|
|
22
|
+
renderSize?: "sm" | "md" | "lg" | string;
|
|
23
|
+
useTrim?: boolean;
|
|
24
|
+
required?: boolean;
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
validate?: boolean | Omit<ValidateOptions, "setValidationResult">;
|
|
27
|
+
labelAfter?: SnippetWithId | THC;
|
|
28
|
+
below?: SnippetWithId | THC;
|
|
29
|
+
labelLeft?: boolean;
|
|
30
|
+
labelLeftWidth?: "normal" | "wide";
|
|
31
|
+
labelLeftBreakpoint?: number;
|
|
32
|
+
classInput?: string;
|
|
33
|
+
classLabel?: string;
|
|
34
|
+
classLabelBox?: string;
|
|
35
|
+
classInputBox?: string;
|
|
36
|
+
classInputBoxWrap?: string;
|
|
37
|
+
classDescBox?: string;
|
|
38
|
+
classBelowBox?: string;
|
|
39
|
+
classOption?: string;
|
|
40
|
+
classOptionActive?: string;
|
|
41
|
+
classModalField?: string;
|
|
42
|
+
noScrollLock?: boolean;
|
|
43
|
+
style?: string;
|
|
44
|
+
t?: (key: string) => string;
|
|
45
|
+
renderValue?: (strigifiedItems: string) => string;
|
|
46
|
+
getOptions: (s: string, current: Item[]) => Promise<Item[]>;
|
|
47
|
+
notifications?: NotificationsStack;
|
|
48
|
+
cardinality?: number;
|
|
49
|
+
renderOptionLabel?: (item: Item) => string;
|
|
50
|
+
allowUnknown?: boolean;
|
|
51
|
+
showIcons?: boolean;
|
|
52
|
+
searchPlaceholder?: string;
|
|
53
|
+
name: string;
|
|
54
|
+
itemIdPropName?: string;
|
|
55
|
+
}
|
|
56
|
+
declare const FieldOptions: import("svelte").Component<Props, {}, "value" | "input">;
|
|
57
|
+
type FieldOptions = ReturnType<typeof FieldOptions>;
|
|
58
|
+
export default FieldOptions;
|