@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,47 +1,39 @@
1
- <svelte:options runes />
2
-
3
- <script lang="ts">
4
- import LoadingAnimation from './LoadingAnimation.svelte';
5
- import type { LoadingModalProps } from './LoadingModalProps.js';
6
-
7
- const { showModal, message, name, caption }: LoadingModalProps = $props();
8
-
9
- let dialog: HTMLDialogElement | undefined = $state();
10
-
11
- $effect(() => {
12
- if (!dialog) {
13
- return;
14
- }
15
- if (showModal && !dialog.open) {
16
- dialog.showModal();
17
- } else if (!showModal && dialog.open) {
18
- dialog.close();
19
- }
20
- });
21
-
22
- function uncloseable(
23
- e: KeyboardEvent & { currentTarget: EventTarget & HTMLDialogElement }
24
- ): void {
25
- if (e.key === 'Escape') {
26
- e.preventDefault();
27
- }
1
+ <svelte:options runes />
2
+
3
+ <script lang="ts">import LoadingAnimation from "./LoadingAnimation.svelte";
4
+ const { showModal, message, name, caption } = $props();
5
+ let dialog = $state();
6
+ $effect(() => {
7
+ if (!dialog) {
8
+ return;
28
9
  }
29
- </script>
30
-
31
- <dialog
32
- bind:this={dialog}
33
- onkeydown={uncloseable}
34
- aria-label={message ?? 'Loading'}
35
- aria-live="polite"
36
- >
37
- <div class="modal-root">
38
- <LoadingAnimation
39
- {name}
40
- caption={message ?? caption}
41
- />
42
- </div>
43
- </dialog>
44
-
10
+ if (showModal && !dialog.open) {
11
+ dialog.showModal();
12
+ } else if (!showModal && dialog.open) {
13
+ dialog.close();
14
+ }
15
+ });
16
+ function uncloseable(e) {
17
+ if (e.key === "Escape") {
18
+ e.preventDefault();
19
+ }
20
+ }
21
+ </script>
22
+
23
+ <dialog
24
+ bind:this={dialog}
25
+ onkeydown={uncloseable}
26
+ aria-label={message ?? 'Loading'}
27
+ aria-live="polite"
28
+ >
29
+ <div class="modal-root">
30
+ <LoadingAnimation
31
+ {name}
32
+ caption={message ?? caption}
33
+ />
34
+ </div>
35
+ </dialog>
36
+
45
37
  <style>dialog {
46
38
  overflow: clip;
47
39
  background-color: #e9ecf1;
@@ -306,4 +298,4 @@ dialog .modal-root {
306
298
  align-items: center;
307
299
  background: rgba(0, 0, 0, 0);
308
300
  position: relative;
309
- }</style>
301
+ }</style>
@@ -1,28 +1,24 @@
1
- <svelte:options runes />
2
-
3
- <script lang="ts">
4
- import LoadingAnimation from './LoadingAnimation.svelte';
5
- import type { LoadingOverlayProps } from './LoadingOverlayProps.js';
6
-
7
- const { message, absolute, borderRadius, name, caption }: LoadingOverlayProps =
8
- $props();
9
- </script>
10
-
11
- <div
12
- class="loading-overlay"
13
- class:absolute
14
- role="status"
15
- aria-live="polite"
16
- style={borderRadius != null && borderRadius.length > 0
17
- ? `border-radius: ${borderRadius};`
18
- : undefined}
19
- >
20
- <LoadingAnimation
21
- {name}
22
- caption={message ?? caption}
23
- />
24
- </div>
25
-
1
+ <svelte:options runes />
2
+
3
+ <script lang="ts">import LoadingAnimation from "./LoadingAnimation.svelte";
4
+ const { message, absolute, borderRadius, name, caption } = $props();
5
+ </script>
6
+
7
+ <div
8
+ class="loading-overlay"
9
+ class:absolute
10
+ role="status"
11
+ aria-live="polite"
12
+ style={borderRadius != null && borderRadius.length > 0
13
+ ? `border-radius: ${borderRadius};`
14
+ : undefined}
15
+ >
16
+ <LoadingAnimation
17
+ {name}
18
+ caption={message ?? caption}
19
+ />
20
+ </div>
21
+
26
22
  <style>.loading-overlay {
27
23
  display: flex;
28
24
  position: fixed;
@@ -41,4 +37,4 @@
41
37
  }
42
38
  .loading-overlay.absolute {
43
39
  position: absolute;
44
- }</style>
40
+ }</style>
@@ -1,260 +1,210 @@
1
- <svelte:options runes />
2
-
3
- <script
4
- module
5
- lang="ts"
6
- >
7
- import { browser } from '$app/environment';
8
- import { DATAMatrix } from '../Helpers/Datamatrix.js';
9
- import { passthrough } from '../Helpers/Helpers.svelte.js';
10
- import { ColourSet } from '../scss/colours.js';
11
- import { Size } from '../Types/Internal/Size.js';
12
- import { onMount } from 'svelte';
13
- import Action from './Action.svelte';
14
- import BaseModal from './Base/BaseModal.svelte';
15
- import DataMatrixIcon from './DataMatrixIcon.svelte';
16
- import type { ModalProps } from './ModalProps.js';
17
- </script>
18
-
19
- <script lang="ts">
20
- let {
21
- header,
22
- buttons,
23
- mandatory = false,
24
- staticHeight = false,
25
- staticWidth = false,
26
- minWidth,
27
- minHeight,
28
- width,
29
- height,
30
- onShowCallback,
31
- submitRef = $bindable(),
32
- defaultTimer,
33
- isValid = true,
34
- noscroll = false,
35
- onsubmit,
36
- headerExtra,
37
- explanation,
38
- children,
39
- footer,
40
- onclose,
41
- autofocusSelector,
42
- }: ModalProps = $props();
43
-
44
- // `open` drives BaseModal's bindable `value`. Default true (the
45
- // legacy "open immediately on mount" semantic). Flipping it to
46
- // false closes the dialog; BaseModal will fire `onclose` after
47
- // the native `close` event.
48
- let open = $state(true);
49
- let form: HTMLFormElement | undefined = $state();
50
- let timeout: ReturnType<typeof setTimeout> | undefined = undefined;
51
- let paused = $state(false);
52
- let isActive = $state(false);
53
-
54
- // Pre-compute barcode SVGs once per `buttons` array. Building a DataMatrix
55
- // barcode is non-trivial; rebuilding inside the each-block re-runs the
56
- // encoder on every render.
57
- //
58
- // `DATAMatrix` calls `document.createElement` internally, which is
59
- // undefined during SvelteKit's server render. Returning `null` on the
60
- // server keeps the SVG slots empty for SSR; the client re-renders with
61
- // the real encoded payload after hydration.
62
- const barcodeIcons = $derived.by(
63
- () =>
64
- buttons?.map((b) =>
65
- b.barcodeValue != null && browser ? DATAMatrix(b.barcodeValue) : null
66
- ) ?? []
67
- );
68
-
69
- onMount(() => {
70
- // Fire onShowCallback after BaseModal has had a chance to call
71
- // `showModal()`. BaseModal uses a tick() internally so we match
72
- // that with a microtask here.
73
- queueMicrotask(() => {
74
- onShowCallback?.();
75
- });
76
-
77
- const activeTimer = setTimeout(() => {
78
- isActive = true;
79
- }, 200);
80
- if (defaultTimer) {
81
- timeout = setTimeout(() => {
82
- if (open) {
83
- if (defaultTimer.action === 'submit') {
84
- form?.requestSubmit();
85
- } else {
86
- open = false;
87
- }
88
- }
89
- }, defaultTimer.time);
90
- }
91
-
92
- return () => {
93
- clearTimeout(activeTimer);
94
- clearTimer();
95
- };
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ module
5
+ lang="ts"
6
+ >import { browser } from "$app/environment";
7
+ import { DATAMatrix } from "../Helpers/Datamatrix.js";
8
+ import { passthrough } from "../Helpers/Helpers.svelte.js";
9
+ import { ColourSet } from "../scss/colours.js";
10
+ import { Size } from "../Types/Internal/Size.js";
11
+ import { onMount } from "svelte";
12
+ import Action from "./Action.svelte";
13
+ import BaseModal from "./Base/BaseModal.svelte";
14
+ import DataMatrixIcon from "./DataMatrixIcon.svelte";
15
+ </script>
16
+
17
+ <script lang="ts">let { header, buttons, mandatory = false, staticHeight = false, staticWidth = false, minWidth, minHeight, width, height, onShowCallback, submitRef = $bindable(), defaultTimer, isValid = true, noscroll = false, onsubmit, headerExtra, explanation, children, footer, onclose, autofocusSelector } = $props();
18
+ // `open` drives BaseModal's bindable `value`. Default true (the
19
+ // legacy "open immediately on mount" semantic). Flipping it to
20
+ // false closes the dialog; BaseModal will fire `onclose` after
21
+ // the native `close` event.
22
+ let open = $state(true);
23
+ let form = $state();
24
+ let timeout = undefined;
25
+ let paused = $state(false);
26
+ let isActive = $state(false);
27
+ // Pre-compute barcode SVGs once per `buttons` array. Building a DataMatrix
28
+ // barcode is non-trivial; rebuilding inside the each-block re-runs the
29
+ // encoder on every render.
30
+ //
31
+ // `DATAMatrix` calls `document.createElement` internally, which is
32
+ // undefined during SvelteKit's server render. Returning `null` on the
33
+ // server keeps the SVG slots empty for SSR; the client re-renders with
34
+ // the real encoded payload after hydration.
35
+ const barcodeIcons = $derived.by(() => buttons?.map((b) => b.barcodeValue != null && browser ? DATAMatrix(b.barcodeValue) : null) ?? []);
36
+ onMount(() => {
37
+ // Fire onShowCallback after BaseModal has had a chance to call
38
+ // `showModal()`. BaseModal uses a tick() internally so we match
39
+ // that with a microtask here.
40
+ queueMicrotask(() => {
41
+ onShowCallback?.();
96
42
  });
97
-
98
- function clearTimer() {
99
- if (timeout != undefined) {
100
- paused = true;
101
- clearTimeout(timeout);
102
- }
103
- }
104
-
105
- function handleEsc(e: KeyboardEvent) {
106
- // Forwarded to the Action button's onkeydown so an Escape press
107
- // while the close icon has focus still closes the dialog rather
108
- // than triggering the button's default activation.
109
- e.stopPropagation();
110
- if (e.key === 'Escape') {
111
- e.preventDefault();
112
- if (!mandatory) {
113
- open = false;
43
+ const activeTimer = setTimeout(() => {
44
+ isActive = true;
45
+ }, 200);
46
+ if (defaultTimer) {
47
+ timeout = setTimeout(() => {
48
+ if (open) {
49
+ if (defaultTimer.action === "submit") {
50
+ form?.requestSubmit();
51
+ } else {
52
+ open = false;
53
+ }
114
54
  }
115
- }
55
+ }, defaultTimer.time);
116
56
  }
117
-
118
- function requestClose() {
119
- open = false;
57
+ return () => {
58
+ clearTimeout(activeTimer);
59
+ clearTimer();
60
+ };
61
+ });
62
+ function clearTimer() {
63
+ if (timeout != undefined) {
64
+ paused = true;
65
+ clearTimeout(timeout);
120
66
  }
121
-
122
- const dialogClassNames = $derived(
123
- [
124
- staticHeight ? 'static-height' : null,
125
- staticWidth ? 'static-width' : null,
126
- noscroll ? 'noscroll' : null,
127
- ]
128
- .filter((c): c is string => c !== null)
129
- .join(' ')
130
- );
131
-
132
- const dialogStyle = $derived(
133
- `--timer: ${defaultTimer ? defaultTimer.time.toString() + 'ms' : 'unset'};` +
134
- (minWidth != null ? `--dialog-min-width: ${minWidth};` : '') +
135
- (minHeight != null ? `--dialog-min-height: ${minHeight};` : '') +
136
- (height != null ? `--dialog-height: ${height};` : '') +
137
- (width != null ? `--dialog-width: ${width};` : '')
138
- );
139
- </script>
140
-
141
- <BaseModal
142
- bind:value={open}
143
- {onclose}
144
- {mandatory}
145
- {autofocusSelector}
146
- dialogClass={dialogClassNames}
147
- {dialogStyle}
148
- >
149
- <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
150
- <!-- svelte-ignore a11y_click_events_have_key_events -->
151
- <form
152
- method="dialog"
153
- bind:this={form}
154
- onsubmit={(e) => {
155
- e.preventDefault();
156
- clearTimer();
157
- if (isActive) {
158
- onsubmit?.(e);
159
- }
160
- }}
161
- onclick={clearTimer}
162
- class="modal-root"
163
- >
164
- <div class="modal-header">
165
- {#if typeof header === 'string'}
166
- {#if mandatory}
167
- <h3 class="modal-heading">{header}</h3>
168
- {:else}
169
- <div class="title-wrapper">
170
- <h3 class="modal-heading">{header}</h3>
171
- <div class="close-button">
172
- <Action
173
- size={Size.DoubleXLarge}
174
- onclick={requestClose}
175
- icon={{
176
- name: 'cross',
177
- }}
178
- onkeydown={handleEsc}
179
- colourSet={ColourSet.Primary}
180
- label="Close Modal"
181
- />
182
- </div>
183
- </div>
184
- {/if}
185
- {:else if typeof header === 'function'}
186
- {@render header()}
187
- {/if}
188
-
189
- {#if headerExtra}
190
- {@render headerExtra()}
191
- {/if}
192
- </div>
193
-
194
- {#if defaultTimer}
195
- <div class="bar-container">
196
- <div
197
- class:paused
198
- class="bar-timer"
199
- ></div>
200
- </div>
201
- {/if}
202
-
203
- <div
204
- class="modal-main"
205
- class:noscroll
206
- >
207
- {#if explanation}
208
- {@render explanation()}
209
- {/if}
210
- {@render children()}
211
- </div>
212
-
213
- {#if footer}
214
- {@render footer()}
215
- {:else if buttons?.length}
216
- <div class="modal-footer">
217
- {#each buttons as button, index (button.label)}
218
- {#if button.callback}
219
- <div class="button-barcode-set">
220
- {#if barcodeIcons[index]}
221
- <DataMatrixIcon
222
- title={button.label}
223
- icon={{ kind: 'svg', svg: barcodeIcons[index] }}
224
- />
225
- {/if}
226
- <button
227
- onkeydown={passthrough}
228
- class:margin-left={button.margin === 'left'}
229
- class:margin-right={button.margin === 'right'}
230
- type={button.type ?? 'button'}
231
- onclick={button.callback}>{button.label}</button
232
- >
233
- </div>
234
- {:else}
235
- <div class="button-barcode-set">
236
- {#if barcodeIcons[index]}
237
- <DataMatrixIcon
238
- title={button.label}
239
- icon={{ kind: 'svg', svg: barcodeIcons[index] }}
240
- />
241
- {/if}
242
- <button
243
- onkeydown={passthrough}
244
- disabled={!isValid}
245
- class:margin-left={button.margin === 'left'}
246
- class:margin-right={button.margin === 'right'}
247
- bind:this={submitRef}
248
- type={button.type ?? 'submit'}>{button.label}</button
249
- >
250
- </div>
251
- {/if}
252
- {/each}
253
- </div>
254
- {/if}
255
- </form>
256
- </BaseModal>
257
-
67
+ }
68
+ function handleEsc(e) {
69
+ // Forwarded to the Action button's onkeydown so an Escape press
70
+ // while the close icon has focus still closes the dialog rather
71
+ // than triggering the button's default activation.
72
+ e.stopPropagation();
73
+ if (e.key === "Escape") {
74
+ e.preventDefault();
75
+ if (!mandatory) {
76
+ open = false;
77
+ }
78
+ }
79
+ }
80
+ function requestClose() {
81
+ open = false;
82
+ }
83
+ const dialogClassNames = $derived([
84
+ staticHeight ? "static-height" : null,
85
+ staticWidth ? "static-width" : null,
86
+ noscroll ? "noscroll" : null
87
+ ].filter((c) => c !== null).join(" "));
88
+ const dialogStyle = $derived(`--timer: ${defaultTimer ? defaultTimer.time.toString() + "ms" : "unset"};` + (minWidth != null ? `--dialog-min-width: ${minWidth};` : "") + (minHeight != null ? `--dialog-min-height: ${minHeight};` : "") + (height != null ? `--dialog-height: ${height};` : "") + (width != null ? `--dialog-width: ${width};` : ""));
89
+ </script>
90
+
91
+ <BaseModal
92
+ bind:value={open}
93
+ {onclose}
94
+ {mandatory}
95
+ {autofocusSelector}
96
+ dialogClass={dialogClassNames}
97
+ {dialogStyle}
98
+ >
99
+ <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
100
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
101
+ <form
102
+ method="dialog"
103
+ bind:this={form}
104
+ onsubmit={(e) => {
105
+ e.preventDefault();
106
+ clearTimer();
107
+ if (isActive) {
108
+ onsubmit?.(e);
109
+ }
110
+ }}
111
+ onclick={clearTimer}
112
+ class="modal-root"
113
+ >
114
+ <div class="modal-header">
115
+ {#if typeof header === 'string'}
116
+ {#if mandatory}
117
+ <h3 class="modal-heading">{header}</h3>
118
+ {:else}
119
+ <div class="title-wrapper">
120
+ <h3 class="modal-heading">{header}</h3>
121
+ <div class="close-button">
122
+ <Action
123
+ size={Size.DoubleXLarge}
124
+ onclick={requestClose}
125
+ icon={{
126
+ name: 'cross',
127
+ }}
128
+ onkeydown={handleEsc}
129
+ colourSet={ColourSet.Primary}
130
+ label="Close Modal"
131
+ />
132
+ </div>
133
+ </div>
134
+ {/if}
135
+ {:else if typeof header === 'function'}
136
+ {@render header()}
137
+ {/if}
138
+
139
+ {#if headerExtra}
140
+ {@render headerExtra()}
141
+ {/if}
142
+ </div>
143
+
144
+ {#if defaultTimer}
145
+ <div class="bar-container">
146
+ <div
147
+ class:paused
148
+ class="bar-timer"
149
+ ></div>
150
+ </div>
151
+ {/if}
152
+
153
+ <div
154
+ class="modal-main"
155
+ class:noscroll
156
+ >
157
+ {#if explanation}
158
+ {@render explanation()}
159
+ {/if}
160
+ {@render children()}
161
+ </div>
162
+
163
+ {#if footer}
164
+ {@render footer()}
165
+ {:else if buttons?.length}
166
+ <div class="modal-footer">
167
+ {#each buttons as button, index (button.label)}
168
+ {#if button.callback}
169
+ <div class="button-barcode-set">
170
+ {#if barcodeIcons[index]}
171
+ <DataMatrixIcon
172
+ title={button.label}
173
+ icon={{ kind: 'svg', svg: barcodeIcons[index] }}
174
+ />
175
+ {/if}
176
+ <button
177
+ onkeydown={passthrough}
178
+ class:margin-left={button.margin === 'left'}
179
+ class:margin-right={button.margin === 'right'}
180
+ type={button.type ?? 'button'}
181
+ onclick={button.callback}>{button.label}</button
182
+ >
183
+ </div>
184
+ {:else}
185
+ <div class="button-barcode-set">
186
+ {#if barcodeIcons[index]}
187
+ <DataMatrixIcon
188
+ title={button.label}
189
+ icon={{ kind: 'svg', svg: barcodeIcons[index] }}
190
+ />
191
+ {/if}
192
+ <button
193
+ onkeydown={passthrough}
194
+ disabled={!isValid}
195
+ class:margin-left={button.margin === 'left'}
196
+ class:margin-right={button.margin === 'right'}
197
+ bind:this={submitRef}
198
+ type={button.type ?? 'submit'}>{button.label}</button
199
+ >
200
+ </div>
201
+ {/if}
202
+ {/each}
203
+ </div>
204
+ {/if}
205
+ </form>
206
+ </BaseModal>
207
+
258
208
  <style>dialog {
259
209
  overflow: clip;
260
210
  background-color: #e9ecf1;
@@ -604,4 +554,4 @@ div.bar-container div.bar-timer.paused {
604
554
  }
605
555
  :global form > *:last-child {
606
556
  border-radius: 0px 0px 4px 4px;
607
- }</style>
557
+ }</style>