@sveltia/ui 0.62.0 → 0.63.0
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/dist/components/button/button.svelte +6 -1
- package/dist/components/resizable-pane/resizable-handle.svelte +12 -3
- package/dist/components/select/select-tags.svelte +8 -1
- package/dist/components/text-editor/constants.d.ts +0 -1
- package/dist/components/text-editor/constants.js +1 -36
- package/dist/components/text-editor/core.js +24 -31
- package/dist/components/text-editor/lexical-root.svelte +0 -68
- package/dist/components/text-editor/shiki/cache.d.ts +3 -0
- package/dist/components/text-editor/shiki/cache.js +121 -0
- package/dist/components/text-editor/shiki/engine-entry.d.ts +2 -0
- package/dist/components/text-editor/shiki/engine-entry.js +20 -0
- package/dist/components/text-editor/shiki/facade.d.ts +16 -0
- package/dist/components/text-editor/shiki/facade.js +452 -0
- package/dist/components/text-editor/shiki/generated.d.ts +28 -0
- package/dist/components/text-editor/shiki/generated.js +25 -0
- package/dist/components/text-editor/shiki/highlighter.d.ts +11 -0
- package/dist/components/text-editor/shiki/highlighter.js +477 -0
- package/dist/components/text-editor/shiki/loader.d.ts +6 -0
- package/dist/components/text-editor/shiki/loader.js +102 -0
- package/dist/components/text-editor/shiki/theme.d.ts +12 -0
- package/dist/components/text-editor/shiki/theme.js +86 -0
- package/dist/components/text-editor/toolbar/code-language-switcher.svelte +24 -34
- package/dist/components/text-editor/toolbar/toggle-block-menu-item.svelte +1 -5
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/services/group.svelte.d.ts +2 -1
- package/dist/services/group.svelte.js +183 -50
- package/dist/services/tree.svelte.d.ts +8 -6
- package/dist/services/tree.svelte.js +104 -45
- package/dist/shiki-engine.js +152 -0
- package/dist/typedefs.d.ts +52 -0
- package/dist/typedefs.js +29 -0
- package/package.json +13 -11
|
@@ -16,10 +16,6 @@ const TYPE_AHEAD_TIMEOUT = 500;
|
|
|
16
16
|
* CSS selector to retrieve the tree items.
|
|
17
17
|
*/
|
|
18
18
|
const ITEM_SELECTOR = '[role="treeitem"]';
|
|
19
|
-
/**
|
|
20
|
-
* CSS selector to retrieve the tree item containers, including the widget root.
|
|
21
|
-
*/
|
|
22
|
-
const GROUP_SELECTOR = '[role="group"], [role="tree"]';
|
|
23
19
|
|
|
24
20
|
/**
|
|
25
21
|
* Implement keyboard and mouse interactions for the `tree` composite widget, following the ARIA
|
|
@@ -164,9 +160,48 @@ export class Tree {
|
|
|
164
160
|
* @type {HTMLElement[]}
|
|
165
161
|
*/
|
|
166
162
|
get visibleItems() {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
163
|
+
/** @type {HTMLElement[]} */
|
|
164
|
+
const items = [];
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Collect the items below the given node in document order, descending only into the parents
|
|
168
|
+
* that are actually expanded. Pruning the collapsed subtrees outright is what keeps this
|
|
169
|
+
* proportional to the number of displayed items; testing each item in the tree for a collapsed
|
|
170
|
+
* ancestor instead costs a walk back up per item.
|
|
171
|
+
* @param {Element} node Node whose children to scan.
|
|
172
|
+
*/
|
|
173
|
+
const collect = (node) => {
|
|
174
|
+
[...node.children].forEach((child) => {
|
|
175
|
+
if (child.getAttribute('role') !== 'treeitem') {
|
|
176
|
+
// Anything else is a wrapper to see through — including a group that no item owns, whose
|
|
177
|
+
// items sit at the level of the group itself
|
|
178
|
+
collect(child);
|
|
179
|
+
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const item = /** @type {HTMLElement} */ (child);
|
|
184
|
+
|
|
185
|
+
if (!item.matches('[hidden], [aria-hidden="true"]')) {
|
|
186
|
+
items.push(item);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// A collapsed parent hides everything below it, so there is nothing to descend into
|
|
190
|
+
if (this.isParent(item) && !this.isExpanded(item)) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const group = this.getGroup(item);
|
|
195
|
+
|
|
196
|
+
if (group) {
|
|
197
|
+
collect(group);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
collect(this.parent);
|
|
203
|
+
|
|
204
|
+
return items;
|
|
170
205
|
}
|
|
171
206
|
|
|
172
207
|
/**
|
|
@@ -182,7 +217,9 @@ export class Tree {
|
|
|
182
217
|
* @type {HTMLElement[]}
|
|
183
218
|
*/
|
|
184
219
|
get selectedItems() {
|
|
185
|
-
return
|
|
220
|
+
return /** @type {HTMLElement[]} */ ([
|
|
221
|
+
...this.parent.querySelectorAll(`${ITEM_SELECTOR}[aria-selected="true"]`),
|
|
222
|
+
]);
|
|
186
223
|
}
|
|
187
224
|
|
|
188
225
|
/**
|
|
@@ -221,9 +258,31 @@ export class Tree {
|
|
|
221
258
|
* @returns {HTMLElement[]} Child items.
|
|
222
259
|
*/
|
|
223
260
|
getItemsInGroup(group) {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
261
|
+
/** @type {HTMLElement[]} */
|
|
262
|
+
const items = [];
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Scan the children of the given node, descending through plain wrapper elements but never into
|
|
266
|
+
* an item or a nested group — whatever lies below those belongs to the item that owns them.
|
|
267
|
+
* Querying the whole subtree and then discarding the deeper items with a `closest()` call each
|
|
268
|
+
* costs `update()`, which runs this once per group, quadratic time overall.
|
|
269
|
+
* @param {Element} node Node whose children to scan.
|
|
270
|
+
*/
|
|
271
|
+
const walk = (node) => {
|
|
272
|
+
[...node.children].forEach((child) => {
|
|
273
|
+
const role = child.getAttribute('role');
|
|
274
|
+
|
|
275
|
+
if (role === 'treeitem') {
|
|
276
|
+
items.push(/** @type {HTMLElement} */ (child));
|
|
277
|
+
} else if (role !== 'group' && role !== 'tree') {
|
|
278
|
+
walk(child);
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
walk(group);
|
|
284
|
+
|
|
285
|
+
return items;
|
|
227
286
|
}
|
|
228
287
|
|
|
229
288
|
/**
|
|
@@ -255,25 +314,6 @@ export class Tree {
|
|
|
255
314
|
return item.getAttribute('aria-expanded') === 'true';
|
|
256
315
|
}
|
|
257
316
|
|
|
258
|
-
/**
|
|
259
|
-
* Whether any of the ancestors of the given item is collapsed, meaning the item is not displayed.
|
|
260
|
-
* @param {HTMLElement} item Item.
|
|
261
|
-
* @returns {boolean} Result.
|
|
262
|
-
*/
|
|
263
|
-
hasCollapsedAncestor(item) {
|
|
264
|
-
let ancestor = this.getParentItem(item);
|
|
265
|
-
|
|
266
|
-
while (ancestor) {
|
|
267
|
-
if (!this.isExpanded(ancestor)) {
|
|
268
|
-
return true;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
ancestor = this.getParentItem(ancestor);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
return false;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
317
|
/**
|
|
278
318
|
* Get the text label of the given item, which is used for the type-ahead search.
|
|
279
319
|
* @param {HTMLElement} item Item.
|
|
@@ -316,12 +356,10 @@ export class Tree {
|
|
|
316
356
|
const current =
|
|
317
357
|
activeItems.find((item) => item === document.activeElement) ??
|
|
318
358
|
activeItems.find((item) => item.tabIndex === 0) ??
|
|
319
|
-
activeItems.find((item) => item.
|
|
359
|
+
activeItems.find((item) => item.getAttribute('aria-selected') === 'true') ??
|
|
320
360
|
activeItems[0];
|
|
321
361
|
|
|
322
|
-
|
|
323
|
-
item.tabIndex = item === current ? 0 : -1;
|
|
324
|
-
});
|
|
362
|
+
this.setTabStop(current);
|
|
325
363
|
}
|
|
326
364
|
|
|
327
365
|
/**
|
|
@@ -336,6 +374,27 @@ export class Tree {
|
|
|
336
374
|
}
|
|
337
375
|
}
|
|
338
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Put exactly one item in the tab order. Only the items actually in it are touched: writing a
|
|
379
|
+
* `tabindex` to every item costs a pass over the whole widget on each arrow key, and all but one
|
|
380
|
+
* of those writes set the value the item already had.
|
|
381
|
+
* @param {HTMLElement} [item] Item to become the tab stop. When omitted, no item is left in the
|
|
382
|
+
* tab order, which is the case for a tree with nothing to focus.
|
|
383
|
+
*/
|
|
384
|
+
setTabStop(item) {
|
|
385
|
+
this.parent
|
|
386
|
+
.querySelectorAll(`${ITEM_SELECTOR}[tabindex]:not([tabindex="-1"])`)
|
|
387
|
+
.forEach((element) => {
|
|
388
|
+
if (element !== item) {
|
|
389
|
+
/** @type {HTMLElement} */ (element).tabIndex = -1;
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
if (item) {
|
|
394
|
+
item.tabIndex = 0;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
339
398
|
/**
|
|
340
399
|
* Move focus to the given item.
|
|
341
400
|
* @param {HTMLElement} item Item to be focused.
|
|
@@ -344,10 +403,7 @@ export class Tree {
|
|
|
344
403
|
* `selectionFollowsFocus` option.
|
|
345
404
|
*/
|
|
346
405
|
focusItem(item, { select = this.selectionFollowsFocus } = {}) {
|
|
347
|
-
this.
|
|
348
|
-
element.tabIndex = element === item ? 0 : -1;
|
|
349
|
-
});
|
|
350
|
-
|
|
406
|
+
this.setTabStop(item);
|
|
351
407
|
item.focus();
|
|
352
408
|
item.dispatchEvent(new CustomEvent('Focus'));
|
|
353
409
|
this.scrollIntoView(item);
|
|
@@ -363,7 +419,7 @@ export class Tree {
|
|
|
363
419
|
* @param {boolean} selected Whether to select the item.
|
|
364
420
|
*/
|
|
365
421
|
setSelected(item, selected) {
|
|
366
|
-
if (item.
|
|
422
|
+
if ((item.getAttribute('aria-selected') === 'true') === selected) {
|
|
367
423
|
return;
|
|
368
424
|
}
|
|
369
425
|
|
|
@@ -402,13 +458,18 @@ export class Tree {
|
|
|
402
458
|
);
|
|
403
459
|
});
|
|
404
460
|
} else if (multi && additive) {
|
|
405
|
-
this.setSelected(item,
|
|
461
|
+
this.setSelected(item, item.getAttribute('aria-selected') !== 'true');
|
|
406
462
|
this.anchor = item;
|
|
407
463
|
} else {
|
|
408
|
-
|
|
409
|
-
|
|
464
|
+
// Only the items that are actually selected need clearing; running every item in the tree
|
|
465
|
+
// through `setSelected()` would leave all but one of them untouched anyway
|
|
466
|
+
this.selectedItems.forEach((element) => {
|
|
467
|
+
if (element !== item) {
|
|
468
|
+
this.setSelected(element, false);
|
|
469
|
+
}
|
|
410
470
|
});
|
|
411
471
|
|
|
472
|
+
this.setSelected(item, true);
|
|
412
473
|
this.anchor = item;
|
|
413
474
|
}
|
|
414
475
|
|
|
@@ -517,9 +578,7 @@ export class Tree {
|
|
|
517
578
|
return;
|
|
518
579
|
}
|
|
519
580
|
|
|
520
|
-
this.
|
|
521
|
-
element.tabIndex = element === item ? 0 : -1;
|
|
522
|
-
});
|
|
581
|
+
this.setTabStop(item);
|
|
523
582
|
}
|
|
524
583
|
|
|
525
584
|
/**
|