@lavalogic/scoria 0.40.1 → 0.40.2
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/AlertModal.svelte +195 -195
- package/dist/Components/AppointmentCalendar/AppointmentCalendar.svelte +729 -729
- 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/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 +86 -86
- 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/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/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 -196
- 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/Icons.js +357 -357
- package/dist/Components/InfoAlert.svelte +35 -35
- package/dist/Components/LoadingAnimation.svelte +29 -29
- package/dist/Components/LoadingModal.svelte +45 -45
- package/dist/Components/LoadingOverlay.svelte +25 -25
- package/dist/Components/Modal.svelte +258 -258
- package/dist/Components/MultiSelect.svelte +220 -220
- package/dist/Components/Nav/Nav.svelte +110 -110
- package/dist/Components/Nav/NavServiceMenuList.svelte +43 -43
- package/dist/Components/Nav/NavTab.svelte +62 -62
- package/dist/Components/Nav/ServiceMenuItem.svelte +112 -112
- 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 -107
- package/dist/Components/QuerySelect.svelte +366 -366
- package/dist/Components/SingleSelect.svelte +250 -250
- 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 -298
- package/dist/Components/Table/Body/QuickSearchCell.svelte +679 -679
- 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 +454 -454
- package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +79 -79
- package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +185 -185
- package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +124 -124
- package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +131 -120
- package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +234 -234
- package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +105 -105
- 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/TableNumberInput.svelte +216 -216
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +252 -252
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +179 -179
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +221 -221
- 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/ColumnFactory.svelte.js +1 -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 -415
- package/dist/Components/Table/Misc/ColumnPanel.svelte +39 -39
- package/dist/Components/Table/Misc/ColumnPanelModal.svelte +39 -39
- package/dist/Components/Table/Misc/FilterInput.svelte +641 -641
- package/dist/Components/Table/Misc/FilterPanel.svelte +190 -190
- package/dist/Components/Table/Misc/FilterPanelModal.svelte +31 -31
- package/dist/Components/Table/Misc/ShareViewModal.svelte +291 -291
- package/dist/Components/Table/Misc/SidePanel.svelte +35 -35
- package/dist/Components/Table/Misc/TableConfigurationModal.svelte +644 -644
- package/dist/Components/Table/Misc/TableFooter.svelte +340 -340
- package/dist/Components/Table/Misc/TableHorizontalBar.svelte +140 -140
- package/dist/Components/Table/Misc/TableSidebar.svelte +200 -200
- package/dist/Components/Table/Misc/TableViewDropdown.svelte +105 -105
- package/dist/Components/Table/Misc/ToolboxPanel.svelte +100 -100
- package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +107 -107
- package/dist/Components/Table/Misc/UpdateViewOptionsModal.svelte +192 -192
- package/dist/Components/Table/NestedTable.svelte +130 -130
- package/dist/Components/Table/Table.svelte +692 -692
- package/dist/Components/Table/Types/Columns/Definitions/Expand/ExpandDef.svelte.d.ts +5 -0
- package/dist/Components/Table/Types/Columns/Definitions/Expand/ExpandDef.svelte.js +3 -0
- package/dist/Components/Table/Types/Public/ColumnOptions.d.ts +10 -0
- 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 +127 -127
- 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/Helpers/Datamatrix.d.ts +19 -19
- package/dist/Helpers/Datamatrix.js +291 -291
- package/dist/Types/Examples/ExampleModal.svelte +35 -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,19 +1,19 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<!--
|
|
4
|
-
@component
|
|
5
|
-
Visual separator for {@link ContextMenu}. Renders a thin horizontal
|
|
6
|
-
rule. The native `<hr>` ARIA mapping is `role="separator"`, which is
|
|
7
|
-
the correct semantic inside a `role="menu"` group, so no explicit
|
|
8
|
-
role is set.
|
|
9
|
-
|
|
10
|
-
Intended for use between groups of `ContextMenuOption` entries inside
|
|
11
|
-
a context menu rendered via the visual host.
|
|
12
|
-
-->
|
|
13
|
-
<hr />
|
|
14
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
@component
|
|
5
|
+
Visual separator for {@link ContextMenu}. Renders a thin horizontal
|
|
6
|
+
rule. The native `<hr>` ARIA mapping is `role="separator"`, which is
|
|
7
|
+
the correct semantic inside a `role="menu"` group, so no explicit
|
|
8
|
+
role is set.
|
|
9
|
+
|
|
10
|
+
Intended for use between groups of `ContextMenuOption` entries inside
|
|
11
|
+
a context menu rendered via the visual host.
|
|
12
|
+
-->
|
|
13
|
+
<hr />
|
|
14
|
+
|
|
15
15
|
<style>hr {
|
|
16
16
|
border-top: solid 1px #cbd4da;
|
|
17
17
|
width: 100%;
|
|
18
18
|
margin: 2px 0;
|
|
19
|
-
}</style>
|
|
19
|
+
}</style>
|
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<!--
|
|
4
|
-
@component
|
|
5
|
-
A single row inside the {@link ContextMenu} host. Renders a
|
|
6
|
-
`<button role="menuitem">` and assigns a roving `tabindex`: the
|
|
7
|
-
first option (index `0`) receives focus on mount and is the only
|
|
8
|
-
tab stop, all subsequent options carry `tabindex="-1"` so arrow-key
|
|
9
|
-
navigation owns focus traversal within the menu.
|
|
10
|
-
|
|
11
|
-
Consumers do not usually mount `ContextMenuOption` directly; the
|
|
12
|
-
visual host iterates over `ContextMenuContext.items` and renders one
|
|
13
|
-
option per entry.
|
|
14
|
-
-->
|
|
15
|
-
<script lang="ts">
|
|
16
|
-
import { devCatch } from '../../Helpers/Helpers.svelte.js';
|
|
17
|
-
import { tick } from 'svelte';
|
|
18
|
-
import type { ContextMenuOptionProps } from './ContextMenuOptionProps.js';
|
|
19
|
-
|
|
20
|
-
let { text = '', index, disabled = false, onclick, children }: ContextMenuOptionProps = $props();
|
|
21
|
-
|
|
22
|
-
let element = $state<HTMLButtonElement | undefined>();
|
|
23
|
-
|
|
24
|
-
$effect(() => {
|
|
25
|
-
void element;
|
|
26
|
-
// Only the first option seeds focus. The check stays inside the
|
|
27
|
-
// effect (rather than gating registration) so Svelte's reactive
|
|
28
|
-
// dependency on `index` is recorded.
|
|
29
|
-
if (index === 0) {
|
|
30
|
-
tick()
|
|
31
|
-
.then(() => {
|
|
32
|
-
element?.focus();
|
|
33
|
-
})
|
|
34
|
-
.catch(devCatch);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
</script>
|
|
38
|
-
|
|
39
|
-
<button
|
|
40
|
-
class="context-menu-item"
|
|
41
|
-
role="menuitem"
|
|
42
|
-
class:disabled
|
|
43
|
-
tabindex={index === 0 ? 0 : -1}
|
|
44
|
-
aria-disabled={disabled ? 'true' : undefined}
|
|
45
|
-
bind:this={element}
|
|
46
|
-
onclick={(e) => {
|
|
47
|
-
e.stopImmediatePropagation();
|
|
48
|
-
e.stopPropagation();
|
|
49
|
-
e.preventDefault();
|
|
50
|
-
void onclick?.(e);
|
|
51
|
-
}}
|
|
52
|
-
>
|
|
53
|
-
{#if text}
|
|
54
|
-
{text}
|
|
55
|
-
{:else if children}
|
|
56
|
-
{@render children()}
|
|
57
|
-
{/if}
|
|
58
|
-
</button>
|
|
59
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
@component
|
|
5
|
+
A single row inside the {@link ContextMenu} host. Renders a
|
|
6
|
+
`<button role="menuitem">` and assigns a roving `tabindex`: the
|
|
7
|
+
first option (index `0`) receives focus on mount and is the only
|
|
8
|
+
tab stop, all subsequent options carry `tabindex="-1"` so arrow-key
|
|
9
|
+
navigation owns focus traversal within the menu.
|
|
10
|
+
|
|
11
|
+
Consumers do not usually mount `ContextMenuOption` directly; the
|
|
12
|
+
visual host iterates over `ContextMenuContext.items` and renders one
|
|
13
|
+
option per entry.
|
|
14
|
+
-->
|
|
15
|
+
<script lang="ts">
|
|
16
|
+
import { devCatch } from '../../Helpers/Helpers.svelte.js';
|
|
17
|
+
import { tick } from 'svelte';
|
|
18
|
+
import type { ContextMenuOptionProps } from './ContextMenuOptionProps.js';
|
|
19
|
+
|
|
20
|
+
let { text = '', index, disabled = false, onclick, children }: ContextMenuOptionProps = $props();
|
|
21
|
+
|
|
22
|
+
let element = $state<HTMLButtonElement | undefined>();
|
|
23
|
+
|
|
24
|
+
$effect(() => {
|
|
25
|
+
void element;
|
|
26
|
+
// Only the first option seeds focus. The check stays inside the
|
|
27
|
+
// effect (rather than gating registration) so Svelte's reactive
|
|
28
|
+
// dependency on `index` is recorded.
|
|
29
|
+
if (index === 0) {
|
|
30
|
+
tick()
|
|
31
|
+
.then(() => {
|
|
32
|
+
element?.focus();
|
|
33
|
+
})
|
|
34
|
+
.catch(devCatch);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<button
|
|
40
|
+
class="context-menu-item"
|
|
41
|
+
role="menuitem"
|
|
42
|
+
class:disabled
|
|
43
|
+
tabindex={index === 0 ? 0 : -1}
|
|
44
|
+
aria-disabled={disabled ? 'true' : undefined}
|
|
45
|
+
bind:this={element}
|
|
46
|
+
onclick={(e) => {
|
|
47
|
+
e.stopImmediatePropagation();
|
|
48
|
+
e.stopPropagation();
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
void onclick?.(e);
|
|
51
|
+
}}
|
|
52
|
+
>
|
|
53
|
+
{#if text}
|
|
54
|
+
{text}
|
|
55
|
+
{:else if children}
|
|
56
|
+
{@render children()}
|
|
57
|
+
{/if}
|
|
58
|
+
</button>
|
|
59
|
+
|
|
60
60
|
<style>button {
|
|
61
61
|
background-color: #ffffff;
|
|
62
62
|
border: none;
|
|
@@ -85,4 +85,4 @@ button.disabled {
|
|
|
85
85
|
|
|
86
86
|
button.disabled:hover {
|
|
87
87
|
background: #ffffff;
|
|
88
|
-
}</style>
|
|
88
|
+
}</style>
|
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<!--
|
|
4
|
-
@component
|
|
5
|
-
Single toast rendering. Renders a pill near the bottom-right of the
|
|
6
|
-
viewport via `ToastContainer`, sliding in vertically. The severity of
|
|
7
|
-
the underlying toast drives both the colouring and the live-region
|
|
8
|
-
semantics:
|
|
9
|
-
|
|
10
|
-
- `Validity.Invalid` -> `role="alert"`, `aria-live="assertive"`.
|
|
11
|
-
- All other severities -> `role="status"`, `aria-live="polite"`.
|
|
12
|
-
|
|
13
|
-
The slide transition animates the pill's height (the `y` axis) so the
|
|
14
|
-
message keeps its final width for the whole animation — animating the
|
|
15
|
-
`x` axis instead reflows the text from stacked-and-wrapped to a single
|
|
16
|
-
line as the pill widens. It honours `prefers-reduced-motion` through
|
|
17
|
-
the shared `usePrefersReducedMotion` helper; when the user has opted in
|
|
18
|
-
the duration collapses to zero. The copy action is only shown when
|
|
19
|
-
`navigator.clipboard` is present (HTTPS or `localhost`).
|
|
20
|
-
-->
|
|
21
|
-
<script
|
|
22
|
-
lang="ts"
|
|
23
|
-
module
|
|
24
|
-
>
|
|
25
|
-
import { ColourSet } from '../../scss/colours.js';
|
|
26
|
-
import { Size } from '../../Types/Internal/Size.js';
|
|
27
|
-
import { Validity } from '../../Types/Internal/Validity.js';
|
|
28
|
-
import { slide } from 'svelte/transition';
|
|
29
|
-
import Action from '../Action.svelte';
|
|
30
|
-
import Icon from '../Icon.svelte';
|
|
31
|
-
import type { ToastProps } from './ToastProps.js';
|
|
32
|
-
</script>
|
|
33
|
-
|
|
34
|
-
<script lang="ts">
|
|
35
|
-
import { usePrefersReducedMotion } from '../../Helpers/prefersReducedMotion.svelte.js';
|
|
36
|
-
|
|
37
|
-
let { toast, copy }: ToastProps = $props();
|
|
38
|
-
|
|
39
|
-
const reducedMotion = usePrefersReducedMotion();
|
|
40
|
-
const slideDuration = $derived(reducedMotion.matches ? 0 : 500);
|
|
41
|
-
</script>
|
|
42
|
-
|
|
43
|
-
<output
|
|
44
|
-
role={toast.result == Validity.Invalid ? 'alert' : 'status'}
|
|
45
|
-
aria-live={toast.result == Validity.Invalid ? 'assertive' : 'polite'}
|
|
46
|
-
class:info={toast.result == Validity.Info}
|
|
47
|
-
class:success={toast.result == Validity.Valid}
|
|
48
|
-
class:warning={toast.result == Validity.Warning}
|
|
49
|
-
class:error={toast.result == Validity.Invalid}
|
|
50
|
-
transition:slide={{ axis: 'y', duration: slideDuration }}
|
|
51
|
-
>
|
|
52
|
-
<div>
|
|
53
|
-
<div class="noshrink">
|
|
54
|
-
{#if toast.copyable != false && navigator.clipboard}
|
|
55
|
-
<Action
|
|
56
|
-
onclick={copy}
|
|
57
|
-
icon={{ name: 'copy' }}
|
|
58
|
-
label="Copy to clipboard"
|
|
59
|
-
size={Size.MediumLarge}
|
|
60
|
-
colourSet={ColourSet.Auxiliary}
|
|
61
|
-
/>
|
|
62
|
-
{:else}
|
|
63
|
-
<Icon
|
|
64
|
-
name="info"
|
|
65
|
-
size={Size.MediumLarge}
|
|
66
|
-
/>
|
|
67
|
-
{/if}
|
|
68
|
-
</div>
|
|
69
|
-
<span>{toast.message}</span>
|
|
70
|
-
{#if toast.closeable}
|
|
71
|
-
<div class="noshrink">
|
|
72
|
-
<Action
|
|
73
|
-
size={Size.MediumLarge}
|
|
74
|
-
icon={{ name: 'cross' }}
|
|
75
|
-
label="Dismiss"
|
|
76
|
-
onclick={() => {
|
|
77
|
-
toast.close?.();
|
|
78
|
-
}}
|
|
79
|
-
colourSet={ColourSet.Auxiliary}
|
|
80
|
-
/>
|
|
81
|
-
</div>
|
|
82
|
-
{/if}
|
|
83
|
-
</div>
|
|
84
|
-
</output>
|
|
85
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
@component
|
|
5
|
+
Single toast rendering. Renders a pill near the bottom-right of the
|
|
6
|
+
viewport via `ToastContainer`, sliding in vertically. The severity of
|
|
7
|
+
the underlying toast drives both the colouring and the live-region
|
|
8
|
+
semantics:
|
|
9
|
+
|
|
10
|
+
- `Validity.Invalid` -> `role="alert"`, `aria-live="assertive"`.
|
|
11
|
+
- All other severities -> `role="status"`, `aria-live="polite"`.
|
|
12
|
+
|
|
13
|
+
The slide transition animates the pill's height (the `y` axis) so the
|
|
14
|
+
message keeps its final width for the whole animation — animating the
|
|
15
|
+
`x` axis instead reflows the text from stacked-and-wrapped to a single
|
|
16
|
+
line as the pill widens. It honours `prefers-reduced-motion` through
|
|
17
|
+
the shared `usePrefersReducedMotion` helper; when the user has opted in
|
|
18
|
+
the duration collapses to zero. The copy action is only shown when
|
|
19
|
+
`navigator.clipboard` is present (HTTPS or `localhost`).
|
|
20
|
+
-->
|
|
21
|
+
<script
|
|
22
|
+
lang="ts"
|
|
23
|
+
module
|
|
24
|
+
>
|
|
25
|
+
import { ColourSet } from '../../scss/colours.js';
|
|
26
|
+
import { Size } from '../../Types/Internal/Size.js';
|
|
27
|
+
import { Validity } from '../../Types/Internal/Validity.js';
|
|
28
|
+
import { slide } from 'svelte/transition';
|
|
29
|
+
import Action from '../Action.svelte';
|
|
30
|
+
import Icon from '../Icon.svelte';
|
|
31
|
+
import type { ToastProps } from './ToastProps.js';
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<script lang="ts">
|
|
35
|
+
import { usePrefersReducedMotion } from '../../Helpers/prefersReducedMotion.svelte.js';
|
|
36
|
+
|
|
37
|
+
let { toast, copy }: ToastProps = $props();
|
|
38
|
+
|
|
39
|
+
const reducedMotion = usePrefersReducedMotion();
|
|
40
|
+
const slideDuration = $derived(reducedMotion.matches ? 0 : 500);
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<output
|
|
44
|
+
role={toast.result == Validity.Invalid ? 'alert' : 'status'}
|
|
45
|
+
aria-live={toast.result == Validity.Invalid ? 'assertive' : 'polite'}
|
|
46
|
+
class:info={toast.result == Validity.Info}
|
|
47
|
+
class:success={toast.result == Validity.Valid}
|
|
48
|
+
class:warning={toast.result == Validity.Warning}
|
|
49
|
+
class:error={toast.result == Validity.Invalid}
|
|
50
|
+
transition:slide={{ axis: 'y', duration: slideDuration }}
|
|
51
|
+
>
|
|
52
|
+
<div>
|
|
53
|
+
<div class="noshrink">
|
|
54
|
+
{#if toast.copyable != false && navigator.clipboard}
|
|
55
|
+
<Action
|
|
56
|
+
onclick={copy}
|
|
57
|
+
icon={{ name: 'copy' }}
|
|
58
|
+
label="Copy to clipboard"
|
|
59
|
+
size={Size.MediumLarge}
|
|
60
|
+
colourSet={ColourSet.Auxiliary}
|
|
61
|
+
/>
|
|
62
|
+
{:else}
|
|
63
|
+
<Icon
|
|
64
|
+
name="info"
|
|
65
|
+
size={Size.MediumLarge}
|
|
66
|
+
/>
|
|
67
|
+
{/if}
|
|
68
|
+
</div>
|
|
69
|
+
<span>{toast.message}</span>
|
|
70
|
+
{#if toast.closeable}
|
|
71
|
+
<div class="noshrink">
|
|
72
|
+
<Action
|
|
73
|
+
size={Size.MediumLarge}
|
|
74
|
+
icon={{ name: 'cross' }}
|
|
75
|
+
label="Dismiss"
|
|
76
|
+
onclick={() => {
|
|
77
|
+
toast.close?.();
|
|
78
|
+
}}
|
|
79
|
+
colourSet={ColourSet.Auxiliary}
|
|
80
|
+
/>
|
|
81
|
+
</div>
|
|
82
|
+
{/if}
|
|
83
|
+
</div>
|
|
84
|
+
</output>
|
|
85
|
+
|
|
86
86
|
<style>output {
|
|
87
87
|
font-weight: 700;
|
|
88
88
|
font-size: 1.125rem;
|
|
@@ -116,4 +116,4 @@ output span {
|
|
|
116
116
|
overflow-wrap: anywhere;
|
|
117
117
|
min-width: 0;
|
|
118
118
|
flex: 1 1 auto;
|
|
119
|
-
}</style>
|
|
119
|
+
}</style>
|
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<!--
|
|
4
|
-
@component
|
|
5
|
-
Live region for the {@link ToastContext}. Iterates the context's
|
|
6
|
-
queue and renders one `Toast` per message, providing the
|
|
7
|
-
copy-to-clipboard callback (the container owns the clipboard logic
|
|
8
|
-
because the toast itself only knows the message it should copy).
|
|
9
|
-
|
|
10
|
-
The wrapping `<section>` carries `role="region"` plus
|
|
11
|
-
`aria-live="polite"` so multiple toast appearances are announced as
|
|
12
|
-
a single rolling region without interrupting the user; individual
|
|
13
|
-
`Toast` elements override `aria-live` to `assertive` for hard errors.
|
|
14
|
-
|
|
15
|
-
Mounted once at the app root by `ContextWrapper`; consumers should
|
|
16
|
-
not render this directly.
|
|
17
|
-
-->
|
|
18
|
-
<script lang="ts">
|
|
19
|
-
import { ToastContext } from '../../Contexts/ToastContext.svelte.js';
|
|
20
|
-
import { devCatch } from '../../Helpers/Helpers.svelte.js';
|
|
21
|
-
import { Validity } from '../../Types/Internal/Validity.js';
|
|
22
|
-
import { getContext } from 'svelte';
|
|
23
|
-
import Toast from './Toast.svelte';
|
|
24
|
-
|
|
25
|
-
const toastContext = getContext<ToastContext>(ToastContext.identifier);
|
|
26
|
-
|
|
27
|
-
function copyDataToClipboard(text: string): void {
|
|
28
|
-
// `navigator.clipboard` is `undefined` on insecure (HTTP)
|
|
29
|
-
// origins and in some embedded WebViews. The compile-time
|
|
30
|
-
// type says it is always defined, hence the eslint disable;
|
|
31
|
-
// the runtime check is the load-bearing one.
|
|
32
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
33
|
-
if (!navigator.clipboard) {
|
|
34
|
-
toastContext.toast({
|
|
35
|
-
result: Validity.Invalid,
|
|
36
|
-
message: 'Cannot Copy in an Insecure Connection',
|
|
37
|
-
copyable: false,
|
|
38
|
-
});
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
navigator.clipboard.writeText(text).catch(devCatch);
|
|
43
|
-
toastContext.toast({
|
|
44
|
-
result: Validity.Info,
|
|
45
|
-
message: 'Message copied to clipboard',
|
|
46
|
-
copyable: false,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
</script>
|
|
50
|
-
|
|
51
|
-
<section
|
|
52
|
-
aria-live="polite"
|
|
53
|
-
aria-label="Notifications"
|
|
54
|
-
>
|
|
55
|
-
{#each toastContext.toasts as toast (toast.id)}
|
|
56
|
-
<Toast
|
|
57
|
-
{toast}
|
|
58
|
-
copy={() => {
|
|
59
|
-
copyDataToClipboard(toast.getVerbose?.() ?? toast.message);
|
|
60
|
-
}}
|
|
61
|
-
/>
|
|
62
|
-
{/each}
|
|
63
|
-
</section>
|
|
64
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
@component
|
|
5
|
+
Live region for the {@link ToastContext}. Iterates the context's
|
|
6
|
+
queue and renders one `Toast` per message, providing the
|
|
7
|
+
copy-to-clipboard callback (the container owns the clipboard logic
|
|
8
|
+
because the toast itself only knows the message it should copy).
|
|
9
|
+
|
|
10
|
+
The wrapping `<section>` carries `role="region"` plus
|
|
11
|
+
`aria-live="polite"` so multiple toast appearances are announced as
|
|
12
|
+
a single rolling region without interrupting the user; individual
|
|
13
|
+
`Toast` elements override `aria-live` to `assertive` for hard errors.
|
|
14
|
+
|
|
15
|
+
Mounted once at the app root by `ContextWrapper`; consumers should
|
|
16
|
+
not render this directly.
|
|
17
|
+
-->
|
|
18
|
+
<script lang="ts">
|
|
19
|
+
import { ToastContext } from '../../Contexts/ToastContext.svelte.js';
|
|
20
|
+
import { devCatch } from '../../Helpers/Helpers.svelte.js';
|
|
21
|
+
import { Validity } from '../../Types/Internal/Validity.js';
|
|
22
|
+
import { getContext } from 'svelte';
|
|
23
|
+
import Toast from './Toast.svelte';
|
|
24
|
+
|
|
25
|
+
const toastContext = getContext<ToastContext>(ToastContext.identifier);
|
|
26
|
+
|
|
27
|
+
function copyDataToClipboard(text: string): void {
|
|
28
|
+
// `navigator.clipboard` is `undefined` on insecure (HTTP)
|
|
29
|
+
// origins and in some embedded WebViews. The compile-time
|
|
30
|
+
// type says it is always defined, hence the eslint disable;
|
|
31
|
+
// the runtime check is the load-bearing one.
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
33
|
+
if (!navigator.clipboard) {
|
|
34
|
+
toastContext.toast({
|
|
35
|
+
result: Validity.Invalid,
|
|
36
|
+
message: 'Cannot Copy in an Insecure Connection',
|
|
37
|
+
copyable: false,
|
|
38
|
+
});
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
navigator.clipboard.writeText(text).catch(devCatch);
|
|
43
|
+
toastContext.toast({
|
|
44
|
+
result: Validity.Info,
|
|
45
|
+
message: 'Message copied to clipboard',
|
|
46
|
+
copyable: false,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<section
|
|
52
|
+
aria-live="polite"
|
|
53
|
+
aria-label="Notifications"
|
|
54
|
+
>
|
|
55
|
+
{#each toastContext.toasts as toast (toast.id)}
|
|
56
|
+
<Toast
|
|
57
|
+
{toast}
|
|
58
|
+
copy={() => {
|
|
59
|
+
copyDataToClipboard(toast.getVerbose?.() ?? toast.message);
|
|
60
|
+
}}
|
|
61
|
+
/>
|
|
62
|
+
{/each}
|
|
63
|
+
</section>
|
|
64
|
+
|
|
65
65
|
<style>section {
|
|
66
66
|
user-select: none;
|
|
67
67
|
gap: 0.5rem;
|
|
@@ -73,4 +73,4 @@ not render this directly.
|
|
|
73
73
|
justify-content: flex-end;
|
|
74
74
|
align-items: flex-end;
|
|
75
75
|
z-index: 99999;
|
|
76
|
-
}</style>
|
|
76
|
+
}</style>
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<!--
|
|
4
|
-
@component
|
|
5
|
-
Visual host for `TooltipContext`. Renders a fixed-position tooltip at
|
|
6
|
-
the coordinates the context exposes, with a CSS arrow that points
|
|
7
|
-
back toward the anchored element on the configured side.
|
|
8
|
-
|
|
9
|
-
The tooltip just appears and disappears; no transition is applied,
|
|
10
|
-
which is the conservative choice for `prefers-reduced-motion`. Reads
|
|
11
|
-
the context with `getContext` and relies on `ContextWrapper` to have
|
|
12
|
-
set it up at the app root.
|
|
13
|
-
-->
|
|
14
|
-
<script lang="ts">
|
|
15
|
-
import { TooltipContext } from '../../Contexts/TooltipContext.svelte.js';
|
|
16
|
-
import { Side } from '../../Types/Internal/Side.js';
|
|
17
|
-
import { getContext } from 'svelte';
|
|
18
|
-
const tooltipContext = getContext<TooltipContext>(TooltipContext.identifier);
|
|
19
|
-
</script>
|
|
20
|
-
|
|
21
|
-
{#if tooltipContext.isShowingTooltip}
|
|
22
|
-
<div
|
|
23
|
-
role="tooltip"
|
|
24
|
-
style="--y: {tooltipContext.y}px; --x: {tooltipContext.x}px;"
|
|
25
|
-
class="tooltip-wrapper"
|
|
26
|
-
class:top-arrow={tooltipContext.anchor === Side.Top}
|
|
27
|
-
class:bottom-arrow={tooltipContext.anchor === Side.Bottom}
|
|
28
|
-
class:left-arrow={tooltipContext.anchor === Side.Left}
|
|
29
|
-
class:right-arrow={tooltipContext.anchor === Side.Right}
|
|
30
|
-
>
|
|
31
|
-
<div class="tooltip">
|
|
32
|
-
{tooltipContext.text}
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
{/if}
|
|
36
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
@component
|
|
5
|
+
Visual host for `TooltipContext`. Renders a fixed-position tooltip at
|
|
6
|
+
the coordinates the context exposes, with a CSS arrow that points
|
|
7
|
+
back toward the anchored element on the configured side.
|
|
8
|
+
|
|
9
|
+
The tooltip just appears and disappears; no transition is applied,
|
|
10
|
+
which is the conservative choice for `prefers-reduced-motion`. Reads
|
|
11
|
+
the context with `getContext` and relies on `ContextWrapper` to have
|
|
12
|
+
set it up at the app root.
|
|
13
|
+
-->
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import { TooltipContext } from '../../Contexts/TooltipContext.svelte.js';
|
|
16
|
+
import { Side } from '../../Types/Internal/Side.js';
|
|
17
|
+
import { getContext } from 'svelte';
|
|
18
|
+
const tooltipContext = getContext<TooltipContext>(TooltipContext.identifier);
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
{#if tooltipContext.isShowingTooltip}
|
|
22
|
+
<div
|
|
23
|
+
role="tooltip"
|
|
24
|
+
style="--y: {tooltipContext.y}px; --x: {tooltipContext.x}px;"
|
|
25
|
+
class="tooltip-wrapper"
|
|
26
|
+
class:top-arrow={tooltipContext.anchor === Side.Top}
|
|
27
|
+
class:bottom-arrow={tooltipContext.anchor === Side.Bottom}
|
|
28
|
+
class:left-arrow={tooltipContext.anchor === Side.Left}
|
|
29
|
+
class:right-arrow={tooltipContext.anchor === Side.Right}
|
|
30
|
+
>
|
|
31
|
+
<div class="tooltip">
|
|
32
|
+
{tooltipContext.text}
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
{/if}
|
|
36
|
+
|
|
37
37
|
<style>.tooltip-wrapper {
|
|
38
38
|
position: fixed;
|
|
39
39
|
z-index: 99999;
|
|
@@ -121,4 +121,4 @@ set it up at the app root.
|
|
|
121
121
|
transform: rotate(45deg);
|
|
122
122
|
background-color: #3a4952;
|
|
123
123
|
border: solid 2px #dae0e5;
|
|
124
|
-
}</style>
|
|
124
|
+
}</style>
|