@selkit/dom 0.2.0 → 0.4.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/index.cjs +105 -31
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +112 -32
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -72,6 +72,7 @@ function attachPositioner(trigger, dropdown, autoWidth = false) {
|
|
|
72
72
|
// src/dom.ts
|
|
73
73
|
var LOAD_MORE_THRESHOLD = 32;
|
|
74
74
|
var DEFAULT_ITEM_HEIGHT = 36;
|
|
75
|
+
var DEFAULT_GROUP_HEIGHT = 28;
|
|
75
76
|
var SR_ONLY_CSS = "position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0";
|
|
76
77
|
function resolveParent(parent) {
|
|
77
78
|
if (!parent) return null;
|
|
@@ -152,6 +153,7 @@ var SelkitDom = class {
|
|
|
152
153
|
#name;
|
|
153
154
|
#virtual;
|
|
154
155
|
#itemHeight;
|
|
156
|
+
#groupHeight;
|
|
155
157
|
#dropdownParent;
|
|
156
158
|
#templateSelection;
|
|
157
159
|
#templateOption;
|
|
@@ -170,6 +172,8 @@ var SelkitDom = class {
|
|
|
170
172
|
#hiddenContainer = null;
|
|
171
173
|
#selectPrevDisplay = "";
|
|
172
174
|
#dragFrom = -1;
|
|
175
|
+
/** 上次已捲入可視的 activeIndex 僅在變動時才捲 避免跟使用者手動捲動打架 */
|
|
176
|
+
#lastActive = -1;
|
|
173
177
|
#positioner = null;
|
|
174
178
|
#unsubscribe;
|
|
175
179
|
#offClose;
|
|
@@ -194,6 +198,7 @@ var SelkitDom = class {
|
|
|
194
198
|
this.#name = cfg.name;
|
|
195
199
|
this.#virtual = cfg.virtualScroll ?? false;
|
|
196
200
|
this.#itemHeight = cfg.itemHeight ?? DEFAULT_ITEM_HEIGHT;
|
|
201
|
+
this.#groupHeight = cfg.groupHeight ?? DEFAULT_GROUP_HEIGHT;
|
|
197
202
|
this.#dropdownParent = resolveParent(cfg.dropdownParent);
|
|
198
203
|
this.#templateSelection = cfg.templateSelection;
|
|
199
204
|
this.#templateOption = cfg.templateOption;
|
|
@@ -442,6 +447,54 @@ var SelkitDom = class {
|
|
|
442
447
|
this.#syncForm();
|
|
443
448
|
this.element.classList.toggle(this.#cls("", "open"), s.isOpen);
|
|
444
449
|
this.element.classList.toggle(this.#cls("", "disabled"), s.disabled);
|
|
450
|
+
this.#scrollActiveIntoView(s);
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* 鍵盤導航/開啟時讓作用中選項保持可見(aria-activedescendant 完整度)
|
|
454
|
+
* 僅在 activeIndex 變動時動作 手動捲動觸發的重繪不會跟著捲
|
|
455
|
+
*/
|
|
456
|
+
#scrollActiveIntoView(s) {
|
|
457
|
+
if (!s.isOpen) {
|
|
458
|
+
this.#lastActive = -1;
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if (s.activeIndex === this.#lastActive || s.activeIndex < 0) return;
|
|
462
|
+
this.#lastActive = s.activeIndex;
|
|
463
|
+
const rows = this.controller.getGroupedView().rows;
|
|
464
|
+
const hasGroups = rows.some((r) => r.type === "group");
|
|
465
|
+
if (this.#virtual && !hasGroups) {
|
|
466
|
+
const next = (0, import_core.computeScrollIntoView)({
|
|
467
|
+
index: s.activeIndex,
|
|
468
|
+
scrollTop: this.#dropdown.scrollTop,
|
|
469
|
+
viewportHeight: this.#dropdown.clientHeight,
|
|
470
|
+
itemHeight: this.#itemHeight
|
|
471
|
+
});
|
|
472
|
+
if (next !== null) {
|
|
473
|
+
this.#dropdown.scrollTop = next;
|
|
474
|
+
this.#renderOptions(s);
|
|
475
|
+
}
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
if (this.#virtual && hasGroups) {
|
|
479
|
+
const rowIndex = rows.findIndex(
|
|
480
|
+
(r) => r.type !== "group" && r.index === s.activeIndex
|
|
481
|
+
);
|
|
482
|
+
const next = (0, import_core.computeScrollIntoViewVariable)({
|
|
483
|
+
heights: this.#rowHeights(rows),
|
|
484
|
+
rowIndex,
|
|
485
|
+
scrollTop: this.#dropdown.scrollTop,
|
|
486
|
+
viewportHeight: this.#dropdown.clientHeight
|
|
487
|
+
});
|
|
488
|
+
if (next !== null) {
|
|
489
|
+
this.#dropdown.scrollTop = next;
|
|
490
|
+
this.#renderOptions(s);
|
|
491
|
+
}
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
const active = this.#dropdown.querySelector(
|
|
495
|
+
`.${this.#cls("option", "active")}`
|
|
496
|
+
);
|
|
497
|
+
active?.scrollIntoView?.({ block: "nearest" });
|
|
445
498
|
}
|
|
446
499
|
/** 套用模板輸出:字串走 textContent(防 XSS)Node 直接掛入 */
|
|
447
500
|
#applyTemplate(host, out) {
|
|
@@ -555,40 +608,61 @@ var SelkitDom = class {
|
|
|
555
608
|
itemHeight: this.#itemHeight,
|
|
556
609
|
itemCount: view.rows.length
|
|
557
610
|
});
|
|
558
|
-
this.#
|
|
559
|
-
for (let i = range.startIndex; i < range.endIndex; i++) {
|
|
560
|
-
const row = view.rows[i];
|
|
561
|
-
if (row?.type === "option") {
|
|
562
|
-
this.#dropdown.append(this.#buildOption(row, a11y, s.activeIndex));
|
|
563
|
-
} else if (row?.type === "create") {
|
|
564
|
-
this.#dropdown.append(this.#buildCreateRow(row, a11y, s.activeIndex));
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
this.#dropdown.append(this.#spacer(range.paddingBottom));
|
|
611
|
+
this.#renderVirtualSlice(view.rows, range, a11y, s.activeIndex);
|
|
568
612
|
return;
|
|
569
613
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
614
|
+
if (this.#virtual && hasGroups) {
|
|
615
|
+
const win = (0, import_core.computeVirtualWindow)({
|
|
616
|
+
heights: this.#rowHeights(view.rows),
|
|
617
|
+
scrollTop: this.#dropdown.scrollTop,
|
|
618
|
+
viewportHeight: this.#dropdown.clientHeight
|
|
619
|
+
});
|
|
620
|
+
this.#renderVirtualSlice(view.rows, win, a11y, s.activeIndex);
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
for (const row of view.rows) this.#renderRow(row, a11y, s.activeIndex);
|
|
624
|
+
}
|
|
625
|
+
/** 每列高度:分組標題用 groupHeight 其餘(option/create)用 itemHeight */
|
|
626
|
+
#rowHeights(rows) {
|
|
627
|
+
return rows.map(
|
|
628
|
+
(r) => r.type === "group" ? this.#groupHeight : this.#itemHeight
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
/** 渲染虛擬切片:上下佔位 + range 內各列 共用扁平與分組兩路徑 */
|
|
632
|
+
#renderVirtualSlice(rows, range, a11y, activeIndex) {
|
|
633
|
+
this.#dropdown.append(this.#spacer(range.paddingTop));
|
|
634
|
+
for (let i = range.startIndex; i < range.endIndex; i++) {
|
|
635
|
+
const row = rows[i];
|
|
636
|
+
if (row) this.#renderRow(row, a11y, activeIndex);
|
|
637
|
+
}
|
|
638
|
+
this.#dropdown.append(this.#spacer(range.paddingBottom));
|
|
639
|
+
}
|
|
640
|
+
/** 依列型別渲染並掛入下拉 group / create / option */
|
|
641
|
+
#renderRow(row, a11y, activeIndex) {
|
|
642
|
+
if (row.type === "group") {
|
|
643
|
+
this.#dropdown.append(this.#buildGroupRow(row));
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
if (row.type === "create") {
|
|
647
|
+
this.#dropdown.append(this.#buildCreateRow(row, a11y, activeIndex));
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
this.#dropdown.append(this.#buildOption(row, a11y, activeIndex));
|
|
651
|
+
}
|
|
652
|
+
/** 分組標題列 套用 templateGroup(無則用 label)*/
|
|
653
|
+
#buildGroupRow(row) {
|
|
654
|
+
const group = document.createElement("div");
|
|
655
|
+
group.className = this.#cls("group");
|
|
656
|
+
if (row.disabled) group.classList.add(this.#cls("group", "disabled"));
|
|
657
|
+
if (this.#templateGroup) {
|
|
658
|
+
this.#applyTemplate(
|
|
659
|
+
group,
|
|
660
|
+
this.#templateGroup({ label: row.label, disabled: !!row.disabled })
|
|
661
|
+
);
|
|
662
|
+
} else {
|
|
663
|
+
group.textContent = row.label;
|
|
591
664
|
}
|
|
665
|
+
return group;
|
|
592
666
|
}
|
|
593
667
|
/** 「建立新項」列 共用 option 樣式與 a11y 但點擊走 createTag */
|
|
594
668
|
#buildCreateRow(row, a11y, activeIndex) {
|
package/dist/index.d.cts
CHANGED
|
@@ -15,6 +15,8 @@ interface SelkitDomConfig<T = unknown> extends SelkitConfig<T> {
|
|
|
15
15
|
virtualScroll?: boolean;
|
|
16
16
|
/** 虛擬捲動的單列固定高度 px 預設 36 須與實際樣式高度一致 */
|
|
17
17
|
itemHeight?: number;
|
|
18
|
+
/** 虛擬捲動下分組標題列的固定高度 px 預設 28 須與實際樣式高度一致 */
|
|
19
|
+
groupHeight?: number;
|
|
18
20
|
/** 把下拉浮層掛到指定容器(元素或選擇器)逃離 overflow/transform 祖先的裁切 常用 document.body */
|
|
19
21
|
dropdownParent?: HTMLElement | string;
|
|
20
22
|
/** 自訂已選顯示內容(tag 或單值) 回傳字串走 textContent 防 XSS 需 markup(icon 等)請回傳 Node */
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ interface SelkitDomConfig<T = unknown> extends SelkitConfig<T> {
|
|
|
15
15
|
virtualScroll?: boolean;
|
|
16
16
|
/** 虛擬捲動的單列固定高度 px 預設 36 須與實際樣式高度一致 */
|
|
17
17
|
itemHeight?: number;
|
|
18
|
+
/** 虛擬捲動下分組標題列的固定高度 px 預設 28 須與實際樣式高度一致 */
|
|
19
|
+
groupHeight?: number;
|
|
18
20
|
/** 把下拉浮層掛到指定容器(元素或選擇器)逃離 overflow/transform 祖先的裁切 常用 document.body */
|
|
19
21
|
dropdownParent?: HTMLElement | string;
|
|
20
22
|
/** 自訂已選顯示內容(tag 或單值) 回傳字串走 textContent 防 XSS 需 markup(icon 等)請回傳 Node */
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
// src/dom.ts
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
computeScrollIntoView,
|
|
4
|
+
computeScrollIntoViewVariable,
|
|
5
|
+
computeVirtualRange,
|
|
6
|
+
computeVirtualWindow,
|
|
7
|
+
createSelkit
|
|
8
|
+
} from "@selkit/core";
|
|
3
9
|
|
|
4
10
|
// src/positioner.ts
|
|
5
11
|
function computePosition(triggerRect, dropdownHeight, viewportHeight, gap = 4) {
|
|
@@ -41,6 +47,7 @@ function attachPositioner(trigger, dropdown, autoWidth = false) {
|
|
|
41
47
|
// src/dom.ts
|
|
42
48
|
var LOAD_MORE_THRESHOLD = 32;
|
|
43
49
|
var DEFAULT_ITEM_HEIGHT = 36;
|
|
50
|
+
var DEFAULT_GROUP_HEIGHT = 28;
|
|
44
51
|
var SR_ONLY_CSS = "position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0";
|
|
45
52
|
function resolveParent(parent) {
|
|
46
53
|
if (!parent) return null;
|
|
@@ -121,6 +128,7 @@ var SelkitDom = class {
|
|
|
121
128
|
#name;
|
|
122
129
|
#virtual;
|
|
123
130
|
#itemHeight;
|
|
131
|
+
#groupHeight;
|
|
124
132
|
#dropdownParent;
|
|
125
133
|
#templateSelection;
|
|
126
134
|
#templateOption;
|
|
@@ -139,6 +147,8 @@ var SelkitDom = class {
|
|
|
139
147
|
#hiddenContainer = null;
|
|
140
148
|
#selectPrevDisplay = "";
|
|
141
149
|
#dragFrom = -1;
|
|
150
|
+
/** 上次已捲入可視的 activeIndex 僅在變動時才捲 避免跟使用者手動捲動打架 */
|
|
151
|
+
#lastActive = -1;
|
|
142
152
|
#positioner = null;
|
|
143
153
|
#unsubscribe;
|
|
144
154
|
#offClose;
|
|
@@ -163,6 +173,7 @@ var SelkitDom = class {
|
|
|
163
173
|
this.#name = cfg.name;
|
|
164
174
|
this.#virtual = cfg.virtualScroll ?? false;
|
|
165
175
|
this.#itemHeight = cfg.itemHeight ?? DEFAULT_ITEM_HEIGHT;
|
|
176
|
+
this.#groupHeight = cfg.groupHeight ?? DEFAULT_GROUP_HEIGHT;
|
|
166
177
|
this.#dropdownParent = resolveParent(cfg.dropdownParent);
|
|
167
178
|
this.#templateSelection = cfg.templateSelection;
|
|
168
179
|
this.#templateOption = cfg.templateOption;
|
|
@@ -411,6 +422,54 @@ var SelkitDom = class {
|
|
|
411
422
|
this.#syncForm();
|
|
412
423
|
this.element.classList.toggle(this.#cls("", "open"), s.isOpen);
|
|
413
424
|
this.element.classList.toggle(this.#cls("", "disabled"), s.disabled);
|
|
425
|
+
this.#scrollActiveIntoView(s);
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* 鍵盤導航/開啟時讓作用中選項保持可見(aria-activedescendant 完整度)
|
|
429
|
+
* 僅在 activeIndex 變動時動作 手動捲動觸發的重繪不會跟著捲
|
|
430
|
+
*/
|
|
431
|
+
#scrollActiveIntoView(s) {
|
|
432
|
+
if (!s.isOpen) {
|
|
433
|
+
this.#lastActive = -1;
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
if (s.activeIndex === this.#lastActive || s.activeIndex < 0) return;
|
|
437
|
+
this.#lastActive = s.activeIndex;
|
|
438
|
+
const rows = this.controller.getGroupedView().rows;
|
|
439
|
+
const hasGroups = rows.some((r) => r.type === "group");
|
|
440
|
+
if (this.#virtual && !hasGroups) {
|
|
441
|
+
const next = computeScrollIntoView({
|
|
442
|
+
index: s.activeIndex,
|
|
443
|
+
scrollTop: this.#dropdown.scrollTop,
|
|
444
|
+
viewportHeight: this.#dropdown.clientHeight,
|
|
445
|
+
itemHeight: this.#itemHeight
|
|
446
|
+
});
|
|
447
|
+
if (next !== null) {
|
|
448
|
+
this.#dropdown.scrollTop = next;
|
|
449
|
+
this.#renderOptions(s);
|
|
450
|
+
}
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
if (this.#virtual && hasGroups) {
|
|
454
|
+
const rowIndex = rows.findIndex(
|
|
455
|
+
(r) => r.type !== "group" && r.index === s.activeIndex
|
|
456
|
+
);
|
|
457
|
+
const next = computeScrollIntoViewVariable({
|
|
458
|
+
heights: this.#rowHeights(rows),
|
|
459
|
+
rowIndex,
|
|
460
|
+
scrollTop: this.#dropdown.scrollTop,
|
|
461
|
+
viewportHeight: this.#dropdown.clientHeight
|
|
462
|
+
});
|
|
463
|
+
if (next !== null) {
|
|
464
|
+
this.#dropdown.scrollTop = next;
|
|
465
|
+
this.#renderOptions(s);
|
|
466
|
+
}
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
const active = this.#dropdown.querySelector(
|
|
470
|
+
`.${this.#cls("option", "active")}`
|
|
471
|
+
);
|
|
472
|
+
active?.scrollIntoView?.({ block: "nearest" });
|
|
414
473
|
}
|
|
415
474
|
/** 套用模板輸出:字串走 textContent(防 XSS)Node 直接掛入 */
|
|
416
475
|
#applyTemplate(host, out) {
|
|
@@ -524,40 +583,61 @@ var SelkitDom = class {
|
|
|
524
583
|
itemHeight: this.#itemHeight,
|
|
525
584
|
itemCount: view.rows.length
|
|
526
585
|
});
|
|
527
|
-
this.#
|
|
528
|
-
for (let i = range.startIndex; i < range.endIndex; i++) {
|
|
529
|
-
const row = view.rows[i];
|
|
530
|
-
if (row?.type === "option") {
|
|
531
|
-
this.#dropdown.append(this.#buildOption(row, a11y, s.activeIndex));
|
|
532
|
-
} else if (row?.type === "create") {
|
|
533
|
-
this.#dropdown.append(this.#buildCreateRow(row, a11y, s.activeIndex));
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
this.#dropdown.append(this.#spacer(range.paddingBottom));
|
|
586
|
+
this.#renderVirtualSlice(view.rows, range, a11y, s.activeIndex);
|
|
537
587
|
return;
|
|
538
588
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
589
|
+
if (this.#virtual && hasGroups) {
|
|
590
|
+
const win = computeVirtualWindow({
|
|
591
|
+
heights: this.#rowHeights(view.rows),
|
|
592
|
+
scrollTop: this.#dropdown.scrollTop,
|
|
593
|
+
viewportHeight: this.#dropdown.clientHeight
|
|
594
|
+
});
|
|
595
|
+
this.#renderVirtualSlice(view.rows, win, a11y, s.activeIndex);
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
for (const row of view.rows) this.#renderRow(row, a11y, s.activeIndex);
|
|
599
|
+
}
|
|
600
|
+
/** 每列高度:分組標題用 groupHeight 其餘(option/create)用 itemHeight */
|
|
601
|
+
#rowHeights(rows) {
|
|
602
|
+
return rows.map(
|
|
603
|
+
(r) => r.type === "group" ? this.#groupHeight : this.#itemHeight
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
/** 渲染虛擬切片:上下佔位 + range 內各列 共用扁平與分組兩路徑 */
|
|
607
|
+
#renderVirtualSlice(rows, range, a11y, activeIndex) {
|
|
608
|
+
this.#dropdown.append(this.#spacer(range.paddingTop));
|
|
609
|
+
for (let i = range.startIndex; i < range.endIndex; i++) {
|
|
610
|
+
const row = rows[i];
|
|
611
|
+
if (row) this.#renderRow(row, a11y, activeIndex);
|
|
612
|
+
}
|
|
613
|
+
this.#dropdown.append(this.#spacer(range.paddingBottom));
|
|
614
|
+
}
|
|
615
|
+
/** 依列型別渲染並掛入下拉 group / create / option */
|
|
616
|
+
#renderRow(row, a11y, activeIndex) {
|
|
617
|
+
if (row.type === "group") {
|
|
618
|
+
this.#dropdown.append(this.#buildGroupRow(row));
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
if (row.type === "create") {
|
|
622
|
+
this.#dropdown.append(this.#buildCreateRow(row, a11y, activeIndex));
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
this.#dropdown.append(this.#buildOption(row, a11y, activeIndex));
|
|
626
|
+
}
|
|
627
|
+
/** 分組標題列 套用 templateGroup(無則用 label)*/
|
|
628
|
+
#buildGroupRow(row) {
|
|
629
|
+
const group = document.createElement("div");
|
|
630
|
+
group.className = this.#cls("group");
|
|
631
|
+
if (row.disabled) group.classList.add(this.#cls("group", "disabled"));
|
|
632
|
+
if (this.#templateGroup) {
|
|
633
|
+
this.#applyTemplate(
|
|
634
|
+
group,
|
|
635
|
+
this.#templateGroup({ label: row.label, disabled: !!row.disabled })
|
|
636
|
+
);
|
|
637
|
+
} else {
|
|
638
|
+
group.textContent = row.label;
|
|
560
639
|
}
|
|
640
|
+
return group;
|
|
561
641
|
}
|
|
562
642
|
/** 「建立新項」列 共用 option 樣式與 a11y 但點擊走 createTag */
|
|
563
643
|
#buildCreateRow(row, a11y, activeIndex) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@selkit/dom",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Vanilla JS renderer for Selkit — DOM, events, a11y and default positioner.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"sideEffects": false,
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@selkit/core": "0.
|
|
22
|
+
"@selkit/core": "0.4.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"axe-core": "^4.12.1",
|