@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="T extends object, IdType extends Primitive"
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ lang="ts"
5
+ generics="T extends object, IdType extends Primitive"
6
6
  >import Action from "../../Action.svelte";
7
7
  import TextInput from "../../TextInput.svelte";
8
8
  import { Colour, ColourSet } from "../../../scss/colours.js";
@@ -102,79 +102,79 @@ function toggleGroup(name) {
102
102
  function noopKeydown(_e) {
103
103
  // intentionally empty
104
104
  }
105
- </script>
106
-
107
- <section class="side-panel-section">
108
- <header class="side-panel-header">
109
- <h2>{i18n['scoria.action.advanced_filter']()}</h2>
110
- </header>
111
-
112
- <div class="toolbar">
113
- <!-- Quick-switch dropdown for saved filter sets. Sits above the
114
- search box; saving a filter is done from the Table
115
- Configuration modal's "Save a new Filter" tab. -->
116
- <TableViewDropdown kind="filter" />
117
- <div class="quick-find">
118
- <TextInput
119
- labelTop={i18n['scoria.label.quick_find_filter']()}
120
- placeholder={i18n['scoria.label.filter_placeholder']()}
121
- bind:value={quickFindValue}
122
- rightIcon={{ name: 'search', size: Size.Medium }}
123
- onkeydown={noopKeydown}
124
- />
125
- </div>
126
- </div>
127
-
128
- <div class="side-panel-body">
129
- {#if filterableDefs.length === 0}
130
- <p class="empty">{i18n['scoria.text.no_filterable_columns']()}</p>
131
- {:else if matchingDefs.length === 0}
132
- <p class="empty">
133
- {i18n['scoria.text.no_filters_match']({ query: quickFindValue })}
134
- </p>
135
- {:else}
136
- <div class="groups">
137
- {#each orderedGroupNames as groupName (groupName)}
138
- {@const defsInGroup = groupedDefs.get(groupName) ?? []}
139
- {@const isCollapsed = collapsedGroups.has(groupName)}
140
- {#if defsInGroup.length > 0}
141
- <section
142
- class="group"
143
- class:collapsed={isCollapsed}
144
- >
145
- <header class="group-header">
146
- <h3>{groupName}</h3>
147
- <Action
148
- label={isCollapsed ? `Expand ${groupName}` : `Collapse ${groupName}`}
149
- colourSet={ColourSet.Auxiliary}
150
- icon={{
151
- name: isCollapsed ? 'circle-plus' : 'circle-minus',
152
- size: Size.Medium,
153
- colour: Colour['$ui-blue-9'],
154
- }}
155
- onclick={() => {
156
- toggleGroup(groupName);
157
- }}
158
- />
159
- </header>
160
- {#if !isCollapsed}
161
- <div class="group-body">
162
- {#each defsInGroup as def (def.id)}
163
- <FilterInput
164
- {def}
165
- customFilters={tableContext.remoteFilters}
166
- />
167
- {/each}
168
- </div>
169
- {/if}
170
- </section>
171
- {/if}
172
- {/each}
173
- </div>
174
- {/if}
175
- </div>
176
- </section>
177
-
105
+ </script>
106
+
107
+ <section class="side-panel-section">
108
+ <header class="side-panel-header">
109
+ <h2>{i18n['scoria.action.advanced_filter']()}</h2>
110
+ </header>
111
+
112
+ <div class="toolbar">
113
+ <!-- Quick-switch dropdown for saved filter sets. Sits above the
114
+ search box; saving a filter is done from the Table
115
+ Configuration modal's "Save a new Filter" tab. -->
116
+ <TableViewDropdown kind="filter" />
117
+ <div class="quick-find">
118
+ <TextInput
119
+ labelTop={i18n['scoria.label.quick_find_filter']()}
120
+ placeholder={i18n['scoria.label.filter_placeholder']()}
121
+ bind:value={quickFindValue}
122
+ rightIcon={{ name: 'search', size: Size.Medium }}
123
+ onkeydown={noopKeydown}
124
+ />
125
+ </div>
126
+ </div>
127
+
128
+ <div class="side-panel-body">
129
+ {#if filterableDefs.length === 0}
130
+ <p class="empty">{i18n['scoria.text.no_filterable_columns']()}</p>
131
+ {:else if matchingDefs.length === 0}
132
+ <p class="empty">
133
+ {i18n['scoria.text.no_filters_match']({ query: quickFindValue })}
134
+ </p>
135
+ {:else}
136
+ <div class="groups">
137
+ {#each orderedGroupNames as groupName (groupName)}
138
+ {@const defsInGroup = groupedDefs.get(groupName) ?? []}
139
+ {@const isCollapsed = collapsedGroups.has(groupName)}
140
+ {#if defsInGroup.length > 0}
141
+ <section
142
+ class="group"
143
+ class:collapsed={isCollapsed}
144
+ >
145
+ <header class="group-header">
146
+ <h3>{groupName}</h3>
147
+ <Action
148
+ label={isCollapsed ? `Expand ${groupName}` : `Collapse ${groupName}`}
149
+ colourSet={ColourSet.Auxiliary}
150
+ icon={{
151
+ name: isCollapsed ? 'circle-plus' : 'circle-minus',
152
+ size: Size.Medium,
153
+ colour: Colour['$ui-blue-9'],
154
+ }}
155
+ onclick={() => {
156
+ toggleGroup(groupName);
157
+ }}
158
+ />
159
+ </header>
160
+ {#if !isCollapsed}
161
+ <div class="group-body">
162
+ {#each defsInGroup as def (def.id)}
163
+ <FilterInput
164
+ {def}
165
+ customFilters={tableContext.remoteFilters}
166
+ />
167
+ {/each}
168
+ </div>
169
+ {/if}
170
+ </section>
171
+ {/if}
172
+ {/each}
173
+ </div>
174
+ {/if}
175
+ </div>
176
+ </section>
177
+
178
178
  <style>.side-panel-section {
179
179
  display: flex;
180
180
  flex-flow: column nowrap;
@@ -313,4 +313,4 @@ p.empty {
313
313
  display: flex;
314
314
  flex-flow: column nowrap;
315
315
  gap: 0.5rem;
316
- }</style>
316
+ }</style>
@@ -1,28 +1,28 @@
1
- <svelte:options runes />
2
-
3
- <script
4
- lang="ts"
5
- module
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ lang="ts"
5
+ module
6
6
  >import DesktopModal from "../../DesktopModal.svelte";
7
7
  import { cssLength } from "../../../Helpers/Helpers.svelte.js";
8
8
  import { m as i18n } from "../../../paraglide/messages.js";
9
9
  import FilterPanel from "./FilterPanel.svelte";
10
- </script>
11
-
10
+ </script>
11
+
12
12
  <script lang="ts">const { onclose } = $props();
13
- </script>
14
-
15
- <DesktopModal
16
- width={cssLength('800px')}
17
- headerLabel={i18n['scoria.label.filter_by']()}
18
- onclose={() => onclose?.()}
19
- buttons={[{ label: i18n['scoria.action.close'](), callback: () => onclose?.() }]}
20
- >
21
- <div class="flex">
22
- <FilterPanel />
23
- </div>
24
- </DesktopModal>
25
-
13
+ </script>
14
+
15
+ <DesktopModal
16
+ width={cssLength('800px')}
17
+ headerLabel={i18n['scoria.label.filter_by']()}
18
+ onclose={() => onclose?.()}
19
+ buttons={[{ label: i18n['scoria.action.close'](), callback: () => onclose?.() }]}
20
+ >
21
+ <div class="flex">
22
+ <FilterPanel />
23
+ </div>
24
+ </DesktopModal>
25
+
26
26
  <style>.flex {
27
27
  display: flex;
28
28
  flex-flow: column nowrap;
@@ -30,4 +30,4 @@ import FilterPanel from "./FilterPanel.svelte";
30
30
  width: 100%;
31
31
  flex: 1;
32
32
  overflow: hidden;
33
- }</style>
33
+ }</style>
@@ -1,8 +1,8 @@
1
- <svelte:options runes />
2
-
3
- <script
4
- lang="ts"
5
- generics="T extends object, IdType extends Primitive"
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ lang="ts"
5
+ generics="T extends object, IdType extends Primitive"
6
6
  >import Button from "../../Button.svelte";
7
7
  import DesktopModal from "../../DesktopModal.svelte";
8
8
  import Icon from "../../Icon.svelte";
@@ -157,118 +157,118 @@ async function save() {
157
157
  saving = false;
158
158
  }
159
159
  }
160
- </script>
161
-
162
- <DesktopModal
163
- headerLabel={i18n['scoria.label.share_header']({ name: view.name })}
164
- headerSubtitle={view.kind === 'filter'
165
- ? i18n['scoria.text.share_filter_subtitle']()
166
- : i18n['scoria.text.share_layout_subtitle']()}
167
- onclose={() => {
168
- if (!saving) {
169
- onclose();
170
- }
171
- }}
172
- width={cssLength('40vw')}
173
- minWidth={cssLength('32rem')}
174
- buttons={[
175
- {
176
- label: i18n['scoria.action.cancel'](),
177
- callback: () => {
178
- if (!saving) {
179
- onclose();
180
- }
181
- },
182
- disabled: saving,
183
- },
184
- {
185
- label: saving ? i18n['scoria.action.saving']() : i18n['scoria.action.save'](),
186
- callback: () => {
187
- void save();
188
- },
189
- colourSet: ColourSet.Primary,
190
- disabled: saving || !dirty || allUsers === null,
191
- },
192
- ]}
193
- >
194
- <div class="share-body">
195
- {#if errorMessage}
196
- <div
197
- class="error-banner"
198
- role="alert"
199
- >
200
- <Icon
201
- name="circle-exclamation"
202
- size={Size.Small}
203
- />
204
- <span>{errorMessage}</span>
205
- </div>
206
- {/if}
207
-
208
- <div class="picker">
209
- {#if loadingUsers && allUsers === null}
210
- <InfoAlert>{i18n['scoria.message.loading_users']()}</InfoAlert>
211
- {:else if allUsers !== null}
212
- <MultiSelect
213
- label={i18n['scoria.label.users']()}
214
- name="User"
215
- placeholder={i18n['scoria.label.select_user']()}
216
- options={allUsers as Array<DatatableViewUser>}
217
- labelProp="displayName"
218
- valueProp="id"
219
- valueAsObject={true}
220
- selectedValues={selected}
221
- onchange={(values) => {
222
- selected = values;
223
- }}
224
- />
225
- {/if}
226
- </div>
227
-
228
- {#if selected.length === 0}
229
- <InfoAlert>
230
- {view.kind === 'filter'
231
- ? i18n['scoria.text.no_users_filter']()
232
- : i18n['scoria.text.no_users_layout']()}
233
- </InfoAlert>
234
- {:else}
235
- <ul class="user-card-list">
236
- {#each selected as user (user.id)}
237
- <li class="user-card">
238
- <div class="user-info">
239
- <Icon
240
- name="user-3"
241
- size={Size.Medium}
242
- />
243
- <span class="user-name">{user.displayName}</span>
244
- </div>
245
- <div class="user-meta">
246
- <!--
247
- v1 sharing exposes a single role - subscriber - so
248
- the "permission" surface is informational only. The
249
- backend's `editor` / `systemOwned` flags are
250
- reserved no-ops in v1 (see `DatatableView` DTO
251
- JSDoc); scoria never sets them.
252
- -->
253
- <span class="permission-pill">{i18n['scoria.label.subscriber']()}</span>
254
- <Button
255
- variant={Variant.Secondary}
256
- size={Size.MediumSmall}
257
- nowrap
258
- iconLeft={{ name: 'circle-cross', size: Size.Small }}
259
- disabled={saving}
260
- onclick={() => {
261
- removeFromSelection(user.id);
262
- }}>{i18n['scoria.action.remove']()}</Button
263
- >
264
- </div>
265
- </li>
266
- {/each}
267
- </ul>
268
- {/if}
269
- </div>
270
- </DesktopModal>
271
-
160
+ </script>
161
+
162
+ <DesktopModal
163
+ headerLabel={i18n['scoria.label.share_header']({ name: view.name })}
164
+ headerSubtitle={view.kind === 'filter'
165
+ ? i18n['scoria.text.share_filter_subtitle']()
166
+ : i18n['scoria.text.share_layout_subtitle']()}
167
+ onclose={() => {
168
+ if (!saving) {
169
+ onclose();
170
+ }
171
+ }}
172
+ width={cssLength('40vw')}
173
+ minWidth={cssLength('32rem')}
174
+ buttons={[
175
+ {
176
+ label: i18n['scoria.action.cancel'](),
177
+ callback: () => {
178
+ if (!saving) {
179
+ onclose();
180
+ }
181
+ },
182
+ disabled: saving,
183
+ },
184
+ {
185
+ label: saving ? i18n['scoria.action.saving']() : i18n['scoria.action.save'](),
186
+ callback: () => {
187
+ void save();
188
+ },
189
+ colourSet: ColourSet.Primary,
190
+ disabled: saving || !dirty || allUsers === null,
191
+ },
192
+ ]}
193
+ >
194
+ <div class="share-body">
195
+ {#if errorMessage}
196
+ <div
197
+ class="error-banner"
198
+ role="alert"
199
+ >
200
+ <Icon
201
+ name="circle-exclamation"
202
+ size={Size.Small}
203
+ />
204
+ <span>{errorMessage}</span>
205
+ </div>
206
+ {/if}
207
+
208
+ <div class="picker">
209
+ {#if loadingUsers && allUsers === null}
210
+ <InfoAlert>{i18n['scoria.message.loading_users']()}</InfoAlert>
211
+ {:else if allUsers !== null}
212
+ <MultiSelect
213
+ label={i18n['scoria.label.users']()}
214
+ name="User"
215
+ placeholder={i18n['scoria.label.select_user']()}
216
+ options={allUsers as Array<DatatableViewUser>}
217
+ labelProp="displayName"
218
+ valueProp="id"
219
+ valueAsObject={true}
220
+ selectedValues={selected}
221
+ onchange={(values) => {
222
+ selected = values;
223
+ }}
224
+ />
225
+ {/if}
226
+ </div>
227
+
228
+ {#if selected.length === 0}
229
+ <InfoAlert>
230
+ {view.kind === 'filter'
231
+ ? i18n['scoria.text.no_users_filter']()
232
+ : i18n['scoria.text.no_users_layout']()}
233
+ </InfoAlert>
234
+ {:else}
235
+ <ul class="user-card-list">
236
+ {#each selected as user (user.id)}
237
+ <li class="user-card">
238
+ <div class="user-info">
239
+ <Icon
240
+ name="user-3"
241
+ size={Size.Medium}
242
+ />
243
+ <span class="user-name">{user.displayName}</span>
244
+ </div>
245
+ <div class="user-meta">
246
+ <!--
247
+ v1 sharing exposes a single role - subscriber - so
248
+ the "permission" surface is informational only. The
249
+ backend's `editor` / `systemOwned` flags are
250
+ reserved no-ops in v1 (see `DatatableView` DTO
251
+ JSDoc); scoria never sets them.
252
+ -->
253
+ <span class="permission-pill">{i18n['scoria.label.subscriber']()}</span>
254
+ <Button
255
+ variant={Variant.Secondary}
256
+ size={Size.MediumSmall}
257
+ nowrap
258
+ iconLeft={{ name: 'circle-cross', size: Size.Small }}
259
+ disabled={saving}
260
+ onclick={() => {
261
+ removeFromSelection(user.id);
262
+ }}>{i18n['scoria.action.remove']()}</Button
263
+ >
264
+ </div>
265
+ </li>
266
+ {/each}
267
+ </ul>
268
+ {/if}
269
+ </div>
270
+ </DesktopModal>
271
+
272
272
  <style>.share-body {
273
273
  display: flex;
274
274
  flex-flow: column nowrap;
@@ -351,4 +351,4 @@ async function save() {
351
351
  border-radius: 999px;
352
352
  background-color: #e9ecf1;
353
353
  color: #3a4952;
354
- }</style>
354
+ }</style>
@@ -1,34 +1,34 @@
1
- <svelte:options runes />
2
-
3
- <script
4
- lang="ts"
5
- module
1
+ <svelte:options runes />
2
+
3
+ <script
4
+ lang="ts"
5
+ module
6
6
  >import { quintOut } from "svelte/easing";
7
7
  import { slide } from "svelte/transition";
8
8
  import { Delay } from "../../../Delay/Delay.js";
9
9
  import { usePrefersReducedMotion } from "../../../Helpers/prefersReducedMotion.svelte.js";
10
10
  import { ToolbarPosition } from "../Types/Toolbar/ToolbarPosition.js";
11
- </script>
12
-
11
+ </script>
12
+
13
13
  <script lang="ts">const { toolbarPosition, onkeydown, ariaLabel, children } = $props();
14
14
  const reducedMotion = usePrefersReducedMotion();
15
15
  const slideDuration = $derived(reducedMotion.matches ? 0 : Delay.Default);
16
- </script>
17
-
18
- <!-- svelte-ignore a11y_no_static_element_interactions -->
19
- <div
20
- class="side-panel"
21
- class:left={toolbarPosition === ToolbarPosition.Left}
22
- class:right={toolbarPosition === ToolbarPosition.Right}
23
- aria-label={ariaLabel}
24
- {onkeydown}
25
- transition:slide={{ duration: slideDuration, easing: quintOut, axis: 'x' }}
26
- >
27
- <div class="side-content">
28
- {#if children}{@render children()}{/if}
29
- </div>
30
- </div>
31
-
16
+ </script>
17
+
18
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
19
+ <div
20
+ class="side-panel"
21
+ class:left={toolbarPosition === ToolbarPosition.Left}
22
+ class:right={toolbarPosition === ToolbarPosition.Right}
23
+ aria-label={ariaLabel}
24
+ {onkeydown}
25
+ transition:slide={{ duration: slideDuration, easing: quintOut, axis: 'x' }}
26
+ >
27
+ <div class="side-content">
28
+ {#if children}{@render children()}{/if}
29
+ </div>
30
+ </div>
31
+
32
32
  <style>.side-panel {
33
33
  display: flex;
34
34
  flex-shrink: 0;
@@ -48,4 +48,4 @@ const slideDuration = $derived(reducedMotion.matches ? 0 : Delay.Default);
48
48
  flex-flow: column nowrap;
49
49
  flex: 1;
50
50
  width: 400px;
51
- }</style>
51
+ }</style>