@lavalogic/scoria 0.40.13 → 0.40.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +58 -58
  2. package/dist/Components/AccordionGroup.svelte +35 -46
  3. package/dist/Components/AccordionGroupButton.svelte +68 -76
  4. package/dist/Components/Action.svelte +103 -135
  5. package/dist/Components/AlertModal.svelte +171 -190
  6. package/dist/Components/AppointmentCalendar/AppointmentCalendar.svelte +614 -697
  7. package/dist/Components/Base/BaseModal.svelte +90 -116
  8. package/dist/Components/Base/ContextWrapper.svelte +67 -72
  9. package/dist/Components/Base/Pagination.svelte +173 -196
  10. package/dist/Components/Base/Snippets.svelte +34 -36
  11. package/dist/Components/BigRadioSet.svelte +36 -38
  12. package/dist/Components/Bubble.svelte +78 -101
  13. package/dist/Components/Button.svelte +175 -208
  14. package/dist/Components/Checkbox.svelte +75 -86
  15. package/dist/Components/CollapsibleCard.svelte +72 -87
  16. package/dist/Components/CollapsibleMenuGroup.svelte +53 -57
  17. package/dist/Components/ConditionBuilder/ConditionBuilder.svelte +39 -64
  18. package/dist/Components/Contexts/ContextMenu.svelte +141 -156
  19. package/dist/Components/Contexts/ContextMenuDivider.svelte +15 -15
  20. package/dist/Components/Contexts/ContextMenuOption.svelte +53 -60
  21. package/dist/Components/Contexts/Toast.svelte +81 -86
  22. package/dist/Components/Contexts/ToastContainer.svelte +58 -62
  23. package/dist/Components/Contexts/Tooltip.svelte +36 -37
  24. package/dist/Components/DataMatrixIcon.svelte +95 -108
  25. package/dist/Components/DateInput.svelte +118 -146
  26. package/dist/Components/DatePicker.svelte +255 -294
  27. package/dist/Components/DesktopModal.svelte +70 -90
  28. package/dist/Components/Dial.svelte +167 -197
  29. package/dist/Components/DimensionInput.svelte +124 -169
  30. package/dist/Components/DragMenu/DragMenuHolder.svelte +98 -114
  31. package/dist/Components/DragMenu/DraggableCard.svelte +64 -76
  32. package/dist/Components/FileCard.svelte +21 -24
  33. package/dist/Components/FileUpload.svelte +190 -225
  34. package/dist/Components/GridInput.svelte +159 -196
  35. package/dist/Components/GridInputSet.svelte +24 -29
  36. package/dist/Components/HorizontalTabGroup.svelte +73 -89
  37. package/dist/Components/HorizontalTabGroupButton.svelte +40 -44
  38. package/dist/Components/Icon.svelte +99 -128
  39. package/dist/Components/Icons.js +357 -357
  40. package/dist/Components/InfoAlert.svelte +35 -38
  41. package/dist/Components/LoadingAnimation.svelte +691 -755
  42. package/dist/Components/LoadingModal.svelte +36 -44
  43. package/dist/Components/LoadingOverlay.svelte +22 -26
  44. package/dist/Components/Modal.svelte +204 -254
  45. package/dist/Components/MultiSelect.svelte +186 -216
  46. package/dist/Components/Nav/Nav.svelte +94 -110
  47. package/dist/Components/Nav/NavServiceMenuList.svelte +57 -61
  48. package/dist/Components/Nav/NavTab.svelte +58 -62
  49. package/dist/Components/Nav/ServiceMenuItem.svelte +103 -111
  50. package/dist/Components/Nav/ServicesNav.svelte +72 -79
  51. package/dist/Components/NumberInput.svelte +121 -155
  52. package/dist/Components/OptionCards.svelte +62 -73
  53. package/dist/Components/PageHeading.svelte +23 -25
  54. package/dist/Components/PasswordInput.svelte +69 -88
  55. package/dist/Components/PopoverButton.svelte +151 -0
  56. package/dist/Components/PopoverButton.svelte.d.ts +9 -0
  57. package/dist/Components/PopoverButtonProps.d.ts +21 -0
  58. package/dist/Components/PopoverButtonProps.js +1 -0
  59. package/dist/Components/Portal.svelte +29 -35
  60. package/dist/Components/ProgressBubble.svelte +91 -106
  61. package/dist/Components/QuerySelect.svelte +260 -346
  62. package/dist/Components/SidebarPanel.svelte +34 -36
  63. package/dist/Components/SingleSelect.svelte +196 -244
  64. package/dist/Components/StepButton.svelte +65 -70
  65. package/dist/Components/StepForm.svelte +115 -135
  66. package/dist/Components/Switch.svelte +57 -69
  67. package/dist/Components/Table/ARCHITECTURE.md +298 -298
  68. package/dist/Components/Table/Body/QuickSearchCell.svelte +578 -655
  69. package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +42 -51
  70. package/dist/Components/Table/Body/Rows/ColumnList.svelte +42 -58
  71. package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +403 -442
  72. package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +51 -78
  73. package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +165 -184
  74. package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +110 -123
  75. package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +134 -160
  76. package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +190 -231
  77. package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +82 -104
  78. package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +52 -87
  79. package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +122 -150
  80. package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +132 -159
  81. package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +190 -236
  82. package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +173 -211
  83. package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +204 -244
  84. package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +140 -177
  85. package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +188 -217
  86. package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +173 -193
  87. package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +166 -187
  88. package/dist/Components/Table/Body/Rows/TableRow.svelte +245 -288
  89. package/dist/Components/Table/Body/TableBody.svelte +141 -154
  90. package/dist/Components/Table/Headers/HighlightAllHeader.svelte +35 -41
  91. package/dist/Components/Table/Headers/SelectAllHeader.svelte +24 -30
  92. package/dist/Components/Table/Headers/TableHead.svelte +348 -402
  93. package/dist/Components/Table/Misc/ColumnPanel.svelte +37 -39
  94. package/dist/Components/Table/Misc/ColumnPanelModal.svelte +35 -39
  95. package/dist/Components/Table/Misc/FilterInput.svelte +556 -619
  96. package/dist/Components/Table/Misc/FilterPanel.svelte +170 -183
  97. package/dist/Components/Table/Misc/FilterPanelModal.svelte +25 -31
  98. package/dist/Components/Table/Misc/ShareViewModal.svelte +252 -281
  99. package/dist/Components/Table/Misc/SidePanel.svelte +32 -35
  100. package/dist/Components/Table/Misc/TableConfigurationModal.svelte +574 -629
  101. package/dist/Components/Table/Misc/TableFooter.svelte +326 -332
  102. package/dist/Components/Table/Misc/TableHorizontalBar.svelte +134 -140
  103. package/dist/Components/Table/Misc/TableSidebar.svelte +183 -198
  104. package/dist/Components/Table/Misc/TableViewDropdown.svelte +83 -103
  105. package/dist/Components/Table/Misc/ToolboxPanel.svelte +83 -100
  106. package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +88 -107
  107. package/dist/Components/Table/Misc/UpdateViewOptionsModal.svelte +163 -190
  108. package/dist/Components/Table/NestedTable.svelte +102 -128
  109. package/dist/Components/Table/Table.svelte +531 -663
  110. package/dist/Components/Test/TestContextConsumer.svelte +11 -13
  111. package/dist/Components/TextArea.svelte +95 -130
  112. package/dist/Components/TextInput.svelte +125 -176
  113. package/dist/Components/ThreeStateRadio.svelte +111 -130
  114. package/dist/Components/Touch/BoolCard.svelte +33 -45
  115. package/dist/Components/Touch/DateModal.svelte +164 -204
  116. package/dist/Components/Touch/EditCard.svelte +48 -59
  117. package/dist/Components/Touch/InfoCard.svelte +28 -31
  118. package/dist/Components/Touch/InfoTextCard.svelte +26 -28
  119. package/dist/Components/Touch/ModalExplanation.svelte +15 -17
  120. package/dist/Components/Touch/NumberKeyboard.svelte +181 -218
  121. package/dist/Components/Touch/NumberModal.svelte +59 -79
  122. package/dist/Components/Touch/PlusMinusCard.svelte +43 -46
  123. package/dist/Components/Touch/SelectModal.svelte +111 -126
  124. package/dist/Components/Touch/SummaryCard.svelte +80 -93
  125. package/dist/Components/Touch/TextAreaModal.svelte +72 -94
  126. package/dist/Components/Touch/TextModal.svelte +77 -105
  127. package/dist/Components/Touch/TouchCard.svelte +31 -33
  128. package/dist/Components/Touch/TouchModal.svelte +214 -270
  129. package/dist/Components/Touch/UtilityButton.svelte +88 -109
  130. package/dist/Components/VerticalTabGroup.svelte +60 -78
  131. package/dist/Components/VerticalTabGroupButton.svelte +54 -58
  132. package/dist/Helpers/Datamatrix.d.ts +19 -19
  133. package/dist/Helpers/Datamatrix.js +291 -291
  134. package/dist/Types/Examples/ExampleModal.svelte +31 -35
  135. package/dist/index.d.ts +2 -0
  136. package/dist/index.js +1 -0
  137. package/dist/scss/_basics.scss +12 -12
  138. package/dist/scss/_colours.scss +134 -134
  139. package/dist/scss/_mixins.scss +3392 -3392
  140. package/dist/scss/_motion.scss +57 -57
  141. package/dist/scss/_sizing.scss +85 -85
  142. package/dist/scss/_transitions.scss +8 -8
  143. package/package.json +1 -1
