@dosgato/dialog 0.0.19 → 0.0.21
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/Button.svelte +77 -0
- package/Button.svelte.d.ts +30 -0
- package/ButtonGroup.svelte.d.ts +3 -3
- package/Checkbox.svelte +2 -1
- package/Checkbox.svelte.d.ts +4 -3
- package/Container.svelte +18 -19
- package/Container.svelte.d.ts +5 -3
- package/Dialog.svelte +155 -0
- package/Dialog.svelte.d.ts +50 -0
- package/FieldAutocomplete.svelte +4 -7
- package/FieldAutocomplete.svelte.d.ts +4 -4
- package/FieldCheckbox.svelte +3 -2
- package/FieldCheckbox.svelte.d.ts +5 -4
- package/FieldChoices.svelte +3 -2
- package/FieldChoices.svelte.d.ts +4 -3
- package/FieldChooserLink.svelte +17 -13
- package/FieldChooserLink.svelte.d.ts +4 -5
- package/FieldDate.svelte +3 -2
- package/FieldDate.svelte.d.ts +4 -3
- package/FieldDateTime.svelte +3 -2
- package/FieldDateTime.svelte.d.ts +4 -3
- package/FieldDualListbox.svelte.d.ts +3 -3
- package/FieldHidden.svelte.d.ts +3 -3
- package/FieldIdentifier.svelte.d.ts +3 -3
- package/FieldMultiple.svelte +14 -7
- package/FieldMultiple.svelte.d.ts +6 -3
- package/FieldMultiselect.svelte +29 -22
- package/FieldMultiselect.svelte.d.ts +3 -3
- package/FieldNumber.svelte +3 -2
- package/FieldNumber.svelte.d.ts +4 -3
- package/FieldRadio.svelte +9 -4
- package/FieldRadio.svelte.d.ts +9 -3
- package/FieldSelect.svelte +9 -3
- package/FieldSelect.svelte.d.ts +9 -3
- package/FieldStandard.svelte +8 -3
- package/FieldStandard.svelte.d.ts +9 -3
- package/FieldText.svelte +3 -2
- package/FieldText.svelte.d.ts +4 -3
- package/FieldTextArea.svelte +5 -3
- package/FieldTextArea.svelte.d.ts +4 -3
- package/FileIcon.svelte.d.ts +3 -3
- package/Form.svelte +3 -3
- package/Form.svelte.d.ts +3 -3
- package/FormDialog.svelte +34 -0
- package/FormDialog.svelte.d.ts +38 -0
- package/Icon.svelte.d.ts +3 -3
- package/InlineMessage.svelte.d.ts +3 -3
- package/InlineMessages.svelte.d.ts +3 -3
- package/Input.svelte +4 -1
- package/Input.svelte.d.ts +4 -3
- package/Listbox.svelte.d.ts +3 -3
- package/Radio.svelte +5 -2
- package/Radio.svelte.d.ts +4 -3
- package/Tab.svelte +3 -2
- package/Tab.svelte.d.ts +3 -3
- package/TabStore.d.ts +11 -1
- package/TabStore.js +30 -3
- package/Tabs.svelte +66 -18
- package/Tabs.svelte.d.ts +5 -7
- package/chooser/Chooser.svelte +76 -99
- package/chooser/Chooser.svelte.d.ts +5 -5
- package/chooser/ChooserAPI.d.ts +10 -3
- package/chooser/ChooserStore.d.ts +15 -33
- package/chooser/ChooserStore.js +32 -149
- package/chooser/Details.svelte.d.ts +6 -5
- package/chooser/Thumbnail.svelte +9 -2
- package/chooser/Thumbnail.svelte.d.ts +6 -5
- package/colorpicker/FieldColorPicker.svelte +78 -24
- package/colorpicker/FieldColorPicker.svelte.d.ts +5 -6
- package/fileIcons.d.ts +2 -1
- package/helpers.d.ts +1 -0
- package/helpers.js +5 -0
- package/iconpicker/FieldIconPicker.svelte +4 -2
- package/iconpicker/FieldIconPicker.svelte.d.ts +4 -3
- package/index.d.ts +7 -0
- package/index.js +7 -0
- package/package.json +20 -13
- package/tree/LoadIcon.svelte +24 -0
- package/tree/LoadIcon.svelte.d.ts +23 -0
- package/tree/Tree.svelte +203 -0
- package/tree/Tree.svelte.d.ts +28 -0
- package/tree/TreeCell.svelte +18 -0
- package/tree/TreeCell.svelte.d.ts +18 -0
- package/tree/TreeNode.svelte +418 -0
- package/tree/TreeNode.svelte.d.ts +30 -0
- package/tree/index.d.ts +3 -0
- package/tree/index.js +3 -0
- package/tree/treestore.d.ts +117 -0
- package/tree/treestore.js +336 -0
- package/chooser/Asset.svelte +0 -83
- package/chooser/Asset.svelte.d.ts +0 -25
- package/chooser/AssetFolder.svelte +0 -127
- package/chooser/AssetFolder.svelte.d.ts +0 -25
- package/chooser/Page.svelte +0 -121
- package/chooser/Page.svelte.d.ts +0 -25
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import { ActiveStore, derivedStore } from '@txstate-mws/svelte-store';
|
|
2
|
+
import { keyby } from 'txstate-utils';
|
|
3
|
+
export const TREE_STORE_CONTEXT = {};
|
|
4
|
+
export class TreeStore extends ActiveStore {
|
|
5
|
+
fetchChildren;
|
|
6
|
+
treeElement;
|
|
7
|
+
rootItems = derivedStore(this, 'rootItems');
|
|
8
|
+
draggable = derivedStore(this, v => v.draggable && !v.loading);
|
|
9
|
+
dragging = derivedStore(this, 'dragging');
|
|
10
|
+
selectedUndraggable = derivedStore(this, 'selectedUndraggable');
|
|
11
|
+
selected = derivedStore(this, 'selected');
|
|
12
|
+
focused = derivedStore(this, 'focused');
|
|
13
|
+
copied = derivedStore(this, 'copied');
|
|
14
|
+
headerOverride = derivedStore(this, 'headerWidthOverrides');
|
|
15
|
+
moveHandler;
|
|
16
|
+
copyHandler;
|
|
17
|
+
dragEligibleHandler;
|
|
18
|
+
dropEffectHandler;
|
|
19
|
+
singleSelect;
|
|
20
|
+
refreshPromise;
|
|
21
|
+
constructor(fetchChildren, { moveHandler, copyHandler, dragEligible, dropEffect, singleSelect } = {}) {
|
|
22
|
+
super({ itemsById: {}, selected: new Map(), selectedItems: [], copied: new Map(), dragging: false, draggable: !!moveHandler, headerWidthOverrides: {} });
|
|
23
|
+
this.fetchChildren = fetchChildren;
|
|
24
|
+
this.moveHandler = moveHandler;
|
|
25
|
+
this.copyHandler = copyHandler;
|
|
26
|
+
this.dragEligibleHandler = dragEligible;
|
|
27
|
+
this.dropEffectHandler = dropEffect;
|
|
28
|
+
this.singleSelect = singleSelect;
|
|
29
|
+
}
|
|
30
|
+
async visit(item, cb) {
|
|
31
|
+
await cb(item);
|
|
32
|
+
await Promise.all((item.children ?? []).map(async (child) => await this.visit(child, cb)));
|
|
33
|
+
}
|
|
34
|
+
visitSync(item, cb) {
|
|
35
|
+
cb(item);
|
|
36
|
+
for (const child of item.children ?? [])
|
|
37
|
+
this.visitSync(child, cb);
|
|
38
|
+
}
|
|
39
|
+
addLookup(items) {
|
|
40
|
+
for (const item of items) {
|
|
41
|
+
this.visitSync(item, itm => {
|
|
42
|
+
this.value.itemsById[itm.id] = itm;
|
|
43
|
+
if (this.value.selected.has(itm.id))
|
|
44
|
+
this.value.selected.set(itm.id, itm);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
this.cleanSelected();
|
|
48
|
+
}
|
|
49
|
+
cleanSelected() {
|
|
50
|
+
for (const selected of this.value.selected.values()) {
|
|
51
|
+
if (!this.value.itemsById[selected.id])
|
|
52
|
+
this.value.selected.delete(selected.id);
|
|
53
|
+
}
|
|
54
|
+
this.determineDraggable();
|
|
55
|
+
}
|
|
56
|
+
determineDraggable() {
|
|
57
|
+
this.value.selectedItems = Array.from(this.value.selected.values());
|
|
58
|
+
this.value.selectedUndraggable = !this.dragEligible(this.value.selectedItems, true) && !this.dragEligible(this.value.selectedItems, false);
|
|
59
|
+
}
|
|
60
|
+
trigger() {
|
|
61
|
+
this.set(this.value);
|
|
62
|
+
}
|
|
63
|
+
async fetch(item) {
|
|
64
|
+
const children = await this.fetchChildren(item);
|
|
65
|
+
for (const child of children) {
|
|
66
|
+
child.level = (item?.level ?? 0) + 1;
|
|
67
|
+
child.parent = item;
|
|
68
|
+
}
|
|
69
|
+
return children;
|
|
70
|
+
}
|
|
71
|
+
async #refresh(item, skipNotify = false) {
|
|
72
|
+
if (item)
|
|
73
|
+
item.loading = true;
|
|
74
|
+
else
|
|
75
|
+
this.value.loading = true;
|
|
76
|
+
this.trigger();
|
|
77
|
+
try {
|
|
78
|
+
const children = await this.fetch(item);
|
|
79
|
+
// re-open any open children
|
|
80
|
+
await Promise.all(children.map(async (child) => await this.visit(child, async (child) => {
|
|
81
|
+
child.open = this.value.itemsById[child.id]?.open;
|
|
82
|
+
if (child.open) {
|
|
83
|
+
child.children = await this.fetch(child);
|
|
84
|
+
child.hasChildren = child.children.length > 0;
|
|
85
|
+
if (!child.hasChildren)
|
|
86
|
+
child.open = false;
|
|
87
|
+
}
|
|
88
|
+
})));
|
|
89
|
+
if (item) {
|
|
90
|
+
this.visitSync(item, itm => { if (itm.id !== item.id)
|
|
91
|
+
this.value.itemsById[itm.id] = undefined; });
|
|
92
|
+
item.children = children;
|
|
93
|
+
item.hasChildren = children.length > 0;
|
|
94
|
+
if (!item.hasChildren)
|
|
95
|
+
item.open = false;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
this.value.itemsById = {};
|
|
99
|
+
for (const child of children)
|
|
100
|
+
child.level = 1;
|
|
101
|
+
this.value.rootItems = children;
|
|
102
|
+
}
|
|
103
|
+
this.addLookup(children);
|
|
104
|
+
// if the focused item disappeared in the refresh, we need to replace it,
|
|
105
|
+
// as without a focus the tree becomes invisible to keyboard nav
|
|
106
|
+
if (!this.value.itemsById[this.value.focused?.id])
|
|
107
|
+
this.focus(this.value.selectedItems.slice(-1)[0] ?? this.value.rootItems?.[0], true);
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
if (item)
|
|
111
|
+
item.loading = false;
|
|
112
|
+
this.value.loading = false;
|
|
113
|
+
if (!skipNotify)
|
|
114
|
+
this.trigger();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async refresh(item, skipNotify = false) {
|
|
118
|
+
this.refreshPromise ??= this.#refresh(item, skipNotify);
|
|
119
|
+
await this.refreshPromise;
|
|
120
|
+
this.refreshPromise = undefined;
|
|
121
|
+
}
|
|
122
|
+
focus(item, notify = true) {
|
|
123
|
+
this.value.focused = item;
|
|
124
|
+
if (notify)
|
|
125
|
+
this.trigger();
|
|
126
|
+
}
|
|
127
|
+
select(item, { clear = false, notify = true, toggle = false }) {
|
|
128
|
+
const selected = this.isSelected(item);
|
|
129
|
+
const numSelected = this.value.selected.size;
|
|
130
|
+
if (this.singleSelect)
|
|
131
|
+
clear = true;
|
|
132
|
+
if (clear) {
|
|
133
|
+
this.value.selected.clear();
|
|
134
|
+
this.focus(item, false);
|
|
135
|
+
}
|
|
136
|
+
if (toggle && selected && (!clear || numSelected === 1))
|
|
137
|
+
this.value.selected.delete(item.id);
|
|
138
|
+
else
|
|
139
|
+
this.value.selected.set(item.id, item);
|
|
140
|
+
this.determineDraggable();
|
|
141
|
+
if (notify)
|
|
142
|
+
this.trigger();
|
|
143
|
+
}
|
|
144
|
+
selectById(id, { clear = false, notify = true, toggle = false }) {
|
|
145
|
+
const item = this.value.itemsById[id];
|
|
146
|
+
if (item)
|
|
147
|
+
this.select(item, { clear, notify, toggle });
|
|
148
|
+
}
|
|
149
|
+
deselect(notify = true) {
|
|
150
|
+
this.value.selected.clear();
|
|
151
|
+
this.determineDraggable();
|
|
152
|
+
if (notify)
|
|
153
|
+
this.trigger();
|
|
154
|
+
}
|
|
155
|
+
isSelected(item) {
|
|
156
|
+
return this.value.selected.has(item.id);
|
|
157
|
+
}
|
|
158
|
+
async open(item, notify = true) {
|
|
159
|
+
if (item.open || item.hasChildren === false)
|
|
160
|
+
return;
|
|
161
|
+
await this.openAndRefresh(item, notify);
|
|
162
|
+
}
|
|
163
|
+
async openAndRefresh(item, notify = true) {
|
|
164
|
+
await this.refresh(item, true);
|
|
165
|
+
item.open = !!item.children?.length;
|
|
166
|
+
if (notify)
|
|
167
|
+
this.trigger();
|
|
168
|
+
}
|
|
169
|
+
close(item) {
|
|
170
|
+
for (const child of item.children ?? [])
|
|
171
|
+
this.value.itemsById[child.id] = undefined;
|
|
172
|
+
this.cleanSelected();
|
|
173
|
+
item.children = undefined;
|
|
174
|
+
item.open = false;
|
|
175
|
+
this.trigger();
|
|
176
|
+
}
|
|
177
|
+
async toggle(item) {
|
|
178
|
+
if (item.open)
|
|
179
|
+
this.close(item);
|
|
180
|
+
else
|
|
181
|
+
await this.open(item);
|
|
182
|
+
}
|
|
183
|
+
async viewUnder(item) {
|
|
184
|
+
if (item)
|
|
185
|
+
await this.open(item);
|
|
186
|
+
this.trigger();
|
|
187
|
+
}
|
|
188
|
+
dragStart(item) {
|
|
189
|
+
if (this.value.dragging || !this.value.draggable)
|
|
190
|
+
return;
|
|
191
|
+
if (!this.value.selected.has(item.id)) {
|
|
192
|
+
this.select(item, { clear: true, notify: false });
|
|
193
|
+
}
|
|
194
|
+
this.value.dragging = true;
|
|
195
|
+
this.trigger();
|
|
196
|
+
}
|
|
197
|
+
async _drop(item, droppedItems, above, userWantsCopy, userWantsRecursive) {
|
|
198
|
+
const dropEffect = this._dropEffect(item, droppedItems, above, userWantsCopy);
|
|
199
|
+
if (dropEffect === 'none')
|
|
200
|
+
return false;
|
|
201
|
+
this.value.dragging = false;
|
|
202
|
+
this.value.loading = true;
|
|
203
|
+
this.trigger();
|
|
204
|
+
const selectedItems = Array.from(droppedItems.values());
|
|
205
|
+
const commonparent = this.findCommonParent([...selectedItems, item]);
|
|
206
|
+
try {
|
|
207
|
+
const result = dropEffect === 'move'
|
|
208
|
+
? await this.moveHandler(selectedItems, item, above)
|
|
209
|
+
: await this.copyHandler(selectedItems, item, above, userWantsRecursive);
|
|
210
|
+
await this.openAndRefresh(item);
|
|
211
|
+
await this.refresh(commonparent);
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
catch (e) {
|
|
215
|
+
console.error(e);
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
this.update(v => ({ ...v, loading: false }));
|
|
219
|
+
}
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
async drop(item, above, userWantsCopy) {
|
|
223
|
+
const ret = await this._drop(item, this.value.selected, above, userWantsCopy, undefined);
|
|
224
|
+
return ret;
|
|
225
|
+
}
|
|
226
|
+
collectAncestors(item) {
|
|
227
|
+
const ret = [];
|
|
228
|
+
let itm = item;
|
|
229
|
+
while (itm.parent) {
|
|
230
|
+
ret.push(itm.parent);
|
|
231
|
+
itm = itm.parent;
|
|
232
|
+
}
|
|
233
|
+
return ret;
|
|
234
|
+
}
|
|
235
|
+
root(item) {
|
|
236
|
+
let root = item;
|
|
237
|
+
while (root.parent)
|
|
238
|
+
root = root.parent;
|
|
239
|
+
return root;
|
|
240
|
+
}
|
|
241
|
+
findCommonParent(items) {
|
|
242
|
+
if (items.length <= 1)
|
|
243
|
+
return;
|
|
244
|
+
const [first, ...rest] = items;
|
|
245
|
+
const ancestors = [first, ...this.collectAncestors(first)];
|
|
246
|
+
const lookup = keyby(ancestors, 'id');
|
|
247
|
+
const depthById = ancestors.reduce((depthById, a, i) => { depthById[a.id] = i; return depthById; }, {});
|
|
248
|
+
let idx = -1;
|
|
249
|
+
for (const item of rest) {
|
|
250
|
+
const itemAncestors = this.collectAncestors(item);
|
|
251
|
+
const firstcommon = itemAncestors.find(a => lookup[a.id]);
|
|
252
|
+
if (!firstcommon)
|
|
253
|
+
return;
|
|
254
|
+
const found = depthById[firstcommon.id];
|
|
255
|
+
if (found > idx)
|
|
256
|
+
idx = found;
|
|
257
|
+
}
|
|
258
|
+
return ancestors[idx];
|
|
259
|
+
}
|
|
260
|
+
dragEligible(selectedItems, userWantsCopy) {
|
|
261
|
+
return !this.dragEligibleHandler || this.dragEligibleHandler(selectedItems, userWantsCopy);
|
|
262
|
+
}
|
|
263
|
+
_dropEffect(item, droppedItems, above, userWantsCopy) {
|
|
264
|
+
const handlerAnswer = this.dropEffectHandler?.(Array.from(droppedItems.values()), item, above, userWantsCopy) ?? 'move';
|
|
265
|
+
if (handlerAnswer === 'none')
|
|
266
|
+
return 'none';
|
|
267
|
+
if (handlerAnswer === 'move') {
|
|
268
|
+
// I could make the user's dropEffectHandler check this, but it's pretty universal that you
|
|
269
|
+
// can't move a thing into itself or one of its own descendants
|
|
270
|
+
// and it would be super weird to just automagically turn it into a copy, not to mention it would
|
|
271
|
+
// mean placing it back on itself would feel like canceling the move but make a copy instead
|
|
272
|
+
if (droppedItems.has(item.id))
|
|
273
|
+
return 'none';
|
|
274
|
+
for (const ancestor of this.collectAncestors(item)) {
|
|
275
|
+
if (droppedItems.has(ancestor.id))
|
|
276
|
+
return 'none';
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (handlerAnswer === 'move' && !this.moveHandler)
|
|
280
|
+
return 'none';
|
|
281
|
+
if (handlerAnswer === 'copy' && !this.copyHandler)
|
|
282
|
+
return 'none';
|
|
283
|
+
return handlerAnswer;
|
|
284
|
+
}
|
|
285
|
+
dropEffect(item, above, userWantsCopy) {
|
|
286
|
+
return this._dropEffect(item, this.value.selected, above, userWantsCopy);
|
|
287
|
+
}
|
|
288
|
+
cut() {
|
|
289
|
+
if (!this.cutEligible())
|
|
290
|
+
return;
|
|
291
|
+
this.value.copied = new Map(this.value.selected);
|
|
292
|
+
this.value.cut = true;
|
|
293
|
+
this.trigger();
|
|
294
|
+
}
|
|
295
|
+
copy() {
|
|
296
|
+
if (!this.copyEligible())
|
|
297
|
+
return;
|
|
298
|
+
this.value.copied = new Map(this.value.selected);
|
|
299
|
+
this.value.cut = false;
|
|
300
|
+
this.trigger();
|
|
301
|
+
}
|
|
302
|
+
cutEligible() {
|
|
303
|
+
return this.moveHandler && this.dragEligible(this.value.selectedItems, false);
|
|
304
|
+
}
|
|
305
|
+
copyEligible() {
|
|
306
|
+
return this.copyHandler && this.dragEligible(this.value.selectedItems, true);
|
|
307
|
+
}
|
|
308
|
+
cancelCopy() {
|
|
309
|
+
this.value.copied = new Map();
|
|
310
|
+
this.value.cut = undefined;
|
|
311
|
+
this.trigger();
|
|
312
|
+
}
|
|
313
|
+
pasteEligible(above = false) {
|
|
314
|
+
return this.value.copied.size && this.pasteEffect(above) !== 'none';
|
|
315
|
+
}
|
|
316
|
+
pasteEffect(above = false) {
|
|
317
|
+
return this._dropEffect(this.value.selectedItems[0], this.value.copied, above, !this.value.cut);
|
|
318
|
+
}
|
|
319
|
+
async paste(above = false, userWantsRecursive = false) {
|
|
320
|
+
if (this.pasteEffect(above) === 'none')
|
|
321
|
+
return;
|
|
322
|
+
const copied = this.value.copied;
|
|
323
|
+
const cut = this.value.cut;
|
|
324
|
+
this.value.copied = new Map();
|
|
325
|
+
this.value.cut = undefined;
|
|
326
|
+
return await this._drop(this.value.selectedItems[0], copied, above, !cut, userWantsRecursive);
|
|
327
|
+
}
|
|
328
|
+
setHeaderOverride(id, width) {
|
|
329
|
+
this.value.headerWidthOverrides[id] = `max(20px, ${width})`;
|
|
330
|
+
this.trigger();
|
|
331
|
+
}
|
|
332
|
+
resetHeaderOverride() {
|
|
333
|
+
this.value.headerWidthOverrides = {};
|
|
334
|
+
this.trigger();
|
|
335
|
+
}
|
|
336
|
+
}
|
package/chooser/Asset.svelte
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
<script>import { modifierKey } from '@txstate-mws/svelte-components';
|
|
2
|
-
import { createEventDispatcher, getContext } from 'svelte';
|
|
3
|
-
import { hashid } from 'txstate-utils';
|
|
4
|
-
import { CHOOSER_STORE_CONTEXT } from './ChooserStore';
|
|
5
|
-
import FileIcon from '../FileIcon.svelte';
|
|
6
|
-
export let asset;
|
|
7
|
-
export let level;
|
|
8
|
-
export let posinset;
|
|
9
|
-
export let setsize;
|
|
10
|
-
export let next;
|
|
11
|
-
export let prev;
|
|
12
|
-
export let parent = undefined;
|
|
13
|
-
const store = getContext(CHOOSER_STORE_CONTEXT);
|
|
14
|
-
$: id = hashid(asset.id);
|
|
15
|
-
$: haveFocus = $store?.focus === asset.id;
|
|
16
|
-
$: isPreview = $store.preview?.id === asset.id;
|
|
17
|
-
const dispatch = createEventDispatcher();
|
|
18
|
-
function onKeyDown(e) {
|
|
19
|
-
if (modifierKey(e))
|
|
20
|
-
return;
|
|
21
|
-
if (['Enter', ' '].includes(e.key)) {
|
|
22
|
-
onClick(e);
|
|
23
|
-
}
|
|
24
|
-
else if (e.key === 'ArrowDown') {
|
|
25
|
-
e.preventDefault();
|
|
26
|
-
e.stopPropagation();
|
|
27
|
-
if (next) {
|
|
28
|
-
store.setFocus(next);
|
|
29
|
-
document.getElementById(hashid(next.id)).focus();
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
else if (e.key === 'ArrowUp') {
|
|
33
|
-
e.preventDefault();
|
|
34
|
-
e.stopPropagation();
|
|
35
|
-
const anyprev = prev;
|
|
36
|
-
const myprev = anyprev?.open && anyprev.children?.length && anyprev.path === asset.path ? anyprev.children[anyprev.children.length - 1] : prev;
|
|
37
|
-
if (myprev) {
|
|
38
|
-
store.setFocus(myprev);
|
|
39
|
-
document.getElementById(hashid(myprev.id)).focus();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
else if (e.key === 'ArrowLeft') {
|
|
43
|
-
e.preventDefault();
|
|
44
|
-
e.stopPropagation();
|
|
45
|
-
if (parent) {
|
|
46
|
-
store.setFocus(parent);
|
|
47
|
-
document.getElementById(hashid(parent.id)).focus();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function onClick(e) {
|
|
52
|
-
e.preventDefault();
|
|
53
|
-
e.stopPropagation();
|
|
54
|
-
// if the id was already the same as the one that was clicked, the user
|
|
55
|
-
// has clicked it twice, so we should choose the item and end the modal
|
|
56
|
-
if ($store.preview?.id === asset.id)
|
|
57
|
-
dispatch('choose', asset);
|
|
58
|
-
else
|
|
59
|
-
store.preview(asset);
|
|
60
|
-
}
|
|
61
|
-
</script>
|
|
62
|
-
|
|
63
|
-
<li
|
|
64
|
-
{id}
|
|
65
|
-
role="treeitem"
|
|
66
|
-
tabindex={haveFocus ? 0 : -1}
|
|
67
|
-
aria-setsize={setsize}
|
|
68
|
-
aria-posinset={posinset}
|
|
69
|
-
aria-level={level}
|
|
70
|
-
aria-selected={isPreview}
|
|
71
|
-
class="dialog-asset-file"
|
|
72
|
-
class:isPreview
|
|
73
|
-
on:keydown={onKeyDown}
|
|
74
|
-
on:click={onClick}
|
|
75
|
-
>
|
|
76
|
-
<FileIcon mime={asset.mime} inline /> {asset.name}
|
|
77
|
-
</li>
|
|
78
|
-
|
|
79
|
-
<style>
|
|
80
|
-
li {
|
|
81
|
-
cursor: pointer;
|
|
82
|
-
}
|
|
83
|
-
</style>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
import type { UIAsset, UIFolder, AnyUIItem } from './ChooserStore';
|
|
3
|
-
declare const __propDef: {
|
|
4
|
-
props: {
|
|
5
|
-
asset: UIAsset;
|
|
6
|
-
level: number;
|
|
7
|
-
posinset: number;
|
|
8
|
-
setsize: number;
|
|
9
|
-
next: AnyUIItem | undefined;
|
|
10
|
-
prev: AnyUIItem | undefined;
|
|
11
|
-
parent?: UIFolder | undefined;
|
|
12
|
-
};
|
|
13
|
-
events: {
|
|
14
|
-
choose: CustomEvent<any>;
|
|
15
|
-
} & {
|
|
16
|
-
[evt: string]: CustomEvent<any>;
|
|
17
|
-
};
|
|
18
|
-
slots: {};
|
|
19
|
-
};
|
|
20
|
-
export declare type AssetProps = typeof __propDef.props;
|
|
21
|
-
export declare type AssetEvents = typeof __propDef.events;
|
|
22
|
-
export declare type AssetSlots = typeof __propDef.slots;
|
|
23
|
-
export default class Asset extends SvelteComponentTyped<AssetProps, AssetEvents, AssetSlots> {
|
|
24
|
-
}
|
|
25
|
-
export {};
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
<script>import folderOutline from '@iconify-icons/mdi/folder-outline.js';
|
|
2
|
-
import folderOpenOutline from '@iconify-icons/mdi/folder-open-outline.js';
|
|
3
|
-
import folderSyncOutline from '@iconify-icons/mdi/folder-sync-outline.js';
|
|
4
|
-
import { modifierKey } from '@txstate-mws/svelte-components';
|
|
5
|
-
import { createEventDispatcher, getContext } from 'svelte';
|
|
6
|
-
import { hashid } from 'txstate-utils';
|
|
7
|
-
import { CHOOSER_STORE_CONTEXT } from './ChooserStore';
|
|
8
|
-
import Asset from './Asset.svelte';
|
|
9
|
-
import Icon from '../Icon.svelte';
|
|
10
|
-
export let folder;
|
|
11
|
-
export let level;
|
|
12
|
-
export let posinset;
|
|
13
|
-
export let setsize;
|
|
14
|
-
export let next;
|
|
15
|
-
export let prev;
|
|
16
|
-
export let parent = undefined;
|
|
17
|
-
const store = getContext(CHOOSER_STORE_CONTEXT);
|
|
18
|
-
$: open = folder.open && folder.children?.length;
|
|
19
|
-
$: nextlevel = level + 1;
|
|
20
|
-
$: id = hashid(folder.id);
|
|
21
|
-
$: haveFocus = $store.focus === folder.id;
|
|
22
|
-
$: isPreview = $store.preview?.id === folder.id;
|
|
23
|
-
const dispatch = createEventDispatcher();
|
|
24
|
-
function onKeyDown(e) {
|
|
25
|
-
if (modifierKey(e))
|
|
26
|
-
return;
|
|
27
|
-
if (['Enter', ' '].includes(e.key)) {
|
|
28
|
-
onClick(e);
|
|
29
|
-
}
|
|
30
|
-
else if (e.key === 'ArrowRight') {
|
|
31
|
-
e.preventDefault();
|
|
32
|
-
e.stopPropagation();
|
|
33
|
-
if (folder.open && folder.children?.length) {
|
|
34
|
-
const child = folder.children[0];
|
|
35
|
-
store.setFocus(child);
|
|
36
|
-
document.getElementById(hashid(child.id)).focus();
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
store.open(folder);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
else if (e.key === 'ArrowLeft') {
|
|
43
|
-
e.preventDefault();
|
|
44
|
-
e.stopPropagation();
|
|
45
|
-
if (folder.open) {
|
|
46
|
-
store.close(folder);
|
|
47
|
-
}
|
|
48
|
-
else if (parent) {
|
|
49
|
-
store.setFocus(parent);
|
|
50
|
-
document.getElementById(hashid(parent.id)).focus();
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
else if (e.key === 'ArrowDown') {
|
|
54
|
-
e.preventDefault();
|
|
55
|
-
e.stopPropagation();
|
|
56
|
-
const mynext = open ? folder.children[0] : next;
|
|
57
|
-
if (mynext) {
|
|
58
|
-
store.setFocus(mynext);
|
|
59
|
-
document.getElementById(hashid(mynext.id)).focus();
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
else if (e.key === 'ArrowUp') {
|
|
63
|
-
e.preventDefault();
|
|
64
|
-
e.stopPropagation();
|
|
65
|
-
const anyprev = prev;
|
|
66
|
-
const myprev = anyprev?.open && anyprev.children?.length && anyprev.path === folder.path ? anyprev.children[anyprev.children.length - 1] : prev;
|
|
67
|
-
if (myprev) {
|
|
68
|
-
store.setFocus(myprev);
|
|
69
|
-
document.getElementById(hashid(myprev.id)).focus();
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
function onClick(e) {
|
|
74
|
-
e.preventDefault();
|
|
75
|
-
e.stopPropagation();
|
|
76
|
-
// if the id was already the same as the one that was clicked, the user
|
|
77
|
-
// has clicked it twice, so we should choose the item and end the modal
|
|
78
|
-
if ($store.preview?.id === folder.id)
|
|
79
|
-
dispatch('choose', folder);
|
|
80
|
-
else {
|
|
81
|
-
store.preview(folder);
|
|
82
|
-
store.toggle(folder);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
</script>
|
|
86
|
-
|
|
87
|
-
<li
|
|
88
|
-
{id}
|
|
89
|
-
role="treeitem"
|
|
90
|
-
class:isPreview
|
|
91
|
-
aria-expanded={!!folder.open}
|
|
92
|
-
aria-selected={isPreview}
|
|
93
|
-
aria-level={level}
|
|
94
|
-
aria-setsize={setsize}
|
|
95
|
-
aria-posinset={posinset}
|
|
96
|
-
aria-busy={folder.loading}
|
|
97
|
-
tabindex={haveFocus ? 0 : -1}
|
|
98
|
-
on:keydown={onKeyDown}
|
|
99
|
-
on:click={onClick}
|
|
100
|
-
>
|
|
101
|
-
<Icon icon={folder.open ? folderOpenOutline : (folder.loading ? folderSyncOutline : folderOutline)} inline /> {folder.name}
|
|
102
|
-
</li>
|
|
103
|
-
{#if open}
|
|
104
|
-
<ul role="group" class="dialog-asset-sublist">
|
|
105
|
-
{#each folder.children as child, i (child.id)}
|
|
106
|
-
{@const setsize = folder.children.length}
|
|
107
|
-
{@const posinset = i + 1}
|
|
108
|
-
{@const subprev = i === 0 ? folder : folder.children[i - 1]}
|
|
109
|
-
{@const subnext = i === setsize - 1 ? next : folder.children[i + 1]}
|
|
110
|
-
{#if child.type === 'folder'}
|
|
111
|
-
<svelte:self folder={child} {setsize} {posinset} level={nextlevel} prev={subprev} next={subnext} parent={folder} on:choose />
|
|
112
|
-
{:else}
|
|
113
|
-
<Asset asset={child} {setsize} {posinset} level={nextlevel} prev={subprev} next={subnext} parent={folder} on:choose />
|
|
114
|
-
{/if}
|
|
115
|
-
{/each}
|
|
116
|
-
</ul>
|
|
117
|
-
{/if}
|
|
118
|
-
|
|
119
|
-
<style>
|
|
120
|
-
.dialog-asset-sublist {
|
|
121
|
-
list-style: none;
|
|
122
|
-
padding-left: 1em;
|
|
123
|
-
}
|
|
124
|
-
li {
|
|
125
|
-
cursor: pointer;
|
|
126
|
-
}
|
|
127
|
-
</style>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
import type { UIFolder, AnyUIItem } from './ChooserStore';
|
|
3
|
-
declare const __propDef: {
|
|
4
|
-
props: {
|
|
5
|
-
folder: UIFolder;
|
|
6
|
-
level: number;
|
|
7
|
-
posinset: number;
|
|
8
|
-
setsize: number;
|
|
9
|
-
next: AnyUIItem | undefined;
|
|
10
|
-
prev: AnyUIItem | undefined;
|
|
11
|
-
parent?: UIFolder | undefined;
|
|
12
|
-
};
|
|
13
|
-
events: {
|
|
14
|
-
choose: CustomEvent<any>;
|
|
15
|
-
} & {
|
|
16
|
-
[evt: string]: CustomEvent<any>;
|
|
17
|
-
};
|
|
18
|
-
slots: {};
|
|
19
|
-
};
|
|
20
|
-
export declare type AssetFolderProps = typeof __propDef.props;
|
|
21
|
-
export declare type AssetFolderEvents = typeof __propDef.events;
|
|
22
|
-
export declare type AssetFolderSlots = typeof __propDef.slots;
|
|
23
|
-
export default class AssetFolder extends SvelteComponentTyped<AssetFolderProps, AssetFolderEvents, AssetFolderSlots> {
|
|
24
|
-
}
|
|
25
|
-
export {};
|