@lavalogic/scoria 0.40.14 → 0.40.16
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 +35 -46
- package/dist/Components/AccordionGroupButton.svelte +68 -76
- package/dist/Components/Action.svelte +103 -135
- package/dist/Components/AlertModal.svelte +171 -190
- package/dist/Components/AppointmentCalendar/AppointmentCalendar.svelte +614 -697
- package/dist/Components/Base/BaseModal.svelte +90 -116
- package/dist/Components/Base/ContextWrapper.svelte +67 -72
- package/dist/Components/Base/Pagination.svelte +173 -196
- package/dist/Components/Base/Snippets.svelte +34 -36
- package/dist/Components/BigRadioSet.svelte +36 -38
- package/dist/Components/Bubble.svelte +78 -101
- package/dist/Components/Button.svelte +175 -208
- package/dist/Components/Checkbox.svelte +75 -86
- package/dist/Components/CollapsibleCard.svelte +72 -86
- package/dist/Components/CollapsibleMenuGroup.svelte +52 -56
- package/dist/Components/ConditionBuilder/ConditionBuilder.svelte +39 -64
- package/dist/Components/Contexts/ContextMenu.svelte +141 -156
- package/dist/Components/Contexts/ContextMenuDivider.svelte +15 -15
- package/dist/Components/Contexts/ContextMenuOption.svelte +53 -60
- package/dist/Components/Contexts/Toast.svelte +81 -86
- package/dist/Components/Contexts/ToastContainer.svelte +58 -62
- package/dist/Components/Contexts/Tooltip.svelte +36 -37
- package/dist/Components/DataMatrixIcon.svelte +95 -108
- package/dist/Components/DateInput.svelte +118 -146
- package/dist/Components/DatePicker.svelte +255 -294
- package/dist/Components/DesktopModal.svelte +70 -90
- package/dist/Components/Dial.svelte +167 -197
- package/dist/Components/DimensionInput.svelte +124 -169
- package/dist/Components/DragMenu/DragMenuHolder.svelte +98 -114
- package/dist/Components/DragMenu/DraggableCard.svelte +64 -76
- package/dist/Components/FileCard.svelte +21 -24
- package/dist/Components/FileUpload.svelte +190 -225
- package/dist/Components/GridInput.svelte +159 -196
- package/dist/Components/GridInputSet.svelte +24 -29
- package/dist/Components/HorizontalTabGroup.svelte +73 -89
- package/dist/Components/HorizontalTabGroupButton.svelte +40 -44
- package/dist/Components/Icon.svelte +99 -128
- package/dist/Components/Icons.js +357 -357
- package/dist/Components/InfoAlert.svelte +35 -38
- package/dist/Components/LoadingAnimation.svelte +691 -755
- package/dist/Components/LoadingModal.svelte +36 -44
- package/dist/Components/LoadingOverlay.svelte +22 -26
- package/dist/Components/Modal.svelte +204 -254
- package/dist/Components/MultiSelect.svelte +186 -216
- package/dist/Components/Nav/Nav.svelte +94 -110
- package/dist/Components/Nav/NavServiceMenuList.svelte +57 -61
- package/dist/Components/Nav/NavTab.svelte +58 -62
- package/dist/Components/Nav/ServiceMenuItem.svelte +103 -111
- package/dist/Components/Nav/ServicesNav.svelte +72 -79
- package/dist/Components/NumberInput.svelte +121 -155
- package/dist/Components/OptionCards.svelte +62 -73
- package/dist/Components/PageHeading.svelte +23 -25
- package/dist/Components/PasswordInput.svelte +69 -88
- package/dist/Components/PopoverButton.svelte +69 -82
- package/dist/Components/Portal.svelte +29 -35
- package/dist/Components/ProgressBubble.svelte +91 -106
- package/dist/Components/QuerySelect.svelte +260 -346
- package/dist/Components/SidebarPanel.svelte +34 -36
- package/dist/Components/SingleSelect.svelte +196 -244
- package/dist/Components/StepButton.svelte +65 -70
- package/dist/Components/StepForm.svelte +115 -135
- package/dist/Components/Switch.svelte +57 -69
- package/dist/Components/Table/ARCHITECTURE.md +298 -298
- package/dist/Components/Table/Body/QuickSearchCell.svelte +578 -655
- package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +42 -51
- package/dist/Components/Table/Body/Rows/ColumnList.svelte +42 -58
- package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +403 -442
- package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +51 -78
- package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +165 -184
- package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +110 -123
- package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +134 -160
- package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +190 -231
- package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +82 -104
- package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +52 -87
- package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +122 -150
- package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +132 -159
- package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +190 -236
- package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +173 -211
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +204 -244
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +140 -177
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +188 -217
- package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +173 -193
- package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +166 -187
- package/dist/Components/Table/Body/Rows/TableRow.svelte +245 -288
- package/dist/Components/Table/Body/TableBody.svelte +141 -154
- package/dist/Components/Table/ColumnFactory.svelte.js +1 -0
- package/dist/Components/Table/Headers/HighlightAllHeader.svelte +35 -41
- package/dist/Components/Table/Headers/SelectAllHeader.svelte +24 -30
- package/dist/Components/Table/Headers/TableHead.svelte +348 -402
- package/dist/Components/Table/Misc/ColumnPanel.svelte +37 -39
- package/dist/Components/Table/Misc/ColumnPanelModal.svelte +35 -39
- package/dist/Components/Table/Misc/FilterInput.svelte +556 -619
- package/dist/Components/Table/Misc/FilterPanel.svelte +170 -183
- package/dist/Components/Table/Misc/FilterPanelModal.svelte +25 -31
- package/dist/Components/Table/Misc/ShareViewModal.svelte +252 -281
- package/dist/Components/Table/Misc/SidePanel.svelte +32 -35
- package/dist/Components/Table/Misc/TableConfigurationModal.svelte +574 -629
- package/dist/Components/Table/Misc/TableFooter.svelte +326 -332
- package/dist/Components/Table/Misc/TableHorizontalBar.svelte +134 -140
- package/dist/Components/Table/Misc/TableSidebar.svelte +183 -198
- package/dist/Components/Table/Misc/TableViewDropdown.svelte +83 -103
- package/dist/Components/Table/Misc/ToolboxPanel.svelte +83 -100
- package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +88 -107
- package/dist/Components/Table/Misc/UpdateViewOptionsModal.svelte +163 -190
- package/dist/Components/Table/NestedTable.svelte +102 -128
- package/dist/Components/Table/Table.svelte +531 -663
- package/dist/Components/Table/Types/Columns/Definitions/Actions/ActionsDef.svelte.d.ts +8 -6
- package/dist/Components/Table/Types/Columns/Definitions/Actions/ActionsDef.svelte.js +3 -3
- package/dist/Components/Test/TestContextConsumer.svelte +11 -13
- package/dist/Components/TextArea.svelte +95 -130
- package/dist/Components/TextInput.svelte +125 -176
- package/dist/Components/ThreeStateRadio.svelte +111 -130
- package/dist/Components/Touch/BoolCard.svelte +33 -45
- package/dist/Components/Touch/DateModal.svelte +164 -204
- package/dist/Components/Touch/EditCard.svelte +48 -59
- package/dist/Components/Touch/InfoCard.svelte +28 -31
- package/dist/Components/Touch/InfoTextCard.svelte +26 -28
- package/dist/Components/Touch/ModalExplanation.svelte +15 -17
- package/dist/Components/Touch/NumberKeyboard.svelte +181 -218
- package/dist/Components/Touch/NumberModal.svelte +59 -79
- package/dist/Components/Touch/PlusMinusCard.svelte +43 -46
- package/dist/Components/Touch/SelectModal.svelte +111 -126
- package/dist/Components/Touch/SummaryCard.svelte +80 -93
- package/dist/Components/Touch/TextAreaModal.svelte +72 -94
- package/dist/Components/Touch/TextModal.svelte +77 -105
- package/dist/Components/Touch/TouchCard.svelte +31 -33
- package/dist/Components/Touch/TouchModal.svelte +214 -270
- package/dist/Components/Touch/UtilityButton.svelte +88 -109
- package/dist/Components/VerticalTabGroup.svelte +60 -78
- package/dist/Components/VerticalTabGroupButton.svelte +54 -58
- package/dist/Helpers/Datamatrix.d.ts +19 -19
- package/dist/Helpers/Datamatrix.js +291 -291
- package/dist/Types/Examples/ExampleModal.svelte +31 -35
- package/dist/scss/_basics.scss +12 -12
- package/dist/scss/_colours.scss +134 -134
- package/dist/scss/_mixins.scss +3392 -3392
- package/dist/scss/_motion.scss +57 -57
- package/dist/scss/_sizing.scss +85 -85
- package/dist/scss/_transitions.scss +8 -8
- package/package.json +1 -1
|
@@ -1,86 +1,73 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<!--
|
|
4
|
-
@component
|
|
5
|
-
An icon button that toggles a floating popover anchored beneath it, with a
|
|
6
|
-
caret pointing back at the button. The popover holds arbitrary content (the
|
|
7
|
-
default snippet) and closes on click-outside or Escape.
|
|
8
|
-
-->
|
|
9
|
-
<script lang="ts">
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
label,
|
|
18
|
-
children,
|
|
19
|
-
align = 'center',
|
|
20
|
-
borderless = false,
|
|
21
|
-
open = $bindable(false),
|
|
22
|
-
}: PopoverButtonProps = $props();
|
|
23
|
-
|
|
24
|
-
let wrapper: HTMLDivElement | undefined = $state();
|
|
25
|
-
|
|
26
|
-
function onWindowPointerDown(e: MouseEvent) {
|
|
27
|
-
if (!open) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
if (wrapper && e.target instanceof Node && !wrapper.contains(e.target)) {
|
|
31
|
-
open = false;
|
|
32
|
-
}
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
@component
|
|
5
|
+
An icon button that toggles a floating popover anchored beneath it, with a
|
|
6
|
+
caret pointing back at the button. The popover holds arbitrary content (the
|
|
7
|
+
default snippet) and closes on click-outside or Escape.
|
|
8
|
+
-->
|
|
9
|
+
<script lang="ts">import { Colour } from "../scss/colours.js";
|
|
10
|
+
import { Size } from "../Types/Internal/Size.js";
|
|
11
|
+
import Icon from "./Icon.svelte";
|
|
12
|
+
let { icon, label, children, align = "center", borderless = false, open = $bindable(false) } = $props();
|
|
13
|
+
let wrapper = $state();
|
|
14
|
+
function onWindowPointerDown(e) {
|
|
15
|
+
if (!open) {
|
|
16
|
+
return;
|
|
33
17
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (open && e.key === 'Escape') {
|
|
37
|
-
open = false;
|
|
38
|
-
}
|
|
18
|
+
if (wrapper && e.target instanceof Node && !wrapper.contains(e.target)) {
|
|
19
|
+
open = false;
|
|
39
20
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
21
|
+
}
|
|
22
|
+
function onWindowKeydown(e) {
|
|
23
|
+
if (open && e.key === "Escape") {
|
|
24
|
+
open = false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<svelte:window
|
|
30
|
+
onpointerdown={onWindowPointerDown}
|
|
31
|
+
onkeydown={onWindowKeydown}
|
|
32
|
+
/>
|
|
33
|
+
|
|
34
|
+
<div
|
|
35
|
+
class="popover-button"
|
|
36
|
+
bind:this={wrapper}
|
|
37
|
+
>
|
|
38
|
+
<button
|
|
39
|
+
type="button"
|
|
40
|
+
class="trigger"
|
|
41
|
+
class:open
|
|
42
|
+
class:borderless
|
|
43
|
+
aria-label={label}
|
|
44
|
+
aria-expanded={open}
|
|
45
|
+
aria-haspopup="dialog"
|
|
46
|
+
onclick={() => {
|
|
47
|
+
open = !open;
|
|
48
|
+
}}
|
|
49
|
+
>
|
|
50
|
+
<Icon
|
|
51
|
+
name={icon}
|
|
52
|
+
size={Size.Large}
|
|
53
|
+
colour={open ? Colour['$brand-primary'] : Colour['$font-secondary']}
|
|
54
|
+
/>
|
|
55
|
+
</button>
|
|
56
|
+
|
|
57
|
+
{#if open}
|
|
58
|
+
<div
|
|
59
|
+
class="popover align-{align}"
|
|
60
|
+
role="dialog"
|
|
61
|
+
aria-label={label}
|
|
62
|
+
>
|
|
63
|
+
<span class="caret"></span>
|
|
64
|
+
<div class="popover-inner">
|
|
65
|
+
{@render children()}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
{/if}
|
|
69
|
+
</div>
|
|
70
|
+
|
|
84
71
|
<style>.popover-button {
|
|
85
72
|
position: relative;
|
|
86
73
|
display: inline-flex;
|
|
@@ -161,4 +148,4 @@ default snippet) and closes on click-outside or Escape.
|
|
|
161
148
|
|
|
162
149
|
.align-end .caret {
|
|
163
150
|
right: 1.5rem;
|
|
164
|
-
}</style>
|
|
151
|
+
}</style>
|
|
@@ -1,36 +1,30 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<script lang="ts">
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
// re-fires the effect without changing identity.
|
|
17
|
-
if (target && ref && target !== lastTarget) {
|
|
18
|
-
if (target.ownerDocument === globalThis.document) {
|
|
19
|
-
target.appendChild(ref);
|
|
20
|
-
lastTarget = target;
|
|
21
|
-
}
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<script lang="ts">import { browser } from "$app/environment";
|
|
4
|
+
let { target = browser ? globalThis.document.body : undefined, children } = $props();
|
|
5
|
+
let ref = $state();
|
|
6
|
+
let lastTarget;
|
|
7
|
+
$effect(() => {
|
|
8
|
+
// Identity guard: only re-parent when `target` actually changes.
|
|
9
|
+
// `appendChild` already moves the node when called, so this avoids
|
|
10
|
+
// unnecessary detach/attach when an upstream `$state` target
|
|
11
|
+
// re-fires the effect without changing identity.
|
|
12
|
+
if (target && ref && target !== lastTarget) {
|
|
13
|
+
if (target.ownerDocument === globalThis.document) {
|
|
14
|
+
target.appendChild(ref);
|
|
15
|
+
lastTarget = target;
|
|
22
16
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
</script>
|
|
33
|
-
|
|
34
|
-
<div bind:this={ref}>
|
|
35
|
-
{@render children()}
|
|
36
|
-
</div>
|
|
17
|
+
}
|
|
18
|
+
// Cleanup is necessary, not redundant: without it, the appended
|
|
19
|
+
// node would remain inside `target` after the Portal unmounts,
|
|
20
|
+
// because `target` outlives the component.
|
|
21
|
+
return () => {
|
|
22
|
+
ref?.parentNode?.removeChild(ref);
|
|
23
|
+
lastTarget = undefined;
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<div bind:this={ref}>
|
|
29
|
+
{@render children()}
|
|
30
|
+
</div>
|
|
@@ -1,109 +1,94 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<script lang="ts">
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
let barWidth = $state(0);
|
|
29
|
-
$effect(() => {
|
|
30
|
-
if (!progressBarRef) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
const ro = new ResizeObserver((entries) => {
|
|
34
|
-
const entry = entries[0];
|
|
35
|
-
barWidth = entry.borderBoxSize[0]?.inlineSize ?? entry.contentRect.width;
|
|
36
|
-
});
|
|
37
|
-
ro.observe(progressBarRef);
|
|
38
|
-
return () => {
|
|
39
|
-
ro.disconnect();
|
|
40
|
-
};
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<script lang="ts">import { useAsyncFlag } from "../Helpers/AsyncFlag.svelte.js";
|
|
4
|
+
import { getCanvasContext } from "../Helpers/Helpers.svelte.js";
|
|
5
|
+
const { value, colours } = $props();
|
|
6
|
+
const current = $derived(value[0]);
|
|
7
|
+
const total = $derived(value[1]);
|
|
8
|
+
const progress = $derived(`${current}/${total}`);
|
|
9
|
+
// Clamp the percentage so callers passing `current > total` do not
|
|
10
|
+
// blow past the bar's edge.
|
|
11
|
+
const percent = $derived(Math.min(current / total * 100, 100));
|
|
12
|
+
let progressBarRef = $state();
|
|
13
|
+
// Observed inline-size of the filled bar. A `ResizeObserver` is used
|
|
14
|
+
// instead of `getBoundingClientRect()` inside an `$effect`: the latter
|
|
15
|
+
// forces a synchronous layout flush on every `progress` change, which
|
|
16
|
+
// is expensive inside a table with many `ProgressBubble` cells. The
|
|
17
|
+
// observer notifies us only when the bar's actual rendered size
|
|
18
|
+
// changes, and does so via a microtask scheduled by the browser so we
|
|
19
|
+
// never force layout ourselves.
|
|
20
|
+
let barWidth = $state(0);
|
|
21
|
+
$effect(() => {
|
|
22
|
+
if (!progressBarRef) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const ro = new ResizeObserver((entries) => {
|
|
26
|
+
const entry = entries[0];
|
|
27
|
+
barWidth = entry.borderBoxSize[0]?.inlineSize ?? entry.contentRect.width;
|
|
41
28
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
aria-
|
|
89
|
-
aria-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
</div>
|
|
106
|
-
|
|
29
|
+
ro.observe(progressBarRef);
|
|
30
|
+
return () => {
|
|
31
|
+
ro.disconnect();
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
// Whether the `current/total` label fits inside the filled bar.
|
|
35
|
+
// Measured via a memoised offscreen canvas so we do not trigger
|
|
36
|
+
// layout.
|
|
37
|
+
const fitsInProgressBar = $derived.by(() => {
|
|
38
|
+
const textWidth = getCanvasContext()?.measureText(`__${progress}__`).width ?? 0;
|
|
39
|
+
return barWidth > textWidth;
|
|
40
|
+
});
|
|
41
|
+
// `colours` may be a bare `BubbleColour`, a Promise resolving to one,
|
|
42
|
+
// or undefined. Routed through `useAsyncFlag` which (a) cancels stale
|
|
43
|
+
// Promises via a sequence ticket so the freshest value always wins,
|
|
44
|
+
// (b) reports errors through `ToastContext` when one is mounted, and
|
|
45
|
+
// (c) falls back to `undefined` while no resolution is available.
|
|
46
|
+
const awaitedColoursFlag = useAsyncFlag(() => colours, undefined);
|
|
47
|
+
const awaitedColours = $derived(awaitedColoursFlag.value);
|
|
48
|
+
// Precompute the wrapper and bar style strings. Each colour comes
|
|
49
|
+
// from the trusted `Colour` registry (see `Bubble.svelte` security
|
|
50
|
+
// note) so interpolation into `style="..."` is safe.
|
|
51
|
+
const wrapperStyle = $derived(awaitedColours ? `--bar-background-colour: ${awaitedColours.backgroundColour}; --text-colour: ${awaitedColours.colour};` : "");
|
|
52
|
+
const barStyle = $derived(`width: ${percent}%;`);
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<div
|
|
56
|
+
class="progress-wrapper"
|
|
57
|
+
style={wrapperStyle}
|
|
58
|
+
>
|
|
59
|
+
<!--
|
|
60
|
+
Native `<progress>` is kept as a fallback for assistive tech that
|
|
61
|
+
ignores ARIA progressbar roles. Visually hidden rather than
|
|
62
|
+
`display: none` so the element stays in the accessibility tree.
|
|
63
|
+
-->
|
|
64
|
+
<progress
|
|
65
|
+
class="visually-hidden"
|
|
66
|
+
value={current}
|
|
67
|
+
max={total}>{progress}</progress
|
|
68
|
+
>
|
|
69
|
+
|
|
70
|
+
<div
|
|
71
|
+
class="progress-background"
|
|
72
|
+
role="progressbar"
|
|
73
|
+
aria-valuenow={current}
|
|
74
|
+
aria-valuemin={0}
|
|
75
|
+
aria-valuemax={total}
|
|
76
|
+
aria-valuetext={progress}
|
|
77
|
+
>
|
|
78
|
+
<div
|
|
79
|
+
class:fits={fitsInProgressBar}
|
|
80
|
+
class="progress-value"
|
|
81
|
+
bind:this={progressBarRef}
|
|
82
|
+
style={barStyle}
|
|
83
|
+
>
|
|
84
|
+
<span
|
|
85
|
+
class:fits={fitsInProgressBar}
|
|
86
|
+
class="progress-text">{progress}</span
|
|
87
|
+
>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
107
92
|
<style>.progress-wrapper {
|
|
108
93
|
width: 100%;
|
|
109
94
|
height: 100%;
|
|
@@ -172,4 +157,4 @@
|
|
|
172
157
|
}
|
|
173
158
|
.progress-text.fits {
|
|
174
159
|
color: var(--text-colour, #3a4952);
|
|
175
|
-
}</style>
|
|
160
|
+
}</style>
|