@lavalogic/scoria 0.40.32 → 0.40.33
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 +28 -28
- package/dist/Components/AccordionGroupButton.svelte +60 -60
- package/dist/Components/Action.svelte +48 -48
- package/dist/Components/AlertModal.svelte +102 -102
- package/dist/Components/Base/ContextWrapper.svelte +45 -45
- package/dist/Components/Base/Pagination.svelte +135 -135
- package/dist/Components/Base/Snippets.svelte +25 -25
- package/dist/Components/BigRadioSet.svelte +34 -34
- package/dist/Components/Bubble.svelte +38 -38
- package/dist/Components/Button.svelte +83 -83
- package/dist/Components/Checkbox.svelte +71 -71
- package/dist/Components/CollapsibleCard.svelte +59 -59
- package/dist/Components/CollapsibleMenuGroup.svelte +43 -43
- package/dist/Components/ConditionBuilder/ConditionBuilder.svelte +101 -101
- package/dist/Components/Contexts/ContextMenu.svelte +76 -76
- package/dist/Components/Contexts/ContextMenuDivider.svelte +15 -15
- package/dist/Components/Contexts/ContextMenuOption.svelte +38 -38
- package/dist/Components/Contexts/Toast.svelte +71 -71
- package/dist/Components/Contexts/ToastContainer.svelte +34 -34
- package/dist/Components/Contexts/Tooltip.svelte +32 -32
- package/dist/Components/DataMatrixIcon.svelte +37 -37
- package/dist/Components/DateInput.svelte +80 -80
- package/dist/Components/DatePicker.svelte +86 -86
- package/dist/Components/DesktopModal.svelte +65 -65
- package/dist/Components/Dial.svelte +35 -35
- package/dist/Components/DimensionInput.svelte +95 -95
- package/dist/Components/DragMenu/DragMenuHolder.svelte +53 -53
- package/dist/Components/DragMenu/DraggableCard.svelte +49 -49
- package/dist/Components/FileCard.svelte +18 -18
- package/dist/Components/FileUpload.svelte +115 -115
- package/dist/Components/GridInput.svelte +123 -123
- package/dist/Components/GridInputSet.svelte +21 -21
- package/dist/Components/HorizontalTabGroup.svelte +54 -54
- package/dist/Components/HorizontalTabGroupButton.svelte +32 -32
- package/dist/Components/Icon.svelte +68 -68
- package/dist/Components/InfoAlert.svelte +32 -32
- package/dist/Components/LoadingAnimation.svelte +228 -227
- package/dist/Components/LoadingModal.svelte +19 -19
- package/dist/Components/LoadingOverlay.svelte +20 -20
- package/dist/Components/Modal.svelte +127 -127
- package/dist/Components/MultiSelect.svelte +126 -126
- package/dist/Components/Nav/Nav.svelte +71 -71
- package/dist/Components/Nav/NavServiceMenuList.svelte +37 -37
- package/dist/Components/Nav/NavTab.svelte +46 -46
- package/dist/Components/Nav/ServiceMenuItem.svelte +62 -62
- package/dist/Components/Nav/ServicesNav.svelte +50 -50
- package/dist/Components/NumberInput.svelte +98 -98
- package/dist/Components/OptionCards.svelte +58 -58
- package/dist/Components/PageHeading.svelte +21 -21
- package/dist/Components/PasswordInput.svelte +61 -61
- package/dist/Components/PopoverButton.svelte +53 -53
- package/dist/Components/Portal.svelte +7 -7
- package/dist/Components/ProgressBubble.svelte +42 -42
- package/dist/Components/QuerySelect.svelte +102 -102
- package/dist/Components/ResourceCalendar/ResourceCalendar.svelte +241 -241
- package/dist/Components/SidebarPanel.svelte +32 -32
- package/dist/Components/SingleSelect.svelte +122 -122
- package/dist/Components/StepButton.svelte +48 -48
- package/dist/Components/StepForm.svelte +58 -58
- package/dist/Components/Switch.svelte +43 -43
- package/dist/Components/Table/ARCHITECTURE.md +298 -298
- package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +30 -30
- package/dist/Components/Table/Body/Rows/ColumnList.svelte +24 -24
- package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +165 -165
- package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +13 -13
- package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +120 -120
- package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +81 -81
- package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +92 -92
- package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +110 -110
- package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +54 -54
- package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +35 -35
- package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +64 -64
- package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +82 -82
- package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +88 -88
- package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +90 -90
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +96 -96
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +71 -71
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +124 -124
- package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +91 -91
- package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +88 -88
- package/dist/Components/Table/Body/Rows/TableRow.svelte +127 -127
- package/dist/Components/Table/Body/TableBody.svelte +92 -92
- package/dist/Components/Table/Headers/HighlightAllHeader.svelte +25 -25
- package/dist/Components/Table/Headers/SelectAllHeader.svelte +20 -20
- package/dist/Components/Table/Headers/TableHead.svelte +175 -175
- package/dist/Components/Table/Misc/ColumnPanel.svelte +32 -32
- package/dist/Components/Table/Misc/ColumnPanelModal.svelte +29 -29
- package/dist/Components/Table/Misc/FilterInput.svelte +326 -326
- package/dist/Components/Table/Misc/FilterPanel.svelte +79 -79
- package/dist/Components/Table/Misc/FilterPanelModal.svelte +21 -21
- package/dist/Components/Table/Misc/ShareViewModal.svelte +118 -118
- package/dist/Components/Table/Misc/SidePanel.svelte +24 -24
- package/dist/Components/Table/Misc/TableConfigurationModal.svelte +318 -318
- package/dist/Components/Table/Misc/TableFooter.svelte +201 -201
- package/dist/Components/Table/Misc/TableHorizontalBar.svelte +112 -112
- package/dist/Components/Table/Misc/TableSidebar.svelte +116 -116
- package/dist/Components/Table/Misc/TableViewDropdown.svelte +25 -25
- package/dist/Components/Table/Misc/ToolboxPanel.svelte +60 -60
- package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +63 -63
- package/dist/Components/Table/Misc/UpdateViewOptionsModal.svelte +101 -101
- package/dist/Components/Table/NestedTable.svelte +29 -29
- package/dist/Components/Table/Table.svelte +140 -140
- package/dist/Components/Test/TestContextConsumer.svelte +8 -8
- package/dist/Components/TextArea.svelte +92 -90
- package/dist/Components/TextInput.svelte +128 -117
- package/dist/Components/ThreeStateRadio.svelte +101 -101
- package/dist/Components/Touch/BoolCard.svelte +27 -27
- package/dist/Components/Touch/DateModal.svelte +98 -98
- package/dist/Components/Touch/EditCard.svelte +44 -44
- package/dist/Components/Touch/InfoCard.svelte +25 -25
- package/dist/Components/Touch/InfoTextCard.svelte +22 -22
- package/dist/Components/Touch/ModalExplanation.svelte +13 -13
- package/dist/Components/Touch/NumberKeyboard.svelte +81 -81
- package/dist/Components/Touch/NumberModal.svelte +49 -49
- package/dist/Components/Touch/PlusMinusCard.svelte +40 -40
- package/dist/Components/Touch/SelectModal.svelte +86 -86
- package/dist/Components/Touch/SummaryCard.svelte +74 -74
- package/dist/Components/Touch/TextAreaModal.svelte +53 -53
- package/dist/Components/Touch/TextModal.svelte +56 -56
- package/dist/Components/Touch/TouchCard.svelte +28 -28
- package/dist/Components/Touch/TouchModal.svelte +141 -141
- package/dist/Components/Touch/UtilityButton.svelte +63 -63
- package/dist/Components/VerticalTabGroup.svelte +38 -38
- package/dist/Components/VerticalTabGroupButton.svelte +46 -46
- package/dist/Helpers/Datamatrix.d.ts +19 -19
- package/dist/Helpers/Datamatrix.js +291 -291
- package/dist/Types/Examples/ExampleModal.svelte +27 -27
- package/dist/paraglide/README.md +1 -1
- package/dist/scss/_basics.scss +12 -12
- package/dist/scss/_colours.scss +140 -140
- 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,8 +1,8 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<script
|
|
4
|
-
lang="ts"
|
|
5
|
-
generics="F extends string | number, O extends string | number, V"
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<script
|
|
4
|
+
lang="ts"
|
|
5
|
+
generics="F extends string | number, O extends string | number, V"
|
|
6
6
|
>import { m as i18n } from "../../paraglide/messages.js";
|
|
7
7
|
import SingleSelect from "../SingleSelect.svelte";
|
|
8
8
|
import Button from "../Button.svelte";
|
|
@@ -43,101 +43,101 @@ function setValue(leaf, value) {
|
|
|
43
43
|
leaf.value = value;
|
|
44
44
|
onChange(root);
|
|
45
45
|
}
|
|
46
|
-
</script>
|
|
47
|
-
|
|
48
|
-
<div
|
|
49
|
-
class="group"
|
|
50
|
-
class:nested={depth > 0}
|
|
51
|
-
>
|
|
52
|
-
<div class="combinator">
|
|
53
|
-
<Button
|
|
54
|
-
label={andLabel}
|
|
55
|
-
toggled={root.combinator === 'and'}
|
|
56
|
-
onclick={() => setCombinator('and')}>{andLabel}</Button
|
|
57
|
-
>
|
|
58
|
-
<Button
|
|
59
|
-
label={orLabel}
|
|
60
|
-
toggled={root.combinator === 'or'}
|
|
61
|
-
onclick={() => setCombinator('or')}>{orLabel}</Button
|
|
62
|
-
>
|
|
63
|
-
</div>
|
|
64
|
-
|
|
65
|
-
<div class="children">
|
|
66
|
-
{#each root.children as child (child.id)}
|
|
67
|
-
{#if child.kind === 'leaf'}
|
|
68
|
-
<div class="leaf">
|
|
69
|
-
<SingleSelect
|
|
70
|
-
label={i18n['scoria.label.field']()}
|
|
71
|
-
options={[...fields]}
|
|
72
|
-
labelProp="label"
|
|
73
|
-
valueProp="value"
|
|
74
|
-
valueAsObject={false}
|
|
75
|
-
clearable
|
|
76
|
-
value={child.field}
|
|
77
|
-
onchange={(value) => setField(child, value)}
|
|
78
|
-
/>
|
|
79
|
-
<SingleSelect
|
|
80
|
-
label={i18n['scoria.label.operator']()}
|
|
81
|
-
options={[...operatorsFor(child.field)]}
|
|
82
|
-
labelProp="label"
|
|
83
|
-
valueProp="value"
|
|
84
|
-
valueAsObject={false}
|
|
85
|
-
clearable
|
|
86
|
-
value={child.operator}
|
|
87
|
-
onchange={(value) => setOperator(child, value)}
|
|
88
|
-
/>
|
|
89
|
-
<div class="value-editor">
|
|
90
|
-
{@render valueEditor(child, (value) => setValue(child, value))}
|
|
91
|
-
</div>
|
|
92
|
-
<Button
|
|
93
|
-
label={i18n['scoria.action.remove_condition']()}
|
|
94
|
-
iconLeft={{ name: 'circle-cross' }}
|
|
95
|
-
onclick={() => removeChild(child)}
|
|
96
|
-
/>
|
|
97
|
-
</div>
|
|
98
|
-
{:else}
|
|
99
|
-
<div class="subgroup">
|
|
100
|
-
<Self
|
|
101
|
-
root={child}
|
|
102
|
-
{onChange}
|
|
103
|
-
{fields}
|
|
104
|
-
{operatorsFor}
|
|
105
|
-
{valueEditor}
|
|
106
|
-
{defaultValueFor}
|
|
107
|
-
{allowGroups}
|
|
108
|
-
{maxDepth}
|
|
109
|
-
{addConditionLabel}
|
|
110
|
-
{addGroupLabel}
|
|
111
|
-
{andLabel}
|
|
112
|
-
{orLabel}
|
|
113
|
-
depth={depth + 1}
|
|
114
|
-
/>
|
|
115
|
-
<Button
|
|
116
|
-
label={i18n['scoria.action.remove_group']()}
|
|
117
|
-
iconLeft={{ name: 'circle-cross' }}
|
|
118
|
-
onclick={() => removeChild(child)}
|
|
119
|
-
/>
|
|
120
|
-
</div>
|
|
121
|
-
{/if}
|
|
122
|
-
{/each}
|
|
123
|
-
</div>
|
|
124
|
-
|
|
125
|
-
<div class="actions">
|
|
126
|
-
<Button
|
|
127
|
-
label={addConditionLabel}
|
|
128
|
-
iconLeft={{ name: 'circle-plus' }}
|
|
129
|
-
onclick={addLeaf}>{addConditionLabel}</Button
|
|
130
|
-
>
|
|
131
|
-
{#if allowGroups && depth < maxDepth}
|
|
132
|
-
<Button
|
|
133
|
-
label={addGroupLabel}
|
|
134
|
-
iconLeft={{ name: 'circle-plus' }}
|
|
135
|
-
onclick={addGroup}>{addGroupLabel}</Button
|
|
136
|
-
>
|
|
137
|
-
{/if}
|
|
138
|
-
</div>
|
|
139
|
-
</div>
|
|
140
|
-
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<div
|
|
49
|
+
class="group"
|
|
50
|
+
class:nested={depth > 0}
|
|
51
|
+
>
|
|
52
|
+
<div class="combinator">
|
|
53
|
+
<Button
|
|
54
|
+
label={andLabel}
|
|
55
|
+
toggled={root.combinator === 'and'}
|
|
56
|
+
onclick={() => setCombinator('and')}>{andLabel}</Button
|
|
57
|
+
>
|
|
58
|
+
<Button
|
|
59
|
+
label={orLabel}
|
|
60
|
+
toggled={root.combinator === 'or'}
|
|
61
|
+
onclick={() => setCombinator('or')}>{orLabel}</Button
|
|
62
|
+
>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="children">
|
|
66
|
+
{#each root.children as child (child.id)}
|
|
67
|
+
{#if child.kind === 'leaf'}
|
|
68
|
+
<div class="leaf">
|
|
69
|
+
<SingleSelect
|
|
70
|
+
label={i18n['scoria.label.field']()}
|
|
71
|
+
options={[...fields]}
|
|
72
|
+
labelProp="label"
|
|
73
|
+
valueProp="value"
|
|
74
|
+
valueAsObject={false}
|
|
75
|
+
clearable
|
|
76
|
+
value={child.field}
|
|
77
|
+
onchange={(value) => setField(child, value)}
|
|
78
|
+
/>
|
|
79
|
+
<SingleSelect
|
|
80
|
+
label={i18n['scoria.label.operator']()}
|
|
81
|
+
options={[...operatorsFor(child.field)]}
|
|
82
|
+
labelProp="label"
|
|
83
|
+
valueProp="value"
|
|
84
|
+
valueAsObject={false}
|
|
85
|
+
clearable
|
|
86
|
+
value={child.operator}
|
|
87
|
+
onchange={(value) => setOperator(child, value)}
|
|
88
|
+
/>
|
|
89
|
+
<div class="value-editor">
|
|
90
|
+
{@render valueEditor(child, (value) => setValue(child, value))}
|
|
91
|
+
</div>
|
|
92
|
+
<Button
|
|
93
|
+
label={i18n['scoria.action.remove_condition']()}
|
|
94
|
+
iconLeft={{ name: 'circle-cross' }}
|
|
95
|
+
onclick={() => removeChild(child)}
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
{:else}
|
|
99
|
+
<div class="subgroup">
|
|
100
|
+
<Self
|
|
101
|
+
root={child}
|
|
102
|
+
{onChange}
|
|
103
|
+
{fields}
|
|
104
|
+
{operatorsFor}
|
|
105
|
+
{valueEditor}
|
|
106
|
+
{defaultValueFor}
|
|
107
|
+
{allowGroups}
|
|
108
|
+
{maxDepth}
|
|
109
|
+
{addConditionLabel}
|
|
110
|
+
{addGroupLabel}
|
|
111
|
+
{andLabel}
|
|
112
|
+
{orLabel}
|
|
113
|
+
depth={depth + 1}
|
|
114
|
+
/>
|
|
115
|
+
<Button
|
|
116
|
+
label={i18n['scoria.action.remove_group']()}
|
|
117
|
+
iconLeft={{ name: 'circle-cross' }}
|
|
118
|
+
onclick={() => removeChild(child)}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
{/if}
|
|
122
|
+
{/each}
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<div class="actions">
|
|
126
|
+
<Button
|
|
127
|
+
label={addConditionLabel}
|
|
128
|
+
iconLeft={{ name: 'circle-plus' }}
|
|
129
|
+
onclick={addLeaf}>{addConditionLabel}</Button
|
|
130
|
+
>
|
|
131
|
+
{#if allowGroups && depth < maxDepth}
|
|
132
|
+
<Button
|
|
133
|
+
label={addGroupLabel}
|
|
134
|
+
iconLeft={{ name: 'circle-plus' }}
|
|
135
|
+
onclick={addGroup}>{addGroupLabel}</Button
|
|
136
|
+
>
|
|
137
|
+
{/if}
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
141
|
<style>.group {
|
|
142
142
|
display: flex;
|
|
143
143
|
flex-flow: column nowrap;
|
|
@@ -185,4 +185,4 @@ function setValue(leaf, value) {
|
|
|
185
185
|
display: flex;
|
|
186
186
|
flex-flow: row nowrap;
|
|
187
187
|
gap: 0.5rem;
|
|
188
|
-
}</style>
|
|
188
|
+
}</style>
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<!--
|
|
4
|
-
@component
|
|
5
|
-
Visual host for `ContextMenuContext`. Renders the fixed-positioned
|
|
6
|
-
`<ul role="menu">` near the `(x, y)` coordinates the context exposes,
|
|
7
|
-
and clamps the position so the menu never spills off the viewport.
|
|
8
|
-
|
|
9
|
-
Mounted exactly once at the app root by `ContextWrapper`; consumers do
|
|
10
|
-
not render `ContextMenu` directly. Open a menu through the context:
|
|
11
|
-
|
|
12
|
-
```svelte
|
|
13
|
-
<script lang="ts">
|
|
14
|
-
import { ContextMenuContext } from '@lavalogic/scoria';
|
|
15
|
-
import { getContext } from 'svelte';
|
|
16
|
-
|
|
17
|
-
const ctx = getContext<ContextMenuContext>(ContextMenuContext.identifier);
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<button oncontextmenu={(e) => ctx.openContextMenu(e, items)}>
|
|
21
|
-
Right-click me
|
|
22
|
-
</button>
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
### Keyboard
|
|
26
|
-
|
|
27
|
-
`Escape` closes the menu and returns focus to the previously focused
|
|
28
|
-
element; `ArrowUp` / `ArrowDown` cycle focus through the items.
|
|
29
|
-
-->
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
@component
|
|
5
|
+
Visual host for `ContextMenuContext`. Renders the fixed-positioned
|
|
6
|
+
`<ul role="menu">` near the `(x, y)` coordinates the context exposes,
|
|
7
|
+
and clamps the position so the menu never spills off the viewport.
|
|
8
|
+
|
|
9
|
+
Mounted exactly once at the app root by `ContextWrapper`; consumers do
|
|
10
|
+
not render `ContextMenu` directly. Open a menu through the context:
|
|
11
|
+
|
|
12
|
+
```svelte
|
|
13
|
+
<script lang="ts">
|
|
14
|
+
import { ContextMenuContext } from '@lavalogic/scoria';
|
|
15
|
+
import { getContext } from 'svelte';
|
|
16
|
+
|
|
17
|
+
const ctx = getContext<ContextMenuContext>(ContextMenuContext.identifier);
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<button oncontextmenu={(e) => ctx.openContextMenu(e, items)}>
|
|
21
|
+
Right-click me
|
|
22
|
+
</button>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Keyboard
|
|
26
|
+
|
|
27
|
+
`Escape` closes the menu and returns focus to the previously focused
|
|
28
|
+
element; `ArrowUp` / `ArrowDown` cycle focus through the items.
|
|
29
|
+
-->
|
|
30
30
|
<script lang="ts">import { m as i18n } from "../../paraglide/messages.js";
|
|
31
31
|
import { ContextMenuContext } from "../../Contexts/ContextMenuContext.svelte.js";
|
|
32
32
|
import { devCatch } from "../../Helpers/Helpers.svelte.js";
|
|
@@ -101,52 +101,52 @@ function focusPrev() {
|
|
|
101
101
|
const index = items.indexOf(document.activeElement);
|
|
102
102
|
items.at((index - 1 + items.length) % items.length)?.focus();
|
|
103
103
|
}
|
|
104
|
-
</script>
|
|
105
|
-
|
|
106
|
-
<svelte:body onclick={closeOnClickOutside} />
|
|
107
|
-
|
|
108
|
-
{#if contextMenuContext.showMenu}
|
|
109
|
-
<ul
|
|
110
|
-
transition:fade={{ duration: fadeDuration }}
|
|
111
|
-
bind:this={menuEl}
|
|
112
|
-
style="top: {_y}px; left: {_x}px;"
|
|
113
|
-
role="menu"
|
|
114
|
-
aria-label={i18n['scoria.label.context_menu']()}
|
|
115
|
-
tabindex="-1"
|
|
116
|
-
onkeydown={(e) => {
|
|
117
|
-
if (e.key === 'Escape') {
|
|
118
|
-
e.stopImmediatePropagation();
|
|
119
|
-
e.stopPropagation();
|
|
120
|
-
e.preventDefault();
|
|
121
|
-
contextMenuContext.closeMenu();
|
|
122
|
-
refocusPrevious();
|
|
123
|
-
} else if (e.key == 'ArrowUp') {
|
|
124
|
-
e.stopImmediatePropagation();
|
|
125
|
-
e.stopPropagation();
|
|
126
|
-
e.preventDefault();
|
|
127
|
-
focusPrev();
|
|
128
|
-
} else if (e.key == 'ArrowDown') {
|
|
129
|
-
e.stopImmediatePropagation();
|
|
130
|
-
e.stopPropagation();
|
|
131
|
-
e.preventDefault();
|
|
132
|
-
focusNext();
|
|
133
|
-
}
|
|
134
|
-
}}
|
|
135
|
-
>
|
|
136
|
-
{#each contextMenuContext.items as item, index (item)}
|
|
137
|
-
<ContextMenuOption
|
|
138
|
-
{index}
|
|
139
|
-
disabled={item.disabled}
|
|
140
|
-
onclick={() => {
|
|
141
|
-
void item.callback();
|
|
142
|
-
contextMenuContext.closeMenu();
|
|
143
|
-
}}
|
|
144
|
-
text={item.text}
|
|
145
|
-
/>
|
|
146
|
-
{/each}
|
|
147
|
-
</ul>
|
|
148
|
-
{/if}
|
|
149
|
-
|
|
104
|
+
</script>
|
|
105
|
+
|
|
106
|
+
<svelte:body onclick={closeOnClickOutside} />
|
|
107
|
+
|
|
108
|
+
{#if contextMenuContext.showMenu}
|
|
109
|
+
<ul
|
|
110
|
+
transition:fade={{ duration: fadeDuration }}
|
|
111
|
+
bind:this={menuEl}
|
|
112
|
+
style="top: {_y}px; left: {_x}px;"
|
|
113
|
+
role="menu"
|
|
114
|
+
aria-label={i18n['scoria.label.context_menu']()}
|
|
115
|
+
tabindex="-1"
|
|
116
|
+
onkeydown={(e) => {
|
|
117
|
+
if (e.key === 'Escape') {
|
|
118
|
+
e.stopImmediatePropagation();
|
|
119
|
+
e.stopPropagation();
|
|
120
|
+
e.preventDefault();
|
|
121
|
+
contextMenuContext.closeMenu();
|
|
122
|
+
refocusPrevious();
|
|
123
|
+
} else if (e.key == 'ArrowUp') {
|
|
124
|
+
e.stopImmediatePropagation();
|
|
125
|
+
e.stopPropagation();
|
|
126
|
+
e.preventDefault();
|
|
127
|
+
focusPrev();
|
|
128
|
+
} else if (e.key == 'ArrowDown') {
|
|
129
|
+
e.stopImmediatePropagation();
|
|
130
|
+
e.stopPropagation();
|
|
131
|
+
e.preventDefault();
|
|
132
|
+
focusNext();
|
|
133
|
+
}
|
|
134
|
+
}}
|
|
135
|
+
>
|
|
136
|
+
{#each contextMenuContext.items as item, index (item)}
|
|
137
|
+
<ContextMenuOption
|
|
138
|
+
{index}
|
|
139
|
+
disabled={item.disabled}
|
|
140
|
+
onclick={() => {
|
|
141
|
+
void item.callback();
|
|
142
|
+
contextMenuContext.closeMenu();
|
|
143
|
+
}}
|
|
144
|
+
text={item.text}
|
|
145
|
+
/>
|
|
146
|
+
{/each}
|
|
147
|
+
</ul>
|
|
148
|
+
{/if}
|
|
149
|
+
|
|
150
150
|
<style>ul {
|
|
151
151
|
padding: 0.375rem;
|
|
152
152
|
position: fixed;
|
|
@@ -161,4 +161,4 @@ function focusPrev() {
|
|
|
161
161
|
|
|
162
162
|
ul:focus {
|
|
163
163
|
outline: none;
|
|
164
|
-
}</style>
|
|
164
|
+
}</style>
|
|
@@ -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,17 +1,17 @@
|
|
|
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
|
-
-->
|
|
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
15
|
<script lang="ts">import { devCatch } from "../../Helpers/Helpers.svelte.js";
|
|
16
16
|
import { tick } from "svelte";
|
|
17
17
|
let { text = "", index, disabled = false, onclick, children } = $props();
|
|
@@ -27,29 +27,29 @@ $effect(() => {
|
|
|
27
27
|
}).catch(devCatch);
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
|
-
</script>
|
|
31
|
-
|
|
32
|
-
<button
|
|
33
|
-
class="context-menu-item"
|
|
34
|
-
role="menuitem"
|
|
35
|
-
class:disabled
|
|
36
|
-
tabindex={index === 0 ? 0 : -1}
|
|
37
|
-
aria-disabled={disabled ? 'true' : undefined}
|
|
38
|
-
bind:this={element}
|
|
39
|
-
onclick={(e) => {
|
|
40
|
-
e.stopImmediatePropagation();
|
|
41
|
-
e.stopPropagation();
|
|
42
|
-
e.preventDefault();
|
|
43
|
-
void onclick?.(e);
|
|
44
|
-
}}
|
|
45
|
-
>
|
|
46
|
-
{#if text}
|
|
47
|
-
{text}
|
|
48
|
-
{:else if children}
|
|
49
|
-
{@render children()}
|
|
50
|
-
{/if}
|
|
51
|
-
</button>
|
|
52
|
-
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<button
|
|
33
|
+
class="context-menu-item"
|
|
34
|
+
role="menuitem"
|
|
35
|
+
class:disabled
|
|
36
|
+
tabindex={index === 0 ? 0 : -1}
|
|
37
|
+
aria-disabled={disabled ? 'true' : undefined}
|
|
38
|
+
bind:this={element}
|
|
39
|
+
onclick={(e) => {
|
|
40
|
+
e.stopImmediatePropagation();
|
|
41
|
+
e.stopPropagation();
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
void onclick?.(e);
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
{#if text}
|
|
47
|
+
{text}
|
|
48
|
+
{:else if children}
|
|
49
|
+
{@render children()}
|
|
50
|
+
{/if}
|
|
51
|
+
</button>
|
|
52
|
+
|
|
53
53
|
<style>button {
|
|
54
54
|
background-color: #ffffff;
|
|
55
55
|
border: none;
|
|
@@ -78,4 +78,4 @@ button.disabled {
|
|
|
78
78
|
|
|
79
79
|
button.disabled:hover {
|
|
80
80
|
background: #ffffff;
|
|
81
|
-
}</style>
|
|
81
|
+
}</style>
|
|
@@ -1,26 +1,26 @@
|
|
|
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
|
|
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
24
|
>import { m as i18n } from "../../paraglide/messages.js";
|
|
25
25
|
import { ColourSet } from "../../scss/colours.js";
|
|
26
26
|
import { Size } from "../../Types/Internal/Size.js";
|
|
@@ -28,57 +28,57 @@ import { Validity } from "../../Types/Internal/Validity.js";
|
|
|
28
28
|
import { slide } from "svelte/transition";
|
|
29
29
|
import Action from "../Action.svelte";
|
|
30
30
|
import Icon from "../Icon.svelte";
|
|
31
|
-
</script>
|
|
32
|
-
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
33
|
<script lang="ts">import { usePrefersReducedMotion } from "../../Helpers/prefersReducedMotion.svelte.js";
|
|
34
34
|
let { toast, copy } = $props();
|
|
35
35
|
const reducedMotion = usePrefersReducedMotion();
|
|
36
36
|
const slideDuration = $derived(reducedMotion.matches ? 0 : 500);
|
|
37
|
-
</script>
|
|
38
|
-
|
|
39
|
-
<output
|
|
40
|
-
role={toast.result == Validity.Invalid ? 'alert' : 'status'}
|
|
41
|
-
aria-live={toast.result == Validity.Invalid ? 'assertive' : 'polite'}
|
|
42
|
-
class:info={toast.result == Validity.Info}
|
|
43
|
-
class:success={toast.result == Validity.Valid}
|
|
44
|
-
class:warning={toast.result == Validity.Warning}
|
|
45
|
-
class:error={toast.result == Validity.Invalid}
|
|
46
|
-
transition:slide={{ axis: 'y', duration: slideDuration }}
|
|
47
|
-
>
|
|
48
|
-
<div>
|
|
49
|
-
<div class="noshrink">
|
|
50
|
-
{#if toast.copyable != false && navigator.clipboard}
|
|
51
|
-
<Action
|
|
52
|
-
onclick={copy}
|
|
53
|
-
icon={{ name: 'copy' }}
|
|
54
|
-
label={i18n['scoria.action.copy_to_clipboard']()}
|
|
55
|
-
size={Size.MediumLarge}
|
|
56
|
-
colourSet={ColourSet.Auxiliary}
|
|
57
|
-
/>
|
|
58
|
-
{:else}
|
|
59
|
-
<Icon
|
|
60
|
-
name="info"
|
|
61
|
-
size={Size.MediumLarge}
|
|
62
|
-
/>
|
|
63
|
-
{/if}
|
|
64
|
-
</div>
|
|
65
|
-
<span>{toast.message}</span>
|
|
66
|
-
{#if toast.closeable}
|
|
67
|
-
<div class="noshrink">
|
|
68
|
-
<Action
|
|
69
|
-
size={Size.MediumLarge}
|
|
70
|
-
icon={{ name: 'cross' }}
|
|
71
|
-
label={i18n['scoria.action.dismiss']()}
|
|
72
|
-
onclick={() => {
|
|
73
|
-
toast.close?.();
|
|
74
|
-
}}
|
|
75
|
-
colourSet={ColourSet.Auxiliary}
|
|
76
|
-
/>
|
|
77
|
-
</div>
|
|
78
|
-
{/if}
|
|
79
|
-
</div>
|
|
80
|
-
</output>
|
|
81
|
-
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<output
|
|
40
|
+
role={toast.result == Validity.Invalid ? 'alert' : 'status'}
|
|
41
|
+
aria-live={toast.result == Validity.Invalid ? 'assertive' : 'polite'}
|
|
42
|
+
class:info={toast.result == Validity.Info}
|
|
43
|
+
class:success={toast.result == Validity.Valid}
|
|
44
|
+
class:warning={toast.result == Validity.Warning}
|
|
45
|
+
class:error={toast.result == Validity.Invalid}
|
|
46
|
+
transition:slide={{ axis: 'y', duration: slideDuration }}
|
|
47
|
+
>
|
|
48
|
+
<div>
|
|
49
|
+
<div class="noshrink">
|
|
50
|
+
{#if toast.copyable != false && navigator.clipboard}
|
|
51
|
+
<Action
|
|
52
|
+
onclick={copy}
|
|
53
|
+
icon={{ name: 'copy' }}
|
|
54
|
+
label={i18n['scoria.action.copy_to_clipboard']()}
|
|
55
|
+
size={Size.MediumLarge}
|
|
56
|
+
colourSet={ColourSet.Auxiliary}
|
|
57
|
+
/>
|
|
58
|
+
{:else}
|
|
59
|
+
<Icon
|
|
60
|
+
name="info"
|
|
61
|
+
size={Size.MediumLarge}
|
|
62
|
+
/>
|
|
63
|
+
{/if}
|
|
64
|
+
</div>
|
|
65
|
+
<span>{toast.message}</span>
|
|
66
|
+
{#if toast.closeable}
|
|
67
|
+
<div class="noshrink">
|
|
68
|
+
<Action
|
|
69
|
+
size={Size.MediumLarge}
|
|
70
|
+
icon={{ name: 'cross' }}
|
|
71
|
+
label={i18n['scoria.action.dismiss']()}
|
|
72
|
+
onclick={() => {
|
|
73
|
+
toast.close?.();
|
|
74
|
+
}}
|
|
75
|
+
colourSet={ColourSet.Auxiliary}
|
|
76
|
+
/>
|
|
77
|
+
</div>
|
|
78
|
+
{/if}
|
|
79
|
+
</div>
|
|
80
|
+
</output>
|
|
81
|
+
|
|
82
82
|
<style>output {
|
|
83
83
|
font-weight: 700;
|
|
84
84
|
font-size: 1.125rem;
|
|
@@ -112,4 +112,4 @@ output span {
|
|
|
112
112
|
overflow-wrap: anywhere;
|
|
113
113
|
min-width: 0;
|
|
114
114
|
flex: 1 1 auto;
|
|
115
|
-
}</style>
|
|
115
|
+
}</style>
|