@happyvertical/smrt-svelte 0.55.1 → 0.55.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 +29 -2
- package/agents/components.md +44 -1
- package/agents/workspace.md +77 -2
- package/dist/components/app/AppShell.svelte +121 -9
- package/dist/components/app/AppShell.svelte.d.ts +24 -2
- package/dist/components/app/AppShell.svelte.d.ts.map +1 -1
- package/dist/components/app/DockToggles.svelte +103 -0
- package/dist/components/app/DockToggles.svelte.d.ts +8 -0
- package/dist/components/app/DockToggles.svelte.d.ts.map +1 -0
- package/dist/components/app/dock-toggle.d.ts +14 -0
- package/dist/components/app/dock-toggle.d.ts.map +1 -0
- package/dist/components/app/dock-toggle.js +1 -0
- package/dist/components/app/index.d.ts +2 -0
- package/dist/components/app/index.d.ts.map +1 -1
- package/dist/components/app/index.js +1 -0
- package/dist/components/board/Board.svelte +92 -394
- package/dist/components/board/Board.svelte.d.ts.map +1 -1
- package/dist/components/forms/RelationInput.svelte +379 -0
- package/dist/components/forms/RelationInput.svelte.d.ts +75 -0
- package/dist/components/forms/RelationInput.svelte.d.ts.map +1 -0
- package/dist/components/forms/index.d.ts +2 -1
- package/dist/components/forms/index.d.ts.map +1 -1
- package/dist/components/forms/index.js +1 -0
- package/dist/components/forms/types.d.ts +9 -0
- package/dist/components/forms/types.d.ts.map +1 -1
- package/dist/components/sortable/Sortable.svelte +359 -0
- package/dist/components/sortable/Sortable.svelte.d.ts +26 -0
- package/dist/components/sortable/Sortable.svelte.d.ts.map +1 -0
- package/dist/components/sortable/controller.svelte.d.ts +152 -0
- package/dist/components/sortable/controller.svelte.d.ts.map +1 -0
- package/dist/components/sortable/controller.svelte.js +453 -0
- package/dist/components/sortable/index.d.ts +5 -0
- package/dist/components/sortable/index.d.ts.map +1 -0
- package/dist/components/sortable/index.js +2 -0
- package/dist/components/sortable/types.d.ts +80 -0
- package/dist/components/sortable/types.d.ts.map +1 -0
- package/dist/components/sortable/types.js +1 -0
- package/dist/components/workspace/admin-shell/AdminShell.svelte +49 -1
- package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte +196 -0
- package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte.d.ts +17 -0
- package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/TenantNav.svelte +69 -3
- package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/dock.d.ts +37 -0
- package/dist/components/workspace/admin-shell/dock.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/dock.js +25 -0
- package/dist/components/workspace/admin-shell/layout-context.d.ts +7 -0
- package/dist/components/workspace/admin-shell/layout-context.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/layout-context.js +17 -0
- package/dist/components/workspace/admin-shell/layout-controller.svelte.d.ts +69 -0
- package/dist/components/workspace/admin-shell/layout-controller.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/layout-controller.svelte.js +91 -0
- package/dist/components/workspace/admin-shell/layout.d.ts +120 -0
- package/dist/components/workspace/admin-shell/layout.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/layout.js +402 -0
- package/dist/components/workspace/admin-shell/settings.d.ts +6 -4
- package/dist/components/workspace/admin-shell/settings.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/settings.js +14 -4
- package/dist/components/workspace/admin-shell/state.svelte.d.ts +59 -1
- package/dist/components/workspace/admin-shell/state.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/state.svelte.js +146 -2
- package/dist/components/workspace/admin-shell/types.d.ts +52 -0
- package/dist/components/workspace/admin-shell/types.d.ts.map +1 -1
- package/dist/components/workspace/index.d.ts +6 -1
- package/dist/components/workspace/index.d.ts.map +1 -1
- package/dist/components/workspace/index.js +5 -0
- package/dist/i18n/server.d.ts +1 -0
- package/dist/i18n/server.d.ts.map +1 -1
- package/dist/i18n/server.js +1 -0
- package/dist/i18n/strings.sortable.d.ts +13 -0
- package/dist/i18n/strings.sortable.d.ts.map +1 -0
- package/dist/i18n/strings.sortable.js +13 -0
- package/dist/i18n/strings.workspace.d.ts +13 -0
- package/dist/i18n/strings.workspace.d.ts.map +1 -1
- package/dist/i18n/strings.workspace.js +13 -0
- package/package.json +26 -15
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
<script lang="ts" generics="Item extends SortableItem, Container extends SortableContainer">
|
|
2
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
3
|
+
import { M } from '../../i18n/strings.sortable.js';
|
|
4
|
+
import {
|
|
5
|
+
createSortable,
|
|
6
|
+
type SortableAnnouncement,
|
|
7
|
+
} from './controller.svelte.js';
|
|
8
|
+
import type {
|
|
9
|
+
SortableContainer,
|
|
10
|
+
SortableItem,
|
|
11
|
+
SortableProps,
|
|
12
|
+
} from './types.js';
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
containers,
|
|
16
|
+
items,
|
|
17
|
+
label,
|
|
18
|
+
reorderContainers = false,
|
|
19
|
+
allowSameContainerReorder = true,
|
|
20
|
+
item: itemSnippet,
|
|
21
|
+
containerHeader,
|
|
22
|
+
onmove,
|
|
23
|
+
oncontainermove,
|
|
24
|
+
}: SortableProps<Item, Container> = $props();
|
|
25
|
+
|
|
26
|
+
const { t } = useI18n();
|
|
27
|
+
const instanceId = $props.id();
|
|
28
|
+
const itemLiveId = `${instanceId}-item-live`;
|
|
29
|
+
const containerLiveId = `${instanceId}-container-live`;
|
|
30
|
+
const LIST_ID = '__smrt-sortable-containers__';
|
|
31
|
+
let root: HTMLElement;
|
|
32
|
+
|
|
33
|
+
// Fixed containers lead (in the order given); the rest follow. With
|
|
34
|
+
// reordering off, the owner's order is used as is.
|
|
35
|
+
const fixed = $derived(
|
|
36
|
+
reorderContainers ? containers.filter((container) => container.fixed) : [],
|
|
37
|
+
);
|
|
38
|
+
const movable = $derived(
|
|
39
|
+
reorderContainers
|
|
40
|
+
? containers.filter((container) => !container.fixed)
|
|
41
|
+
: containers,
|
|
42
|
+
);
|
|
43
|
+
const ordered = $derived([...fixed, ...movable]);
|
|
44
|
+
const itemsByContainer = $derived.by(() => {
|
|
45
|
+
const next = new Map<string, Item[]>();
|
|
46
|
+
for (const container of containers) next.set(container.id, []);
|
|
47
|
+
for (const entry of items) next.get(entry.containerId)?.push(entry);
|
|
48
|
+
return next;
|
|
49
|
+
});
|
|
50
|
+
const itemsById = $derived(new Map(items.map((entry) => [entry.id, entry])));
|
|
51
|
+
const containersById = $derived(
|
|
52
|
+
new Map(containers.map((container) => [container.id, container])),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
function itemMessage(announcement: SortableAnnouncement): string {
|
|
56
|
+
switch (announcement.type) {
|
|
57
|
+
case 'pickup':
|
|
58
|
+
return t(M['ui.sortable.pickup'], {
|
|
59
|
+
item: announcement.item,
|
|
60
|
+
destinations: announcement.destinations.join(', '),
|
|
61
|
+
});
|
|
62
|
+
case 'position':
|
|
63
|
+
return t(M['ui.sortable.position'], {
|
|
64
|
+
item: announcement.item,
|
|
65
|
+
container: announcement.container,
|
|
66
|
+
position: announcement.position,
|
|
67
|
+
count: announcement.count,
|
|
68
|
+
});
|
|
69
|
+
case 'drop':
|
|
70
|
+
return t(M['ui.sortable.drop'], {
|
|
71
|
+
item: announcement.item,
|
|
72
|
+
container: announcement.container,
|
|
73
|
+
position: announcement.position,
|
|
74
|
+
count: announcement.count,
|
|
75
|
+
});
|
|
76
|
+
case 'unavailable':
|
|
77
|
+
return t(M['ui.sortable.unavailable'], {
|
|
78
|
+
container: announcement.container,
|
|
79
|
+
});
|
|
80
|
+
case 'failed':
|
|
81
|
+
return t(M['ui.sortable.failed'], { item: announcement.item });
|
|
82
|
+
case 'cancel':
|
|
83
|
+
return t(M['ui.sortable.cancel'], { item: announcement.item });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const itemSortable = createSortable({
|
|
88
|
+
root: () => root,
|
|
89
|
+
selectors: {
|
|
90
|
+
container: '[data-smrt-sortable-container-id]',
|
|
91
|
+
containerKey: 'smrtSortableContainerId',
|
|
92
|
+
item: '[data-smrt-sortable-item-id]',
|
|
93
|
+
itemKey: 'smrtSortableItemId',
|
|
94
|
+
},
|
|
95
|
+
containers: () => ordered,
|
|
96
|
+
itemIds: (containerId) =>
|
|
97
|
+
(itemsByContainer.get(containerId) ?? []).map((entry) => entry.id),
|
|
98
|
+
itemLabel: (itemId) => itemsById.get(itemId)?.label,
|
|
99
|
+
allowSameContainerReorder: () => allowSameContainerReorder,
|
|
100
|
+
enabled: () => onmove !== undefined,
|
|
101
|
+
orientation: () => 'vertical',
|
|
102
|
+
announce: itemMessage,
|
|
103
|
+
focusTarget: (element) =>
|
|
104
|
+
element.querySelector<HTMLElement>('[data-smrt-sortable-handle="item"]'),
|
|
105
|
+
async commit(move) {
|
|
106
|
+
const moving = itemsById.get(move.itemId);
|
|
107
|
+
const sourceContainer = containersById.get(move.source.containerId);
|
|
108
|
+
const targetContainer = containersById.get(move.target.containerId);
|
|
109
|
+
if (!moving || !sourceContainer || !targetContainer) return;
|
|
110
|
+
await onmove?.({
|
|
111
|
+
item: moving,
|
|
112
|
+
source: move.source,
|
|
113
|
+
target: move.target,
|
|
114
|
+
sourceContainer,
|
|
115
|
+
targetContainer,
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Containers are sorted by a second engine whose single "container" is the
|
|
121
|
+
// list of movable containers and whose "items" are those containers.
|
|
122
|
+
const containerSortable = createSortable({
|
|
123
|
+
root: () => root,
|
|
124
|
+
selectors: {
|
|
125
|
+
container: '[data-smrt-sortable-container-list]',
|
|
126
|
+
containerKey: 'smrtSortableContainerList',
|
|
127
|
+
item: '[data-smrt-sortable-container-item]',
|
|
128
|
+
itemKey: 'smrtSortableContainerItem',
|
|
129
|
+
},
|
|
130
|
+
containers: () => [
|
|
131
|
+
{ id: LIST_ID, label: label ?? t(M['ui.sortable.label']) },
|
|
132
|
+
],
|
|
133
|
+
itemIds: () => movable.map((container) => container.id),
|
|
134
|
+
itemLabel: (id) => containersById.get(id)?.label,
|
|
135
|
+
allowSameContainerReorder: () => true,
|
|
136
|
+
enabled: () => reorderContainers && oncontainermove !== undefined,
|
|
137
|
+
orientation: () => 'vertical',
|
|
138
|
+
announce: itemMessage,
|
|
139
|
+
focusTarget: (element) =>
|
|
140
|
+
Array.from(element.children)
|
|
141
|
+
.find((child) => child.tagName === 'HEADER')
|
|
142
|
+
?.querySelector<HTMLElement>('[data-smrt-sortable-handle="container"]') ??
|
|
143
|
+
null,
|
|
144
|
+
async commit(move) {
|
|
145
|
+
const moving = containersById.get(move.itemId);
|
|
146
|
+
if (!moving) return;
|
|
147
|
+
await oncontainermove?.({
|
|
148
|
+
container: moving,
|
|
149
|
+
source: move.source.index,
|
|
150
|
+
target: move.target.index,
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
/** Items of `containerId` with the drop marker's slot, for rendering. */
|
|
156
|
+
function markerBefore(containerId: string, rank: number): boolean {
|
|
157
|
+
const target = itemSortable.drag?.target;
|
|
158
|
+
return target?.containerId === containerId && target.index === rank;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function nonDraggedRank(list: readonly Item[], index: number): number {
|
|
162
|
+
const dragged = itemSortable.drag?.itemId;
|
|
163
|
+
let rank = 0;
|
|
164
|
+
for (let i = 0; i < index; i += 1) if (list[i].id !== dragged) rank += 1;
|
|
165
|
+
return rank;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function containerMarkerBefore(rank: number): boolean {
|
|
169
|
+
return containerSortable.drag?.target.index === rank;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function containerRank(id: string): number {
|
|
173
|
+
const dragged = containerSortable.drag?.itemId;
|
|
174
|
+
let rank = 0;
|
|
175
|
+
for (const container of movable) {
|
|
176
|
+
if (container.id === id) break;
|
|
177
|
+
if (container.id !== dragged) rank += 1;
|
|
178
|
+
}
|
|
179
|
+
return rank;
|
|
180
|
+
}
|
|
181
|
+
</script>
|
|
182
|
+
|
|
183
|
+
{#snippet containerBody(container: Container)}
|
|
184
|
+
{@const list = itemsByContainer.get(container.id) ?? []}
|
|
185
|
+
{@const dragged = itemSortable.drag?.itemId}
|
|
186
|
+
{@const count = list.length}
|
|
187
|
+
<div
|
|
188
|
+
class="smrt-sortable__items"
|
|
189
|
+
role="list"
|
|
190
|
+
aria-label={t(M['ui.sortable.group'], { label: container.label, count })}
|
|
191
|
+
>
|
|
192
|
+
{#each list as entry, index (entry.id)}
|
|
193
|
+
{#if markerBefore(container.id, nonDraggedRank(list, index)) && entry.id !== dragged}
|
|
194
|
+
<div class="smrt-sortable__marker" aria-hidden="true"></div>
|
|
195
|
+
{/if}
|
|
196
|
+
<div
|
|
197
|
+
role="listitem"
|
|
198
|
+
class="smrt-sortable__item"
|
|
199
|
+
class:smrt-sortable__item--dragging={dragged === entry.id}
|
|
200
|
+
data-smrt-sortable-item-id={entry.id}
|
|
201
|
+
ondragover={(event) => event.preventDefault()}
|
|
202
|
+
ondrop={(event) => {
|
|
203
|
+
if (!itemSortable.drag) return;
|
|
204
|
+
event.stopPropagation();
|
|
205
|
+
itemSortable.dropOnItem(event, container.id, index);
|
|
206
|
+
}}
|
|
207
|
+
>
|
|
208
|
+
<!-- raw-primitive-allow: native button owns keyboard pickup and HTML drag/drop -->
|
|
209
|
+
<button
|
|
210
|
+
type="button"
|
|
211
|
+
class="smrt-sortable__handle"
|
|
212
|
+
data-smrt-sortable-handle="item"
|
|
213
|
+
draggable={itemSortable.nativeDraggable}
|
|
214
|
+
aria-label={t(M['ui.sortable.move'], { item: entry.label })}
|
|
215
|
+
aria-pressed={dragged === entry.id}
|
|
216
|
+
aria-describedby={dragged === entry.id ? itemLiveId : undefined}
|
|
217
|
+
onclick={() => itemSortable.consumeClick(entry.id)}
|
|
218
|
+
onkeydown={(event) => itemSortable.keydown(event, entry.id)}
|
|
219
|
+
onblur={(event) => itemSortable.blur(event, entry.id)}
|
|
220
|
+
onpointerdown={(event) => itemSortable.pointerDown(event, entry.id)}
|
|
221
|
+
onpointermove={(event) => itemSortable.pointerMove(event)}
|
|
222
|
+
onpointerup={(event) => itemSortable.pointerUp(event)}
|
|
223
|
+
onpointercancel={(event) => itemSortable.pointerCancel(event)}
|
|
224
|
+
ondragstart={(event) => itemSortable.dragStart(event, entry.id)}
|
|
225
|
+
ondragend={() => itemSortable.dragEnd()}
|
|
226
|
+
><span aria-hidden="true">⠿</span></button>
|
|
227
|
+
<div class="smrt-sortable__content">
|
|
228
|
+
{@render itemSnippet({
|
|
229
|
+
item: entry,
|
|
230
|
+
container,
|
|
231
|
+
index,
|
|
232
|
+
isDragging: dragged === entry.id,
|
|
233
|
+
})}
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
{:else}
|
|
237
|
+
<div role="listitem" class="smrt-sortable__empty">
|
|
238
|
+
{t(M['ui.sortable.empty'], { container: container.label })}
|
|
239
|
+
</div>
|
|
240
|
+
{/each}
|
|
241
|
+
{#if markerBefore(container.id, list.filter((entry) => entry.id !== dragged).length)}
|
|
242
|
+
<div class="smrt-sortable__marker" aria-hidden="true"></div>
|
|
243
|
+
{/if}
|
|
244
|
+
</div>
|
|
245
|
+
{/snippet}
|
|
246
|
+
|
|
247
|
+
{#snippet containerBlock(container: Container, sortableContainer: boolean)}
|
|
248
|
+
{@const count = (itemsByContainer.get(container.id) ?? []).length}
|
|
249
|
+
{@const draggingContainer = containerSortable.drag?.itemId === container.id}
|
|
250
|
+
<section
|
|
251
|
+
class="smrt-sortable__container"
|
|
252
|
+
class:smrt-sortable__container--disabled={container.disabled}
|
|
253
|
+
class:smrt-sortable__container--dragging={draggingContainer}
|
|
254
|
+
data-smrt-sortable-container-id={container.id}
|
|
255
|
+
data-smrt-sortable-container-item={sortableContainer ? container.id : undefined}
|
|
256
|
+
aria-label={container.label}
|
|
257
|
+
ondragover={(event) => event.preventDefault()}
|
|
258
|
+
ondrop={(event) => {
|
|
259
|
+
if (itemSortable.drag) {
|
|
260
|
+
itemSortable.dropOnContainer(event, container.id);
|
|
261
|
+
} else if (sortableContainer) {
|
|
262
|
+
containerSortable.dropOnItem(
|
|
263
|
+
event,
|
|
264
|
+
LIST_ID,
|
|
265
|
+
movable.findIndex((candidate) => candidate.id === container.id),
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}}
|
|
269
|
+
>
|
|
270
|
+
<header class="smrt-sortable__header">
|
|
271
|
+
{#if sortableContainer}
|
|
272
|
+
<!-- raw-primitive-allow: native button owns keyboard pickup and HTML drag/drop -->
|
|
273
|
+
<button
|
|
274
|
+
type="button"
|
|
275
|
+
class="smrt-sortable__handle"
|
|
276
|
+
data-smrt-sortable-handle="container"
|
|
277
|
+
draggable={containerSortable.nativeDraggable}
|
|
278
|
+
aria-label={t(M['ui.sortable.move'], { item: container.label })}
|
|
279
|
+
aria-pressed={draggingContainer}
|
|
280
|
+
aria-describedby={draggingContainer ? containerLiveId : undefined}
|
|
281
|
+
onclick={() => containerSortable.consumeClick(container.id)}
|
|
282
|
+
onkeydown={(event) => containerSortable.keydown(event, container.id)}
|
|
283
|
+
onblur={(event) => containerSortable.blur(event, container.id)}
|
|
284
|
+
onpointerdown={(event) => containerSortable.pointerDown(event, container.id)}
|
|
285
|
+
onpointermove={(event) => containerSortable.pointerMove(event)}
|
|
286
|
+
onpointerup={(event) => containerSortable.pointerUp(event)}
|
|
287
|
+
onpointercancel={(event) => containerSortable.pointerCancel(event)}
|
|
288
|
+
ondragstart={(event) => containerSortable.dragStart(event, container.id)}
|
|
289
|
+
ondragend={() => containerSortable.dragEnd()}
|
|
290
|
+
><span aria-hidden="true">⠿</span></button>
|
|
291
|
+
{/if}
|
|
292
|
+
<div class="smrt-sortable__content">
|
|
293
|
+
{#if containerHeader}
|
|
294
|
+
{@render containerHeader({ container, count, isDragging: draggingContainer })}
|
|
295
|
+
{:else}
|
|
296
|
+
<strong>{container.label}</strong>
|
|
297
|
+
{/if}
|
|
298
|
+
</div>
|
|
299
|
+
</header>
|
|
300
|
+
{@render containerBody(container)}
|
|
301
|
+
</section>
|
|
302
|
+
{/snippet}
|
|
303
|
+
|
|
304
|
+
<div
|
|
305
|
+
bind:this={root}
|
|
306
|
+
class="smrt-sortable"
|
|
307
|
+
role="group"
|
|
308
|
+
aria-label={label ?? t(M['ui.sortable.label'])}
|
|
309
|
+
>
|
|
310
|
+
{#each fixed as container (container.id)}
|
|
311
|
+
{@render containerBlock(container, false)}
|
|
312
|
+
{/each}
|
|
313
|
+
{#if reorderContainers}
|
|
314
|
+
<div
|
|
315
|
+
class="smrt-sortable__containers"
|
|
316
|
+
role="list"
|
|
317
|
+
data-smrt-sortable-container-list={LIST_ID}
|
|
318
|
+
>
|
|
319
|
+
{#each movable as container (container.id)}
|
|
320
|
+
{#if containerMarkerBefore(containerRank(container.id)) && containerSortable.drag?.itemId !== container.id}
|
|
321
|
+
<div class="smrt-sortable__marker" aria-hidden="true"></div>
|
|
322
|
+
{/if}
|
|
323
|
+
<div role="listitem" class="smrt-sortable__container-slot">
|
|
324
|
+
{@render containerBlock(container, true)}
|
|
325
|
+
</div>
|
|
326
|
+
{/each}
|
|
327
|
+
{#if containerMarkerBefore(movable.filter((c) => c.id !== containerSortable.drag?.itemId).length)}
|
|
328
|
+
<div class="smrt-sortable__marker" aria-hidden="true"></div>
|
|
329
|
+
{/if}
|
|
330
|
+
</div>
|
|
331
|
+
{:else}
|
|
332
|
+
{#each movable as container (container.id)}
|
|
333
|
+
{@render containerBlock(container, false)}
|
|
334
|
+
{/each}
|
|
335
|
+
{/if}
|
|
336
|
+
<div id={itemLiveId} class="smrt-sortable__live" aria-live="assertive" aria-atomic="true">{itemSortable.announcement}</div>
|
|
337
|
+
<div id={containerLiveId} class="smrt-sortable__live" aria-live="assertive" aria-atomic="true">{containerSortable.announcement}</div>
|
|
338
|
+
</div>
|
|
339
|
+
|
|
340
|
+
<style>
|
|
341
|
+
.smrt-sortable { display: grid; gap: var(--smrt-spacing-3); min-width: 0; position: relative; }
|
|
342
|
+
.smrt-sortable__containers { display: grid; gap: var(--smrt-spacing-3); }
|
|
343
|
+
.smrt-sortable__container { display: grid; gap: var(--smrt-spacing-2); padding: var(--smrt-spacing-3); border: 1px solid var(--smrt-color-outline-variant); border-radius: var(--smrt-radius-md); background: var(--smrt-color-surface-container); min-width: 0; }
|
|
344
|
+
.smrt-sortable__container--disabled { opacity: 0.6; }
|
|
345
|
+
.smrt-sortable__container--dragging { opacity: 0.55; }
|
|
346
|
+
.smrt-sortable__header { display: flex; align-items: center; gap: var(--smrt-spacing-2); min-block-size: 2.25rem; }
|
|
347
|
+
.smrt-sortable__content { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: var(--smrt-spacing-2); }
|
|
348
|
+
.smrt-sortable__items { display: grid; gap: var(--smrt-spacing-1); min-block-size: 2.25rem; }
|
|
349
|
+
.smrt-sortable__item { display: flex; align-items: center; gap: var(--smrt-spacing-2); padding: var(--smrt-spacing-1) var(--smrt-spacing-2); border: 1px solid var(--smrt-color-outline-variant); border-radius: var(--smrt-radius-sm); background: var(--smrt-color-surface); min-width: 0; }
|
|
350
|
+
.smrt-sortable__item--dragging { opacity: 0.55; }
|
|
351
|
+
.smrt-sortable__handle { display: inline-grid; place-items: center; flex: 0 0 auto; inline-size: 2rem; block-size: 2rem; padding: 0; border: 0; border-radius: var(--smrt-radius-sm); background: transparent; color: var(--smrt-color-on-surface-variant); cursor: grab; touch-action: none; }
|
|
352
|
+
.smrt-sortable__handle:active { cursor: grabbing; }
|
|
353
|
+
.smrt-sortable__handle:hover { background: var(--smrt-color-surface-container-high); }
|
|
354
|
+
.smrt-sortable__handle:focus-visible { outline: 2px solid var(--smrt-color-primary); outline-offset: 2px; }
|
|
355
|
+
.smrt-sortable__handle[aria-pressed='true'] { background: var(--smrt-color-primary-container, var(--smrt-color-surface-container-high)); color: var(--smrt-color-on-primary-container, inherit); }
|
|
356
|
+
.smrt-sortable__marker { block-size: 0.1875rem; border-radius: var(--smrt-radius-full); background: var(--smrt-color-primary); }
|
|
357
|
+
.smrt-sortable__empty { margin: 0; padding: var(--smrt-spacing-2); color: var(--smrt-color-on-surface-variant); font: var(--smrt-typography-body-small-font); }
|
|
358
|
+
.smrt-sortable__live { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
|
|
359
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { SortableContainer, SortableItem, SortableProps } from './types.js';
|
|
2
|
+
declare function $$render<Item extends SortableItem, Container extends SortableContainer>(): {
|
|
3
|
+
props: SortableProps<Item, Container>;
|
|
4
|
+
exports: {};
|
|
5
|
+
bindings: "";
|
|
6
|
+
slots: {};
|
|
7
|
+
events: {};
|
|
8
|
+
};
|
|
9
|
+
declare class __sveltets_Render<Item extends SortableItem, Container extends SortableContainer> {
|
|
10
|
+
props(): ReturnType<typeof $$render<Item, Container>>['props'];
|
|
11
|
+
events(): ReturnType<typeof $$render<Item, Container>>['events'];
|
|
12
|
+
slots(): ReturnType<typeof $$render<Item, Container>>['slots'];
|
|
13
|
+
bindings(): "";
|
|
14
|
+
exports(): {};
|
|
15
|
+
}
|
|
16
|
+
interface $$IsomorphicComponent {
|
|
17
|
+
new <Item extends SortableItem, Container extends SortableContainer>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Item, Container>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Item, Container>['props']>, ReturnType<__sveltets_Render<Item, Container>['events']>, ReturnType<__sveltets_Render<Item, Container>['slots']>> & {
|
|
18
|
+
$$bindings?: ReturnType<__sveltets_Render<Item, Container>['bindings']>;
|
|
19
|
+
} & ReturnType<__sveltets_Render<Item, Container>['exports']>;
|
|
20
|
+
<Item extends SortableItem, Container extends SortableContainer>(internal: unknown, props: ReturnType<__sveltets_Render<Item, Container>['props']> & {}): ReturnType<__sveltets_Render<Item, Container>['exports']>;
|
|
21
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any, any>['bindings']>;
|
|
22
|
+
}
|
|
23
|
+
declare const Sortable: $$IsomorphicComponent;
|
|
24
|
+
type Sortable<Item extends SortableItem, Container extends SortableContainer> = InstanceType<typeof Sortable<Item, Container>>;
|
|
25
|
+
export default Sortable;
|
|
26
|
+
//# sourceMappingURL=Sortable.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sortable.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/sortable/Sortable.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACd,MAAM,YAAY,CAAC;AACpB,iBAAS,QAAQ,CAAC,IAAI,SAAS,YAAY,EAAE,SAAS,SAAS,iBAAiB;WAiRnD,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC;;;;;EAA4E;AACvI,cAAM,iBAAiB,CAAC,IAAI,SAAS,YAAY,EAAC,SAAS,SAAS,iBAAiB;IACjF,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;IAC7D,MAAM,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC/D,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;IAC7D,QAAQ;IACR,OAAO;CACV;AAED,UAAU,qBAAqB;IAC3B,KAAK,IAAI,SAAS,YAAY,EAAC,SAAS,SAAS,iBAAiB,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACtgB,CAAC,IAAI,SAAS,YAAY,EAAC,SAAS,SAAS,iBAAiB,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACjN,YAAY,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,GAAG,EAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;CACrE;AACD,QAAA,MAAM,QAAQ,EAAE,qBAAmC,CAAC;AAClC,KAAK,QAAQ,CAAC,IAAI,SAAS,YAAY,EAAC,SAAS,SAAS,iBAAiB,IAAI,YAAY,CAAC,OAAO,QAAQ,CAAC,IAAI,EAAC,SAAS,CAAC,CAAC,CAAC;AAC/H,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/** Where an item sits: a container and a zero-based index within it. */
|
|
2
|
+
export interface SortablePosition {
|
|
3
|
+
containerId: string;
|
|
4
|
+
index: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A drop, as ids. `target.index` is counted after removing the item from
|
|
8
|
+
* `source`, so it is directly usable with an immutable list update.
|
|
9
|
+
*/
|
|
10
|
+
export interface SortableMove {
|
|
11
|
+
itemId: string;
|
|
12
|
+
source: SortablePosition;
|
|
13
|
+
target: SortablePosition;
|
|
14
|
+
}
|
|
15
|
+
/** The minimum a container exposes to the engine. */
|
|
16
|
+
export interface SortableContainerInfo {
|
|
17
|
+
id: string;
|
|
18
|
+
label: string;
|
|
19
|
+
/** Items cannot be dropped into a disabled container. */
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/** What the engine wants announced; the host turns it into localized text. */
|
|
23
|
+
export type SortableAnnouncement = {
|
|
24
|
+
type: 'pickup';
|
|
25
|
+
item: string;
|
|
26
|
+
destinations: string[];
|
|
27
|
+
} | {
|
|
28
|
+
type: 'position';
|
|
29
|
+
item: string;
|
|
30
|
+
container: string;
|
|
31
|
+
position: number;
|
|
32
|
+
count: number;
|
|
33
|
+
} | {
|
|
34
|
+
type: 'unavailable';
|
|
35
|
+
container: string;
|
|
36
|
+
} | {
|
|
37
|
+
type: 'failed';
|
|
38
|
+
item: string;
|
|
39
|
+
} | {
|
|
40
|
+
type: 'drop';
|
|
41
|
+
item: string;
|
|
42
|
+
container: string;
|
|
43
|
+
position: number;
|
|
44
|
+
count: number;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'cancel';
|
|
47
|
+
item: string;
|
|
48
|
+
};
|
|
49
|
+
/** How the host marks its DOM so pointer hit-testing can find ids. */
|
|
50
|
+
export interface SortableSelectors {
|
|
51
|
+
/** CSS selector of a container's list element. */
|
|
52
|
+
container: string;
|
|
53
|
+
/** `dataset` key holding the container id. */
|
|
54
|
+
containerKey: string;
|
|
55
|
+
/** CSS selector of an item element. */
|
|
56
|
+
item: string;
|
|
57
|
+
/** `dataset` key holding the item id. */
|
|
58
|
+
itemKey: string;
|
|
59
|
+
}
|
|
60
|
+
export interface SortableControllerOptions {
|
|
61
|
+
/** The element hit-testing is confined to (never escapes it). */
|
|
62
|
+
root: () => HTMLElement | undefined;
|
|
63
|
+
selectors: SortableSelectors;
|
|
64
|
+
containers: () => readonly SortableContainerInfo[];
|
|
65
|
+
/** Ids in a container, in display order. */
|
|
66
|
+
itemIds: (containerId: string) => readonly string[];
|
|
67
|
+
/** Accessible label of an item, or `undefined` when it no longer exists. */
|
|
68
|
+
itemLabel: (itemId: string) => string | undefined;
|
|
69
|
+
/** Whether items may be reordered within their current container. */
|
|
70
|
+
allowSameContainerReorder: () => boolean;
|
|
71
|
+
/** Whether moving is allowed at all (e.g. a read-only list is not). */
|
|
72
|
+
enabled: () => boolean;
|
|
73
|
+
/**
|
|
74
|
+
* `horizontal` (default): Left/Right choose the container, Up/Down the
|
|
75
|
+
* position. `vertical`: Up/Down walk the whole list, crossing into the
|
|
76
|
+
* adjacent container at either end.
|
|
77
|
+
*/
|
|
78
|
+
orientation?: () => 'horizontal' | 'vertical';
|
|
79
|
+
/**
|
|
80
|
+
* Persist a move. May be async; a rejection restores the presentation and
|
|
81
|
+
* is announced. The engine allows the next move only after it settles.
|
|
82
|
+
*/
|
|
83
|
+
commit: (move: SortableMove) => void | Promise<void>;
|
|
84
|
+
announce: (announcement: SortableAnnouncement) => string;
|
|
85
|
+
/** Element to focus for an item (default: the item element itself). */
|
|
86
|
+
focusTarget?: (itemElement: HTMLElement) => HTMLElement | null;
|
|
87
|
+
}
|
|
88
|
+
interface DragState {
|
|
89
|
+
itemId: string;
|
|
90
|
+
source: SortablePosition;
|
|
91
|
+
target: SortablePosition;
|
|
92
|
+
mode: 'keyboard' | 'pointer';
|
|
93
|
+
}
|
|
94
|
+
export declare class SortableController {
|
|
95
|
+
private readonly options;
|
|
96
|
+
drag: DragState | undefined;
|
|
97
|
+
announcement: string;
|
|
98
|
+
private focusItemId;
|
|
99
|
+
private suppressedSelectionId;
|
|
100
|
+
private pending;
|
|
101
|
+
private pointerSession;
|
|
102
|
+
constructor(options: SortableControllerOptions);
|
|
103
|
+
/** Whether a new move may start now. */
|
|
104
|
+
get movable(): boolean;
|
|
105
|
+
/** Whether native HTML drag should be offered (not while a pointer session runs). */
|
|
106
|
+
get nativeDraggable(): boolean;
|
|
107
|
+
private get containers();
|
|
108
|
+
private itemsIn;
|
|
109
|
+
private findContainer;
|
|
110
|
+
private positionFor;
|
|
111
|
+
private label;
|
|
112
|
+
private say;
|
|
113
|
+
pickup(itemId: string, mode: DragState['mode']): void;
|
|
114
|
+
private announcePosition;
|
|
115
|
+
private moveKeyboardTarget;
|
|
116
|
+
drop(): Promise<void>;
|
|
117
|
+
/** Cancel the move in flight. Focus returns to the item when `restoreFocus`. */
|
|
118
|
+
cancel(announce?: boolean, restoreFocus?: boolean): void;
|
|
119
|
+
private suppressSelection;
|
|
120
|
+
/**
|
|
121
|
+
* Keyboard pick-up and native drag gestures can both dispatch a click after
|
|
122
|
+
* their key/pointer sequence. Returns `true` when this click must be
|
|
123
|
+
* consumed so a move never doubles as an application-level activation.
|
|
124
|
+
*/
|
|
125
|
+
consumeClick(itemId: string): boolean;
|
|
126
|
+
keydown(event: KeyboardEvent, itemId: string): void;
|
|
127
|
+
/**
|
|
128
|
+
* Focus left the item while a keyboard move was in flight: abandon it so
|
|
129
|
+
* the item is not left "picked up" with no way to steer it.
|
|
130
|
+
*/
|
|
131
|
+
blur(event: FocusEvent, itemId: string): void;
|
|
132
|
+
dragStart(event: DragEvent, itemId: string): void;
|
|
133
|
+
dragEnd(): void;
|
|
134
|
+
pointerDown(event: PointerEvent, itemId: string): void;
|
|
135
|
+
private elementAtPointer;
|
|
136
|
+
private setPointerTargetFromElement;
|
|
137
|
+
/** Index to insert at when hovering item `rawIndex`, after removing the dragged item. */
|
|
138
|
+
private insertionIndex;
|
|
139
|
+
private finishPointerSession;
|
|
140
|
+
pointerUp(event: PointerEvent): void;
|
|
141
|
+
pointerCancel(event: PointerEvent): void;
|
|
142
|
+
pointerMove(event: PointerEvent): void;
|
|
143
|
+
private pointerTarget;
|
|
144
|
+
/** Native drop on an item (`rawIndex` is its index in its container). */
|
|
145
|
+
dropOnItem(event: DragEvent, containerId: string, rawIndex: number): void;
|
|
146
|
+
/** Native drop on a container's empty space: append. */
|
|
147
|
+
dropOnContainer(event: DragEvent, containerId: string): void;
|
|
148
|
+
}
|
|
149
|
+
/** Create a controller; call during component initialization. */
|
|
150
|
+
export declare function createSortable(options: SortableControllerOptions): SortableController;
|
|
151
|
+
export {};
|
|
152
|
+
//# sourceMappingURL=controller.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/sortable/controller.svelte.ts"],"names":[],"mappings":"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"}
|