@selkit/dom 0.1.1 → 0.2.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 +51 -8
- package/dist/index.d.cts +22 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +51 -8
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -155,6 +155,11 @@ var SelkitDom = class {
|
|
|
155
155
|
#dropdownParent;
|
|
156
156
|
#templateSelection;
|
|
157
157
|
#templateOption;
|
|
158
|
+
#templateArrow;
|
|
159
|
+
#templateClear;
|
|
160
|
+
#templateTagRemove;
|
|
161
|
+
#templateGroup;
|
|
162
|
+
#templateEmpty;
|
|
158
163
|
#sourceSelect;
|
|
159
164
|
#control;
|
|
160
165
|
#field;
|
|
@@ -192,6 +197,11 @@ var SelkitDom = class {
|
|
|
192
197
|
this.#dropdownParent = resolveParent(cfg.dropdownParent);
|
|
193
198
|
this.#templateSelection = cfg.templateSelection;
|
|
194
199
|
this.#templateOption = cfg.templateOption;
|
|
200
|
+
this.#templateArrow = cfg.templateArrow;
|
|
201
|
+
this.#templateClear = cfg.templateClear;
|
|
202
|
+
this.#templateTagRemove = cfg.templateTagRemove;
|
|
203
|
+
this.#templateGroup = cfg.templateGroup;
|
|
204
|
+
this.#templateEmpty = cfg.templateEmpty;
|
|
195
205
|
this.controller = (0, import_core.createSelkit)(cfg);
|
|
196
206
|
this.element = document.createElement("div");
|
|
197
207
|
this.element.className = this.#prefix;
|
|
@@ -433,15 +443,18 @@ var SelkitDom = class {
|
|
|
433
443
|
this.element.classList.toggle(this.#cls("", "open"), s.isOpen);
|
|
434
444
|
this.element.classList.toggle(this.#cls("", "disabled"), s.disabled);
|
|
435
445
|
}
|
|
436
|
-
/**
|
|
446
|
+
/** 套用模板輸出:字串走 textContent(防 XSS)Node 直接掛入 */
|
|
447
|
+
#applyTemplate(host, out) {
|
|
448
|
+
if (out instanceof Node) host.append(out);
|
|
449
|
+
else host.textContent = out;
|
|
450
|
+
}
|
|
451
|
+
/** 套用 templateSelection 到已選容器 無模板則用 label */
|
|
437
452
|
#fillSelection(host, option, meta) {
|
|
438
453
|
if (!this.#templateSelection) {
|
|
439
454
|
host.textContent = option.label;
|
|
440
455
|
return;
|
|
441
456
|
}
|
|
442
|
-
|
|
443
|
-
if (out instanceof Node) host.append(out);
|
|
444
|
-
else host.textContent = out;
|
|
457
|
+
this.#applyTemplate(host, this.#templateSelection(option, meta));
|
|
445
458
|
}
|
|
446
459
|
#renderField(s) {
|
|
447
460
|
for (const child of Array.from(this.#field.children)) {
|
|
@@ -462,7 +475,11 @@ var SelkitDom = class {
|
|
|
462
475
|
remove.className = this.#cls("tag-remove");
|
|
463
476
|
remove.dataset.index = String(i);
|
|
464
477
|
remove.setAttribute("aria-label", `Remove ${opt.label}`);
|
|
465
|
-
|
|
478
|
+
if (this.#templateTagRemove) {
|
|
479
|
+
this.#applyTemplate(remove, this.#templateTagRemove(opt, { index: i }));
|
|
480
|
+
} else {
|
|
481
|
+
remove.textContent = "\xD7";
|
|
482
|
+
}
|
|
466
483
|
tag.append(label, remove);
|
|
467
484
|
frag.append(tag);
|
|
468
485
|
});
|
|
@@ -492,12 +509,19 @@ var SelkitDom = class {
|
|
|
492
509
|
clear.type = "button";
|
|
493
510
|
clear.className = this.#cls("clear");
|
|
494
511
|
clear.setAttribute("aria-label", "Clear");
|
|
495
|
-
|
|
512
|
+
if (this.#templateClear) {
|
|
513
|
+
this.#applyTemplate(clear, this.#templateClear());
|
|
514
|
+
} else {
|
|
515
|
+
clear.textContent = "\xD7";
|
|
516
|
+
}
|
|
496
517
|
this.#indicators.append(clear);
|
|
497
518
|
}
|
|
498
519
|
const arrow = document.createElement("span");
|
|
499
520
|
arrow.className = this.#cls("arrow");
|
|
500
521
|
arrow.setAttribute("aria-hidden", "true");
|
|
522
|
+
if (this.#templateArrow) {
|
|
523
|
+
this.#applyTemplate(arrow, this.#templateArrow({ open: s.isOpen }));
|
|
524
|
+
}
|
|
501
525
|
this.#indicators.append(arrow);
|
|
502
526
|
}
|
|
503
527
|
#renderOptions(s) {
|
|
@@ -507,7 +531,19 @@ var SelkitDom = class {
|
|
|
507
531
|
if (view.rows.length === 0) {
|
|
508
532
|
const empty = document.createElement("div");
|
|
509
533
|
empty.className = this.#cls("empty");
|
|
510
|
-
|
|
534
|
+
const message = this.controller.getEmptyMessage();
|
|
535
|
+
if (this.#templateEmpty) {
|
|
536
|
+
this.#applyTemplate(
|
|
537
|
+
empty,
|
|
538
|
+
this.#templateEmpty({
|
|
539
|
+
reason: this.controller.getEmptyReason(),
|
|
540
|
+
message,
|
|
541
|
+
query: s.query
|
|
542
|
+
})
|
|
543
|
+
);
|
|
544
|
+
} else {
|
|
545
|
+
empty.textContent = message;
|
|
546
|
+
}
|
|
511
547
|
this.#dropdown.append(empty);
|
|
512
548
|
return;
|
|
513
549
|
}
|
|
@@ -536,7 +572,14 @@ var SelkitDom = class {
|
|
|
536
572
|
const group = document.createElement("div");
|
|
537
573
|
group.className = this.#cls("group");
|
|
538
574
|
if (row.disabled) group.classList.add(this.#cls("group", "disabled"));
|
|
539
|
-
|
|
575
|
+
if (this.#templateGroup) {
|
|
576
|
+
this.#applyTemplate(
|
|
577
|
+
group,
|
|
578
|
+
this.#templateGroup({ label: row.label, disabled: !!row.disabled })
|
|
579
|
+
);
|
|
580
|
+
} else {
|
|
581
|
+
group.textContent = row.label;
|
|
582
|
+
}
|
|
540
583
|
this.#dropdown.append(group);
|
|
541
584
|
continue;
|
|
542
585
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SelkitController, SelkitConfig, SelkitOption } from '@selkit/core';
|
|
1
|
+
import { SelkitController, SelkitConfig, SelkitOption, SelkitEmptyReason } from '@selkit/core';
|
|
2
2
|
|
|
3
3
|
interface SelkitDomConfig<T = unknown> extends SelkitConfig<T> {
|
|
4
4
|
/** class 前綴 預設 "selkit" */
|
|
@@ -28,6 +28,27 @@ interface SelkitDomConfig<T = unknown> extends SelkitConfig<T> {
|
|
|
28
28
|
active: boolean;
|
|
29
29
|
selected: boolean;
|
|
30
30
|
}) => string | Node;
|
|
31
|
+
/** 自訂下拉箭頭內容(▾)外殼保留 回傳 string 走 textContent Node 直接掛入 */
|
|
32
|
+
templateArrow?: (meta: {
|
|
33
|
+
open: boolean;
|
|
34
|
+
}) => string | Node;
|
|
35
|
+
/** 自訂清除鈕內容(×)按鈕外殼與 click 行為保留 */
|
|
36
|
+
templateClear?: () => string | Node;
|
|
37
|
+
/** 自訂多選標籤移除鈕內容(×)按鈕外殼與 click 行為保留 */
|
|
38
|
+
templateTagRemove?: (option: SelkitOption<T>, meta: {
|
|
39
|
+
index: number;
|
|
40
|
+
}) => string | Node;
|
|
41
|
+
/** 自訂分組標題內容 外殼保留 */
|
|
42
|
+
templateGroup?: (meta: {
|
|
43
|
+
label: string;
|
|
44
|
+
disabled: boolean;
|
|
45
|
+
}) => string | Node;
|
|
46
|
+
/** 自訂下拉為空/載入中的整塊內容 reason 分流 message 為預設文字 */
|
|
47
|
+
templateEmpty?: (meta: {
|
|
48
|
+
reason: SelkitEmptyReason;
|
|
49
|
+
message: string;
|
|
50
|
+
query: string;
|
|
51
|
+
}) => string | Node;
|
|
31
52
|
}
|
|
32
53
|
interface SelkitDomInstance<T = unknown> {
|
|
33
54
|
readonly controller: SelkitController<T>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SelkitController, SelkitConfig, SelkitOption } from '@selkit/core';
|
|
1
|
+
import { SelkitController, SelkitConfig, SelkitOption, SelkitEmptyReason } from '@selkit/core';
|
|
2
2
|
|
|
3
3
|
interface SelkitDomConfig<T = unknown> extends SelkitConfig<T> {
|
|
4
4
|
/** class 前綴 預設 "selkit" */
|
|
@@ -28,6 +28,27 @@ interface SelkitDomConfig<T = unknown> extends SelkitConfig<T> {
|
|
|
28
28
|
active: boolean;
|
|
29
29
|
selected: boolean;
|
|
30
30
|
}) => string | Node;
|
|
31
|
+
/** 自訂下拉箭頭內容(▾)外殼保留 回傳 string 走 textContent Node 直接掛入 */
|
|
32
|
+
templateArrow?: (meta: {
|
|
33
|
+
open: boolean;
|
|
34
|
+
}) => string | Node;
|
|
35
|
+
/** 自訂清除鈕內容(×)按鈕外殼與 click 行為保留 */
|
|
36
|
+
templateClear?: () => string | Node;
|
|
37
|
+
/** 自訂多選標籤移除鈕內容(×)按鈕外殼與 click 行為保留 */
|
|
38
|
+
templateTagRemove?: (option: SelkitOption<T>, meta: {
|
|
39
|
+
index: number;
|
|
40
|
+
}) => string | Node;
|
|
41
|
+
/** 自訂分組標題內容 外殼保留 */
|
|
42
|
+
templateGroup?: (meta: {
|
|
43
|
+
label: string;
|
|
44
|
+
disabled: boolean;
|
|
45
|
+
}) => string | Node;
|
|
46
|
+
/** 自訂下拉為空/載入中的整塊內容 reason 分流 message 為預設文字 */
|
|
47
|
+
templateEmpty?: (meta: {
|
|
48
|
+
reason: SelkitEmptyReason;
|
|
49
|
+
message: string;
|
|
50
|
+
query: string;
|
|
51
|
+
}) => string | Node;
|
|
31
52
|
}
|
|
32
53
|
interface SelkitDomInstance<T = unknown> {
|
|
33
54
|
readonly controller: SelkitController<T>;
|
package/dist/index.js
CHANGED
|
@@ -124,6 +124,11 @@ var SelkitDom = class {
|
|
|
124
124
|
#dropdownParent;
|
|
125
125
|
#templateSelection;
|
|
126
126
|
#templateOption;
|
|
127
|
+
#templateArrow;
|
|
128
|
+
#templateClear;
|
|
129
|
+
#templateTagRemove;
|
|
130
|
+
#templateGroup;
|
|
131
|
+
#templateEmpty;
|
|
127
132
|
#sourceSelect;
|
|
128
133
|
#control;
|
|
129
134
|
#field;
|
|
@@ -161,6 +166,11 @@ var SelkitDom = class {
|
|
|
161
166
|
this.#dropdownParent = resolveParent(cfg.dropdownParent);
|
|
162
167
|
this.#templateSelection = cfg.templateSelection;
|
|
163
168
|
this.#templateOption = cfg.templateOption;
|
|
169
|
+
this.#templateArrow = cfg.templateArrow;
|
|
170
|
+
this.#templateClear = cfg.templateClear;
|
|
171
|
+
this.#templateTagRemove = cfg.templateTagRemove;
|
|
172
|
+
this.#templateGroup = cfg.templateGroup;
|
|
173
|
+
this.#templateEmpty = cfg.templateEmpty;
|
|
164
174
|
this.controller = createSelkit(cfg);
|
|
165
175
|
this.element = document.createElement("div");
|
|
166
176
|
this.element.className = this.#prefix;
|
|
@@ -402,15 +412,18 @@ var SelkitDom = class {
|
|
|
402
412
|
this.element.classList.toggle(this.#cls("", "open"), s.isOpen);
|
|
403
413
|
this.element.classList.toggle(this.#cls("", "disabled"), s.disabled);
|
|
404
414
|
}
|
|
405
|
-
/**
|
|
415
|
+
/** 套用模板輸出:字串走 textContent(防 XSS)Node 直接掛入 */
|
|
416
|
+
#applyTemplate(host, out) {
|
|
417
|
+
if (out instanceof Node) host.append(out);
|
|
418
|
+
else host.textContent = out;
|
|
419
|
+
}
|
|
420
|
+
/** 套用 templateSelection 到已選容器 無模板則用 label */
|
|
406
421
|
#fillSelection(host, option, meta) {
|
|
407
422
|
if (!this.#templateSelection) {
|
|
408
423
|
host.textContent = option.label;
|
|
409
424
|
return;
|
|
410
425
|
}
|
|
411
|
-
|
|
412
|
-
if (out instanceof Node) host.append(out);
|
|
413
|
-
else host.textContent = out;
|
|
426
|
+
this.#applyTemplate(host, this.#templateSelection(option, meta));
|
|
414
427
|
}
|
|
415
428
|
#renderField(s) {
|
|
416
429
|
for (const child of Array.from(this.#field.children)) {
|
|
@@ -431,7 +444,11 @@ var SelkitDom = class {
|
|
|
431
444
|
remove.className = this.#cls("tag-remove");
|
|
432
445
|
remove.dataset.index = String(i);
|
|
433
446
|
remove.setAttribute("aria-label", `Remove ${opt.label}`);
|
|
434
|
-
|
|
447
|
+
if (this.#templateTagRemove) {
|
|
448
|
+
this.#applyTemplate(remove, this.#templateTagRemove(opt, { index: i }));
|
|
449
|
+
} else {
|
|
450
|
+
remove.textContent = "\xD7";
|
|
451
|
+
}
|
|
435
452
|
tag.append(label, remove);
|
|
436
453
|
frag.append(tag);
|
|
437
454
|
});
|
|
@@ -461,12 +478,19 @@ var SelkitDom = class {
|
|
|
461
478
|
clear.type = "button";
|
|
462
479
|
clear.className = this.#cls("clear");
|
|
463
480
|
clear.setAttribute("aria-label", "Clear");
|
|
464
|
-
|
|
481
|
+
if (this.#templateClear) {
|
|
482
|
+
this.#applyTemplate(clear, this.#templateClear());
|
|
483
|
+
} else {
|
|
484
|
+
clear.textContent = "\xD7";
|
|
485
|
+
}
|
|
465
486
|
this.#indicators.append(clear);
|
|
466
487
|
}
|
|
467
488
|
const arrow = document.createElement("span");
|
|
468
489
|
arrow.className = this.#cls("arrow");
|
|
469
490
|
arrow.setAttribute("aria-hidden", "true");
|
|
491
|
+
if (this.#templateArrow) {
|
|
492
|
+
this.#applyTemplate(arrow, this.#templateArrow({ open: s.isOpen }));
|
|
493
|
+
}
|
|
470
494
|
this.#indicators.append(arrow);
|
|
471
495
|
}
|
|
472
496
|
#renderOptions(s) {
|
|
@@ -476,7 +500,19 @@ var SelkitDom = class {
|
|
|
476
500
|
if (view.rows.length === 0) {
|
|
477
501
|
const empty = document.createElement("div");
|
|
478
502
|
empty.className = this.#cls("empty");
|
|
479
|
-
|
|
503
|
+
const message = this.controller.getEmptyMessage();
|
|
504
|
+
if (this.#templateEmpty) {
|
|
505
|
+
this.#applyTemplate(
|
|
506
|
+
empty,
|
|
507
|
+
this.#templateEmpty({
|
|
508
|
+
reason: this.controller.getEmptyReason(),
|
|
509
|
+
message,
|
|
510
|
+
query: s.query
|
|
511
|
+
})
|
|
512
|
+
);
|
|
513
|
+
} else {
|
|
514
|
+
empty.textContent = message;
|
|
515
|
+
}
|
|
480
516
|
this.#dropdown.append(empty);
|
|
481
517
|
return;
|
|
482
518
|
}
|
|
@@ -505,7 +541,14 @@ var SelkitDom = class {
|
|
|
505
541
|
const group = document.createElement("div");
|
|
506
542
|
group.className = this.#cls("group");
|
|
507
543
|
if (row.disabled) group.classList.add(this.#cls("group", "disabled"));
|
|
508
|
-
|
|
544
|
+
if (this.#templateGroup) {
|
|
545
|
+
this.#applyTemplate(
|
|
546
|
+
group,
|
|
547
|
+
this.#templateGroup({ label: row.label, disabled: !!row.disabled })
|
|
548
|
+
);
|
|
549
|
+
} else {
|
|
550
|
+
group.textContent = row.label;
|
|
551
|
+
}
|
|
509
552
|
this.#dropdown.append(group);
|
|
510
553
|
continue;
|
|
511
554
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@selkit/dom",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.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.2.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"axe-core": "^4.12.1",
|