@lmfaole/basics 0.1.0 → 0.2.1
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 +162 -0
- package/components/basic-accordion/index.d.ts +50 -0
- package/components/basic-accordion/index.js +387 -0
- package/components/basic-accordion/register.d.ts +1 -0
- package/components/basic-accordion/register.js +3 -0
- package/components/basic-dialog/index.d.ts +36 -0
- package/components/basic-dialog/index.js +272 -0
- package/components/basic-dialog/register.d.ts +1 -0
- package/components/basic-dialog/register.js +3 -0
- package/components/basic-popover/index.d.ts +70 -0
- package/components/basic-popover/index.js +460 -0
- package/components/basic-popover/register.d.ts +1 -0
- package/components/basic-popover/register.js +3 -0
- package/components/basic-tabs/index.js +12 -8
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +116 -81
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
const ElementBase = globalThis.Element ?? class {};
|
|
2
|
+
const HTMLElementBase = globalThis.HTMLElement ?? class {};
|
|
3
|
+
const HTMLButtonElementBase = globalThis.HTMLButtonElement ?? class {};
|
|
4
|
+
|
|
5
|
+
export const POPOVER_TAG_NAME = "basic-popover";
|
|
6
|
+
|
|
7
|
+
const DEFAULT_LABEL = "Popover";
|
|
8
|
+
const PANEL_SELECTOR = "[data-popover-panel]";
|
|
9
|
+
const TITLE_SELECTOR = "[data-popover-title]";
|
|
10
|
+
const OPEN_SELECTOR = "[data-popover-open]";
|
|
11
|
+
const CLOSE_SELECTOR = "[data-popover-close]";
|
|
12
|
+
const MANAGED_ANCHORED_ATTRIBUTE = "data-basic-popover-anchored";
|
|
13
|
+
const MANAGED_POPOVER_ATTRIBUTE = "data-basic-popover-managed-popover";
|
|
14
|
+
const MANAGED_LABEL_ATTRIBUTE = "data-basic-popover-managed-label";
|
|
15
|
+
const MANAGED_LABELLEDBY_ATTRIBUTE = "data-basic-popover-managed-labelledby";
|
|
16
|
+
const MANAGED_ROLE_ATTRIBUTE = "data-basic-popover-managed-role";
|
|
17
|
+
const MANAGED_MODAL_ATTRIBUTE = "data-basic-popover-managed-modal";
|
|
18
|
+
const MANAGED_POSITION_AREA_VARIABLE = "--basic-popover-position-area";
|
|
19
|
+
const MANAGED_POSITION_TRY_VARIABLE = "--basic-popover-position-try-fallbacks";
|
|
20
|
+
const POPOVER_STYLE_ID = "basic-popover-anchor-styles";
|
|
21
|
+
|
|
22
|
+
let nextPopoverInstanceId = 1;
|
|
23
|
+
|
|
24
|
+
function collectOwnedElements(root, scope, selector) {
|
|
25
|
+
return Array.from(scope.querySelectorAll(selector)).filter(
|
|
26
|
+
(element) => element instanceof HTMLElementBase && element.closest(POPOVER_TAG_NAME) === root,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function ensurePopoverAnchorStyles(documentRef) {
|
|
31
|
+
if (!documentRef?.head || documentRef.getElementById(POPOVER_STYLE_ID)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const style = documentRef.createElement("style");
|
|
36
|
+
style.id = POPOVER_STYLE_ID;
|
|
37
|
+
style.textContent = `${POPOVER_TAG_NAME} [data-popover-panel][${MANAGED_ANCHORED_ATTRIBUTE}] { inset: auto; margin: 0; position-area: var(${MANAGED_POSITION_AREA_VARIABLE}, bottom); position-try-fallbacks: var(${MANAGED_POSITION_TRY_VARIABLE}, flip-block, flip-inline, flip-block flip-inline); position-try: var(${MANAGED_POSITION_TRY_VARIABLE}, flip-block, flip-inline, flip-block flip-inline); }`;
|
|
38
|
+
documentRef.head.append(style);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function normalizePopoverLabel(value) {
|
|
42
|
+
return value?.trim() || DEFAULT_LABEL;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function normalizePopoverAnchorTrigger(value) {
|
|
46
|
+
if (value == null) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const normalized = value.trim().toLowerCase();
|
|
51
|
+
return normalized === "" || normalized === "true";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function normalizePopoverPositionArea(value) {
|
|
55
|
+
return value?.trim() || "bottom";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function getDefaultPopoverPositionTryFallbacks(positionArea) {
|
|
59
|
+
const normalizedArea = normalizePopoverPositionArea(positionArea).toLowerCase();
|
|
60
|
+
const blockDirectionalTokens = [
|
|
61
|
+
"top",
|
|
62
|
+
"bottom",
|
|
63
|
+
"block-start",
|
|
64
|
+
"block-end",
|
|
65
|
+
"y-start",
|
|
66
|
+
"y-end",
|
|
67
|
+
"span-top",
|
|
68
|
+
"span-bottom",
|
|
69
|
+
"span-block-start",
|
|
70
|
+
"span-block-end",
|
|
71
|
+
"span-y-start",
|
|
72
|
+
"span-y-end",
|
|
73
|
+
];
|
|
74
|
+
const inlineDirectionalTokens = [
|
|
75
|
+
"left",
|
|
76
|
+
"right",
|
|
77
|
+
"inline-start",
|
|
78
|
+
"inline-end",
|
|
79
|
+
"x-start",
|
|
80
|
+
"x-end",
|
|
81
|
+
"span-left",
|
|
82
|
+
"span-right",
|
|
83
|
+
"span-inline-start",
|
|
84
|
+
"span-inline-end",
|
|
85
|
+
"span-x-start",
|
|
86
|
+
"span-x-end",
|
|
87
|
+
];
|
|
88
|
+
const primaryFlip = blockDirectionalTokens.some((token) => normalizedArea.includes(token))
|
|
89
|
+
? "flip-block"
|
|
90
|
+
: inlineDirectionalTokens.some((token) => normalizedArea.includes(token))
|
|
91
|
+
? "flip-inline"
|
|
92
|
+
: "flip-block";
|
|
93
|
+
const secondaryFlip = primaryFlip === "flip-block" ? "flip-inline" : "flip-block";
|
|
94
|
+
|
|
95
|
+
return `${primaryFlip}, ${secondaryFlip}, ${primaryFlip} ${secondaryFlip}`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function normalizePopoverPositionTryFallbacks(value, positionArea) {
|
|
99
|
+
return value?.trim() || getDefaultPopoverPositionTryFallbacks(positionArea);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function isPopoverOpen(panel) {
|
|
103
|
+
if (!(panel instanceof HTMLElementBase)) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
return panel.matches(":popover-open");
|
|
109
|
+
} catch {
|
|
110
|
+
return panel.hasAttribute("data-open");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export class PopoverElement extends HTMLElementBase {
|
|
115
|
+
static observedAttributes = [
|
|
116
|
+
"data-anchor-trigger",
|
|
117
|
+
"data-label",
|
|
118
|
+
"data-position-area",
|
|
119
|
+
"data-position-try-fallbacks",
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
#instanceId = `${POPOVER_TAG_NAME}-${nextPopoverInstanceId++}`;
|
|
123
|
+
#panel = null;
|
|
124
|
+
#panelWithEvents = null;
|
|
125
|
+
#title = null;
|
|
126
|
+
#openButtons = [];
|
|
127
|
+
#closeButtons = [];
|
|
128
|
+
#restoreFocusTo = null;
|
|
129
|
+
#eventsBound = false;
|
|
130
|
+
|
|
131
|
+
connectedCallback() {
|
|
132
|
+
if (!this.#eventsBound) {
|
|
133
|
+
this.addEventListener("click", this.#handleClick);
|
|
134
|
+
this.addEventListener("keydown", this.#handleKeyDown);
|
|
135
|
+
this.ownerDocument?.addEventListener("click", this.#handleDocumentClick);
|
|
136
|
+
this.#eventsBound = true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
ensurePopoverAnchorStyles(this.ownerDocument);
|
|
140
|
+
this.#sync();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
disconnectedCallback() {
|
|
144
|
+
if (this.#eventsBound) {
|
|
145
|
+
this.removeEventListener("click", this.#handleClick);
|
|
146
|
+
this.removeEventListener("keydown", this.#handleKeyDown);
|
|
147
|
+
this.ownerDocument?.removeEventListener("click", this.#handleDocumentClick);
|
|
148
|
+
this.#eventsBound = false;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
this.#syncPanelEvents(null);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
attributeChangedCallback() {
|
|
155
|
+
this.#sync();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
show(opener = null) {
|
|
159
|
+
this.#sync();
|
|
160
|
+
|
|
161
|
+
if (
|
|
162
|
+
!(this.#panel instanceof HTMLElementBase)
|
|
163
|
+
|| typeof this.#panel.showPopover !== "function"
|
|
164
|
+
) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (isPopoverOpen(this.#panel)) {
|
|
169
|
+
this.#applyState();
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const fallbackOpener = opener instanceof HTMLElementBase
|
|
174
|
+
? opener
|
|
175
|
+
: this.ownerDocument?.activeElement instanceof HTMLElementBase
|
|
176
|
+
? this.ownerDocument.activeElement
|
|
177
|
+
: null;
|
|
178
|
+
|
|
179
|
+
this.#restoreFocusTo = fallbackOpener;
|
|
180
|
+
|
|
181
|
+
if (this.#shouldAnchorTrigger() && fallbackOpener instanceof HTMLElementBase) {
|
|
182
|
+
try {
|
|
183
|
+
this.#panel.showPopover({ source: fallbackOpener });
|
|
184
|
+
} catch {
|
|
185
|
+
this.#panel.showPopover();
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
this.#panel.showPopover();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
this.#applyState();
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
hide() {
|
|
196
|
+
if (
|
|
197
|
+
!(this.#panel instanceof HTMLElementBase)
|
|
198
|
+
|| typeof this.#panel.hidePopover !== "function"
|
|
199
|
+
|| !isPopoverOpen(this.#panel)
|
|
200
|
+
) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this.#panel.hidePopover();
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
toggle(opener = null) {
|
|
209
|
+
if (isPopoverOpen(this.#panel)) {
|
|
210
|
+
return this.hide();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return this.show(opener);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
#handleClick = (event) => {
|
|
217
|
+
if (!(event.target instanceof ElementBase)) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const openButton = event.target.closest(OPEN_SELECTOR);
|
|
222
|
+
|
|
223
|
+
if (
|
|
224
|
+
openButton instanceof HTMLElementBase
|
|
225
|
+
&& openButton.closest(POPOVER_TAG_NAME) === this
|
|
226
|
+
) {
|
|
227
|
+
event.preventDefault();
|
|
228
|
+
this.toggle(openButton);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const closeButton = event.target.closest(CLOSE_SELECTOR);
|
|
233
|
+
|
|
234
|
+
if (
|
|
235
|
+
closeButton instanceof HTMLElementBase
|
|
236
|
+
&& closeButton.closest(POPOVER_TAG_NAME) === this
|
|
237
|
+
) {
|
|
238
|
+
event.preventDefault();
|
|
239
|
+
this.hide();
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
#shouldAnchorTrigger() {
|
|
244
|
+
return normalizePopoverAnchorTrigger(this.getAttribute("data-anchor-trigger"));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
#getPositionArea() {
|
|
248
|
+
return normalizePopoverPositionArea(this.getAttribute("data-position-area"));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
#getPositionTryFallbacks() {
|
|
252
|
+
return normalizePopoverPositionTryFallbacks(
|
|
253
|
+
this.getAttribute("data-position-try-fallbacks"),
|
|
254
|
+
this.#getPositionArea(),
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
#handleKeyDown = (event) => {
|
|
259
|
+
if (
|
|
260
|
+
event.key !== "Escape"
|
|
261
|
+
|| !isPopoverOpen(this.#panel)
|
|
262
|
+
|| !(event.target instanceof ElementBase)
|
|
263
|
+
|| !this.contains(event.target)
|
|
264
|
+
) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
event.preventDefault();
|
|
269
|
+
this.hide();
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
#handleDocumentClick = (event) => {
|
|
273
|
+
if (
|
|
274
|
+
!isPopoverOpen(this.#panel)
|
|
275
|
+
|| !(event.target instanceof ElementBase)
|
|
276
|
+
|| this.contains(event.target)
|
|
277
|
+
) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
this.hide();
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
#handleToggle = () => {
|
|
285
|
+
this.#applyState();
|
|
286
|
+
|
|
287
|
+
if (isPopoverOpen(this.#panel)) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const activeElement = this.ownerDocument?.activeElement;
|
|
292
|
+
const shouldRestoreFocus = !(
|
|
293
|
+
activeElement instanceof HTMLElementBase
|
|
294
|
+
&& activeElement !== this.ownerDocument?.body
|
|
295
|
+
&& !this.contains(activeElement)
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
if (
|
|
299
|
+
shouldRestoreFocus
|
|
300
|
+
&& this.#restoreFocusTo instanceof HTMLElementBase
|
|
301
|
+
&& this.#restoreFocusTo.isConnected
|
|
302
|
+
) {
|
|
303
|
+
this.#restoreFocusTo.focus();
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
this.#restoreFocusTo = null;
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
#sync() {
|
|
310
|
+
const nextPanel = collectOwnedElements(this, this, PANEL_SELECTOR)[0] ?? null;
|
|
311
|
+
const nextTitle = collectOwnedElements(this, this, TITLE_SELECTOR)[0] ?? null;
|
|
312
|
+
|
|
313
|
+
this.#syncPanelEvents(nextPanel instanceof HTMLElementBase ? nextPanel : null);
|
|
314
|
+
this.#panel = nextPanel instanceof HTMLElementBase ? nextPanel : null;
|
|
315
|
+
this.#title = nextTitle instanceof HTMLElementBase ? nextTitle : null;
|
|
316
|
+
this.#openButtons = collectOwnedElements(this, this, OPEN_SELECTOR);
|
|
317
|
+
this.#closeButtons = collectOwnedElements(this, this, CLOSE_SELECTOR);
|
|
318
|
+
this.#applyState();
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
#syncPanelEvents(nextPanel) {
|
|
322
|
+
if (this.#panelWithEvents === nextPanel) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (this.#panelWithEvents instanceof HTMLElementBase) {
|
|
327
|
+
this.#panelWithEvents.removeEventListener("toggle", this.#handleToggle);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (nextPanel instanceof HTMLElementBase) {
|
|
331
|
+
nextPanel.addEventListener("toggle", this.#handleToggle);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
this.#panelWithEvents = nextPanel;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
#applyState() {
|
|
338
|
+
for (const button of [...this.#openButtons, ...this.#closeButtons]) {
|
|
339
|
+
if (button instanceof HTMLButtonElementBase && !button.hasAttribute("type")) {
|
|
340
|
+
button.type = "button";
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (!(this.#panel instanceof HTMLElementBase)) {
|
|
345
|
+
this.toggleAttribute("data-open", false);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const baseId = this.id || this.#instanceId;
|
|
350
|
+
const open = isPopoverOpen(this.#panel);
|
|
351
|
+
|
|
352
|
+
if (!this.#panel.id) {
|
|
353
|
+
this.#panel.id = `${baseId}-panel`;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (this.#title instanceof HTMLElementBase && !this.#title.id) {
|
|
357
|
+
this.#title.id = `${baseId}-title`;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (
|
|
361
|
+
!this.#panel.hasAttribute("popover")
|
|
362
|
+
|| this.#panel.hasAttribute(MANAGED_POPOVER_ATTRIBUTE)
|
|
363
|
+
) {
|
|
364
|
+
this.#panel.setAttribute("popover", "auto");
|
|
365
|
+
this.#panel.setAttribute(MANAGED_POPOVER_ATTRIBUTE, "");
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (!this.#panel.hasAttribute("role") || this.#panel.hasAttribute(MANAGED_ROLE_ATTRIBUTE)) {
|
|
369
|
+
this.#panel.setAttribute("role", "dialog");
|
|
370
|
+
this.#panel.setAttribute(MANAGED_ROLE_ATTRIBUTE, "");
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (
|
|
374
|
+
!this.#panel.hasAttribute("aria-modal")
|
|
375
|
+
|| this.#panel.hasAttribute(MANAGED_MODAL_ATTRIBUTE)
|
|
376
|
+
) {
|
|
377
|
+
this.#panel.setAttribute("aria-modal", "false");
|
|
378
|
+
this.#panel.setAttribute(MANAGED_MODAL_ATTRIBUTE, "");
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
this.#syncAccessibleLabel();
|
|
382
|
+
|
|
383
|
+
if (this.#shouldAnchorTrigger()) {
|
|
384
|
+
ensurePopoverAnchorStyles(this.ownerDocument);
|
|
385
|
+
this.#panel.setAttribute(MANAGED_ANCHORED_ATTRIBUTE, "");
|
|
386
|
+
this.#panel.style.setProperty(
|
|
387
|
+
MANAGED_POSITION_AREA_VARIABLE,
|
|
388
|
+
this.#getPositionArea(),
|
|
389
|
+
);
|
|
390
|
+
this.#panel.style.setProperty(
|
|
391
|
+
MANAGED_POSITION_TRY_VARIABLE,
|
|
392
|
+
this.#getPositionTryFallbacks(),
|
|
393
|
+
);
|
|
394
|
+
} else {
|
|
395
|
+
this.#panel.removeAttribute(MANAGED_ANCHORED_ATTRIBUTE);
|
|
396
|
+
this.#panel.style.removeProperty(MANAGED_POSITION_AREA_VARIABLE);
|
|
397
|
+
this.#panel.style.removeProperty(MANAGED_POSITION_TRY_VARIABLE);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
for (const button of this.#openButtons) {
|
|
401
|
+
button.setAttribute("aria-haspopup", "dialog");
|
|
402
|
+
button.setAttribute("aria-controls", this.#panel.id);
|
|
403
|
+
button.setAttribute("aria-expanded", String(open));
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
this.#panel.toggleAttribute("data-open", open);
|
|
407
|
+
this.toggleAttribute("data-open", open);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
#syncAccessibleLabel() {
|
|
411
|
+
if (!(this.#panel instanceof HTMLElementBase)) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (this.#title?.id) {
|
|
416
|
+
if (this.#panel.hasAttribute(MANAGED_LABEL_ATTRIBUTE)) {
|
|
417
|
+
this.#panel.removeAttribute("aria-label");
|
|
418
|
+
this.#panel.removeAttribute(MANAGED_LABEL_ATTRIBUTE);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (
|
|
422
|
+
!this.#panel.hasAttribute("aria-labelledby")
|
|
423
|
+
|| this.#panel.hasAttribute(MANAGED_LABELLEDBY_ATTRIBUTE)
|
|
424
|
+
) {
|
|
425
|
+
this.#panel.setAttribute("aria-labelledby", this.#title.id);
|
|
426
|
+
this.#panel.setAttribute(MANAGED_LABELLEDBY_ATTRIBUTE, "");
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (this.#panel.hasAttribute(MANAGED_LABELLEDBY_ATTRIBUTE)) {
|
|
433
|
+
this.#panel.removeAttribute("aria-labelledby");
|
|
434
|
+
this.#panel.removeAttribute(MANAGED_LABELLEDBY_ATTRIBUTE);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (
|
|
438
|
+
!this.#panel.hasAttribute("aria-label")
|
|
439
|
+
|| this.#panel.hasAttribute(MANAGED_LABEL_ATTRIBUTE)
|
|
440
|
+
) {
|
|
441
|
+
this.#panel.setAttribute(
|
|
442
|
+
"aria-label",
|
|
443
|
+
normalizePopoverLabel(this.getAttribute("data-label")),
|
|
444
|
+
);
|
|
445
|
+
this.#panel.setAttribute(MANAGED_LABEL_ATTRIBUTE, "");
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export function definePopover(registry = globalThis.customElements) {
|
|
451
|
+
if (!registry?.get || !registry?.define) {
|
|
452
|
+
return PopoverElement;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (!registry.get(POPOVER_TAG_NAME)) {
|
|
456
|
+
registry.define(POPOVER_TAG_NAME, PopoverElement);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return PopoverElement;
|
|
460
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -36,13 +36,7 @@ export function getInitialSelectedTabIndex(tabStates) {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
if (!tabStates[index]?.disabled) {
|
|
41
|
-
return index;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return -1;
|
|
39
|
+
return findFirstEnabledTabIndex(tabStates);
|
|
46
40
|
}
|
|
47
41
|
|
|
48
42
|
export function findNextEnabledTabIndex(tabStates, startIndex, direction) {
|
|
@@ -80,6 +74,16 @@ function isTabDisabled(tab) {
|
|
|
80
74
|
return tab.hasAttribute("disabled") || tab.getAttribute("aria-disabled") === "true";
|
|
81
75
|
}
|
|
82
76
|
|
|
77
|
+
function findFirstEnabledTabIndex(tabStates) {
|
|
78
|
+
for (let index = 0; index < tabStates.length; index += 1) {
|
|
79
|
+
if (!tabStates[index]?.disabled) {
|
|
80
|
+
return index;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return -1;
|
|
85
|
+
}
|
|
86
|
+
|
|
83
87
|
function findLastEnabledTabIndex(tabStates) {
|
|
84
88
|
for (let index = tabStates.length - 1; index >= 0; index -= 1) {
|
|
85
89
|
if (!tabStates[index]?.disabled) {
|
|
@@ -193,7 +197,7 @@ export class TabsElement extends HTMLElementBase {
|
|
|
193
197
|
}
|
|
194
198
|
break;
|
|
195
199
|
case "Home":
|
|
196
|
-
nextIndex =
|
|
200
|
+
nextIndex = findFirstEnabledTabIndex(tabStates);
|
|
197
201
|
break;
|
|
198
202
|
case "End":
|
|
199
203
|
nextIndex = findLastEnabledTabIndex(tabStates);
|
package/index.d.ts
CHANGED
package/index.js
CHANGED