@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.
Files changed (135) hide show
  1. package/README.md +58 -58
  2. package/dist/Components/AccordionGroup.svelte +28 -28
  3. package/dist/Components/AccordionGroupButton.svelte +60 -60
  4. package/dist/Components/Action.svelte +48 -48
  5. package/dist/Components/AlertModal.svelte +102 -102
  6. package/dist/Components/Base/ContextWrapper.svelte +45 -45
  7. package/dist/Components/Base/Pagination.svelte +135 -135
  8. package/dist/Components/Base/Snippets.svelte +25 -25
  9. package/dist/Components/BigRadioSet.svelte +34 -34
  10. package/dist/Components/Bubble.svelte +38 -38
  11. package/dist/Components/Button.svelte +83 -83
  12. package/dist/Components/Checkbox.svelte +71 -71
  13. package/dist/Components/CollapsibleCard.svelte +59 -59
  14. package/dist/Components/CollapsibleMenuGroup.svelte +43 -43
  15. package/dist/Components/ConditionBuilder/ConditionBuilder.svelte +101 -101
  16. package/dist/Components/Contexts/ContextMenu.svelte +76 -76
  17. package/dist/Components/Contexts/ContextMenuDivider.svelte +15 -15
  18. package/dist/Components/Contexts/ContextMenuOption.svelte +38 -38
  19. package/dist/Components/Contexts/Toast.svelte +71 -71
  20. package/dist/Components/Contexts/ToastContainer.svelte +34 -34
  21. package/dist/Components/Contexts/Tooltip.svelte +32 -32
  22. package/dist/Components/DataMatrixIcon.svelte +37 -37
  23. package/dist/Components/DateInput.svelte +80 -80
  24. package/dist/Components/DatePicker.svelte +86 -86
  25. package/dist/Components/DesktopModal.svelte +65 -65
  26. package/dist/Components/Dial.svelte +35 -35
  27. package/dist/Components/DimensionInput.svelte +95 -95
  28. package/dist/Components/DragMenu/DragMenuHolder.svelte +53 -53
  29. package/dist/Components/DragMenu/DraggableCard.svelte +49 -49
  30. package/dist/Components/FileCard.svelte +18 -18
  31. package/dist/Components/FileUpload.svelte +115 -115
  32. package/dist/Components/GridInput.svelte +123 -123
  33. package/dist/Components/GridInputSet.svelte +21 -21
  34. package/dist/Components/HorizontalTabGroup.svelte +54 -54
  35. package/dist/Components/HorizontalTabGroupButton.svelte +32 -32
  36. package/dist/Components/Icon.svelte +68 -68
  37. package/dist/Components/InfoAlert.svelte +32 -32
  38. package/dist/Components/LoadingAnimation.svelte +228 -227
  39. package/dist/Components/LoadingModal.svelte +19 -19
  40. package/dist/Components/LoadingOverlay.svelte +20 -20
  41. package/dist/Components/Modal.svelte +127 -127
  42. package/dist/Components/MultiSelect.svelte +126 -126
  43. package/dist/Components/Nav/Nav.svelte +71 -71
  44. package/dist/Components/Nav/NavServiceMenuList.svelte +37 -37
  45. package/dist/Components/Nav/NavTab.svelte +46 -46
  46. package/dist/Components/Nav/ServiceMenuItem.svelte +62 -62
  47. package/dist/Components/Nav/ServicesNav.svelte +50 -50
  48. package/dist/Components/NumberInput.svelte +98 -98
  49. package/dist/Components/OptionCards.svelte +58 -58
  50. package/dist/Components/PageHeading.svelte +21 -21
  51. package/dist/Components/PasswordInput.svelte +61 -61
  52. package/dist/Components/PopoverButton.svelte +53 -53
  53. package/dist/Components/Portal.svelte +7 -7
  54. package/dist/Components/ProgressBubble.svelte +42 -42
  55. package/dist/Components/QuerySelect.svelte +102 -102
  56. package/dist/Components/ResourceCalendar/ResourceCalendar.svelte +241 -241
  57. package/dist/Components/SidebarPanel.svelte +32 -32
  58. package/dist/Components/SingleSelect.svelte +122 -122
  59. package/dist/Components/StepButton.svelte +48 -48
  60. package/dist/Components/StepForm.svelte +58 -58
  61. package/dist/Components/Switch.svelte +43 -43
  62. package/dist/Components/Table/ARCHITECTURE.md +298 -298
  63. package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +30 -30
  64. package/dist/Components/Table/Body/Rows/ColumnList.svelte +24 -24
  65. package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +165 -165
  66. package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +13 -13
  67. package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +120 -120
  68. package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +81 -81
  69. package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +92 -92
  70. package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +110 -110
  71. package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +54 -54
  72. package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +35 -35
  73. package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +64 -64
  74. package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +82 -82
  75. package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +88 -88
  76. package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +90 -90
  77. package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +96 -96
  78. package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +71 -71
  79. package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +124 -124
  80. package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +91 -91
  81. package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +88 -88
  82. package/dist/Components/Table/Body/Rows/TableRow.svelte +127 -127
  83. package/dist/Components/Table/Body/TableBody.svelte +92 -92
  84. package/dist/Components/Table/Headers/HighlightAllHeader.svelte +25 -25
  85. package/dist/Components/Table/Headers/SelectAllHeader.svelte +20 -20
  86. package/dist/Components/Table/Headers/TableHead.svelte +175 -175
  87. package/dist/Components/Table/Misc/ColumnPanel.svelte +32 -32
  88. package/dist/Components/Table/Misc/ColumnPanelModal.svelte +29 -29
  89. package/dist/Components/Table/Misc/FilterInput.svelte +326 -326
  90. package/dist/Components/Table/Misc/FilterPanel.svelte +79 -79
  91. package/dist/Components/Table/Misc/FilterPanelModal.svelte +21 -21
  92. package/dist/Components/Table/Misc/ShareViewModal.svelte +118 -118
  93. package/dist/Components/Table/Misc/SidePanel.svelte +24 -24
  94. package/dist/Components/Table/Misc/TableConfigurationModal.svelte +318 -318
  95. package/dist/Components/Table/Misc/TableFooter.svelte +201 -201
  96. package/dist/Components/Table/Misc/TableHorizontalBar.svelte +112 -112
  97. package/dist/Components/Table/Misc/TableSidebar.svelte +116 -116
  98. package/dist/Components/Table/Misc/TableViewDropdown.svelte +25 -25
  99. package/dist/Components/Table/Misc/ToolboxPanel.svelte +60 -60
  100. package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +63 -63
  101. package/dist/Components/Table/Misc/UpdateViewOptionsModal.svelte +101 -101
  102. package/dist/Components/Table/NestedTable.svelte +29 -29
  103. package/dist/Components/Table/Table.svelte +140 -140
  104. package/dist/Components/Test/TestContextConsumer.svelte +8 -8
  105. package/dist/Components/TextArea.svelte +92 -90
  106. package/dist/Components/TextInput.svelte +128 -117
  107. package/dist/Components/ThreeStateRadio.svelte +101 -101
  108. package/dist/Components/Touch/BoolCard.svelte +27 -27
  109. package/dist/Components/Touch/DateModal.svelte +98 -98
  110. package/dist/Components/Touch/EditCard.svelte +44 -44
  111. package/dist/Components/Touch/InfoCard.svelte +25 -25
  112. package/dist/Components/Touch/InfoTextCard.svelte +22 -22
  113. package/dist/Components/Touch/ModalExplanation.svelte +13 -13
  114. package/dist/Components/Touch/NumberKeyboard.svelte +81 -81
  115. package/dist/Components/Touch/NumberModal.svelte +49 -49
  116. package/dist/Components/Touch/PlusMinusCard.svelte +40 -40
  117. package/dist/Components/Touch/SelectModal.svelte +86 -86
  118. package/dist/Components/Touch/SummaryCard.svelte +74 -74
  119. package/dist/Components/Touch/TextAreaModal.svelte +53 -53
  120. package/dist/Components/Touch/TextModal.svelte +56 -56
  121. package/dist/Components/Touch/TouchCard.svelte +28 -28
  122. package/dist/Components/Touch/TouchModal.svelte +141 -141
  123. package/dist/Components/Touch/UtilityButton.svelte +63 -63
  124. package/dist/Components/VerticalTabGroup.svelte +38 -38
  125. package/dist/Components/VerticalTabGroupButton.svelte +46 -46
  126. package/dist/Helpers/Datamatrix.d.ts +19 -19
  127. package/dist/Helpers/Datamatrix.js +291 -291
  128. package/dist/Types/Examples/ExampleModal.svelte +27 -27
  129. package/dist/paraglide/README.md +1 -1
  130. package/dist/scss/_basics.scss +12 -12
  131. package/dist/scss/_colours.scss +140 -140
  132. package/dist/scss/_motion.scss +57 -57
  133. package/dist/scss/_sizing.scss +85 -85
  134. package/dist/scss/_transitions.scss +8 -8
  135. 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>