@unofficialbox/box-open-elements 0.20.0 → 0.21.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/actions/menu-item.d.ts +2 -0
- package/dist/components/actions/menu-item.js +4 -0
- package/dist/components/collections/card.js +6 -0
- package/dist/components/collections/result-blocks.js +4 -1
- package/dist/components/feedback/alert.d.ts +2 -0
- package/dist/components/feedback/alert.js +17 -13
- package/dist/components/feedback/toast.d.ts +10 -1
- package/dist/components/feedback/toast.js +69 -27
- package/dist/components/forms/number-input.d.ts +1 -0
- package/dist/components/forms/number-input.js +9 -6
- package/dist/components/forms/search-field.js +16 -0
- package/dist/components/overlays/context-menu.d.ts +2 -0
- package/dist/components/overlays/context-menu.js +7 -0
- package/dist/components/overlays/dialog.js +19 -3
- package/dist/components/overlays/popover.js +6 -1
- package/dist/element-maps.d.ts +11 -1
- package/dist/foundations/a11y/announcer.d.ts +12 -0
- package/dist/foundations/a11y/announcer.js +75 -0
- package/dist/foundations/a11y/focus.js +46 -25
- package/dist/foundations/a11y/index.d.ts +2 -0
- package/dist/foundations/a11y/index.js +1 -0
- package/dist/foundations/icons/box-iconography.d.ts +472 -472
- package/dist/foundations/icons/box-iconography.generated.d.ts +1151 -679
- package/dist/foundations/icons/box-iconography.generated.js +1006 -3588
- package/dist/foundations/icons/glyphs/index.d.ts +1 -0
- package/dist/foundations/icons/glyphs/index.js +2 -0
- package/dist/foundations/icons/glyphs/package.json +1 -0
- package/dist/foundations/overlay/positioning.js +7 -0
- package/dist/foundations/status/index.d.ts +1 -1
- package/dist/foundations/status/index.js +8 -6
- package/dist/foundations/tokens/box-dark.js +4 -1
- package/dist/foundations/tokens/box-defaults.js +3 -0
- package/dist/foundations/tokens/registry.d.ts +3 -0
- package/dist/foundations/tokens/registry.js +3 -0
- package/dist/foundations/tokens/types.d.ts +3 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/patterns/agent-chat/agent-chat.js +12 -4
- package/dist/patterns/call-console/call-console.d.ts +3 -0
- package/dist/patterns/call-console/call-console.js +114 -20
- package/dist/patterns/content-explorer/adapters/action-menu.js +7 -5
- package/dist/patterns/content-explorer/adapters/toolbar.js +6 -2
- package/dist/patterns/file-request/file-request-builder.js +3 -0
- package/dist/patterns/flow-builder/flow-builder.d.ts +48 -0
- package/dist/patterns/flow-builder/flow-builder.js +200 -0
- package/dist/patterns/flow-builder/index.d.ts +3 -0
- package/dist/patterns/flow-builder/index.js +3 -0
- package/dist/patterns/flow-builder/model.d.ts +33 -0
- package/dist/patterns/flow-builder/model.js +28 -0
- package/dist/patterns/flow-builder/primitives.d.ts +47 -0
- package/dist/patterns/flow-builder/primitives.js +192 -0
- package/dist/patterns/lineage/lineage-graph.js +26 -6
- package/dist/patterns/notifications/notification-inbox.js +19 -3
- package/dist/patterns/preview/annotation-inspector.js +2 -2
- package/dist/patterns/undo/index.d.ts +19 -0
- package/dist/patterns/undo/index.js +106 -0
- package/package.json +11 -2
package/dist/element-maps.d.ts
CHANGED
|
@@ -73,6 +73,9 @@ import type { FactList } from "./components/collections/fact-list.js";
|
|
|
73
73
|
import type { Fieldset } from "./components/forms/fieldset.js";
|
|
74
74
|
import type { FileRequestBuilder } from "./patterns/file-request/file-request-builder.js";
|
|
75
75
|
import type { FilterBar } from "./patterns/search/filter-bar.js";
|
|
76
|
+
import type { FlowBuilder } from "./patterns/flow-builder/flow-builder.js";
|
|
77
|
+
import type { FlowCard } from "./patterns/flow-builder/primitives.js";
|
|
78
|
+
import type { FlowSpine } from "./patterns/flow-builder/primitives.js";
|
|
76
79
|
import type { FormWizard } from "./patterns/form-wizard/form-wizard.js";
|
|
77
80
|
import type { FormattedDate } from "./components/output/formatted-date.js";
|
|
78
81
|
import type { FormattedDuration } from "./components/output/formatted-duration.js";
|
|
@@ -86,9 +89,11 @@ import type { HelpText } from "./components/feedback/help-text.js";
|
|
|
86
89
|
import type { IconButton } from "./components/actions/icon-button.js";
|
|
87
90
|
import type { Illustration } from "./components/visuals/illustration.js";
|
|
88
91
|
import type { Indicator } from "./components/feedback/indicator.js";
|
|
92
|
+
import type { InsertPoint } from "./patterns/flow-builder/primitives.js";
|
|
89
93
|
import type { InviteCollaboratorsModal } from "./patterns/share/invite-collaborators-modal.js";
|
|
90
94
|
import type { ItemDetailsPanel } from "./patterns/item/item-details-panel.js";
|
|
91
95
|
import type { ItemForm } from "./patterns/item/item-form.js";
|
|
96
|
+
import type { KindPicker } from "./patterns/flow-builder/primitives.js";
|
|
92
97
|
import type { LineChart } from "./patterns/insights/line-chart.js";
|
|
93
98
|
import type { LineageGraph } from "./patterns/lineage/lineage-graph.js";
|
|
94
99
|
import type { LinkButton } from "./components/actions/link-button.js";
|
|
@@ -233,6 +238,9 @@ declare global {
|
|
|
233
238
|
"box-fieldset": Fieldset;
|
|
234
239
|
"box-file-request-builder": FileRequestBuilder;
|
|
235
240
|
"box-filter-bar": FilterBar;
|
|
241
|
+
"box-flow-builder": FlowBuilder;
|
|
242
|
+
"box-flow-card": FlowCard;
|
|
243
|
+
"box-flow-spine": FlowSpine;
|
|
236
244
|
"box-form-wizard": FormWizard;
|
|
237
245
|
"box-formatted-date": FormattedDate;
|
|
238
246
|
"box-formatted-duration": FormattedDuration;
|
|
@@ -246,9 +254,11 @@ declare global {
|
|
|
246
254
|
"box-icon-button": IconButton;
|
|
247
255
|
"box-illustration": Illustration;
|
|
248
256
|
"box-indicator": Indicator;
|
|
257
|
+
"box-insert-point": InsertPoint;
|
|
249
258
|
"box-invite-collaborators-modal": InviteCollaboratorsModal;
|
|
250
259
|
"box-item-details-panel": ItemDetailsPanel;
|
|
251
260
|
"box-item-form": ItemForm;
|
|
261
|
+
"box-kind-picker": KindPicker;
|
|
252
262
|
"box-line-chart": LineChart;
|
|
253
263
|
"box-lineage-graph": LineageGraph;
|
|
254
264
|
"box-link-button": LinkButton;
|
|
@@ -327,4 +337,4 @@ declare global {
|
|
|
327
337
|
}
|
|
328
338
|
}
|
|
329
339
|
/** Every element tag the library registers, for host-side narrowing. */
|
|
330
|
-
export type BoxElementTagName = "box-access-stats" | "box-accordion" | "box-activity-density" | "box-agent-chat" | "box-agent-workspace" | "box-alert" | "box-annotation-inspector" | "box-annotation-thread" | "box-annotation-toolbar" | "box-app-shell" | "box-audit-log" | "box-avatar" | "box-badge" | "box-badgeable" | "box-bar-chart" | "box-breadcrumb" | "box-bulk-action-bar" | "box-button" | "box-button-group" | "box-calendar" | "box-call-console" | "box-card" | "box-carousel" | "box-category-selector" | "box-chart-panel" | "box-check-list" | "box-checkbox" | "box-checkbox-group" | "box-chip" | "box-code-block" | "box-collaborator-avatars" | "box-color-picker" | "box-combobox" | "box-command-palette" | "box-comment-thread" | "box-compare-view" | "box-contact-datalist-item" | "box-content-explorer" | "box-content-picker" | "box-content-sidebar" | "box-content-uploader" | "box-context-menu" | "box-datalist-item" | "box-date-field" | "box-dialog" | "box-diff-viewer" | "box-divider" | "box-document-list" | "box-donut-chart" | "box-draggable-list" | "box-drawer" | "box-drop-zone" | "box-dropdown" | "box-dual-listbox" | "box-due-badge" | "box-empty-state" | "box-error-mask" | "box-explorer-action-menu" | "box-explorer-breadcrumbs" | "box-explorer-items" | "box-explorer-list" | "box-explorer-table" | "box-explorer-toolbar" | "box-fact-list" | "box-fieldset" | "box-file-request-builder" | "box-filter-bar" | "box-form-wizard" | "box-formatted-date" | "box-formatted-duration" | "box-formatted-file-size" | "box-formatted-number" | "box-governance-panel" | "box-grid" | "box-grid-view" | "box-guide-tooltip" | "box-help-text" | "box-icon-button" | "box-illustration" | "box-indicator" | "box-invite-collaborators-modal" | "box-item-details-panel" | "box-item-form" | "box-line-chart" | "box-lineage-graph" | "box-link-button" | "box-menu" | "box-menu-item" | "box-metadata-filter-builder" | "box-metadata-inspector" | "box-metric-card" | "box-multi-select" | "box-nav-sidebar" | "box-notification-bell" | "box-notification-inbox" | "box-nudge" | "box-number-input" | "box-pagination" | "box-path" | "box-permission-matrix" | "box-persona" | "box-pill-cloud" | "box-pill-selector-dropdown" | "box-popover" | "box-presence" | "box-preview-element" | "box-preview-header" | "box-progress-bar" | "box-progress-ring" | "box-progress-steps" | "box-provenance-strip" | "box-radio-group" | "box-range-slider" | "box-rating" | "box-relative-time" | "box-result-blocks" | "box-review-queue-item" | "box-rich-text-input" | "box-run-summary" | "box-run-trace" | "box-saved-view-picker" | "box-search-field" | "box-search-results-header" | "box-section" | "box-segmented-control" | "box-select" | "box-share-panel" | "box-shortcuts-overlay" | "box-sidebar-toggle-button" | "box-signature-ceremony" | "box-skeleton" | "box-slider" | "box-spin-button" | "box-spinner" | "box-split-view" | "box-status-icon" | "box-switch" | "box-table" | "box-tabs" | "box-tag-input" | "box-task-assignment-panel" | "box-text-area" | "box-text-field" | "box-thumbnail-card" | "box-tile-group" | "box-time-field" | "box-timeline" | "box-toast" | "box-toolbar" | "box-tooltip" | "box-tree" | "box-tree-grid" | "box-unified-share-modal" | "box-version-graph" | "box-version-list" | "box-wizard-summary" | "box-work-queue" | "box-workload-board";
|
|
340
|
+
export type BoxElementTagName = "box-access-stats" | "box-accordion" | "box-activity-density" | "box-agent-chat" | "box-agent-workspace" | "box-alert" | "box-annotation-inspector" | "box-annotation-thread" | "box-annotation-toolbar" | "box-app-shell" | "box-audit-log" | "box-avatar" | "box-badge" | "box-badgeable" | "box-bar-chart" | "box-breadcrumb" | "box-bulk-action-bar" | "box-button" | "box-button-group" | "box-calendar" | "box-call-console" | "box-card" | "box-carousel" | "box-category-selector" | "box-chart-panel" | "box-check-list" | "box-checkbox" | "box-checkbox-group" | "box-chip" | "box-code-block" | "box-collaborator-avatars" | "box-color-picker" | "box-combobox" | "box-command-palette" | "box-comment-thread" | "box-compare-view" | "box-contact-datalist-item" | "box-content-explorer" | "box-content-picker" | "box-content-sidebar" | "box-content-uploader" | "box-context-menu" | "box-datalist-item" | "box-date-field" | "box-dialog" | "box-diff-viewer" | "box-divider" | "box-document-list" | "box-donut-chart" | "box-draggable-list" | "box-drawer" | "box-drop-zone" | "box-dropdown" | "box-dual-listbox" | "box-due-badge" | "box-empty-state" | "box-error-mask" | "box-explorer-action-menu" | "box-explorer-breadcrumbs" | "box-explorer-items" | "box-explorer-list" | "box-explorer-table" | "box-explorer-toolbar" | "box-fact-list" | "box-fieldset" | "box-file-request-builder" | "box-filter-bar" | "box-flow-builder" | "box-flow-card" | "box-flow-spine" | "box-form-wizard" | "box-formatted-date" | "box-formatted-duration" | "box-formatted-file-size" | "box-formatted-number" | "box-governance-panel" | "box-grid" | "box-grid-view" | "box-guide-tooltip" | "box-help-text" | "box-icon-button" | "box-illustration" | "box-indicator" | "box-insert-point" | "box-invite-collaborators-modal" | "box-item-details-panel" | "box-item-form" | "box-kind-picker" | "box-line-chart" | "box-lineage-graph" | "box-link-button" | "box-menu" | "box-menu-item" | "box-metadata-filter-builder" | "box-metadata-inspector" | "box-metric-card" | "box-multi-select" | "box-nav-sidebar" | "box-notification-bell" | "box-notification-inbox" | "box-nudge" | "box-number-input" | "box-pagination" | "box-path" | "box-permission-matrix" | "box-persona" | "box-pill-cloud" | "box-pill-selector-dropdown" | "box-popover" | "box-presence" | "box-preview-element" | "box-preview-header" | "box-progress-bar" | "box-progress-ring" | "box-progress-steps" | "box-provenance-strip" | "box-radio-group" | "box-range-slider" | "box-rating" | "box-relative-time" | "box-result-blocks" | "box-review-queue-item" | "box-rich-text-input" | "box-run-summary" | "box-run-trace" | "box-saved-view-picker" | "box-search-field" | "box-search-results-header" | "box-section" | "box-segmented-control" | "box-select" | "box-share-panel" | "box-shortcuts-overlay" | "box-sidebar-toggle-button" | "box-signature-ceremony" | "box-skeleton" | "box-slider" | "box-spin-button" | "box-spinner" | "box-split-view" | "box-status-icon" | "box-switch" | "box-table" | "box-tabs" | "box-tag-input" | "box-task-assignment-panel" | "box-text-area" | "box-text-field" | "box-thumbnail-card" | "box-tile-group" | "box-time-field" | "box-timeline" | "box-toast" | "box-toolbar" | "box-tooltip" | "box-tree" | "box-tree-grid" | "box-unified-share-modal" | "box-version-graph" | "box-version-list" | "box-wizard-summary" | "box-work-queue" | "box-workload-board";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type Politeness = "polite" | "assertive";
|
|
2
|
+
/** Install once near application startup. The returned cleanup removes both regions. SSR-safe. */
|
|
3
|
+
export declare function installAnnouncer(doc?: Document | undefined): () => void;
|
|
4
|
+
/** Queue text, including repeated messages, into an already-mounted live region. */
|
|
5
|
+
export declare function announce(message: string, politeness?: Politeness, doc?: Document | undefined): void;
|
|
6
|
+
/** Coalesce synchronous property updates and avoid duplicate component announcements. */
|
|
7
|
+
export declare class FeedbackAnnouncement {
|
|
8
|
+
private previous;
|
|
9
|
+
private revision;
|
|
10
|
+
update(host: HTMLElement, message: string, politeness: Politeness): void;
|
|
11
|
+
reset(): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const instances = new WeakMap();
|
|
2
|
+
/** Install once near application startup. The returned cleanup removes both regions. SSR-safe. */
|
|
3
|
+
export function installAnnouncer(doc = globalThis.document) {
|
|
4
|
+
if (!doc?.body)
|
|
5
|
+
return () => { };
|
|
6
|
+
const existing = instances.get(doc);
|
|
7
|
+
if (existing?.host.isConnected)
|
|
8
|
+
return existing.dispose;
|
|
9
|
+
existing?.dispose();
|
|
10
|
+
const host = doc.createElement("div");
|
|
11
|
+
host.dataset.boeAnnouncer = "";
|
|
12
|
+
host.style.cssText = "position:fixed;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;pointer-events:none";
|
|
13
|
+
const makeChannel = (politeness) => {
|
|
14
|
+
const region = doc.createElement("div");
|
|
15
|
+
region.setAttribute("role", politeness === "assertive" ? "alert" : "status");
|
|
16
|
+
region.setAttribute("aria-live", politeness);
|
|
17
|
+
region.setAttribute("aria-atomic", "true");
|
|
18
|
+
host.append(region);
|
|
19
|
+
return { region, queue: [] };
|
|
20
|
+
};
|
|
21
|
+
const channels = { polite: makeChannel("polite"), assertive: makeChannel("assertive") };
|
|
22
|
+
const dispose = () => {
|
|
23
|
+
for (const channel of Object.values(channels))
|
|
24
|
+
clearTimeout(channel.timer);
|
|
25
|
+
host.remove();
|
|
26
|
+
if (instances.get(doc)?.host === host)
|
|
27
|
+
instances.delete(doc);
|
|
28
|
+
};
|
|
29
|
+
doc.body.append(host);
|
|
30
|
+
instances.set(doc, { host, channels, dispose });
|
|
31
|
+
return dispose;
|
|
32
|
+
}
|
|
33
|
+
/** Queue text, including repeated messages, into an already-mounted live region. */
|
|
34
|
+
export function announce(message, politeness = "polite", doc = globalThis.document) {
|
|
35
|
+
if (!doc?.body || !message.trim())
|
|
36
|
+
return;
|
|
37
|
+
installAnnouncer(doc);
|
|
38
|
+
const channel = instances.get(doc).channels[politeness];
|
|
39
|
+
channel.queue.push(message);
|
|
40
|
+
if (channel.timer !== undefined)
|
|
41
|
+
return;
|
|
42
|
+
const next = () => {
|
|
43
|
+
channel.region.textContent = "";
|
|
44
|
+
// A separate rendering opportunity ensures an empty region exists first.
|
|
45
|
+
channel.timer = setTimeout(() => {
|
|
46
|
+
channel.region.textContent = channel.queue.shift() ?? "";
|
|
47
|
+
channel.timer = setTimeout(() => {
|
|
48
|
+
channel.timer = undefined;
|
|
49
|
+
if (channel.queue.length)
|
|
50
|
+
next();
|
|
51
|
+
}, 100);
|
|
52
|
+
}, 20);
|
|
53
|
+
};
|
|
54
|
+
next();
|
|
55
|
+
}
|
|
56
|
+
/** Coalesce synchronous property updates and avoid duplicate component announcements. */
|
|
57
|
+
export class FeedbackAnnouncement {
|
|
58
|
+
previous = "";
|
|
59
|
+
revision = 0;
|
|
60
|
+
update(host, message, politeness) {
|
|
61
|
+
const revision = ++this.revision;
|
|
62
|
+
if (!message) {
|
|
63
|
+
this.previous = "";
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
queueMicrotask(() => {
|
|
67
|
+
const key = `${politeness}:${message}`;
|
|
68
|
+
if (revision !== this.revision || !host.isConnected || key === this.previous)
|
|
69
|
+
return;
|
|
70
|
+
this.previous = key;
|
|
71
|
+
announce(message, politeness, host.ownerDocument);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
reset() { ++this.revision; this.previous = ""; }
|
|
75
|
+
}
|
|
@@ -9,37 +9,56 @@ const TABBABLE_SELECTOR = [
|
|
|
9
9
|
"textarea:not([disabled])",
|
|
10
10
|
"[tabindex]:not([tabindex='-1'])",
|
|
11
11
|
].join(", ");
|
|
12
|
-
const isDisabled = (element) => element.
|
|
12
|
+
const isDisabled = (element) => element.matches(":disabled") ||
|
|
13
|
+
element.hasAttribute("disabled") ||
|
|
13
14
|
element.disabled === true ||
|
|
14
15
|
element.getAttribute("aria-disabled") === "true";
|
|
15
16
|
const isVisible = (element) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (!style) {
|
|
25
|
-
return true;
|
|
26
|
-
}
|
|
27
|
-
if (style.display === "none" || style.visibility === "hidden") {
|
|
28
|
-
return false;
|
|
17
|
+
for (let current = element; current;) {
|
|
18
|
+
if (current.hasAttribute("hidden") || current.hasAttribute("inert") || current.getAttribute("aria-hidden") === "true")
|
|
19
|
+
return false;
|
|
20
|
+
const style = current.ownerDocument.defaultView?.getComputedStyle(current);
|
|
21
|
+
if (style?.display === "none" || style?.visibility === "hidden")
|
|
22
|
+
return false;
|
|
23
|
+
const root = current.getRootNode();
|
|
24
|
+
current = current.assignedSlot ?? current.parentElement ?? (root instanceof ShadowRoot ? root.host : null);
|
|
29
25
|
}
|
|
30
26
|
return true;
|
|
31
27
|
};
|
|
28
|
+
const deepActiveElement = (root) => {
|
|
29
|
+
let active = root.activeElement;
|
|
30
|
+
while (active?.shadowRoot?.activeElement)
|
|
31
|
+
active = active.shadowRoot.activeElement;
|
|
32
|
+
return active;
|
|
33
|
+
};
|
|
32
34
|
/** Visible, enabled tabbable controls inside `container` (light or shadow). */
|
|
33
35
|
export const getTabbableElements = (container) => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
const result = [];
|
|
37
|
+
const visit = (node) => {
|
|
38
|
+
const children = node instanceof HTMLSlotElement
|
|
39
|
+
? (node.assignedElements().length ? node.assignedElements() : Array.from(node.children))
|
|
40
|
+
: Array.from(node.children);
|
|
41
|
+
for (const child of children) {
|
|
42
|
+
if (!(child instanceof HTMLElement) || !isVisible(child))
|
|
43
|
+
continue;
|
|
44
|
+
const disabled = isDisabled(child);
|
|
45
|
+
// A disabled fieldset still permits controls in its first legend and
|
|
46
|
+
// non-form controls such as links. Let native :disabled filter each
|
|
47
|
+
// descendant instead of pruning the entire fieldset subtree.
|
|
48
|
+
if (disabled && (!(child instanceof HTMLFieldSetElement) || child.getAttribute("aria-disabled") === "true"))
|
|
49
|
+
continue;
|
|
50
|
+
if (!disabled && child.matches(TABBABLE_SELECTOR) && child.tabIndex >= 0)
|
|
51
|
+
result.push(child);
|
|
52
|
+
// An explicit negative tabindex removes a shadow host's entire focus
|
|
53
|
+
// scope from sequential navigation. Ordinary light-DOM containers with
|
|
54
|
+
// tabindex=-1 do not have that behavior.
|
|
55
|
+
if (child.shadowRoot && child.hasAttribute("tabindex") && child.tabIndex < 0)
|
|
56
|
+
continue;
|
|
57
|
+
visit(child.shadowRoot ?? child);
|
|
40
58
|
}
|
|
41
|
-
|
|
42
|
-
|
|
59
|
+
};
|
|
60
|
+
visit(container);
|
|
61
|
+
return result;
|
|
43
62
|
};
|
|
44
63
|
/**
|
|
45
64
|
* Keep Tab / Shift+Tab cycling inside `container` while a modal is open.
|
|
@@ -57,7 +76,7 @@ export const trapTabKey = (event, container) => {
|
|
|
57
76
|
const first = focusables[0];
|
|
58
77
|
const last = focusables[focusables.length - 1];
|
|
59
78
|
const root = container.getRootNode?.();
|
|
60
|
-
const active = root
|
|
79
|
+
const active = deepActiveElement(root ?? document) ?? deepActiveElement(document);
|
|
61
80
|
if (event.shiftKey) {
|
|
62
81
|
if (active === first || !focusables.includes(active)) {
|
|
63
82
|
event.preventDefault();
|
|
@@ -74,6 +93,8 @@ export const trapTabKey = (event, container) => {
|
|
|
74
93
|
export class FocusRestore {
|
|
75
94
|
previous = null;
|
|
76
95
|
capture(from = document.activeElement) {
|
|
96
|
+
while (from?.shadowRoot?.activeElement)
|
|
97
|
+
from = from.shadowRoot.activeElement;
|
|
77
98
|
this.previous = from instanceof HTMLElement ? from : null;
|
|
78
99
|
}
|
|
79
100
|
restore() {
|
|
@@ -83,8 +104,8 @@ export class FocusRestore {
|
|
|
83
104
|
return;
|
|
84
105
|
}
|
|
85
106
|
queueMicrotask(() => {
|
|
86
|
-
if (
|
|
87
|
-
target.focus();
|
|
107
|
+
if (target.isConnected && isVisible(target) && !isDisabled(target)) {
|
|
108
|
+
target.focus({ preventScroll: true });
|
|
88
109
|
}
|
|
89
110
|
});
|
|
90
111
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { announce, installAnnouncer } from "./announcer.js";
|
|
2
|
+
export type { Politeness } from "./announcer.js";
|
|
1
3
|
export { applyRovingTabindex, focusRovingItem, handleRovingKeydown, nextRovingIndex, } from "./keyboard.js";
|
|
2
4
|
export type { RovingKeyOptions, RovingOrientation } from "./keyboard.js";
|
|
3
5
|
export { FocusRestore, getTabbableElements, trapTabKey } from "./focus.js";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { announce, installAnnouncer } from "./announcer.js";
|
|
1
2
|
export { applyRovingTabindex, focusRovingItem, handleRovingKeydown, nextRovingIndex, } from "./keyboard.js";
|
|
2
3
|
export { FocusRestore, getTabbableElements, trapTabKey } from "./focus.js";
|
|
3
4
|
export { boeHeadingResetStyles, headingCloseTag, headingOpenTag, renderHeadingHtml, } from "./heading.js";
|