@lavalogic/scoria 0.37.44 → 0.37.45
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 +58 -58
- package/dist/Components/AccordionGroup.svelte +46 -46
- package/dist/Components/AccordionGroupButton.svelte +76 -76
- package/dist/Components/Action.svelte +136 -136
- package/dist/Components/ActionProps.d.ts +2 -6
- package/dist/Components/AlertModal.svelte +195 -183
- package/dist/Components/AppointmentCalendar/AppointmentCalendar.svelte +702 -702
- package/dist/Components/Base/BaseModal.svelte +125 -125
- package/dist/Components/Base/ContextWrapper.svelte +72 -72
- package/dist/Components/Base/Pagination.svelte +198 -198
- package/dist/Components/Base/Snippets.svelte +36 -36
- package/dist/Components/BigRadioSet.svelte +38 -38
- package/dist/Components/Bubble.svelte +101 -101
- package/dist/Components/Button.svelte +209 -209
- package/dist/Components/ButtonProps.d.ts +2 -6
- package/dist/Components/Checkbox.svelte +86 -86
- package/dist/Components/CollapsibleCard.svelte +78 -78
- package/dist/Components/Contexts/ContextMenu.svelte +164 -164
- package/dist/Components/Contexts/ContextMenuDivider.svelte +15 -15
- package/dist/Components/Contexts/ContextMenuOption.svelte +60 -60
- package/dist/Components/Contexts/Toast.svelte +83 -83
- package/dist/Components/Contexts/ToastContainer.svelte +65 -65
- package/dist/Components/Contexts/Tooltip.svelte +37 -37
- package/dist/Components/DataMatrixIcon.svelte +112 -112
- package/dist/Components/DataMatrixIconProps.d.ts +3 -13
- package/dist/Components/DateInput.svelte +148 -148
- package/dist/Components/DatePicker.svelte +300 -300
- package/dist/Components/DesktopModal.svelte +90 -90
- package/dist/Components/Dial.svelte +204 -204
- package/dist/Components/DialProps.d.ts +1 -18
- package/dist/Components/DimensionInput.svelte +170 -170
- package/dist/Components/DragMenu/DragMenuHolder.svelte +119 -119
- package/dist/Components/DragMenu/DraggableCard.svelte +77 -77
- package/dist/Components/FileCard.svelte +24 -24
- package/dist/Components/FileUpload.svelte +236 -236
- package/dist/Components/GridInput.svelte +196 -200
- package/dist/Components/GridInputSet.svelte +29 -29
- package/dist/Components/HorizontalTabGroup.svelte +82 -82
- package/dist/Components/HorizontalTabGroupButton.svelte +44 -44
- package/dist/Components/Icon.svelte +128 -128
- package/dist/Components/IconProps.d.ts +2 -7
- package/dist/Components/Icons.js +357 -357
- package/dist/Components/LoadingAnimation.svelte +29 -29
- package/dist/Components/LoadingModal.svelte +45 -45
- package/dist/Components/LoadingOverlay.svelte +25 -25
- package/dist/Components/LoadingOverlayProps.d.ts +3 -7
- package/dist/Components/Modal.svelte +258 -258
- package/dist/Components/ModalProps.d.ts +0 -3
- package/dist/Components/MultiSelect.svelte +220 -220
- package/dist/Components/MultiSelectCommonProps.d.ts +6 -17
- package/dist/Components/Nav/Nav.svelte +99 -99
- package/dist/Components/Nav/NavProps.d.ts +4 -11
- package/dist/Components/Nav/NavServiceMenuList.svelte +43 -43
- package/dist/Components/Nav/NavTab.svelte +62 -62
- package/dist/Components/Nav/ServiceMenuItem.svelte +100 -100
- package/dist/Components/Nav/ServicesNav.svelte +80 -80
- package/dist/Components/NumberInput.svelte +157 -157
- package/dist/Components/PageHeading.svelte +25 -25
- package/dist/Components/PasswordInput.svelte +88 -88
- package/dist/Components/Portal.svelte +36 -36
- package/dist/Components/ProgressBubble.svelte +107 -108
- package/dist/Components/ProgressBubbleProps.d.ts +3 -3
- package/dist/Components/QuerySelect.svelte +366 -366
- package/dist/Components/QuerySelectProps.d.ts +4 -14
- package/dist/Components/SingleSelect.svelte +250 -250
- package/dist/Components/SingleSelectCommonProps.d.ts +3 -19
- package/dist/Components/StepButton.svelte +70 -70
- package/dist/Components/StepForm.svelte +140 -140
- package/dist/Components/Switch.svelte +69 -69
- package/dist/Components/Table/ARCHITECTURE.md +298 -0
- package/dist/Components/Table/Body/QuickSearchCell.svelte +679 -694
- package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +51 -51
- package/dist/Components/Table/Body/Rows/ColumnList.svelte +59 -59
- package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +456 -478
- package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +79 -79
- package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +185 -188
- package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +124 -124
- package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +120 -120
- package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +230 -230
- package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +105 -105
- package/dist/Components/Table/Body/Rows/Columns/SelectColumn.d.ts +12 -9
- package/dist/Components/Table/Body/Rows/Columns/SelectTableCell.d.ts +5 -5
- package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +87 -87
- package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +126 -126
- package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +159 -159
- package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +246 -246
- package/dist/Components/Table/Body/Rows/Columns/TableDatePickerProps.d.ts +4 -4
- package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +216 -216
- package/dist/Components/Table/Body/Rows/Columns/TableQueryCell.d.ts +6 -5
- package/dist/Components/Table/Body/Rows/Columns/TableQueryColumn.d.ts +7 -6
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +252 -257
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +179 -179
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +221 -229
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte.d.ts +11 -11
- package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +197 -197
- package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +190 -190
- package/dist/Components/Table/Body/Rows/TableRow.svelte +290 -290
- package/dist/Components/Table/Body/TableBody.svelte +155 -155
- package/dist/Components/Table/ColumnDefinitions/ExampleItemColumnDefRepository.svelte.js +2 -3
- package/dist/Components/Table/ColumnFactory.svelte.d.ts +9 -11
- package/dist/Components/Table/ColumnFactory.svelte.js +101 -118
- package/dist/Components/Table/ColumnKindRegistry.d.ts +112 -0
- package/dist/Components/Table/ColumnKindRegistry.js +63 -0
- package/dist/Components/Table/Headers/HighlightAllHeader.svelte +41 -41
- package/dist/Components/Table/Headers/SelectAllHeader.svelte +30 -30
- package/dist/Components/Table/Headers/TableHead.svelte +415 -413
- package/dist/Components/Table/Misc/ColumnPanel.svelte +94 -94
- package/dist/Components/Table/Misc/ColumnPanelModal.svelte +112 -112
- package/dist/Components/Table/Misc/FilterInput.svelte +620 -644
- package/dist/Components/Table/Misc/FilterInput.svelte.d.ts +12 -12
- package/dist/Components/Table/Misc/FilterInputProps.d.ts +2 -2
- package/dist/Components/Table/Misc/FilterPanel.svelte +257 -257
- package/dist/Components/Table/Misc/FilterPanelModal.svelte +30 -30
- package/dist/Components/Table/Misc/SidePanel.svelte +35 -35
- package/dist/Components/Table/Misc/TableFooter.svelte +311 -311
- package/dist/Components/Table/Misc/TableHorizontalBar.svelte +125 -125
- package/dist/Components/Table/Misc/TableSidebar.svelte +157 -157
- package/dist/Components/Table/Misc/ToolboxPanel.svelte +100 -100
- package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +107 -107
- package/dist/Components/Table/NestedTable.svelte +130 -133
- package/dist/Components/Table/SubApis.svelte.d.ts +1 -5
- package/dist/Components/Table/SubApis.svelte.js +33 -32
- package/dist/Components/Table/Table.svelte +692 -745
- package/dist/Components/Table/TableHelpers.svelte.d.ts +6 -19
- package/dist/Components/Table/TableHelpers.svelte.js +6 -14
- package/dist/Components/Table/Types/Columns/Column.d.ts +2 -2
- package/dist/Components/Table/Types/Columns/DateColumn.d.ts +3 -3
- package/dist/Components/Table/Types/Columns/DateTableCell.d.ts +7 -7
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/AccessorDef.svelte.d.ts +7 -8
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/AccessorDef.svelte.js +4 -5
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/CheckboxDef.svelte.d.ts +11 -14
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/CheckboxDef.svelte.js +3 -4
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/DateInputDef.svelte.d.ts +7 -11
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/DateInputDef.svelte.js +3 -3
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/NumberInputDef.svelte.d.ts +13 -18
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/NumberInputDef.svelte.js +4 -5
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/QueryDef.svelte.d.ts +5 -5
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/QueryDef.svelte.js +2 -2
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/SelectDef.svelte.d.ts +15 -12
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/SelectDef.svelte.js +4 -5
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/TextInputDef.svelte.d.ts +8 -12
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/TextInputDef.svelte.js +3 -3
- package/dist/Components/Table/Types/Columns/Definitions/Actions/ActionsDef.svelte.d.ts +6 -6
- package/dist/Components/Table/Types/Columns/Definitions/Actions/ActionsDef.svelte.js +3 -3
- package/dist/Components/Table/Types/Columns/Definitions/ColumnDef.svelte.d.ts +49 -16
- package/dist/Components/Table/Types/Columns/Definitions/ColumnDef.svelte.js +27 -5
- package/dist/Components/Table/Types/Columns/Definitions/Display/AbstractDisplayDef.svelte.d.ts +7 -7
- package/dist/Components/Table/Types/Columns/Definitions/Display/AbstractDisplayDef.svelte.js +4 -4
- package/dist/Components/Table/Types/Columns/Definitions/Display/BubbleDef.svelte.d.ts +5 -5
- package/dist/Components/Table/Types/Columns/Definitions/Display/BubbleDef.svelte.js +2 -2
- package/dist/Components/Table/Types/Columns/Definitions/Display/DisplayDef.svelte.d.ts +5 -5
- package/dist/Components/Table/Types/Columns/Definitions/Display/DisplayDef.svelte.js +2 -2
- package/dist/Components/Table/Types/Columns/Definitions/Display/ProgressBarDef.svelte.d.ts +5 -5
- package/dist/Components/Table/Types/Columns/Definitions/Display/ProgressBarDef.svelte.js +2 -2
- package/dist/Components/Table/Types/Columns/Definitions/Display/ValidityDef.svelte.d.ts +5 -5
- package/dist/Components/Table/Types/Columns/Definitions/Display/ValidityDef.svelte.js +2 -2
- package/dist/Components/Table/Types/Columns/Definitions/Expand/ExpandDef.svelte.d.ts +11 -19
- package/dist/Components/Table/Types/Columns/Definitions/Expand/ExpandDef.svelte.js +4 -8
- package/dist/Components/Table/Types/Columns/Definitions/FilterOnly/FilterOnlyDef.svelte.d.ts +6 -7
- package/dist/Components/Table/Types/Columns/Definitions/FilterOnly/FilterOnlyDef.svelte.js +3 -4
- package/dist/Components/Table/Types/Columns/Definitions/RowSelection/RowSelectionDef.svelte.d.ts +9 -9
- package/dist/Components/Table/Types/Columns/Definitions/RowSelection/RowSelectionDef.svelte.js +4 -4
- package/dist/Components/Table/Types/Columns/ExpandTableCell.d.ts +5 -5
- package/dist/Components/Table/Types/Columns/ProgressBarTableCell.d.ts +6 -6
- package/dist/Components/Table/Types/Columns/TableCell.d.ts +7 -6
- package/dist/Components/Table/Types/Context/ClipboardState.svelte.d.ts +98 -0
- package/dist/Components/Table/Types/Context/ClipboardState.svelte.js +290 -0
- package/dist/Components/Table/Types/Context/ColumnLayoutState.svelte.d.ts +17 -45
- package/dist/Components/Table/Types/Context/ColumnLayoutState.svelte.js +17 -45
- package/dist/Components/Table/Types/Context/FilteringState.svelte.d.ts +9 -20
- package/dist/Components/Table/Types/Context/FilteringState.svelte.js +9 -20
- package/dist/Components/Table/Types/Context/FocusState.svelte.d.ts +23 -42
- package/dist/Components/Table/Types/Context/FocusState.svelte.js +32 -59
- package/dist/Components/Table/Types/Context/ITable.d.ts +5 -8
- package/dist/Components/Table/Types/Context/PreferencesState.svelte.d.ts +29 -56
- package/dist/Components/Table/Types/Context/PreferencesState.svelte.js +28 -55
- package/dist/Components/Table/Types/Context/QueryValuesState.svelte.d.ts +50 -0
- package/dist/Components/Table/Types/Context/QueryValuesState.svelte.js +62 -0
- package/dist/Components/Table/Types/Context/SelectionState.svelte.d.ts +17 -28
- package/dist/Components/Table/Types/Context/SelectionState.svelte.js +17 -28
- package/dist/Components/Table/Types/Context/SortingState.svelte.d.ts +15 -29
- package/dist/Components/Table/Types/Context/SortingState.svelte.js +17 -31
- package/dist/Components/Table/Types/Context/TableContext.svelte.d.ts +212 -325
- package/dist/Components/Table/Types/Context/TableContext.svelte.js +292 -706
- package/dist/Components/Table/Types/Context/VirtualisationState.svelte.d.ts +62 -79
- package/dist/Components/Table/Types/Context/VirtualisationState.svelte.js +54 -73
- package/dist/Components/Table/Types/DataRepository/BuiltInRemoteRepository.svelte.d.ts +16 -27
- package/dist/Components/Table/Types/DataRepository/BuiltInRemoteRepository.svelte.js +16 -27
- package/dist/Components/Table/Types/DataRepository/IDataRepository.d.ts +12 -15
- package/dist/Components/Table/Types/DataRepository/TableDataRepository.svelte.d.ts +15 -30
- package/dist/Components/Table/Types/DataRepository/TableDataRepository.svelte.js +16 -28
- package/dist/Components/Table/Types/Header.d.ts +4 -4
- package/dist/Components/Table/Types/HeaderGroup.d.ts +5 -5
- package/dist/Components/Table/Types/Public/index.d.ts +2 -4
- package/dist/Components/Table/Types/Public/index.js +2 -4
- package/dist/Components/Table/clipboardEscape.d.ts +32 -0
- package/dist/Components/Table/clipboardEscape.js +45 -0
- package/dist/Components/Table/createTable.svelte.d.ts +8 -18
- package/dist/Components/Table/createTable.svelte.js +19 -47
- package/dist/Components/Test/TestContextConsumer.svelte +13 -13
- package/dist/Components/TextArea.svelte +130 -130
- package/dist/Components/TextInput.svelte +176 -176
- package/dist/Components/ThreeStateRadio.svelte +131 -131
- package/dist/Components/Touch/BoolCard.svelte +45 -45
- package/dist/Components/Touch/DateModal.svelte +209 -209
- package/dist/Components/Touch/EditCard.svelte +59 -59
- package/dist/Components/Touch/InfoCard.svelte +31 -31
- package/dist/Components/Touch/InfoTextCard.svelte +28 -28
- package/dist/Components/Touch/ModalExplanation.svelte +17 -17
- package/dist/Components/Touch/NumberKeyboard.svelte +225 -225
- package/dist/Components/Touch/NumberModal.svelte +79 -79
- package/dist/Components/Touch/PlusMinusCard.svelte +46 -46
- package/dist/Components/Touch/SelectModal.svelte +123 -123
- package/dist/Components/Touch/SummaryCard.svelte +93 -93
- package/dist/Components/Touch/TextAreaModal.svelte +95 -95
- package/dist/Components/Touch/TextModal.svelte +106 -106
- package/dist/Components/Touch/TouchCard.svelte +33 -33
- package/dist/Components/Touch/TouchModal.svelte +274 -274
- package/dist/Components/Touch/UtilityButton.svelte +109 -109
- package/dist/Components/VerticalTabGroup.svelte +79 -79
- package/dist/Components/VerticalTabGroupButton.svelte +58 -58
- package/dist/Contexts/ToastContext.svelte.js +3 -4
- package/dist/Helpers/Datamatrix.d.ts +19 -19
- package/dist/Helpers/Datamatrix.js +291 -291
- package/dist/Helpers/Helpers.svelte.d.ts +2 -4
- package/dist/Helpers/Helpers.svelte.js +2 -4
- package/dist/Helpers/dropdownPortal.d.ts +26 -41
- package/dist/Helpers/dropdownPortal.js +62 -116
- package/dist/Types/Examples/ExampleModal.svelte +35 -35
- package/dist/index.d.ts +0 -1
- package/dist/scss/_basics.scss +12 -12
- package/dist/scss/_colours.scss +134 -134
- package/dist/scss/_mixins.scss +3348 -3360
- package/dist/scss/_motion.scss +57 -57
- package/dist/scss/_sizing.scss +85 -85
- package/dist/scss/_transitions.scss +8 -8
- package/package.json +2 -1
|
@@ -1,222 +1,222 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<script
|
|
4
|
-
lang="ts"
|
|
5
|
-
generics="V extends object, VP extends ValueProp<V>"
|
|
6
|
-
>
|
|
7
|
-
import { autoPluralise, generateWeakId, vowels } from '../Helpers/Helpers.svelte.js';
|
|
8
|
-
import { attachDropdownPortal } from '../Helpers/dropdownPortal.js';
|
|
9
|
-
import { Colour, ColourSet } from '../scss/colours.js';
|
|
10
|
-
import type { ValueProp } from '../Types/Internal/Misc.js';
|
|
11
|
-
import { Size } from '../Types/Internal/Size.js';
|
|
12
|
-
import Svelecte from 'svelecte';
|
|
13
|
-
import { SvelteSet } from 'svelte/reactivity';
|
|
14
|
-
import { onMount } from 'svelte';
|
|
15
|
-
import Action from './Action.svelte';
|
|
16
|
-
import Icon from './Icon.svelte';
|
|
17
|
-
import type { MultiSelectProps } from './MultiSelectProps.js';
|
|
18
|
-
|
|
19
|
-
// NOTE selectedValues is mutated by svelecte without asking, so we sometimes have to reverse it without a callback (side effects)
|
|
20
|
-
const {
|
|
21
|
-
label,
|
|
22
|
-
inputId = generateWeakId(),
|
|
23
|
-
options,
|
|
24
|
-
labelProp,
|
|
25
|
-
valueProp,
|
|
26
|
-
width,
|
|
27
|
-
valueAsObject = true,
|
|
28
|
-
height,
|
|
29
|
-
selectedValues,
|
|
30
|
-
onchange,
|
|
31
|
-
collapseSelection = false,
|
|
32
|
-
name = 'Item',
|
|
33
|
-
disabled,
|
|
34
|
-
required,
|
|
35
|
-
invalid,
|
|
36
|
-
}: MultiSelectProps<V, VP> = $props();
|
|
37
|
-
|
|
38
|
-
const an = $derived(name && vowels.has(name.at(0)?.toLocaleLowerCase() ?? '') ? 'an' : 'a');
|
|
39
|
-
|
|
40
|
-
// Pre-computed set of selected primitive keys. Used in the option snippet
|
|
41
|
-
// to avoid an O(n*m) findIndex sweep per render.
|
|
42
|
-
const selectedKeys = $derived.by(() => {
|
|
43
|
-
const s = new SvelteSet<V[VP]>();
|
|
44
|
-
if (valueAsObject) {
|
|
45
|
-
for (const v of selectedValues as Array<V>) {
|
|
46
|
-
s.add(v[valueProp]);
|
|
47
|
-
}
|
|
48
|
-
} else {
|
|
49
|
-
for (const v of selectedValues as Array<V[VP]>) {
|
|
50
|
-
s.add(v);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return s;
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
let isExpanded = $state(false);
|
|
57
|
-
|
|
58
|
-
onMount(() => {
|
|
59
|
-
const input = document.getElementById(inputId);
|
|
60
|
-
const svelecteRoot = input?.closest('div.svelecte') as HTMLElement | null;
|
|
61
|
-
const dropdownRef =
|
|
62
|
-
(svelecteRoot?.querySelector('.sv_dropdown') as HTMLElement | null) ?? undefined;
|
|
63
|
-
|
|
64
|
-
// HACK callback for is-open on/off; drives the chevron rotation
|
|
65
|
-
// in the action snippet further down.
|
|
66
|
-
const observer = new MutationObserver((mutations: Array<MutationRecord>) => {
|
|
67
|
-
for (let i = mutations.length - 1; i > -1; i--) {
|
|
68
|
-
const mutation = mutations[i];
|
|
69
|
-
if (mutation.attributeName === 'class') {
|
|
70
|
-
isExpanded = dropdownRef?.classList.contains('is-open') ?? false;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
if (dropdownRef) {
|
|
76
|
-
observer.observe(dropdownRef, { attributes: true });
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Teleport the Svelecte dropdown to `document.body` while open
|
|
80
|
-
// so it escapes every ancestor `overflow` / `transform` /
|
|
81
|
-
// `z-index` stacking context. See `Helpers/dropdownPortal.ts`
|
|
82
|
-
// for the rationale and behaviour (auto-flip upwards on tight
|
|
83
|
-
// viewports, scroll-aware repositioning, viewport-bounded
|
|
84
|
-
// max-height).
|
|
85
|
-
const detachPortal = attachDropdownPortal({
|
|
86
|
-
getTrigger: () => svelecteRoot,
|
|
87
|
-
getDropdown: () => dropdownRef,
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
return () => {
|
|
91
|
-
observer.disconnect();
|
|
92
|
-
detachPortal();
|
|
93
|
-
};
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const isInvalid = $derived((required && !selectedValues.length) || invalid);
|
|
97
|
-
</script>
|
|
98
|
-
|
|
99
|
-
<div
|
|
100
|
-
class:invalid={isInvalid}
|
|
101
|
-
class="select-wrapper"
|
|
102
|
-
style={`${width ? `--input-width: ${width};` : ''}${height ? `--input-height: ${height};` : ''}`}
|
|
103
|
-
>
|
|
104
|
-
{#if label}
|
|
105
|
-
<label for={inputId}>
|
|
106
|
-
<span>{label}</span>
|
|
107
|
-
<span class="border">{label}</span>
|
|
108
|
-
</label>
|
|
109
|
-
{/if}
|
|
110
|
-
|
|
111
|
-
<Svelecte
|
|
112
|
-
multiple
|
|
113
|
-
{valueAsObject}
|
|
114
|
-
{disabled}
|
|
115
|
-
{inputId}
|
|
116
|
-
valueField={valueProp}
|
|
117
|
-
labelField={labelProp}
|
|
118
|
-
{options}
|
|
119
|
-
searchable
|
|
120
|
-
value={selectedValues}
|
|
121
|
-
onChange={(e: Array<V>) => {
|
|
122
|
-
// svelecte always emits the full option objects; normalise to the
|
|
123
|
-
// shape the variant promised: primitives for AsPrimitive,
|
|
124
|
-
// objects for AsObject. This is what the discriminated
|
|
125
|
-
// `onchange` typing now guarantees to consumers.
|
|
126
|
-
if (valueAsObject) {
|
|
127
|
-
void (onchange as (v: Array<V>) => void | Promise<void>)(e);
|
|
128
|
-
} else {
|
|
129
|
-
const primitives = e.map((it) => it[valueProp]);
|
|
130
|
-
void (onchange as (v: Array<V[VP]>) => void | Promise<void>)(primitives);
|
|
131
|
-
}
|
|
132
|
-
}}
|
|
133
|
-
{name}
|
|
134
|
-
selectOnTab
|
|
135
|
-
keepSelectionInList
|
|
136
|
-
searchProps={{ keepSelectionInList: true }}
|
|
137
|
-
creatable={false}
|
|
138
|
-
collapseSelection={collapseSelection ? 'always' : null}
|
|
139
|
-
deselectMode="toggle"
|
|
140
|
-
highlightFirstItem={false}
|
|
141
|
-
placeholder="Please Select {name ? `${an} ${name}` : ''}"
|
|
142
|
-
selection={collapseSelection ? selection : undefined}
|
|
143
|
-
>
|
|
144
|
-
{#snippet option(opt)}
|
|
145
|
-
{@const option = opt as V}
|
|
146
|
-
<span class="dropdown-item">
|
|
147
|
-
<div
|
|
148
|
-
class="toggle-icon"
|
|
149
|
-
class:yes={selectedKeys.has(option[valueProp])}
|
|
150
|
-
>
|
|
151
|
-
<Icon
|
|
152
|
-
name="tick"
|
|
153
|
-
size={Size.MediumSmall}
|
|
154
|
-
/>
|
|
155
|
-
</div>
|
|
156
|
-
{option[labelProp]}</span
|
|
157
|
-
>
|
|
158
|
-
{/snippet}
|
|
159
|
-
|
|
160
|
-
{#snippet collapsedSelection(selectedOptions: Array<object> /*_i18n*/)}
|
|
161
|
-
<span class="selection"
|
|
162
|
-
>{#if selectedOptions.length}{selectedOptions.length}
|
|
163
|
-
{#if name}{autoPluralise(name, selectedOptions.length)}{/if} Selected
|
|
164
|
-
{:else}Please Select {#if name}
|
|
165
|
-
{an} {name}{/if}
|
|
166
|
-
{/if}</span
|
|
167
|
-
>
|
|
168
|
-
{/snippet}
|
|
169
|
-
|
|
170
|
-
{#snippet append()}
|
|
171
|
-
<div class="icons">
|
|
172
|
-
<Action
|
|
173
|
-
{disabled}
|
|
174
|
-
size={Size.Small}
|
|
175
|
-
noTabIndex
|
|
176
|
-
colourSet={ColourSet.Auxiliary}
|
|
177
|
-
onclick={(e: MouseEvent) => {
|
|
178
|
-
if (isExpanded) {
|
|
179
|
-
e.stopPropagation();
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (selectedValues.length) {
|
|
183
|
-
// Empty array satisfies both Array<V> and Array<V[VP]>.
|
|
184
|
-
void (onchange as (v: Array<V> | Array<V[VP]>) => void | Promise<void>)([]);
|
|
185
|
-
} else if (valueAsObject) {
|
|
186
|
-
void (onchange as (v: Array<V>) => void | Promise<void>)(options.concat());
|
|
187
|
-
} else {
|
|
188
|
-
const primitives = options.map((it) => it[valueProp]);
|
|
189
|
-
void (onchange as (v: Array<V[VP]>) => void | Promise<void>)(primitives);
|
|
190
|
-
}
|
|
191
|
-
}}
|
|
192
|
-
icon={{
|
|
193
|
-
name: selectedValues.length ? 'close-menu-cross' : 'manage-product-group',
|
|
194
|
-
colour: Colour['$ui-blue-10'],
|
|
195
|
-
}}
|
|
196
|
-
/>
|
|
197
|
-
|
|
198
|
-
<Action
|
|
199
|
-
{disabled}
|
|
200
|
-
size={Size.Small}
|
|
201
|
-
noTabIndex
|
|
202
|
-
colourSet={ColourSet.Auxiliary}
|
|
203
|
-
icon={{
|
|
204
|
-
name: isExpanded ? 'chevron-up' : 'chevron-down',
|
|
205
|
-
colour: Colour['$ui-blue-10'],
|
|
206
|
-
}}
|
|
207
|
-
/>
|
|
208
|
-
</div>
|
|
209
|
-
{/snippet}
|
|
210
|
-
{#snippet toggleIcon()}
|
|
211
|
-
<div class="nothing"></div>
|
|
212
|
-
{/snippet}
|
|
213
|
-
</Svelecte>
|
|
214
|
-
|
|
215
|
-
{#snippet selection(/*_selectedOptions: Array<unknown>*/)}
|
|
216
|
-
<!-- collapsed selection rendered above -->
|
|
217
|
-
{/snippet}
|
|
218
|
-
</div>
|
|
219
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<script
|
|
4
|
+
lang="ts"
|
|
5
|
+
generics="V extends object, VP extends ValueProp<V>"
|
|
6
|
+
>
|
|
7
|
+
import { autoPluralise, generateWeakId, vowels } from '../Helpers/Helpers.svelte.js';
|
|
8
|
+
import { attachDropdownPortal } from '../Helpers/dropdownPortal.js';
|
|
9
|
+
import { Colour, ColourSet } from '../scss/colours.js';
|
|
10
|
+
import type { ValueProp } from '../Types/Internal/Misc.js';
|
|
11
|
+
import { Size } from '../Types/Internal/Size.js';
|
|
12
|
+
import Svelecte from 'svelecte';
|
|
13
|
+
import { SvelteSet } from 'svelte/reactivity';
|
|
14
|
+
import { onMount } from 'svelte';
|
|
15
|
+
import Action from './Action.svelte';
|
|
16
|
+
import Icon from './Icon.svelte';
|
|
17
|
+
import type { MultiSelectProps } from './MultiSelectProps.js';
|
|
18
|
+
|
|
19
|
+
// NOTE selectedValues is mutated by svelecte without asking, so we sometimes have to reverse it without a callback (side effects)
|
|
20
|
+
const {
|
|
21
|
+
label,
|
|
22
|
+
inputId = generateWeakId(),
|
|
23
|
+
options,
|
|
24
|
+
labelProp,
|
|
25
|
+
valueProp,
|
|
26
|
+
width,
|
|
27
|
+
valueAsObject = true,
|
|
28
|
+
height,
|
|
29
|
+
selectedValues,
|
|
30
|
+
onchange,
|
|
31
|
+
collapseSelection = false,
|
|
32
|
+
name = 'Item',
|
|
33
|
+
disabled,
|
|
34
|
+
required,
|
|
35
|
+
invalid,
|
|
36
|
+
}: MultiSelectProps<V, VP> = $props();
|
|
37
|
+
|
|
38
|
+
const an = $derived(name && vowels.has(name.at(0)?.toLocaleLowerCase() ?? '') ? 'an' : 'a');
|
|
39
|
+
|
|
40
|
+
// Pre-computed set of selected primitive keys. Used in the option snippet
|
|
41
|
+
// to avoid an O(n*m) findIndex sweep per render.
|
|
42
|
+
const selectedKeys = $derived.by(() => {
|
|
43
|
+
const s = new SvelteSet<V[VP]>();
|
|
44
|
+
if (valueAsObject) {
|
|
45
|
+
for (const v of selectedValues as Array<V>) {
|
|
46
|
+
s.add(v[valueProp]);
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
for (const v of selectedValues as Array<V[VP]>) {
|
|
50
|
+
s.add(v);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return s;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
let isExpanded = $state(false);
|
|
57
|
+
|
|
58
|
+
onMount(() => {
|
|
59
|
+
const input = document.getElementById(inputId);
|
|
60
|
+
const svelecteRoot = input?.closest('div.svelecte') as HTMLElement | null;
|
|
61
|
+
const dropdownRef =
|
|
62
|
+
(svelecteRoot?.querySelector('.sv_dropdown') as HTMLElement | null) ?? undefined;
|
|
63
|
+
|
|
64
|
+
// HACK callback for is-open on/off; drives the chevron rotation
|
|
65
|
+
// in the action snippet further down.
|
|
66
|
+
const observer = new MutationObserver((mutations: Array<MutationRecord>) => {
|
|
67
|
+
for (let i = mutations.length - 1; i > -1; i--) {
|
|
68
|
+
const mutation = mutations[i];
|
|
69
|
+
if (mutation.attributeName === 'class') {
|
|
70
|
+
isExpanded = dropdownRef?.classList.contains('is-open') ?? false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (dropdownRef) {
|
|
76
|
+
observer.observe(dropdownRef, { attributes: true });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Teleport the Svelecte dropdown to `document.body` while open
|
|
80
|
+
// so it escapes every ancestor `overflow` / `transform` /
|
|
81
|
+
// `z-index` stacking context. See `Helpers/dropdownPortal.ts`
|
|
82
|
+
// for the rationale and behaviour (auto-flip upwards on tight
|
|
83
|
+
// viewports, scroll-aware repositioning, viewport-bounded
|
|
84
|
+
// max-height).
|
|
85
|
+
const detachPortal = attachDropdownPortal({
|
|
86
|
+
getTrigger: () => svelecteRoot,
|
|
87
|
+
getDropdown: () => dropdownRef,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return () => {
|
|
91
|
+
observer.disconnect();
|
|
92
|
+
detachPortal();
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const isInvalid = $derived((required && !selectedValues.length) || invalid);
|
|
97
|
+
</script>
|
|
98
|
+
|
|
99
|
+
<div
|
|
100
|
+
class:invalid={isInvalid}
|
|
101
|
+
class="select-wrapper"
|
|
102
|
+
style={`${width ? `--input-width: ${width};` : ''}${height ? `--input-height: ${height};` : ''}`}
|
|
103
|
+
>
|
|
104
|
+
{#if label}
|
|
105
|
+
<label for={inputId}>
|
|
106
|
+
<span>{label}</span>
|
|
107
|
+
<span class="border">{label}</span>
|
|
108
|
+
</label>
|
|
109
|
+
{/if}
|
|
110
|
+
|
|
111
|
+
<Svelecte
|
|
112
|
+
multiple
|
|
113
|
+
{valueAsObject}
|
|
114
|
+
{disabled}
|
|
115
|
+
{inputId}
|
|
116
|
+
valueField={valueProp}
|
|
117
|
+
labelField={labelProp}
|
|
118
|
+
{options}
|
|
119
|
+
searchable
|
|
120
|
+
value={selectedValues}
|
|
121
|
+
onChange={(e: Array<V>) => {
|
|
122
|
+
// svelecte always emits the full option objects; normalise to the
|
|
123
|
+
// shape the variant promised: primitives for AsPrimitive,
|
|
124
|
+
// objects for AsObject. This is what the discriminated
|
|
125
|
+
// `onchange` typing now guarantees to consumers.
|
|
126
|
+
if (valueAsObject) {
|
|
127
|
+
void (onchange as (v: Array<V>) => void | Promise<void>)(e);
|
|
128
|
+
} else {
|
|
129
|
+
const primitives = e.map((it) => it[valueProp]);
|
|
130
|
+
void (onchange as (v: Array<V[VP]>) => void | Promise<void>)(primitives);
|
|
131
|
+
}
|
|
132
|
+
}}
|
|
133
|
+
{name}
|
|
134
|
+
selectOnTab
|
|
135
|
+
keepSelectionInList
|
|
136
|
+
searchProps={{ keepSelectionInList: true }}
|
|
137
|
+
creatable={false}
|
|
138
|
+
collapseSelection={collapseSelection ? 'always' : null}
|
|
139
|
+
deselectMode="toggle"
|
|
140
|
+
highlightFirstItem={false}
|
|
141
|
+
placeholder="Please Select {name ? `${an} ${name}` : ''}"
|
|
142
|
+
selection={collapseSelection ? selection : undefined}
|
|
143
|
+
>
|
|
144
|
+
{#snippet option(opt)}
|
|
145
|
+
{@const option = opt as V}
|
|
146
|
+
<span class="dropdown-item">
|
|
147
|
+
<div
|
|
148
|
+
class="toggle-icon"
|
|
149
|
+
class:yes={selectedKeys.has(option[valueProp])}
|
|
150
|
+
>
|
|
151
|
+
<Icon
|
|
152
|
+
name="tick"
|
|
153
|
+
size={Size.MediumSmall}
|
|
154
|
+
/>
|
|
155
|
+
</div>
|
|
156
|
+
{option[labelProp]}</span
|
|
157
|
+
>
|
|
158
|
+
{/snippet}
|
|
159
|
+
|
|
160
|
+
{#snippet collapsedSelection(selectedOptions: Array<object> /*_i18n*/)}
|
|
161
|
+
<span class="selection"
|
|
162
|
+
>{#if selectedOptions.length}{selectedOptions.length}
|
|
163
|
+
{#if name}{autoPluralise(name, selectedOptions.length)}{/if} Selected
|
|
164
|
+
{:else}Please Select {#if name}
|
|
165
|
+
{an} {name}{/if}
|
|
166
|
+
{/if}</span
|
|
167
|
+
>
|
|
168
|
+
{/snippet}
|
|
169
|
+
|
|
170
|
+
{#snippet append()}
|
|
171
|
+
<div class="icons">
|
|
172
|
+
<Action
|
|
173
|
+
{disabled}
|
|
174
|
+
size={Size.Small}
|
|
175
|
+
noTabIndex
|
|
176
|
+
colourSet={ColourSet.Auxiliary}
|
|
177
|
+
onclick={(e: MouseEvent) => {
|
|
178
|
+
if (isExpanded) {
|
|
179
|
+
e.stopPropagation();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (selectedValues.length) {
|
|
183
|
+
// Empty array satisfies both Array<V> and Array<V[VP]>.
|
|
184
|
+
void (onchange as (v: Array<V> | Array<V[VP]>) => void | Promise<void>)([]);
|
|
185
|
+
} else if (valueAsObject) {
|
|
186
|
+
void (onchange as (v: Array<V>) => void | Promise<void>)(options.concat());
|
|
187
|
+
} else {
|
|
188
|
+
const primitives = options.map((it) => it[valueProp]);
|
|
189
|
+
void (onchange as (v: Array<V[VP]>) => void | Promise<void>)(primitives);
|
|
190
|
+
}
|
|
191
|
+
}}
|
|
192
|
+
icon={{
|
|
193
|
+
name: selectedValues.length ? 'close-menu-cross' : 'manage-product-group',
|
|
194
|
+
colour: Colour['$ui-blue-10'],
|
|
195
|
+
}}
|
|
196
|
+
/>
|
|
197
|
+
|
|
198
|
+
<Action
|
|
199
|
+
{disabled}
|
|
200
|
+
size={Size.Small}
|
|
201
|
+
noTabIndex
|
|
202
|
+
colourSet={ColourSet.Auxiliary}
|
|
203
|
+
icon={{
|
|
204
|
+
name: isExpanded ? 'chevron-up' : 'chevron-down',
|
|
205
|
+
colour: Colour['$ui-blue-10'],
|
|
206
|
+
}}
|
|
207
|
+
/>
|
|
208
|
+
</div>
|
|
209
|
+
{/snippet}
|
|
210
|
+
{#snippet toggleIcon()}
|
|
211
|
+
<div class="nothing"></div>
|
|
212
|
+
{/snippet}
|
|
213
|
+
</Svelecte>
|
|
214
|
+
|
|
215
|
+
{#snippet selection(/*_selectedOptions: Array<unknown>*/)}
|
|
216
|
+
<!-- collapsed selection rendered above -->
|
|
217
|
+
{/snippet}
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
220
|
<style>.select-wrapper {
|
|
221
221
|
min-width: var(--input-min-width, 12rem);
|
|
222
222
|
width: var(--input-width, 100%);
|
|
@@ -379,4 +379,4 @@ div.icons {
|
|
|
379
379
|
}
|
|
380
380
|
:global(.dropdown-item) .toggle-icon.yes {
|
|
381
381
|
opacity: 1;
|
|
382
|
-
}</style>
|
|
382
|
+
}</style>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { CssLength, NonNullableKey, ValueProp } from '../Types/Internal/Misc.js';
|
|
2
2
|
/**
|
|
3
|
-
* Keys of `V` whose value is a string. Re-exported for callers that want
|
|
4
|
-
*
|
|
5
|
-
* `NonNullableKey<V>`
|
|
6
|
-
*
|
|
3
|
+
* Keys of `V` whose value is a string. Re-exported for callers that want a
|
|
4
|
+
* tighter constraint than `NonNullableKey<V>`. Currently aliased to
|
|
5
|
+
* `NonNullableKey<V>` so tightening the brand later does not force every
|
|
6
|
+
* Table subtree consumer to update at the same time.
|
|
7
7
|
*/
|
|
8
8
|
export type StringValuedKey<V> = NonNullableKey<V>;
|
|
9
9
|
export interface MultiSelectCommonProps<V extends object, VP extends ValueProp<V>> {
|
|
@@ -25,20 +25,9 @@ export interface MultiSelectCommonProps<V extends object, VP extends ValueProp<V
|
|
|
25
25
|
label?: string;
|
|
26
26
|
/** DOM id of the underlying svelecte input. */
|
|
27
27
|
inputId?: string;
|
|
28
|
-
/**
|
|
29
|
-
* CSS width override. Interpolated into a CSS custom property.
|
|
30
|
-
*
|
|
31
|
-
* BREAKING (Phase 7.7): was `string`; now requires the `CssLength`
|
|
32
|
-
* brand. Use the `cssLength('...')` helper to mark intentional CSS
|
|
33
|
-
* length strings.
|
|
34
|
-
*/
|
|
28
|
+
/** CSS width override. Use `cssLength('...')` to construct. */
|
|
35
29
|
width?: CssLength;
|
|
36
|
-
/**
|
|
37
|
-
* CSS height override. Interpolated into a CSS custom property.
|
|
38
|
-
*
|
|
39
|
-
* BREAKING (Phase 7.7): was `string`; now requires the `CssLength`
|
|
40
|
-
* brand. Use the `cssLength('...')` helper.
|
|
41
|
-
*/
|
|
30
|
+
/** CSS height override. Use `cssLength('...')` to construct. */
|
|
42
31
|
height?: CssLength;
|
|
43
32
|
/** When true, render a summary instead of chips. */
|
|
44
33
|
collapseSelection?: boolean;
|