@placeholderco/placeholder-ui 1.0.11 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +134 -130
- package/dist/app.css +178 -0
- package/dist/bootstrap.min.css +3600 -0
- package/dist/cards/GitCard.svelte +115 -0
- package/dist/cards/GitCard.svelte.d.ts +22 -0
- package/dist/display/Avatar.svelte +29 -17
- package/dist/display/Avatar.svelte.d.ts +12 -2
- package/dist/display/LinkCollection.svelte +40 -18
- package/dist/display/LinkCollection.svelte.d.ts +9 -2
- package/dist/display/Paper.svelte +31 -19
- package/dist/display/Paper.svelte.d.ts +12 -3
- package/dist/display/alert/Alert.svelte +129 -0
- package/dist/display/alert/Alert.svelte.d.ts +15 -0
- package/dist/display/alert/AlertVariant.d.ts +1 -0
- package/dist/display/alert/AlertVariant.js +1 -0
- package/dist/display/filetree/FileTree.svelte +259 -0
- package/dist/display/filetree/FileTree.svelte.d.ts +76 -0
- package/dist/display/filetree/FileTreeItem.svelte +396 -0
- package/dist/display/filetree/FileTreeItem.svelte.d.ts +40 -0
- package/dist/display/filetree/FileTreeNode.d.ts +46 -0
- package/dist/display/filetree/FileTreeNode.js +115 -0
- package/dist/display/filetree/index.d.ts +5 -0
- package/dist/display/filetree/index.js +3 -0
- package/dist/editors/CodeMirror.svelte +306 -0
- package/dist/editors/CodeMirror.svelte.d.ts +31 -0
- package/dist/editors/tiptap/LinkActionMenu.svelte +307 -0
- package/dist/editors/tiptap/LinkActionMenu.svelte.d.ts +8 -0
- package/dist/editors/tiptap/TipTap.svelte +856 -0
- package/dist/editors/tiptap/TipTap.svelte.d.ts +54 -0
- package/dist/editors/tiptap/TipTapBubble.svelte +790 -0
- package/dist/editors/tiptap/TipTapBubble.svelte.d.ts +44 -0
- package/dist/editors/tiptap/collaboration.d.ts +55 -0
- package/dist/editors/tiptap/collaboration.js +1 -0
- package/dist/editors/tiptap/extensions/Alert.d.ts +18 -0
- package/dist/editors/tiptap/extensions/Alert.js +72 -0
- package/dist/editors/tiptap/extensions/CodeBlockEditor.d.ts +21 -0
- package/dist/editors/tiptap/extensions/CodeBlockEditor.js +326 -0
- package/dist/editors/tiptap/extensions/Div.d.ts +19 -0
- package/dist/editors/tiptap/extensions/Div.js +89 -0
- package/dist/editors/tiptap/extensions/Span.d.ts +5 -0
- package/dist/editors/tiptap/extensions/Span.js +56 -0
- package/dist/editors/tiptap/extensions/codeBlockEditor.css +236 -0
- package/dist/editors/tiptap/extensions/codeBlockLanguages.d.ts +17 -0
- package/dist/editors/tiptap/extensions/codeBlockLanguages.js +124 -0
- package/dist/editors/tiptap/extensions/index.d.ts +7 -0
- package/dist/editors/tiptap/extensions/index.js +5 -0
- package/dist/editors/tiptap/toolbar/AlertButton.svelte +261 -0
- package/dist/editors/tiptap/toolbar/AlertButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignCenterButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignCenterButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignJustifyButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignJustifyButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignLeftButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignLeftButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignRightButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignRightButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/BoldButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/BoldButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/BulletListButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/BulletListButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/CodeBlockButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/CodeBlockButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/CodeButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/CodeButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/ColorButton.svelte +299 -0
- package/dist/editors/tiptap/toolbar/ColorButton.svelte.d.ts +20 -0
- package/dist/editors/tiptap/toolbar/DocumentButton.svelte +58 -0
- package/dist/editors/tiptap/toolbar/DocumentButton.svelte.d.ts +9 -0
- package/dist/editors/tiptap/toolbar/HeadingButton.svelte +30 -0
- package/dist/editors/tiptap/toolbar/HeadingButton.svelte.d.ts +8 -0
- package/dist/editors/tiptap/toolbar/HtmlButton.svelte +68 -0
- package/dist/editors/tiptap/toolbar/HtmlButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/ImageButton.svelte +54 -0
- package/dist/editors/tiptap/toolbar/ImageButton.svelte.d.ts +8 -0
- package/dist/editors/tiptap/toolbar/ItalicButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/ItalicButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/LinkButton.svelte +257 -0
- package/dist/editors/tiptap/toolbar/LinkButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/OrderedListButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/OrderedListButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/RedoButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/RedoButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/StrikethroughButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/StrikethroughButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/SubscriptButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/SubscriptButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/SuperscriptButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/SuperscriptButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/TableButton.svelte +258 -0
- package/dist/editors/tiptap/toolbar/TableButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/ToolbarButton.svelte +84 -0
- package/dist/editors/tiptap/toolbar/ToolbarButton.svelte.d.ts +10 -0
- package/dist/editors/tiptap/toolbar/UnderlineButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/UnderlineButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/UndoButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/UndoButton.svelte.d.ts +7 -0
- package/dist/form/Autocomplete.svelte +270 -137
- package/dist/form/Autocomplete.svelte.d.ts +58 -10
- package/dist/form/AutocompleteMulti.svelte +385 -227
- package/dist/form/AutocompleteMulti.svelte.d.ts +59 -10
- package/dist/form/Checkbox.svelte +124 -43
- package/dist/form/Checkbox.svelte.d.ts +26 -2
- package/dist/form/Chips.svelte +47 -17
- package/dist/form/Chips.svelte.d.ts +24 -3
- package/dist/form/ComboBox.svelte +30 -20
- package/dist/form/ComboBox.svelte.d.ts +1 -1
- package/dist/form/ComboBoxItemBuilder.svelte +161 -188
- package/dist/form/ComboBoxItemBuilder.svelte.d.ts +19 -2
- package/dist/form/ComboBoxMulti.svelte +38 -24
- package/dist/form/ComboBoxMulti.svelte.d.ts +1 -1
- package/dist/form/CronBuilder.svelte +84 -67
- package/dist/form/CronBuilder.svelte.d.ts +16 -3
- package/dist/form/DatePicker.svelte +177 -191
- package/dist/form/DatePicker.svelte.d.ts +17 -2
- package/dist/form/DateRangePicker.svelte +775 -0
- package/dist/form/DateRangePicker.svelte.d.ts +23 -0
- package/dist/form/DateTimePicker.svelte +168 -209
- package/dist/form/DateTimePicker.svelte.d.ts +10 -2
- package/dist/form/FormGroup.svelte +33 -10
- package/dist/form/FormGroup.svelte.d.ts +12 -2
- package/dist/form/Number.svelte +71 -29
- package/dist/form/Number.svelte.d.ts +39 -6
- package/dist/form/Radio.svelte +174 -0
- package/dist/form/Radio.svelte.d.ts +21 -0
- package/dist/form/RadioGroup.svelte +52 -138
- package/dist/form/RadioGroup.svelte.d.ts +19 -2
- package/dist/form/SegmentedControl.svelte +103 -57
- package/dist/form/SegmentedControl.svelte.d.ts +12 -2
- package/dist/form/Select.svelte +160 -229
- package/dist/form/Select.svelte.d.ts +35 -6
- package/dist/form/SelectMulti.svelte +166 -277
- package/dist/form/SelectMulti.svelte.d.ts +37 -6
- package/dist/form/Slider.svelte +185 -268
- package/dist/form/Slider.svelte.d.ts +33 -16
- package/dist/form/StringArrayBuilder.svelte +249 -0
- package/dist/form/StringArrayBuilder.svelte.d.ts +15 -0
- package/dist/form/Switch.svelte +164 -106
- package/dist/form/Switch.svelte.d.ts +22 -3
- package/dist/form/TextArea.svelte +80 -45
- package/dist/form/TextArea.svelte.d.ts +35 -10
- package/dist/form/Textbox.svelte +80 -47
- package/dist/form/Textbox.svelte.d.ts +41 -8
- package/dist/form/TimePicker.svelte +42 -47
- package/dist/form/TimePicker.svelte.d.ts +12 -2
- package/dist/form/comboBoxCore.svelte.d.ts +99 -0
- package/dist/form/comboBoxCore.svelte.js +243 -0
- package/dist/icon/Icon.svelte +8 -3
- package/dist/icon/Icon.svelte.d.ts +8 -3
- package/dist/icon/cube-send.svg +1 -0
- package/dist/icon/file-type-bmp.svg +1 -0
- package/dist/icon/file-type-csv.svg +1 -0
- package/dist/icon/file-type-doc.svg +1 -0
- package/dist/icon/file-type-docx.svg +1 -0
- package/dist/icon/file-type-jpg.svg +1 -0
- package/dist/icon/file-type-pdf.svg +1 -0
- package/dist/icon/file-type-png.svg +1 -0
- package/dist/icon/file-type-ppt.svg +1 -0
- package/dist/icon/file-type-svg.svg +1 -0
- package/dist/icon/file-type-txt.svg +1 -0
- package/dist/icon/file-type-xls.svg +1 -0
- package/dist/icon/file-type-zip.svg +1 -0
- package/dist/icon/index.d.ts +166 -145
- package/dist/icon/index.js +166 -146
- package/dist/icon/layout-sidebar-left-collapse.svg +1 -0
- package/dist/icon/layout-sidebar-left-expand.svg +1 -0
- package/dist/icon/logo-placeholder.svg +6 -0
- package/dist/icon/paperclip.svg +1 -0
- package/dist/icon/source-code.svg +1 -0
- package/dist/icon/sun-moon.svg +1 -0
- package/dist/icon/table.svg +6 -0
- package/dist/icon/thumb-down.svg +1 -0
- package/dist/icon/thumb-up.svg +1 -0
- package/dist/index.d.ts +93 -22
- package/dist/index.js +28 -27
- package/dist/layout/AppShell.svelte +12 -162
- package/dist/layout/AppShell.svelte.d.ts +6 -27
- package/dist/layout/CustomNavbar.svelte +9 -7
- package/dist/layout/CustomNavbar.svelte.d.ts +4 -2
- package/dist/layout/Navbar.svelte +158 -110
- package/dist/layout/Navbar.svelte.d.ts +26 -12
- package/dist/layout/NavbarItemDisplay.svelte +2 -2
- package/dist/layout/NavbarItemView.svelte +182 -0
- package/dist/layout/NavbarItemView.svelte.d.ts +10 -0
- package/dist/layout/Sidenav.svelte +280 -341
- package/dist/layout/Sidenav.svelte.d.ts +36 -4
- package/dist/models/ComboBoxItem.d.ts +2 -0
- package/dist/models/Employee.d.ts +53 -0
- package/dist/models/Employee.js +23 -0
- package/dist/models/Hyperlink.d.ts +3 -1
- package/dist/models/LinkCollectionItem.d.ts +3 -1
- package/dist/models/NavbarItem.d.ts +6 -2
- package/dist/theme.svelte.d.ts +0 -1
- package/dist/theme.svelte.js +46 -58
- package/dist/ui/Accordion.svelte +81 -242
- package/dist/ui/Accordion.svelte.d.ts +37 -14
- package/dist/ui/AccordionItem.svelte +303 -0
- package/dist/ui/AccordionItem.svelte.d.ts +21 -0
- package/dist/ui/ActionIcon.svelte +25 -21
- package/dist/ui/ActionIcon.svelte.d.ts +15 -2
- package/dist/ui/Badge.svelte +170 -161
- package/dist/ui/Badge.svelte.d.ts +16 -4
- package/dist/ui/Button.svelte +178 -205
- package/dist/ui/Button.svelte.d.ts +19 -2
- package/dist/ui/ButtonVariant.d.ts +15 -1
- package/dist/ui/ContextMenu.svelte +146 -0
- package/dist/ui/ContextMenu.svelte.d.ts +37 -0
- package/dist/ui/ContextMenuList.svelte +188 -0
- package/dist/ui/ContextMenuList.svelte.d.ts +12 -0
- package/dist/ui/Dialog.svelte +183 -104
- package/dist/ui/Dialog.svelte.d.ts +21 -2
- package/dist/ui/Drawer.svelte +237 -184
- package/dist/ui/Drawer.svelte.d.ts +20 -2
- package/dist/ui/Dropdown.svelte +24 -14
- package/dist/ui/Dropdown.svelte.d.ts +11 -2
- package/dist/ui/Dropzone.svelte +159 -57
- package/dist/ui/Dropzone.svelte.d.ts +29 -2
- package/dist/ui/Link.svelte +12 -4
- package/dist/ui/Link.svelte.d.ts +8 -2
- package/dist/ui/Loader.svelte +23 -18
- package/dist/ui/Loader.svelte.d.ts +5 -2
- package/dist/ui/Logo.svelte +37 -0
- package/dist/ui/Logo.svelte.d.ts +16 -0
- package/dist/ui/MultiSortable.svelte +287 -0
- package/dist/ui/MultiSortable.svelte.d.ts +50 -0
- package/dist/ui/Pagination.svelte +12 -6
- package/dist/ui/Pagination.svelte.d.ts +6 -2
- package/dist/ui/Popover.svelte +43 -65
- package/dist/ui/Popover.svelte.d.ts +14 -5
- package/dist/ui/ProgressBar.svelte +169 -0
- package/dist/ui/ProgressBar.svelte.d.ts +30 -0
- package/dist/ui/ProgressBarVariant.d.ts +7 -0
- package/dist/ui/ProgressBarVariant.js +1 -0
- package/dist/ui/SegmentedControl.svelte +0 -0
- package/dist/ui/SegmentedControl.svelte.d.ts +26 -0
- package/dist/ui/Sortable.svelte +163 -0
- package/dist/ui/Sortable.svelte.d.ts +47 -0
- package/dist/ui/Table.svelte +497 -56
- package/dist/ui/Table.svelte.d.ts +64 -2
- package/dist/ui/Tabs.svelte +22 -18
- package/dist/ui/Tabs.svelte.d.ts +6 -2
- package/dist/ui/ThemeSwitcher.svelte +26 -7
- package/dist/ui/ThemeSwitcher.svelte.d.ts +4 -2
- package/dist/ui/Tooltip.svelte +312 -180
- package/dist/ui/Tooltip.svelte.d.ts +4 -3
- package/dist/uiTheme.svelte.d.ts +86 -0
- package/dist/uiTheme.svelte.js +214 -0
- package/dist/util/DateFunctions.js +1 -1
- package/dist/util/DragDrop.d.ts +50 -0
- package/dist/util/DragDrop.js +154 -0
- package/dist/util/NavigateTo.js +2 -2
- package/dist/util/dayjs.d.ts +4 -0
- package/dist/util/dayjs.js +15 -0
- package/dist/util/interceptLinkClick.d.ts +13 -0
- package/dist/util/interceptLinkClick.js +33 -0
- package/package.json +66 -26
- package/dist/display/Alert.svelte +0 -179
- package/dist/display/Alert.svelte.d.ts +0 -13
- package/dist/form/FileInput.svelte +0 -235
- package/dist/form/FileInput.svelte.d.ts +0 -23
- package/dist/form/PasswordInput.svelte +0 -252
- package/dist/form/PasswordInput.svelte.d.ts +0 -33
- package/dist/form/Rating.svelte +0 -235
- package/dist/form/Rating.svelte.d.ts +0 -21
- package/dist/styles/components.css +0 -199
- package/dist/styles/dark.css +0 -146
- package/dist/styles/index.css +0 -116
- package/dist/styles/reset.css +0 -110
- package/dist/styles/semantic.css +0 -86
- package/dist/styles/tokens.css +0 -203
- package/dist/styles/utilities.css +0 -523
- package/dist/ui/Breadcrumbs.svelte +0 -131
- package/dist/ui/Breadcrumbs.svelte.d.ts +0 -16
- package/dist/ui/LoadingOverlay.svelte +0 -53
- package/dist/ui/LoadingOverlay.svelte.d.ts +0 -11
- package/dist/ui/Progress.svelte +0 -191
- package/dist/ui/Progress.svelte.d.ts +0 -15
- package/dist/ui/RingProgress.svelte +0 -141
- package/dist/ui/RingProgress.svelte.d.ts +0 -18
- package/dist/ui/Skeleton.svelte +0 -85
- package/dist/ui/Skeleton.svelte.d.ts +0 -12
- package/dist/ui/Stepper.svelte +0 -355
- package/dist/ui/Stepper.svelte.d.ts +0 -24
- package/dist/ui/Timeline.svelte +0 -225
- package/dist/ui/Timeline.svelte.d.ts +0 -23
- /package/dist/{actions → util}/ClickOutside.d.ts +0 -0
- /package/dist/{actions → util}/ClickOutside.js +0 -0
- /package/dist/{transitions → util}/Transitions.d.ts +0 -0
- /package/dist/{transitions → util}/Transitions.js +0 -0
|
@@ -1,181 +1,282 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import ComboBox from "./ComboBox.svelte";
|
|
3
|
-
import { clickOutside } from "../actions/ClickOutside.js";
|
|
4
|
-
import Textbox from "./Textbox.svelte";
|
|
5
|
-
import type { NotifyModel } from "../models/NotifyModel.js";
|
|
1
|
+
<script module lang="ts">
|
|
6
2
|
import type {
|
|
3
|
+
ComboBoxGroup,
|
|
7
4
|
ComboBoxItem,
|
|
8
5
|
FetchFunctionType,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
RetrieveLabelFunctionType,
|
|
7
|
+
SearchFunctionType
|
|
8
|
+
} from '../models/ComboBoxItem.js';
|
|
9
|
+
import type { Snippet } from 'svelte';
|
|
12
10
|
|
|
13
|
-
interface
|
|
11
|
+
export interface AutocompleteProps {
|
|
12
|
+
/** HTML name attribute for the input */
|
|
13
|
+
name?: string;
|
|
14
|
+
/** Label text displayed above the input */
|
|
14
15
|
label?: string;
|
|
16
|
+
/** Current input value (bindable) */
|
|
15
17
|
value?: string;
|
|
18
|
+
/** Full selected item object (bindable) */
|
|
19
|
+
rawValue?: ComboBoxItem;
|
|
20
|
+
/** Placeholder text when input is empty */
|
|
16
21
|
placeholder?: string;
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
/** Mark field as required (shows asterisk) */
|
|
23
|
+
required?: boolean;
|
|
24
|
+
/** CSS classes for the input element */
|
|
25
|
+
class?: string;
|
|
26
|
+
/** CSS classes for the container element */
|
|
27
|
+
containerClass?: string;
|
|
28
|
+
/** Disable the input */
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
/** Show error state styling */
|
|
31
|
+
showError?: boolean;
|
|
32
|
+
/** Error message to display */
|
|
33
|
+
errorText?: string;
|
|
34
|
+
/** Auto-focus the input on mount */
|
|
19
35
|
autofocus?: boolean;
|
|
20
|
-
|
|
36
|
+
/** Auto-focus on every dialog open */
|
|
37
|
+
autofocusDialog?: boolean;
|
|
38
|
+
/** Hide "no results" message when search finds nothing */
|
|
39
|
+
hideNoResults?: boolean;
|
|
40
|
+
/** Prevent updating value when an option is selected */
|
|
21
41
|
preventChangeOnSelection?: boolean;
|
|
22
|
-
|
|
42
|
+
/** Allow suggesting a new value be added when the input doesn't match an existing option */
|
|
43
|
+
allowAdd?: boolean;
|
|
44
|
+
/** Builds the label shown for the "add new value" suggestion (default: `Add "<value>"`) */
|
|
45
|
+
addItemLabel?: (value: string) => string;
|
|
46
|
+
/** Text shown while loading options */
|
|
23
47
|
loadingText?: string;
|
|
48
|
+
/** CSS classes for the FormGroup wrapper */
|
|
24
49
|
groupClass?: string;
|
|
50
|
+
/** SVG icon displayed on the left side */
|
|
25
51
|
leftIconSvg?: string;
|
|
52
|
+
/** Static list of autocomplete options */
|
|
26
53
|
options?: ComboBoxItem[];
|
|
27
|
-
|
|
28
|
-
|
|
54
|
+
/** Options organized into groups */
|
|
55
|
+
groupedOptions?: ComboBoxGroup[];
|
|
56
|
+
/** Position of the tooltip */
|
|
57
|
+
tooltipLocation?: 'top' | 'bottom' | 'left' | 'right';
|
|
58
|
+
/** Async function to fetch all options */
|
|
59
|
+
fetchFunction?: FetchFunctionType | null;
|
|
60
|
+
/** Async function to search/filter options based on input */
|
|
61
|
+
searchFunction?: SearchFunctionType | null;
|
|
62
|
+
/** Async function to retrieve label for a value */
|
|
63
|
+
retrieveLabelFunction?: RetrieveLabelFunctionType | null;
|
|
64
|
+
/** Rich tooltip content using a Svelte snippet */
|
|
65
|
+
tooltipContent?: Snippet;
|
|
66
|
+
/** Simple tooltip text */
|
|
67
|
+
tooltipText?: string;
|
|
68
|
+
/** Callback when input value changes */
|
|
29
69
|
onchange?: (e: string) => void;
|
|
70
|
+
/** Callback when Enter key is pressed */
|
|
30
71
|
enterPressed?: (e: string) => void;
|
|
72
|
+
/** Callback when an option is selected */
|
|
31
73
|
onSelect?: (e: ComboBoxItem) => void;
|
|
32
|
-
|
|
74
|
+
/** Callback when selection changes (returns full item object) */
|
|
75
|
+
onchangeRaw?: (e: ComboBoxItem | undefined) => void;
|
|
76
|
+
/** Callback when the user chooses to add the typed value as a new item */
|
|
77
|
+
onItemAdded?: (value: string) => void;
|
|
33
78
|
}
|
|
79
|
+
</script>
|
|
80
|
+
|
|
81
|
+
<script lang="ts">
|
|
82
|
+
import ComboBoxMulti from './ComboBoxMulti.svelte';
|
|
83
|
+
import { clickOutside } from '../util/ClickOutside.js';
|
|
84
|
+
import Textbox from './Textbox.svelte';
|
|
85
|
+
import { ComboBoxCore, findItemByValue } from './comboBoxCore.svelte.js';
|
|
86
|
+
import { tick } from 'svelte';
|
|
87
|
+
import { useDialogEvents } from '../ui/DialogEvents.svelte.js';
|
|
34
88
|
|
|
35
89
|
let {
|
|
90
|
+
name,
|
|
36
91
|
label,
|
|
37
|
-
value = $bindable(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
92
|
+
value = $bindable(''),
|
|
93
|
+
rawValue = $bindable(undefined),
|
|
94
|
+
placeholder = 'Start typing to search...',
|
|
95
|
+
required = false,
|
|
96
|
+
class: classes = '',
|
|
97
|
+
containerClass = '',
|
|
98
|
+
disabled = false,
|
|
99
|
+
showError = false,
|
|
100
|
+
errorText = '',
|
|
41
101
|
autofocus = false,
|
|
42
|
-
|
|
102
|
+
autofocusDialog = false,
|
|
103
|
+
hideNoResults = false,
|
|
43
104
|
preventChangeOnSelection = false,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
105
|
+
allowAdd = false,
|
|
106
|
+
addItemLabel = (v: string) => `Add "${v}"`,
|
|
107
|
+
loadingText = '',
|
|
108
|
+
groupClass = '',
|
|
47
109
|
leftIconSvg,
|
|
48
|
-
options,
|
|
49
|
-
|
|
50
|
-
|
|
110
|
+
options = [],
|
|
111
|
+
groupedOptions = [],
|
|
112
|
+
tooltipLocation = 'top',
|
|
113
|
+
fetchFunction = null,
|
|
114
|
+
searchFunction = null,
|
|
115
|
+
retrieveLabelFunction = null,
|
|
116
|
+
tooltipContent,
|
|
117
|
+
tooltipText,
|
|
51
118
|
onchange = undefined,
|
|
52
119
|
enterPressed = undefined,
|
|
53
120
|
onSelect = undefined,
|
|
54
|
-
|
|
55
|
-
|
|
121
|
+
onchangeRaw = undefined,
|
|
122
|
+
onItemAdded = undefined
|
|
123
|
+
}: AutocompleteProps = $props();
|
|
56
124
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
125
|
+
const core = new ComboBoxCore({
|
|
126
|
+
getOptions: () => options,
|
|
127
|
+
getGroupedOptions: () => groupedOptions,
|
|
128
|
+
getValue: () => value,
|
|
129
|
+
setValue: (v) => (value = v ?? ''),
|
|
130
|
+
setRawValue: (r) => (rawValue = r),
|
|
131
|
+
getFetchFunction: () => fetchFunction,
|
|
132
|
+
getSearchFunction: () => searchFunction,
|
|
133
|
+
getRetrieveLabelFunction: () => retrieveLabelFunction,
|
|
134
|
+
clearUnknownStatic: false,
|
|
135
|
+
onOptionsChanged: () => {
|
|
136
|
+
if (value) core.filterLocal(value);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
/** Synthetic "add new value" suggestion shown when the typed value matches no option */
|
|
141
|
+
let addOption: ComboBoxItem | undefined = $derived.by(() => {
|
|
142
|
+
const trimmed = value?.trim();
|
|
143
|
+
if (!allowAdd || !trimmed) return undefined;
|
|
144
|
+
|
|
145
|
+
const exists = core.allGroups
|
|
146
|
+
.flatMap((x) => x.items)
|
|
147
|
+
.some(
|
|
148
|
+
(x) =>
|
|
149
|
+
x.label.toLowerCase() === trimmed.toLowerCase() ||
|
|
150
|
+
x.value.toLowerCase() === trimmed.toLowerCase()
|
|
151
|
+
);
|
|
152
|
+
if (exists) return undefined;
|
|
153
|
+
|
|
154
|
+
return { label: addItemLabel(trimmed), value: trimmed, isAddNew: true };
|
|
155
|
+
});
|
|
60
156
|
|
|
61
|
-
|
|
62
|
-
let
|
|
157
|
+
/** Groups passed to the dropdown, including the add suggestion when applicable */
|
|
158
|
+
let displayGroups: ComboBoxGroup[] = $derived(
|
|
159
|
+
addOption
|
|
160
|
+
? [...core.filteredGroups, { label: '', items: [addOption], showGroupName: false }]
|
|
161
|
+
: core.filteredGroups
|
|
162
|
+
);
|
|
63
163
|
|
|
64
164
|
let open = $state(false);
|
|
165
|
+
let internalValue = $state(value);
|
|
65
166
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
167
|
+
useDialogEvents({
|
|
168
|
+
onFirstOpen: () => {
|
|
169
|
+
if (autofocus) {
|
|
170
|
+
setTimeout(() => {
|
|
171
|
+
doFocus();
|
|
172
|
+
}, 150);
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
onOpen: () => {
|
|
176
|
+
if (autofocusDialog) {
|
|
177
|
+
setTimeout(() => {
|
|
178
|
+
doFocus();
|
|
179
|
+
}, 150);
|
|
180
|
+
}
|
|
75
181
|
}
|
|
76
182
|
});
|
|
77
183
|
|
|
78
|
-
function
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
html: option.label,
|
|
82
|
-
value: option.value,
|
|
83
|
-
selected: option.value == value,
|
|
84
|
-
label: option.label,
|
|
85
|
-
};
|
|
86
|
-
});
|
|
87
|
-
filteredOptions = [...allOptions];
|
|
184
|
+
function doFocus() {
|
|
185
|
+
open = true;
|
|
186
|
+
tick().then(() => textboxElement?.focus());
|
|
88
187
|
}
|
|
89
188
|
|
|
90
|
-
|
|
189
|
+
$effect(() => {
|
|
190
|
+
if (value !== internalValue) {
|
|
191
|
+
internalValue = value;
|
|
192
|
+
rawValue = findItemByValue(core.allGroups, value);
|
|
193
|
+
onchangeRaw?.(rawValue);
|
|
194
|
+
core.preloadValues();
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
let selectionJustMade = false;
|
|
91
199
|
|
|
92
200
|
function onSelection(selectedValue: ComboBoxItem) {
|
|
201
|
+
selectionJustMade = true;
|
|
93
202
|
open = false;
|
|
94
203
|
|
|
95
|
-
if (selectedValue.
|
|
96
|
-
|
|
97
|
-
const newItem: ComboBoxItem = { label: newValue, value: newValue };
|
|
98
|
-
if (options) {
|
|
99
|
-
options.push(newItem);
|
|
100
|
-
convertOptions(options);
|
|
101
|
-
} else {
|
|
102
|
-
allOptions.push({ ...newItem, selected: true });
|
|
103
|
-
}
|
|
104
|
-
if (!preventChangeOnSelection) value = newValue;
|
|
105
|
-
onSelect?.(newItem);
|
|
106
|
-
onCreate?.(newValue);
|
|
204
|
+
if (selectedValue.isAddNew) {
|
|
205
|
+
addItem(selectedValue.value);
|
|
107
206
|
return;
|
|
108
207
|
}
|
|
109
208
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
209
|
+
core.allGroups
|
|
210
|
+
.flatMap((x) => x.items)
|
|
211
|
+
.forEach((option) => {
|
|
212
|
+
option.selected = option.value === selectedValue.value;
|
|
113
213
|
});
|
|
214
|
+
|
|
215
|
+
if (!preventChangeOnSelection) {
|
|
216
|
+
value = selectedValue.value;
|
|
217
|
+
internalValue = value;
|
|
114
218
|
}
|
|
115
219
|
|
|
116
|
-
|
|
220
|
+
rawValue = selectedValue;
|
|
117
221
|
|
|
118
222
|
onSelect?.(selectedValue);
|
|
223
|
+
onchangeRaw?.(selectedValue);
|
|
119
224
|
}
|
|
120
225
|
|
|
121
|
-
function
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
226
|
+
function addItem(newValue: string) {
|
|
227
|
+
open = false;
|
|
228
|
+
|
|
229
|
+
const newItem: ComboBoxItem = { label: newValue, value: newValue };
|
|
230
|
+
|
|
231
|
+
if (!preventChangeOnSelection) {
|
|
232
|
+
value = newValue;
|
|
233
|
+
internalValue = value;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
rawValue = newItem;
|
|
237
|
+
|
|
238
|
+
onItemAdded?.(newValue);
|
|
239
|
+
onchangeRaw?.(newItem);
|
|
127
240
|
}
|
|
128
241
|
|
|
129
|
-
function onFilterChange(
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
);
|
|
141
|
-
}, 300);
|
|
142
|
-
} else if (allOptions) {
|
|
143
|
-
filteredOptions = allOptions.filter((option) =>
|
|
144
|
-
option.label.toLowerCase().includes(value.toLowerCase()),
|
|
145
|
-
);
|
|
146
|
-
filteredOptions = appendCreateOption(filteredOptions, value);
|
|
242
|
+
function onFilterChange(filterValue: string) {
|
|
243
|
+
if (filterValue.length === 0) {
|
|
244
|
+
core.filterLocal('');
|
|
245
|
+
open = true;
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (searchFunction && filterValue) {
|
|
250
|
+
core.search(filterValue, () => (open = true));
|
|
251
|
+
} else {
|
|
252
|
+
core.filterLocal(filterValue);
|
|
147
253
|
open = true;
|
|
148
254
|
}
|
|
149
255
|
|
|
150
|
-
onchange?.(
|
|
256
|
+
onchange?.(filterValue);
|
|
151
257
|
}
|
|
152
258
|
|
|
153
259
|
let textboxElement: HTMLElement | undefined = $state(undefined);
|
|
154
|
-
|
|
155
|
-
// returns true if an item was selected, false otherwise
|
|
156
|
-
let comboBoxKeyDown: ((e: KeyboardEvent) => boolean) | undefined =
|
|
157
|
-
$state(undefined);
|
|
260
|
+
let comboBoxEl: ReturnType<typeof ComboBoxMulti> | undefined = $state(undefined);
|
|
158
261
|
|
|
159
262
|
function onKeyDown(e: KeyboardEvent) {
|
|
160
263
|
if (!open) {
|
|
161
|
-
if (e.key ===
|
|
162
|
-
// If combobox is not open return user entered string
|
|
163
|
-
enterPressed?.(value);
|
|
164
|
-
|
|
264
|
+
if (e.key === 'Enter') enterPressed?.(value);
|
|
165
265
|
return;
|
|
166
266
|
}
|
|
167
267
|
|
|
168
|
-
if (e.key ===
|
|
268
|
+
if (e.key === 'Escape') {
|
|
169
269
|
e.preventDefault();
|
|
170
270
|
open = false;
|
|
171
|
-
} else
|
|
172
|
-
|
|
271
|
+
} else {
|
|
272
|
+
selectionJustMade = false;
|
|
273
|
+
comboBoxEl?.handleKeyDown?.(e);
|
|
173
274
|
|
|
174
|
-
if (!
|
|
275
|
+
if (!selectionJustMade && e.key === 'Enter') enterPressed?.(value);
|
|
175
276
|
}
|
|
176
277
|
}
|
|
177
278
|
|
|
178
|
-
function onFocus(e:
|
|
279
|
+
function onFocus(_value: string, e: FocusEvent) {
|
|
179
280
|
open = true;
|
|
180
281
|
const target = e?.target as HTMLInputElement;
|
|
181
282
|
target?.select();
|
|
@@ -188,36 +289,68 @@
|
|
|
188
289
|
}
|
|
189
290
|
</script>
|
|
190
291
|
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
292
|
+
<div class="autocomplete-container">
|
|
293
|
+
<Textbox
|
|
294
|
+
{name}
|
|
295
|
+
type="search"
|
|
296
|
+
{label}
|
|
297
|
+
class={classes}
|
|
298
|
+
{containerClass}
|
|
299
|
+
{required}
|
|
300
|
+
{showError}
|
|
301
|
+
{errorText}
|
|
302
|
+
{tooltipLocation}
|
|
303
|
+
{tooltipContent}
|
|
304
|
+
{tooltipText}
|
|
305
|
+
bind:textboxElement
|
|
306
|
+
placeholder={core.preloading ? 'Loading...' : placeholder}
|
|
307
|
+
loading={core.searching || core.preloading}
|
|
308
|
+
disabled={core.preloading || disabled}
|
|
309
|
+
autocomplete="off"
|
|
310
|
+
{groupClass}
|
|
311
|
+
{leftIconSvg}
|
|
312
|
+
bind:value
|
|
313
|
+
oninput={() => {
|
|
314
|
+
onFilterChange(value);
|
|
315
|
+
}}
|
|
316
|
+
onfocus={onFocus}
|
|
317
|
+
onkeydown={onKeyDown}
|
|
318
|
+
/>
|
|
319
|
+
<div class="autocomplete-panel {open ? '' : 'hidden'}">
|
|
320
|
+
<div class="autocomplete-panel-inner" use:clickOutside={closePopover}>
|
|
321
|
+
<ComboBoxMulti
|
|
322
|
+
bind:this={comboBoxEl}
|
|
323
|
+
filterString={value}
|
|
324
|
+
values={rawValue ? [rawValue] : []}
|
|
325
|
+
{onSelection}
|
|
326
|
+
groupedOptions={displayGroups}
|
|
327
|
+
{open}
|
|
328
|
+
loading={core.searching}
|
|
329
|
+
{hideNoResults}
|
|
330
|
+
{loadingText}
|
|
331
|
+
/>
|
|
332
|
+
</div>
|
|
219
333
|
</div>
|
|
220
|
-
</
|
|
334
|
+
</div>
|
|
221
335
|
|
|
222
336
|
<style>
|
|
337
|
+
.autocomplete-container {
|
|
338
|
+
position: relative;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.autocomplete-panel {
|
|
342
|
+
position: absolute;
|
|
343
|
+
width: 100%;
|
|
344
|
+
left: 0;
|
|
345
|
+
z-index: 70;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
.autocomplete-panel-inner {
|
|
349
|
+
position: relative;
|
|
350
|
+
width: 100%;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.hidden {
|
|
354
|
+
display: none;
|
|
355
|
+
}
|
|
223
356
|
</style>
|
|
@@ -1,25 +1,73 @@
|
|
|
1
|
-
import type { ComboBoxItem, FetchFunctionType, SearchFunctionType } from
|
|
2
|
-
|
|
1
|
+
import type { ComboBoxGroup, ComboBoxItem, FetchFunctionType, RetrieveLabelFunctionType, SearchFunctionType } from '../models/ComboBoxItem.js';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
export interface AutocompleteProps {
|
|
4
|
+
/** HTML name attribute for the input */
|
|
5
|
+
name?: string;
|
|
6
|
+
/** Label text displayed above the input */
|
|
3
7
|
label?: string;
|
|
8
|
+
/** Current input value (bindable) */
|
|
4
9
|
value?: string;
|
|
10
|
+
/** Full selected item object (bindable) */
|
|
11
|
+
rawValue?: ComboBoxItem;
|
|
12
|
+
/** Placeholder text when input is empty */
|
|
5
13
|
placeholder?: string;
|
|
6
|
-
|
|
7
|
-
|
|
14
|
+
/** Mark field as required (shows asterisk) */
|
|
15
|
+
required?: boolean;
|
|
16
|
+
/** CSS classes for the input element */
|
|
17
|
+
class?: string;
|
|
18
|
+
/** CSS classes for the container element */
|
|
19
|
+
containerClass?: string;
|
|
20
|
+
/** Disable the input */
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/** Show error state styling */
|
|
23
|
+
showError?: boolean;
|
|
24
|
+
/** Error message to display */
|
|
25
|
+
errorText?: string;
|
|
26
|
+
/** Auto-focus the input on mount */
|
|
8
27
|
autofocus?: boolean;
|
|
9
|
-
|
|
28
|
+
/** Auto-focus on every dialog open */
|
|
29
|
+
autofocusDialog?: boolean;
|
|
30
|
+
/** Hide "no results" message when search finds nothing */
|
|
31
|
+
hideNoResults?: boolean;
|
|
32
|
+
/** Prevent updating value when an option is selected */
|
|
10
33
|
preventChangeOnSelection?: boolean;
|
|
11
|
-
|
|
34
|
+
/** Allow suggesting a new value be added when the input doesn't match an existing option */
|
|
35
|
+
allowAdd?: boolean;
|
|
36
|
+
/** Builds the label shown for the "add new value" suggestion (default: `Add "<value>"`) */
|
|
37
|
+
addItemLabel?: (value: string) => string;
|
|
38
|
+
/** Text shown while loading options */
|
|
12
39
|
loadingText?: string;
|
|
40
|
+
/** CSS classes for the FormGroup wrapper */
|
|
13
41
|
groupClass?: string;
|
|
42
|
+
/** SVG icon displayed on the left side */
|
|
14
43
|
leftIconSvg?: string;
|
|
44
|
+
/** Static list of autocomplete options */
|
|
15
45
|
options?: ComboBoxItem[];
|
|
16
|
-
|
|
17
|
-
|
|
46
|
+
/** Options organized into groups */
|
|
47
|
+
groupedOptions?: ComboBoxGroup[];
|
|
48
|
+
/** Position of the tooltip */
|
|
49
|
+
tooltipLocation?: 'top' | 'bottom' | 'left' | 'right';
|
|
50
|
+
/** Async function to fetch all options */
|
|
51
|
+
fetchFunction?: FetchFunctionType | null;
|
|
52
|
+
/** Async function to search/filter options based on input */
|
|
53
|
+
searchFunction?: SearchFunctionType | null;
|
|
54
|
+
/** Async function to retrieve label for a value */
|
|
55
|
+
retrieveLabelFunction?: RetrieveLabelFunctionType | null;
|
|
56
|
+
/** Rich tooltip content using a Svelte snippet */
|
|
57
|
+
tooltipContent?: Snippet;
|
|
58
|
+
/** Simple tooltip text */
|
|
59
|
+
tooltipText?: string;
|
|
60
|
+
/** Callback when input value changes */
|
|
18
61
|
onchange?: (e: string) => void;
|
|
62
|
+
/** Callback when Enter key is pressed */
|
|
19
63
|
enterPressed?: (e: string) => void;
|
|
64
|
+
/** Callback when an option is selected */
|
|
20
65
|
onSelect?: (e: ComboBoxItem) => void;
|
|
21
|
-
|
|
66
|
+
/** Callback when selection changes (returns full item object) */
|
|
67
|
+
onchangeRaw?: (e: ComboBoxItem | undefined) => void;
|
|
68
|
+
/** Callback when the user chooses to add the typed value as a new item */
|
|
69
|
+
onItemAdded?: (value: string) => void;
|
|
22
70
|
}
|
|
23
|
-
declare const Autocomplete: import("svelte").Component<
|
|
71
|
+
declare const Autocomplete: import("svelte").Component<AutocompleteProps, {}, "value" | "rawValue">;
|
|
24
72
|
type Autocomplete = ReturnType<typeof Autocomplete>;
|
|
25
73
|
export default Autocomplete;
|