@k2b/ui 0.24.0 → 0.26.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/README.md +2 -2
- package/dist/browser/actions/Dropdown.js +67 -52
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/GestureMenu.js +5 -5
- package/dist/browser/actions/GestureMenu.js.map +1 -1
- package/dist/browser/actions/SpotlightSearch.js +13 -6
- package/dist/browser/actions/SpotlightSearch.js.map +1 -1
- package/dist/browser/actions/Toolbar.js +75 -1
- package/dist/browser/actions/Toolbar.js.map +1 -1
- package/dist/browser/content/Calendar.js +1539 -911
- package/dist/browser/content/Calendar.js.map +1 -1
- package/dist/browser/content/CalendarDayView.js +5 -4
- package/dist/browser/content/CalendarDayView.js.map +1 -1
- package/dist/browser/content/CalendarWeekView.js +5 -4
- package/dist/browser/content/CalendarWeekView.js.map +1 -1
- package/dist/browser/content/Kbd.js +51 -0
- package/dist/browser/content/Kbd.js.map +1 -0
- package/dist/browser/content/LabelChip.js +38 -0
- package/dist/browser/content/LabelChip.js.map +1 -0
- package/dist/browser/content/MarkdownView.js +2 -1
- package/dist/browser/content/MarkdownView.js.map +1 -1
- package/dist/browser/content/Steps.js +34 -0
- package/dist/browser/content/Steps.js.map +1 -0
- package/dist/browser/content/Timeline.js +3 -3
- package/dist/browser/content/Timeline.js.map +1 -1
- package/dist/browser/content/VirtualFeed.js +33 -1
- package/dist/browser/content/VirtualFeed.js.map +1 -1
- package/dist/browser/content/calendar-dialogs.js +32 -60
- package/dist/browser/content/calendar-dialogs.js.map +1 -1
- package/dist/browser/content/calendar-month-scroll.js +80 -0
- package/dist/browser/content/calendar-month-scroll.js.map +1 -0
- package/dist/browser/content/calendar-time-view.js +0 -1
- package/dist/browser/content/calendar-time-view.js.map +1 -1
- package/dist/browser/content/index.js +4 -1
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/content/markdown-info-blocks.js +33 -5
- package/dist/browser/content/markdown-info-blocks.js.map +1 -1
- package/dist/browser/feedback/prompts.js +17 -3
- package/dist/browser/feedback/prompts.js.map +1 -1
- package/dist/browser/index.js +1 -0
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/inputs/Combobox.js +22 -3
- package/dist/browser/inputs/Combobox.js.map +1 -1
- package/dist/browser/inputs/QrScanner.js +2 -1
- package/dist/browser/inputs/QrScanner.js.map +1 -1
- package/dist/browser/intl/index.js +1 -0
- package/dist/browser/intl/index.js.map +1 -1
- package/dist/browser/intl/shortcut-messages.js +77 -0
- package/dist/browser/intl/shortcut-messages.js.map +1 -0
- package/dist/browser/intl/shortcut.js +123 -0
- package/dist/browser/intl/shortcut.js.map +1 -0
- package/dist/browser/layout/AppWorkspace.js +355 -338
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/TableOfContents.js +115 -0
- package/dist/browser/layout/TableOfContents.js.map +1 -0
- package/dist/browser/layout/app-workspace-controller.js +7 -50
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/index.js +1 -0
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/scroll-fade.js +14 -9
- package/dist/browser/layout/scroll-fade.js.map +1 -1
- package/dist/browser/layout/sidebar-scroll-memory.js +38 -0
- package/dist/browser/layout/sidebar-scroll-memory.js.map +1 -0
- package/dist/browser/layout/table-of-contents-messages.js +19 -0
- package/dist/browser/layout/table-of-contents-messages.js.map +1 -0
- package/dist/browser/motion.js +7 -0
- package/dist/browser/motion.js.map +1 -0
- package/dist/browser/surfaces/LinkCard.js +40 -24
- package/dist/browser/surfaces/LinkCard.js.map +1 -1
- package/dist/ssr/actions/Dropdown.js +11 -5
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/GestureMenu.js +5 -5
- package/dist/ssr/actions/GestureMenu.js.map +1 -1
- package/dist/ssr/actions/SpotlightSearch.js +9 -3
- package/dist/ssr/actions/SpotlightSearch.js.map +1 -1
- package/dist/ssr/actions/Toolbar.js +67 -1
- package/dist/ssr/actions/Toolbar.js.map +1 -1
- package/dist/ssr/content/Calendar.js +864 -312
- package/dist/ssr/content/Calendar.js.map +1 -1
- package/dist/ssr/content/CalendarDayView.js +5 -4
- package/dist/ssr/content/CalendarDayView.js.map +1 -1
- package/dist/ssr/content/CalendarWeekView.js +5 -4
- package/dist/ssr/content/CalendarWeekView.js.map +1 -1
- package/dist/ssr/content/Kbd.js +38 -0
- package/dist/ssr/content/Kbd.js.map +1 -0
- package/dist/ssr/content/LabelChip.js +21 -0
- package/dist/ssr/content/LabelChip.js.map +1 -0
- package/dist/ssr/content/MarkdownView.js +2 -1
- package/dist/ssr/content/MarkdownView.js.map +1 -1
- package/dist/ssr/content/Steps.js +14 -0
- package/dist/ssr/content/Steps.js.map +1 -0
- package/dist/ssr/content/Timeline.js +3 -3
- package/dist/ssr/content/Timeline.js.map +1 -1
- package/dist/ssr/content/VirtualFeed.js +33 -1
- package/dist/ssr/content/VirtualFeed.js.map +1 -1
- package/dist/ssr/content/calendar-dialogs.js +12 -32
- package/dist/ssr/content/calendar-dialogs.js.map +1 -1
- package/dist/ssr/content/calendar-month-scroll.js +80 -0
- package/dist/ssr/content/calendar-month-scroll.js.map +1 -0
- package/dist/ssr/content/calendar-time-view.js +0 -1
- package/dist/ssr/content/calendar-time-view.js.map +1 -1
- package/dist/ssr/content/index.js +4 -1
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/content/markdown-info-blocks.js +33 -5
- package/dist/ssr/content/markdown-info-blocks.js.map +1 -1
- package/dist/ssr/feedback/prompts.js +17 -3
- package/dist/ssr/feedback/prompts.js.map +1 -1
- package/dist/ssr/index.js +1 -0
- package/dist/ssr/index.js.map +1 -1
- package/dist/ssr/inputs/Combobox.js +18 -3
- package/dist/ssr/inputs/Combobox.js.map +1 -1
- package/dist/ssr/inputs/QrScanner.js +2 -1
- package/dist/ssr/inputs/QrScanner.js.map +1 -1
- package/dist/ssr/intl/index.js +1 -0
- package/dist/ssr/intl/index.js.map +1 -1
- package/dist/ssr/intl/shortcut-messages.js +77 -0
- package/dist/ssr/intl/shortcut-messages.js.map +1 -0
- package/dist/ssr/intl/shortcut.js +123 -0
- package/dist/ssr/intl/shortcut.js.map +1 -0
- package/dist/ssr/layout/AppWorkspace.js +77 -72
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/TableOfContents.js +79 -0
- package/dist/ssr/layout/TableOfContents.js.map +1 -0
- package/dist/ssr/layout/app-workspace-controller.js +7 -50
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/index.js +1 -0
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/scroll-fade.js +14 -9
- package/dist/ssr/layout/scroll-fade.js.map +1 -1
- package/dist/ssr/layout/sidebar-scroll-memory.js +38 -0
- package/dist/ssr/layout/sidebar-scroll-memory.js.map +1 -0
- package/dist/ssr/layout/table-of-contents-messages.js +19 -0
- package/dist/ssr/layout/table-of-contents-messages.js.map +1 -0
- package/dist/ssr/motion.js +7 -0
- package/dist/ssr/motion.js.map +1 -0
- package/dist/ssr/surfaces/LinkCard.js +26 -10
- package/dist/ssr/surfaces/LinkCard.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/Dropdown.d.ts +12 -0
- package/dist/types/actions/SpotlightSearch.d.ts +2 -0
- package/dist/types/content/Calendar.d.ts +16 -6
- package/dist/types/content/Kbd.d.ts +16 -0
- package/dist/types/content/LabelChip.d.ts +12 -0
- package/dist/types/content/MarkdownView.d.ts +2 -1
- package/dist/types/content/Steps.d.ts +12 -0
- package/dist/types/content/VirtualFeed.d.ts +8 -0
- package/dist/types/content/calendar-dialogs.d.ts +0 -2
- package/dist/types/content/calendar-month-scroll.d.ts +25 -0
- package/dist/types/content/calendar-time-view.d.ts +0 -1
- package/dist/types/content/index.d.ts +7 -1
- package/dist/types/content/markdown-info-blocks.d.ts +21 -4
- package/dist/types/feedback/prompts.d.ts +8 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/inputs/Combobox.d.ts +1 -0
- package/dist/types/intl/index.d.ts +2 -0
- package/dist/types/intl/shortcut-messages.d.ts +35 -0
- package/dist/types/intl/shortcut.d.ts +29 -0
- package/dist/types/layout/AppWorkspace.d.ts +3 -1
- package/dist/types/layout/TableOfContents.d.ts +24 -0
- package/dist/types/layout/index.d.ts +2 -0
- package/dist/types/layout/scroll-fade.d.ts +2 -0
- package/dist/types/layout/sidebar-scroll-memory.d.ts +6 -0
- package/dist/types/layout/table-of-contents-messages.d.ts +4 -0
- package/dist/types/motion.d.ts +6 -0
- package/dist/types/surfaces/LinkCard.d.ts +3 -0
- package/package.json +3 -3
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { ssr as _$ssr } from "solid-js/web";
|
|
2
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
3
|
+
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
4
|
+
import { escape as _$escape } from "solid-js/web";
|
|
5
|
+
var _tmpl$ = ["<nav class=\"", "\"", "><p class=\"k2b-toc__title\"", ">", "</p><ol class=\"k2b-toc__list\">", "</ol></nav>"],
|
|
6
|
+
_tmpl$2 = ["<li><a class=\"k2b-toc__link\" href=\"", "\"", ">", "</a></li>"];
|
|
7
|
+
import { createEffect, createSignal, createUniqueId, For, onCleanup, Show, untrack } from "solid-js";
|
|
8
|
+
import { resolveMaybeAccessor } from "../inputs/field-contract";
|
|
9
|
+
import { assertStableUiId } from "./stable-id";
|
|
10
|
+
import { useTableOfContentsMessages } from "./table-of-contents-messages";
|
|
11
|
+
/**
|
|
12
|
+
* Native section links with a scroll spy on the window or a content container.
|
|
13
|
+
* @example <TableOfContents items={[{ id: "sharing", label: "Sharing" }]} sticky />
|
|
14
|
+
*/
|
|
15
|
+
export function TableOfContents(props) {
|
|
16
|
+
const t = useTableOfContentsMessages();
|
|
17
|
+
const headingId = assertStableUiId(`k2b-toc-${createUniqueId().replace(/[^a-zA-Z0-9_-]/g, "-")}`, "TableOfContents heading id");
|
|
18
|
+
const [active, setActive] = createSignal(props.items[0]?.id);
|
|
19
|
+
createEffect(() => {
|
|
20
|
+
// Reading every id here makes a changed id or a store update recompute the active section.
|
|
21
|
+
const ids = props.items.map(item => item.id);
|
|
22
|
+
const root = resolveMaybeAccessor(props.scrollRoot);
|
|
23
|
+
const target = root ?? window;
|
|
24
|
+
let frame;
|
|
25
|
+
const update = () => {
|
|
26
|
+
frame = undefined;
|
|
27
|
+
const box = root?.getBoundingClientRect();
|
|
28
|
+
const top = box ? box.top + (root?.clientTop ?? 0) : 0;
|
|
29
|
+
const height = root?.clientHeight ?? window.innerHeight;
|
|
30
|
+
const line = top + height / 4;
|
|
31
|
+
const headings = ids.map(id => ({
|
|
32
|
+
id,
|
|
33
|
+
box: document.getElementById(id)?.getBoundingClientRect()
|
|
34
|
+
}));
|
|
35
|
+
let next = ids[0];
|
|
36
|
+
for (const heading of headings) if (heading.box && heading.box.top <= line) next = heading.id;
|
|
37
|
+
const last = headings.at(-1);
|
|
38
|
+
const atEnd = root ? root.scrollHeight - root.clientHeight - root.scrollTop <= 4 : document.documentElement.scrollHeight - window.innerHeight - window.scrollY <= 4;
|
|
39
|
+
if (atEnd && last?.box && last.box.top < top + height && last.box.bottom > top) next = last.id;
|
|
40
|
+
if (next !== active()) {
|
|
41
|
+
setActive(next);
|
|
42
|
+
props.onActiveChange?.(next);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const schedule = () => {
|
|
46
|
+
if (frame === undefined) frame = requestAnimationFrame(update);
|
|
47
|
+
};
|
|
48
|
+
target.addEventListener("scroll", schedule, {
|
|
49
|
+
passive: true
|
|
50
|
+
});
|
|
51
|
+
window.addEventListener("resize", schedule);
|
|
52
|
+
const observer = typeof ResizeObserver === "undefined" ? undefined : new ResizeObserver(schedule);
|
|
53
|
+
// No scroll or window resize happens when the root, a block above a heading, or a heading's own section changes size.
|
|
54
|
+
const observed = new Set([root ?? document.documentElement, ...(root?.children ?? [document.body]), ...ids.map(id => document.getElementById(id)?.parentElement)]);
|
|
55
|
+
for (const element of observed) if (element) observer?.observe(element);
|
|
56
|
+
untrack(update);
|
|
57
|
+
onCleanup(() => {
|
|
58
|
+
target.removeEventListener("scroll", schedule);
|
|
59
|
+
window.removeEventListener("resize", schedule);
|
|
60
|
+
observer?.disconnect();
|
|
61
|
+
if (frame !== undefined) cancelAnimationFrame(frame);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
return _$createComponent(Show, {
|
|
65
|
+
get when() {
|
|
66
|
+
return props.items.length > 0;
|
|
67
|
+
},
|
|
68
|
+
get children() {
|
|
69
|
+
return _$ssr(_tmpl$, `k2b-toc${props.class ? ` ${_$escape(props.class, true)}` : ""}`, _$ssrAttribute("data-sticky", props.sticky ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("aria-labelledby", _$escape(headingId, true), false), _$ssrAttribute("id", _$escape(headingId, true), false), _$escape(props.title ?? t().title), _$escape(_$createComponent(For, {
|
|
70
|
+
get each() {
|
|
71
|
+
return props.items;
|
|
72
|
+
},
|
|
73
|
+
children: item => _$ssr(_tmpl$2, `#${_$escape(item.id, true)}`, _$ssrAttribute("aria-current", active() === item.id ? "location" : _$escape(undefined, true), false), _$escape(item.label))
|
|
74
|
+
})));
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
export default TableOfContents;
|
|
79
|
+
//# sourceMappingURL=TableOfContents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["layout/TableOfContents.tsx"],"sourcesContent":["import { createEffect, createSignal, createUniqueId, For, type JSX, onCleanup, Show, untrack } from \"solid-js\";\nimport type { MaybeAccessor } from \"../inputs/field-contract\";\nimport { resolveMaybeAccessor } from \"../inputs/field-contract\";\nimport { assertStableUiId } from \"./stable-id\";\nimport { useTableOfContentsMessages } from \"./table-of-contents-messages\";\n\nexport type TableOfContentsItem = { id: string; label: string };\nexport type TableOfContentsProps = {\n items: readonly TableOfContentsItem[];\n /** Visible heading and navigation name. Defaults to the localized \"On this page\". */\n title?: string;\n /** Element whose scrolling decides the active section. Defaults to the window. */\n scrollRoot?: MaybeAccessor<HTMLElement | undefined>;\n /** Stay in view inside the caller's layout. */\n sticky?: boolean;\n /** Called when another section becomes active. */\n onActiveChange?: (id: string | undefined) => void;\n class?: string;\n};\n\n/**\n * Native section links with a scroll spy on the window or a content container.\n * @example <TableOfContents items={[{ id: \"sharing\", label: \"Sharing\" }]} sticky />\n */\nexport function TableOfContents(props: TableOfContentsProps): JSX.Element {\n const t = useTableOfContentsMessages();\n const headingId = assertStableUiId(`k2b-toc-${createUniqueId().replace(/[^a-zA-Z0-9_-]/g, \"-\")}`, \"TableOfContents heading id\");\n const [active, setActive] = createSignal(props.items[0]?.id);\n createEffect(() => {\n // Reading every id here makes a changed id or a store update recompute the active section.\n const ids = props.items.map((item) => item.id);\n const root = resolveMaybeAccessor(props.scrollRoot);\n const target = root ?? window;\n let frame: number | undefined;\n const update = () => {\n frame = undefined;\n const box = root?.getBoundingClientRect();\n const top = box ? box.top + (root?.clientTop ?? 0) : 0;\n const height = root?.clientHeight ?? window.innerHeight;\n const line = top + height / 4;\n const headings = ids.map((id) => ({ id, box: document.getElementById(id)?.getBoundingClientRect() }));\n let next = ids[0];\n for (const heading of headings) if (heading.box && heading.box.top <= line) next = heading.id;\n const last = headings.at(-1);\n const atEnd = root\n ? root.scrollHeight - root.clientHeight - root.scrollTop <= 4\n : document.documentElement.scrollHeight - window.innerHeight - window.scrollY <= 4;\n if (atEnd && last?.box && last.box.top < top + height && last.box.bottom > top) next = last.id;\n if (next !== active()) {\n setActive(next);\n props.onActiveChange?.(next);\n }\n };\n const schedule = () => {\n if (frame === undefined) frame = requestAnimationFrame(update);\n };\n target.addEventListener(\"scroll\", schedule, { passive: true });\n window.addEventListener(\"resize\", schedule);\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(schedule);\n // No scroll or window resize happens when the root, a block above a heading, or a heading's own section changes size.\n const observed = new Set<Element | null | undefined>([\n root ?? document.documentElement,\n ...(root?.children ?? [document.body]),\n ...ids.map((id) => document.getElementById(id)?.parentElement),\n ]);\n for (const element of observed) if (element) observer?.observe(element);\n untrack(update);\n onCleanup(() => {\n target.removeEventListener(\"scroll\", schedule);\n window.removeEventListener(\"resize\", schedule);\n observer?.disconnect();\n if (frame !== undefined) cancelAnimationFrame(frame);\n });\n });\n return (\n <Show when={props.items.length > 0}>\n <nav\n class={`k2b-toc${props.class ? ` ${props.class}` : \"\"}`}\n data-sticky={props.sticky ? \"true\" : undefined}\n aria-labelledby={headingId}\n >\n <p class=\"k2b-toc__title\" id={headingId}>\n {props.title ?? t().title}\n </p>\n <ol class=\"k2b-toc__list\">\n <For each={props.items}>\n {(item) => (\n <li>\n <a class=\"k2b-toc__link\" href={`#${item.id}`} aria-current={active() === item.id ? \"location\" : undefined}>\n {item.label}\n </a>\n </li>\n )}\n </For>\n </ol>\n </nav>\n </Show>\n );\n}\nexport default TableOfContents;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { suppressTextSelection } from "../internal/text-selection";
|
|
2
|
+
import { prefersReducedMotion } from "../motion";
|
|
2
3
|
import { APP_WORKSPACE_DETAIL_DEFAULT, APP_WORKSPACE_DETAIL_MAX, APP_WORKSPACE_DETAIL_MIN, APP_WORKSPACE_DRAWER_MAX, APP_WORKSPACE_DRAWER_MIN, APP_WORKSPACE_MAIN_MIN, APP_WORKSPACE_PANE_MAX, APP_WORKSPACE_PANE_MIN, APP_WORKSPACE_SIDEBAR_COLLAPSED, APP_WORKSPACE_SIDEBAR_MAX, APP_WORKSPACE_SIDEBAR_MIN, appWorkspacePanelVariable, appWorkspaceResizeLimits, fitAppWorkspacePaneSizes, normalizeAppWorkspaceLayoutState, resolveAppWorkspaceSidebarWidth, safeAppWorkspacePanelId, shouldCollapseAppWorkspaceSidebar } from "./app-workspace-state";
|
|
3
4
|
import { installScrollFades } from "./scroll-fade";
|
|
4
5
|
const HANDLE_SELECTOR = "[data-app-workspace-resize]";
|
|
@@ -10,8 +11,6 @@ const COMPACT_QUERY = "(min-width: 48rem) and (max-width: 63.999rem)";
|
|
|
10
11
|
const FOCUSABLE_SELECTOR = ["a[href]", "button:not([disabled])", "input:not([disabled]):not([type='hidden'])", "select:not([disabled])", "textarea:not([disabled])", "[tabindex]:not([tabindex='-1'])"].join(",");
|
|
11
12
|
/** Text entry, menus, dialogs, and open popups keep their own keys. */
|
|
12
13
|
const KEY_OWNER_SELECTOR = "input, textarea, select, [contenteditable]:not([contenteditable='false']), [role='textbox'], [role='combobox'], [role='searchbox'], [role='spinbutton'], [role='menu'], [role='listbox'], [role='dialog'], dialog, [aria-haspopup]:not([aria-haspopup='false'])[aria-expanded='true']";
|
|
13
|
-
const LABEL_SELECTOR = ".k2b-app-workspace__sidebar-item-label[data-marquee='true']";
|
|
14
|
-
const LABEL_TEXT_SELECTOR = ".k2b-app-workspace__sidebar-item-label-text";
|
|
15
14
|
const ITEM_SELECTOR = ".k2b-app-workspace__sidebar-item";
|
|
16
15
|
const clamp = (value, min, max) => Math.round(Math.min(max, Math.max(min, value)));
|
|
17
16
|
const eventElement = event => event.target instanceof Element ? event.target : null;
|
|
@@ -164,25 +163,6 @@ const reconcilePanes = (root, layoutState, active = null) => {
|
|
|
164
163
|
fits.forEach((fit, index) => updateHandleValue(root, fit.handle, "pane", sizes[index]));
|
|
165
164
|
};
|
|
166
165
|
|
|
167
|
-
/**
|
|
168
|
-
* Marquee support for a truncated sidebar label.
|
|
169
|
-
*
|
|
170
|
-
* The animation needs to know how far to travel, and that is only knowable
|
|
171
|
-
* once the label has been laid out — so it is measured lazily, on the same
|
|
172
|
-
* hover/focus that triggers it, and published as a custom property. Labels
|
|
173
|
-
* that fit get no `data-overflow`, so they never animate. A revealed row action
|
|
174
|
-
* pads the label's fading end, so the text is measured against the content box.
|
|
175
|
-
*/
|
|
176
|
-
const measureLabel = label => {
|
|
177
|
-
const text = label.querySelector(LABEL_TEXT_SELECTOR);
|
|
178
|
-
if (!text) return;
|
|
179
|
-
const style = getComputedStyle(label);
|
|
180
|
-
const width = label.clientWidth - (Number.parseFloat(style.paddingLeft) || 0) - (Number.parseFloat(style.paddingRight) || 0);
|
|
181
|
-
const overflow = Math.max(0, text.scrollWidth - width);
|
|
182
|
-
label.style.setProperty("--k2b-sidebar-label-overflow", `${overflow}px`);
|
|
183
|
-
if (overflow > 2) label.dataset.overflow = "true";else delete label.dataset.overflow;
|
|
184
|
-
};
|
|
185
|
-
|
|
186
166
|
/** An open overlay remembers the regions it made inert, so it leaves the application's own `inert` alone. */
|
|
187
167
|
|
|
188
168
|
/**
|
|
@@ -319,7 +299,6 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
319
299
|
const phone = typeof window.matchMedia === "function" ? window.matchMedia("(max-width: 47.999rem)") : null;
|
|
320
300
|
const wide = typeof window.matchMedia === "function" ? window.matchMedia("(min-width: 48rem)") : null;
|
|
321
301
|
const touchDrawer = typeof window.matchMedia === "function" ? window.matchMedia(`${COMPACT_QUERY} and (pointer: coarse)`) : null;
|
|
322
|
-
const reducedMotion = typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null;
|
|
323
302
|
const detailSelector = ".k2b-app-workspace__detail";
|
|
324
303
|
const grabberSelector = ".k2b-app-workspace__detail-grabber";
|
|
325
304
|
const detailHidden = new WeakMap();
|
|
@@ -487,7 +466,7 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
487
466
|
// edge, so the workspace clips while the panel moves (see the stylesheet).
|
|
488
467
|
const slide = (root, aside) => {
|
|
489
468
|
slides.get(root)?.();
|
|
490
|
-
if (!root.hasAttribute("data-workspace-motion") ||
|
|
469
|
+
if (!root.hasAttribute("data-workspace-motion") || prefersReducedMotion() || !wide?.matches) return;
|
|
491
470
|
const end = () => {
|
|
492
471
|
aside.removeEventListener("transitionend", onEnd);
|
|
493
472
|
aside.removeEventListener("transitioncancel", onEnd);
|
|
@@ -515,7 +494,7 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
515
494
|
revealFrames.set(root, requestAnimationFrame(() => {
|
|
516
495
|
revealFrames.delete(root);
|
|
517
496
|
if (!aside.hidden && aside.isConnected && snapshot.item.isConnected && mainElement(root)?.contains(snapshot.item) && snapshot.item.closest(ROOT_SELECTOR) === root) {
|
|
518
|
-
const behavior =
|
|
497
|
+
const behavior = prefersReducedMotion() ? "auto" : "smooth";
|
|
519
498
|
const main = mainElement(root);
|
|
520
499
|
const cell = snapshot.cell;
|
|
521
500
|
const target = cell?.isConnected && main?.contains(cell) ? cell : snapshot.item;
|
|
@@ -584,7 +563,7 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
584
563
|
if (aside.hidden) {
|
|
585
564
|
if (pendingTitle?.aside === aside) cancelTitle();
|
|
586
565
|
if (panelStep === aside) panelStep = null;
|
|
587
|
-
if (root.hasAttribute("data-workspace-motion") && !
|
|
566
|
+
if (root.hasAttribute("data-workspace-motion") && !prefersReducedMotion() && wide?.matches) {
|
|
588
567
|
// Closing holds the detail column until the slide ends; anchor after Main widens.
|
|
589
568
|
const cancel = () => {
|
|
590
569
|
root.removeEventListener("transitionend", onTransitionEnd);
|
|
@@ -1080,43 +1059,23 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
1080
1059
|
if (handle && kind && root && controlsResizableRegion(root, handle, kind)) {
|
|
1081
1060
|
updateHandleValue(root, handle, kind, currentSize(root, handle, kind));
|
|
1082
1061
|
}
|
|
1083
|
-
const label = eventElement(event)?.closest(ITEM_SELECTOR)?.querySelector(LABEL_SELECTOR);
|
|
1084
|
-
if (label) requestAnimationFrame(() => measureLabel(label));
|
|
1085
|
-
};
|
|
1086
|
-
|
|
1087
|
-
// Measured on entry rather than on every render: `scrollWidth` forces layout,
|
|
1088
|
-
// and a sidebar can hold hundreds of rows.
|
|
1089
|
-
const onPointerOver = event => {
|
|
1090
|
-
const label = eventElement(event)?.closest(LABEL_SELECTOR);
|
|
1091
|
-
if (!label || event.relatedTarget instanceof Node && label.contains(event.relatedTarget)) return;
|
|
1092
|
-
requestAnimationFrame(() => measureLabel(label));
|
|
1093
|
-
};
|
|
1094
|
-
|
|
1095
|
-
// A resize changes every label's available width, so the cached measurement
|
|
1096
|
-
// is dropped and taken again on the next hover or focus.
|
|
1097
|
-
const clearMeasuredLabels = () => {
|
|
1098
|
-
eventRoot.querySelectorAll(LABEL_SELECTOR).forEach(label => {
|
|
1099
|
-
delete label.dataset.overflow;
|
|
1100
|
-
label.style.removeProperty("--k2b-sidebar-label-overflow");
|
|
1101
|
-
});
|
|
1102
1062
|
};
|
|
1103
1063
|
|
|
1104
1064
|
// Geometry can change without a window resize: a parent can resize the
|
|
1105
1065
|
// workspace, or a detail/pane can open. All sources share one frame so a
|
|
1106
1066
|
// transition performs at most one layout reconciliation.
|
|
1107
1067
|
let reconcileFrame = null;
|
|
1108
|
-
const scheduleReconcile = (
|
|
1109
|
-
if (clearLabels) clearMeasuredLabels();
|
|
1068
|
+
const scheduleReconcile = () => {
|
|
1110
1069
|
if (reconcileFrame !== null) return;
|
|
1111
1070
|
reconcileFrame = requestAnimationFrame(() => {
|
|
1112
1071
|
reconcileFrame = null;
|
|
1113
1072
|
reconcile();
|
|
1114
1073
|
});
|
|
1115
1074
|
};
|
|
1116
|
-
const onResize = () => scheduleReconcile(
|
|
1075
|
+
const onResize = () => scheduleReconcile();
|
|
1117
1076
|
const observedRoots = new Set();
|
|
1118
1077
|
const resizeObserver = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => {
|
|
1119
|
-
scheduleReconcile(
|
|
1078
|
+
scheduleReconcile();
|
|
1120
1079
|
});
|
|
1121
1080
|
const syncObservedRoots = () => {
|
|
1122
1081
|
for (const elements of [touchedDetails, titleTabIndices, motionRoots]) {
|
|
@@ -1206,7 +1165,6 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
1206
1165
|
compact?.addEventListener("change", onCompactChange);
|
|
1207
1166
|
eventRoot.addEventListener("keydown", onKeyDown);
|
|
1208
1167
|
eventRoot.addEventListener("focusin", onFocusIn);
|
|
1209
|
-
eventRoot.addEventListener("pointerover", onPointerOver);
|
|
1210
1168
|
window.addEventListener("resize", onResize);
|
|
1211
1169
|
syncObservedRoots();
|
|
1212
1170
|
mutationObserver?.observe(eventRoot, {
|
|
@@ -1265,7 +1223,6 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
1265
1223
|
compact?.removeEventListener("change", onCompactChange);
|
|
1266
1224
|
eventRoot.removeEventListener("keydown", onKeyDown);
|
|
1267
1225
|
eventRoot.removeEventListener("focusin", onFocusIn);
|
|
1268
|
-
eventRoot.removeEventListener("pointerover", onPointerOver);
|
|
1269
1226
|
window.removeEventListener("resize", onResize);
|
|
1270
1227
|
};
|
|
1271
1228
|
};
|