@@ -1,222 +1,192 @@
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
- }
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ lang="ts"
5
+ generics="V extends object, VP extends ValueProp<V>"
6
+ >import { autoPluralise, generateWeakId, vowels } from "../Helpers/Helpers.svelte.js";
7
+ import { attachDropdownPortal } from "../Helpers/dropdownPortal.js";
8
+ import { Colour, ColourSet } from "../scss/colours.js";
9
+ import { Size } from "../Types/Internal/Size.js";
10
+ import Svelecte from "svelecte";
11
+ import { SvelteSet } from "svelte/reactivity";
12
+ import { onMount } from "svelte";
13
+ import Action from "./Action.svelte";
14
+ import Icon from "./Icon.svelte";
15
+ // NOTE selectedValues is mutated by svelecte without asking, so we sometimes have to reverse it without a callback (side effects)
16
+ const { label, inputId = generateWeakId(), options, labelProp, valueProp, width, valueAsObject = true, height, selectedValues, onchange, collapseSelection = false, name = "Item", disabled, required, invalid } = $props();
17
+ const an = $derived(name && vowels.has(name.at(0)?.toLocaleLowerCase() ?? "") ? "an" : "a");
18
+ // Pre-computed set of selected primitive keys. Used in the option snippet
19
+ // to avoid an O(n*m) findIndex sweep per render.
20
+ const selectedKeys = $derived.by(() => {
21
+ const s = new SvelteSet();
22
+ if (valueAsObject) {
23
+ for (const v of selectedValues) {
24
+ s.add(v[valueProp]);
52
25
  }
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
- }
26
+ } else {
27
+ for (const v of selectedValues) {
28
+ s.add(v);
29
+ }
30
+ }
31
+ return s;
32
+ });
33
+ let isExpanded = $state(false);
34
+ onMount(() => {
35
+ const input = document.getElementById(inputId);
36
+ const svelecteRoot = input?.closest("div.svelecte");
37
+ const dropdownRef = svelecteRoot?.querySelector(".sv_dropdown") ?? undefined;
38
+ // HACK callback for is-open on/off; drives the chevron rotation
39
+ // in the action snippet further down.
40
+ const observer = new MutationObserver((mutations) => {
41
+ for (let i = mutations.length - 1; i > -1; i--) {
42
+ const mutation = mutations[i];
43
+ if (mutation.attributeName === "class") {
44
+ isExpanded = dropdownRef?.classList.contains("is-open") ?? false;
72
45
  }
73
- });
74
-
75
- if (dropdownRef) {
76
- observer.observe(dropdownRef, { attributes: true });
77
46
  }
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
47
  });
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
-
48
+ if (dropdownRef) {
49
+ observer.observe(dropdownRef, { attributes: true });
50
+ }
51
+ // Teleport the Svelecte dropdown to `document.body` while open
52
+ // so it escapes every ancestor `overflow` / `transform` /
53
+ // `z-index` stacking context. See `Helpers/dropdownPortal.ts`
54
+ // for the rationale and behaviour (auto-flip upwards on tight
55
+ // viewports, scroll-aware repositioning, viewport-bounded
56
+ // max-height).
57
+ const detachPortal = attachDropdownPortal({
58
+ getTrigger: () => svelecteRoot,
59
+ getDropdown: () => dropdownRef
60
+ });
61
+ return () => {
62
+ observer.disconnect();
63
+ detachPortal();
64
+ };
65
+ });
66
+ const isInvalid = $derived(required && !selectedValues.length || invalid);
67
+ </script>
68
+
69
+ <div
70
+ class:invalid={isInvalid}
71
+ class="select-wrapper"
72
+ style={`${width ? `--input-width: ${width};` : ''}${height ? `--input-height: ${height};` : ''}`}
73
+ >
74
+ {#if label}
75
+ <label for={inputId}>
76
+ <span>{label}</span>
77
+ <span class="border">{label}</span>
78
+ </label>
79
+ {/if}
80
+
81
+ <Svelecte
82
+ multiple
83
+ {valueAsObject}
84
+ {disabled}
85
+ {inputId}
86
+ valueField={valueProp}
87
+ labelField={labelProp}
88
+ {options}
89
+ searchable
90
+ value={selectedValues}
91
+ onChange={(e: Array<V>) => {
92
+ // svelecte always emits the full option objects; normalise to the
93
+ // shape the variant promised: primitives for AsPrimitive,
94
+ // objects for AsObject. This is what the discriminated
95
+ // `onchange` typing now guarantees to consumers.
96
+ if (valueAsObject) {
97
+ void (onchange as (v: Array<V>) => void | Promise<void>)(e);
98
+ } else {
99
+ const primitives = e.map((it) => it[valueProp]);
100
+ void (onchange as (v: Array<V[VP]>) => void | Promise<void>)(primitives);
101
+ }
102
+ }}
103
+ {name}
104
+ selectOnTab
105
+ keepSelectionInList
106
+ searchProps={{ keepSelectionInList: true }}
107
+ creatable={false}
108
+ collapseSelection={collapseSelection ? 'always' : null}
109
+ deselectMode="toggle"
110
+ highlightFirstItem={false}
111
+ placeholder="Please Select {name ? `${an} ${name}` : ''}"
112
+ selection={collapseSelection ? selection : undefined}
113
+ >
114
+ {#snippet option(opt)}
115
+ {@const option = opt as V}
116
+ <span class="dropdown-item">
117
+ <div
118
+ class="toggle-icon"
119
+ class:yes={selectedKeys.has(option[valueProp])}
120
+ >
121
+ <Icon
122
+ name="tick"
123
+ size={Size.MediumSmall}
124
+ />
125
+ </div>
126
+ {option[labelProp]}</span
127
+ >
128
+ {/snippet}
129
+
130
+ {#snippet collapsedSelection(selectedOptions: Array<object> /*_i18n*/)}
131
+ <span class="selection"
132
+ >{#if selectedOptions.length}{selectedOptions.length}
133
+ {#if name}{autoPluralise(name, selectedOptions.length)}{/if} Selected
134
+ {:else}Please Select {#if name}
135
+ {an} {name}{/if}
136
+ {/if}</span
137
+ >
138
+ {/snippet}
139
+
140
+ {#snippet append()}
141
+ <div class="icons">
142
+ <Action
143
+ {disabled}
144
+ size={Size.Small}
145
+ noTabIndex
146
+ colourSet={ColourSet.Auxiliary}
147
+ onclick={(e: MouseEvent) => {
148
+ if (isExpanded) {
149
+ e.stopPropagation();
150
+ }
151
+
152
+ if (selectedValues.length) {
153
+ // Empty array satisfies both Array<V> and Array<V[VP]>.
154
+ void (onchange as (v: Array<V> | Array<V[VP]>) => void | Promise<void>)([]);
155
+ } else if (valueAsObject) {
156
+ void (onchange as (v: Array<V>) => void | Promise<void>)(options.concat());
157
+ } else {
158
+ const primitives = options.map((it) => it[valueProp]);
159
+ void (onchange as (v: Array<V[VP]>) => void | Promise<void>)(primitives);
160
+ }
161
+ }}
162
+ icon={{
163
+ name: selectedValues.length ? 'close-menu-cross' : 'manage-product-group',
164
+ colour: Colour['$ui-blue-10'],
165
+ }}
166
+ />
167
+
168
+ <Action
169
+ {disabled}
170
+ size={Size.Small}
171
+ noTabIndex
172
+ colourSet={ColourSet.Auxiliary}
173
+ icon={{
174
+ name: isExpanded ? 'chevron-up' : 'chevron-down',
175
+ colour: Colour['$ui-blue-10'],
176
+ }}
177
+ />
178
+ </div>
179
+ {/snippet}
180
+ {#snippet toggleIcon()}
181
+ <div class="nothing"></div>
182
+ {/snippet}
183
+ </Svelecte>
184
+
185
+ {#snippet selection(/*_selectedOptions: Array<unknown>*/)}
186
+ <!-- collapsed selection rendered above -->
187
+ {/snippet}
188
+ </div>
189
+
220
190
  <style>.select-wrapper {
221
191
  min-width: var(--input-min-width, 12rem);
222
192
  width: var(--input-width, 100%);
@@ -379,4 +349,4 @@ div.icons {
379
349
  }
380
350
  :global(.dropdown-item) .toggle-icon.yes {
381
351
  opacity: 1;
382
- }</style>
352
+ }</style>
@@ -1,112 +1,96 @@
1
- <svelte:options runes />
2
-
3
- <script
4
- lang="ts"
5
- generics="T"
6
- >
7
- import { afterNavigate } from '$app/navigation';
8
- import { Size } from '../../Types/Internal/Size.js';
9
- import Icon from '../Icon.svelte';
10
- import type { NavProps } from './NavProps.js';
11
- import ServicesNav from './ServicesNav.svelte';
12
-
13
- const {
14
- userName,
15
- extras,
16
- userDialog,
17
- serviceTabs,
18
- selectedServiceTab,
19
- brand,
20
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-arguments
21
- }: NavProps<T> = $props();
22
-
23
- const userIcon = $derived.by(() => {
24
- const names = userName.split(' ');
25
-
26
- const initials = names.map((it) => it.charAt(0)).slice(0, 2);
27
- return initials;
28
- });
29
-
30
- const singleLetter = $derived(userIcon.length === 1);
31
- const hasLetters = $derived(userIcon.length > 0);
32
-
33
- let showServicesDialog = $state(false);
34
- let showUserDialog = $state(false);
35
-
36
- // Close both nav popovers after any navigation. Selecting an item in
37
- // the Services menu is a navigation, so the menu must dismiss itself —
38
- // without this it only closed when the consumer happened to remount
39
- // `<Nav>` (e.g. on a main-area change), leaving it open when the user
40
- // picked a sibling item within the same area.
41
- afterNavigate(() => {
42
- showServicesDialog = false;
43
- showUserDialog = false;
44
- });
45
- </script>
46
-
47
- <nav class="main-navigation">
48
- {#if typeof brand === 'string'}
49
- <span class="nav-link brand">{brand}</span>
50
- {:else if brand}
51
- <span class="nav-link brand">{@render brand()}</span>
52
- {/if}
53
-
54
- <div class="nav-link">
55
- <button
56
- onclick={() => {
57
- showServicesDialog = !showServicesDialog;
58
- }}
59
- >
60
- <div class="delimited">
61
- <Icon
62
- name="block-menu"
63
- size={Size.Medium}
64
- />
65
- <span>Services</span>
66
- </div>
67
- </button>
68
-
69
- {#if showServicesDialog}
70
- <ServicesNav
71
- onclose={() => {
72
- showServicesDialog = false;
73
- }}
74
- {serviceTabs}
75
- {selectedServiceTab}
76
- />
77
- {/if}
78
- </div>
79
-
80
- <div class="nav-search-container"></div>
81
- {#if extras}
82
- <div class="nav-link spaced selects">
83
- {@render extras()}
84
- </div>
85
- {/if}
86
-
87
- <div>
88
- <button
89
- onclick={() => {
90
- showUserDialog = !showUserDialog;
91
- }}
92
- >
93
- <span class="nav-link padded">
94
- <span
95
- class="user-icon"
96
- class:visible={hasLetters}
97
- class:single-letter={singleLetter}>{userIcon}</span
98
- >
99
- <span class="user-name">{userName}</span>
100
- </span>
101
- </button>
102
- {#if showUserDialog}
103
- {@render userDialog(() => {
104
- showUserDialog = false;
105
- })}
106
- {/if}
107
- </div>
108
- </nav>
109
-
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ lang="ts"
5
+ generics="T"
6
+ >import { afterNavigate } from "$app/navigation";
7
+ import { Size } from "../../Types/Internal/Size.js";
8
+ import Icon from "../Icon.svelte";
9
+ import ServicesNav from "./ServicesNav.svelte";
10
+ const { userName, extras, userDialog, serviceTabs, selectedServiceTab, brand } = $props();
11
+ const userIcon = $derived.by(() => {
12
+ const names = userName.split(" ");
13
+ const initials = names.map((it) => it.charAt(0)).slice(0, 2);
14
+ return initials;
15
+ });
16
+ const singleLetter = $derived(userIcon.length === 1);
17
+ const hasLetters = $derived(userIcon.length > 0);
18
+ let showServicesDialog = $state(false);
19
+ let showUserDialog = $state(false);
20
+ // Close both nav popovers after any navigation. Selecting an item in
21
+ // the Services menu is a navigation, so the menu must dismiss itself —
22
+ // without this it only closed when the consumer happened to remount
23
+ // `<Nav>` (e.g. on a main-area change), leaving it open when the user
24
+ // picked a sibling item within the same area.
25
+ afterNavigate(() => {
26
+ showServicesDialog = false;
27
+ showUserDialog = false;
28
+ });
29
+ </script>
30
+
31
+ <nav class="main-navigation">
32
+ {#if typeof brand === 'string'}
33
+ <span class="nav-link brand">{brand}</span>
34
+ {:else if brand}
35
+ <span class="nav-link brand">{@render brand()}</span>
36
+ {/if}
37
+
38
+ <div class="nav-link">
39
+ <button
40
+ onclick={() => {
41
+ showServicesDialog = !showServicesDialog;
42
+ }}
43
+ >
44
+ <div class="delimited">
45
+ <Icon
46
+ name="block-menu"
47
+ size={Size.Medium}
48
+ />
49
+ <span>Services</span>
50
+ </div>
51
+ </button>
52
+
53
+ {#if showServicesDialog}
54
+ <ServicesNav
55
+ onclose={() => {
56
+ showServicesDialog = false;
57
+ }}
58
+ {serviceTabs}
59
+ {selectedServiceTab}
60
+ />
61
+ {/if}
62
+ </div>
63
+
64
+ <div class="nav-search-container"></div>
65
+ {#if extras}
66
+ <div class="nav-link spaced selects">
67
+ {@render extras()}
68
+ </div>
69
+ {/if}
70
+
71
+ <div>
72
+ <button
73
+ onclick={() => {
74
+ showUserDialog = !showUserDialog;
75
+ }}
76
+ >
77
+ <span class="nav-link padded">
78
+ <span
79
+ class="user-icon"
80
+ class:visible={hasLetters}
81
+ class:single-letter={singleLetter}>{userIcon}</span
82
+ >
83
+ <span class="user-name">{userName}</span>
84
+ </span>
85
+ </button>
86
+ {#if showUserDialog}
87
+ {@render userDialog(() => {
88
+ showUserDialog = false;
89
+ })}
90
+ {/if}
91
+ </div>
92
+ </nav>
93
+
110
94
  <style>div.overlay {
111
95
  position: fixed;
112
96
  top: calc(3.25rem + var(--env-border-height, 0));
@@ -230,4 +214,4 @@ div.delimited {
230
214
  align-items: center;
231
215
  justify-content: center;
232
216
  gap: 0.5rem;
233
- }</style>
217
+ }</style>