gridsmith-ui 0.30.0 → 0.30.2
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/CHANGELOG.md +61 -1
- package/dist/charts.js +21 -8
- package/dist/charts.js.map +1 -1
- package/dist/chat.js +15 -9
- package/dist/chat.js.map +1 -1
- package/dist/{chunk-OIOII5L6.js → chunk-4HJDOZ2M.js} +303 -20
- package/dist/chunk-4HJDOZ2M.js.map +1 -0
- package/dist/{chunk-INGF2CPW.js → chunk-6C2IUMY7.js} +3 -3
- package/dist/{chunk-INGF2CPW.js.map → chunk-6C2IUMY7.js.map} +1 -1
- package/dist/chunk-ACLKDE5W.js +59 -0
- package/dist/chunk-ACLKDE5W.js.map +1 -0
- package/dist/{chunk-NLXQ323J.js → chunk-BZRZENBS.js} +5 -4
- package/dist/chunk-BZRZENBS.js.map +1 -0
- package/dist/{chunk-RHWTMTU5.js → chunk-DBHVJ7Z3.js} +5 -49
- package/dist/chunk-DBHVJ7Z3.js.map +1 -0
- package/dist/{chunk-Z4MCD73B.js → chunk-HVGHGBKV.js} +6 -7
- package/dist/chunk-HVGHGBKV.js.map +1 -0
- package/dist/{chunk-UNS4TGGK.js → chunk-K6IDOCGE.js} +77 -27
- package/dist/chunk-K6IDOCGE.js.map +1 -0
- package/dist/{chunk-Q36JVJX4.js → chunk-MIUSSYVE.js} +4 -4
- package/dist/{chunk-Q36JVJX4.js.map → chunk-MIUSSYVE.js.map} +1 -1
- package/dist/{chunk-F2BNJSON.js → chunk-SIWERRP2.js} +70 -69
- package/dist/chunk-SIWERRP2.js.map +1 -0
- package/dist/{chunk-KTPGMJUK.js → chunk-SQHKC4HA.js} +8 -5
- package/dist/chunk-SQHKC4HA.js.map +1 -0
- package/dist/{chunk-NI5542ZM.js → chunk-USHW523V.js} +81 -24
- package/dist/chunk-USHW523V.js.map +1 -0
- package/dist/{chunk-GQVBZ4GW.js → chunk-WWN6CQKI.js} +31 -104
- package/dist/chunk-WWN6CQKI.js.map +1 -0
- package/dist/{chunk-JTU7OBYJ.js → chunk-YL5KD5RC.js} +4 -3
- package/dist/chunk-YL5KD5RC.js.map +1 -0
- package/dist/{chunk-6A5RHW2W.js → chunk-ZASGFL5D.js} +4 -5
- package/dist/chunk-ZASGFL5D.js.map +1 -0
- package/dist/chunk-ZCDA74RQ.js +110 -0
- package/dist/chunk-ZCDA74RQ.js.map +1 -0
- package/dist/data-grid.js +8 -10
- package/dist/data-grid.js.map +1 -1
- package/dist/editor-mentions.js +3 -5
- package/dist/editor-mentions.js.map +1 -1
- package/dist/editor.js +8 -7
- package/dist/editor.js.map +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +198 -105
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +11 -12
- package/dist/kanban.js.map +1 -1
- package/dist/resizable.js +42 -14
- package/dist/resizable.js.map +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/virtualized.d.ts +6 -1
- package/dist/virtualized.js +12 -11
- package/dist/virtualized.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6A5RHW2W.js.map +0 -1
- package/dist/chunk-F2BNJSON.js.map +0 -1
- package/dist/chunk-GQVBZ4GW.js.map +0 -1
- package/dist/chunk-HP7WUZPK.js +0 -81
- package/dist/chunk-HP7WUZPK.js.map +0 -1
- package/dist/chunk-HTXP5BMM.js +0 -38
- package/dist/chunk-HTXP5BMM.js.map +0 -1
- package/dist/chunk-JTU7OBYJ.js.map +0 -1
- package/dist/chunk-KTPGMJUK.js.map +0 -1
- package/dist/chunk-NI5542ZM.js.map +0 -1
- package/dist/chunk-NLXQ323J.js.map +0 -1
- package/dist/chunk-OIOII5L6.js.map +0 -1
- package/dist/chunk-RHWTMTU5.js.map +0 -1
- package/dist/chunk-UNS4TGGK.js.map +0 -1
- package/dist/chunk-WH2FUFAC.js +0 -15
- package/dist/chunk-WH2FUFAC.js.map +0 -1
- package/dist/chunk-Z4MCD73B.js.map +0 -1
package/dist/chat.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { Divider, CodeBlock, Link } from './chunk-
|
|
3
|
-
import './chunk-
|
|
4
|
-
import './chunk-
|
|
5
|
-
import './chunk-
|
|
2
|
+
import { Divider, CodeBlock, Link } from './chunk-SQHKC4HA.js';
|
|
3
|
+
import './chunk-BZRZENBS.js';
|
|
4
|
+
import { useKeyboardScroll } from './chunk-ACLKDE5W.js';
|
|
5
|
+
import './chunk-ZCDA74RQ.js';
|
|
6
|
+
import './chunk-WWN6CQKI.js';
|
|
6
7
|
import './chunk-L6HWACK7.js';
|
|
7
|
-
import './chunk-
|
|
8
|
-
import './chunk-
|
|
9
|
-
import { cn } from './chunk-
|
|
10
|
-
import { memo, Children, isValidElement } from 'react';
|
|
8
|
+
import './chunk-7Q46JXSK.js';
|
|
9
|
+
import './chunk-4HJDOZ2M.js';
|
|
10
|
+
import { cn, FOCUS_INSET } from './chunk-YL5KD5RC.js';
|
|
11
|
+
import { memo, useState, Children, isValidElement } from 'react';
|
|
11
12
|
import Markdown from 'react-markdown';
|
|
12
13
|
import remarkGfm from 'remark-gfm';
|
|
13
14
|
import { jsx } from 'react/jsx-runtime';
|
|
@@ -21,6 +22,11 @@ function codeFromPre(children) {
|
|
|
21
22
|
const code = Children.toArray(raw).map((c) => typeof c === "string" || typeof c === "number" ? String(c) : "").join("").replace(/\n$/, "");
|
|
22
23
|
return { code, language };
|
|
23
24
|
}
|
|
25
|
+
function TableFrame(props) {
|
|
26
|
+
const [frame, setFrame] = useState(null);
|
|
27
|
+
useKeyboardScroll(frame, "Table", true, false, "x");
|
|
28
|
+
return /* @__PURE__ */ jsx("div", { ref: setFrame, className: cn("overflow-x-auto rounded-[var(--ds-radius-md)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]", FOCUS_INSET), children: /* @__PURE__ */ jsx("table", { className: "w-full border-collapse text-sm", ...props }) });
|
|
29
|
+
}
|
|
24
30
|
var components = {
|
|
25
31
|
p: ({ node: _n, ...props }) => /* @__PURE__ */ jsx("p", { ...props }),
|
|
26
32
|
a: ({ node: _n, href = "#", children, ...props }) => /* @__PURE__ */ jsx(
|
|
@@ -67,7 +73,7 @@ var components = {
|
|
|
67
73
|
hr: () => /* @__PURE__ */ jsx(Divider, {}),
|
|
68
74
|
strong: ({ node: _n, ...props }) => /* @__PURE__ */ jsx("strong", { className: "font-semibold", ...props }),
|
|
69
75
|
// Wide content scrolls inside its own container; the page never scrolls sideways.
|
|
70
|
-
table: ({ node: _n, ...props }) => /* @__PURE__ */ jsx(
|
|
76
|
+
table: ({ node: _n, ...props }) => /* @__PURE__ */ jsx(TableFrame, { ...props }),
|
|
71
77
|
thead: ({ node: _n, ...props }) => /* @__PURE__ */ jsx("thead", { className: "bg-[var(--ds-bg-muted)]", ...props }),
|
|
72
78
|
th: ({ node: _n, ...props }) => /* @__PURE__ */ jsx("th", { className: "px-ds-3 py-ds-2 text-left text-xs font-semibold uppercase tracking-wide text-[var(--ds-text-secondary)]", ...props }),
|
|
73
79
|
td: ({ node: _n, ...props }) => /* @__PURE__ */ jsx("td", { className: "border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] px-ds-3 py-ds-2 align-top", ...props }),
|
package/dist/chat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/components/MarkdownContent.tsx"],"names":[],"mappings":"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","file":"chat.js","sourcesContent":["import { memo, Children, isValidElement, type ComponentProps, type ReactElement, type ReactNode } from \"react\";\nimport Markdown, { type Components } from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport { cn } from \"../lib/utils\";\nimport { CodeBlock } from \"./CodeBlock\";\nimport { Link } from \"./Link\";\nimport { Divider } from \"./Divider\";\n\nexport interface MarkdownContentProps {\n /** The markdown source — a model's reply, an API's description. Raw HTML in it is never rendered. */\n children: string;\n /** Show a caret at the end of the last block while the source is still arriving. Pass a message's status === \"streaming\" from ChatMessageList's renderContent. */\n streaming?: boolean;\n className?: string;\n}\n\nconst isExternal = (href: string) => /^(https?:)?\\/\\//i.test(href);\n\n/** Pull the code string and language out of the single <code> child react-markdown gives a <pre>. */\nfunction codeFromPre(children: ReactNode): { code: string; language?: string } {\n const only = Children.toArray(children).find(isValidElement) as ReactElement<{ className?: string; children?: ReactNode }> | undefined;\n const cls = only?.props.className ?? \"\";\n const language = /language-([\\w+-]+)/.exec(cls)?.[1];\n const raw = only ? only.props.children : children;\n const code = Children.toArray(raw)\n .map((c) => (typeof c === \"string\" || typeof c === \"number\" ? String(c) : \"\"))\n .join(\"\")\n .replace(/\\n$/, \"\");\n return { code, language };\n}\n\ntype P<T extends keyof React.JSX.IntrinsicElements> = ComponentProps<T> & { node?: unknown };\n\nconst components: Components = {\n p: ({ node: _n, ...props }: P<\"p\">) => <p {...props} />,\n a: ({ node: _n, href = \"#\", children, ...props }: P<\"a\">) => (\n <Link\n href={href}\n underline=\"always\"\n {...(isExternal(href) ? { target: \"_blank\", rel: \"noopener noreferrer\" } : {})}\n {...(props as Record<string, unknown>)}\n >\n {children}\n </Link>\n ),\n pre: ({ node: _n, children }: P<\"pre\">) => {\n const { code, language } = codeFromPre(children);\n return <CodeBlock code={code} language={language} />;\n },\n code: ({ node: _n, className, children, ...props }: P<\"code\">) => (\n <code\n className={cn(\n \"rounded-[var(--ds-radius-sm)] bg-[var(--ds-bg-muted)] px-ds-1 py-[1px] font-[family-name:var(--ds-font-mono)] text-[0.9em]\",\n className,\n )}\n {...props}\n >\n {children}\n </code>\n ),\n ul: ({ node: _n, ...props }: P<\"ul\">) => <ul className=\"list-disc space-y-ds-1 pl-ds-5\" {...props} />,\n ol: ({ node: _n, ...props }: P<\"ol\">) => <ol className=\"list-decimal space-y-ds-1 pl-ds-5\" {...props} />,\n li: ({ node: _n, ...props }: P<\"li\">) => <li {...props} />,\n h1: ({ node: _n, ...props }: P<\"h1\">) => <h3 className=\"text-base font-semibold text-[var(--ds-text-primary)]\" {...props} />,\n h2: ({ node: _n, ...props }: P<\"h2\">) => <h3 className=\"text-base font-semibold text-[var(--ds-text-primary)]\" {...props} />,\n h3: ({ node: _n, ...props }: P<\"h3\">) => <h4 className=\"text-sm font-semibold text-[var(--ds-text-primary)]\" {...props} />,\n h4: ({ node: _n, ...props }: P<\"h4\">) => <h4 className=\"text-sm font-semibold text-[var(--ds-text-primary)]\" {...props} />,\n h5: ({ node: _n, ...props }: P<\"h5\">) => <h5 className=\"text-sm font-medium text-[var(--ds-text-primary)]\" {...props} />,\n h6: ({ node: _n, ...props }: P<\"h6\">) => <h6 className=\"text-sm font-medium text-[var(--ds-text-secondary)]\" {...props} />,\n blockquote: ({ node: _n, ...props }: P<\"blockquote\">) => (\n <blockquote\n className=\"border-l-[length:calc(var(--ds-border-width)*2)] border-[var(--ds-border-default)] pl-ds-3 text-[var(--ds-text-secondary)]\"\n {...props}\n />\n ),\n hr: () => <Divider />,\n strong: ({ node: _n, ...props }: P<\"strong\">) => <strong className=\"font-semibold\" {...props} />,\n // Wide content scrolls inside its own container; the page never scrolls sideways.\n table: ({ node: _n, ...props }: P<\"table\">) => (\n <div className=\"overflow-x-auto rounded-[var(--ds-radius-md)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\">\n <table className=\"w-full border-collapse text-sm\" {...props} />\n </div>\n ),\n thead: ({ node: _n, ...props }: P<\"thead\">) => <thead className=\"bg-[var(--ds-bg-muted)]\" {...props} />,\n th: ({ node: _n, ...props }: P<\"th\">) => (\n <th className=\"px-ds-3 py-ds-2 text-left text-xs font-semibold uppercase tracking-wide text-[var(--ds-text-secondary)]\" {...props} />\n ),\n td: ({ node: _n, ...props }: P<\"td\">) => (\n <td className=\"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] px-ds-3 py-ds-2 align-top\" {...props} />\n ),\n img: ({ node: _n, alt = \"\", ...props }: P<\"img\">) => <img alt={alt} className=\"max-w-full rounded-[var(--ds-radius-md)]\" {...props} />,\n};\n\n/**\n * Renders markdown (GitHub flavour: tables, task lists, strikethrough) with\n * Gridsmith primitives: fenced code becomes CodeBlock, links become Link,\n * a rule becomes Divider, everything else is token-styled markup. Raw HTML is\n * not rendered — the source is untrusted by default. Memoised: an unchanged\n * message never re-parses; a streaming message re-parses only its own string.\n *\n * Lives on the `gridsmith-ui/chat` entry point (react-markdown and remark-gfm\n * are optional peers), so apps without a chat never load a markdown parser.\n */\n// The caret is a pseudo-element on the last block, so it sits at the end of the\n// last line of text instead of on a line of its own below a block element.\nconst STREAMING_CARET = cn(\n \"[&>:last-child]:after:content-['▍'] [&>:last-child]:after:ml-ds-0.5\",\n \"[&>:last-child]:after:text-[var(--ds-accent-ink)] [&>:last-child]:after:animate-pulse\",\n);\n\nconst Memoised = memo(function MarkdownContentInner({ children, streaming, className }: MarkdownContentProps) {\n return (\n <div\n className={cn(\"space-y-ds-4 text-sm leading-relaxed text-[var(--ds-text-primary)]\", streaming && STREAMING_CARET, className)}\n data-markdown=\"\"\n data-streaming={streaming || undefined}\n >\n <Markdown remarkPlugins={[remarkGfm]} components={components} skipHtml>\n {children}\n </Markdown>\n </div>\n );\n});\n\n// A plain function export so the registry extractor (which reads `export function`)\n// documents it; the memo above still skips re-parsing unchanged sources.\nexport function MarkdownContent(props: MarkdownContentProps) {\n return <Memoised {...props} />;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../showcase/src/components/MarkdownContent.tsx"],"names":[],"mappings":"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","file":"chat.js","sourcesContent":["import { memo, Children, isValidElement, useState, type ComponentProps, type ReactElement, type ReactNode } from \"react\";\nimport Markdown, { type Components } from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport { cn, FOCUS_INSET } from \"../lib/utils\";\nimport { useKeyboardScroll } from \"../lib/use-keyboard-scroll\";\nimport { CodeBlock } from \"./CodeBlock\";\nimport { Link } from \"./Link\";\nimport { Divider } from \"./Divider\";\n\nexport interface MarkdownContentProps {\n /** The markdown source — a model's reply, an API's description. Raw HTML in it is never rendered. */\n children: string;\n /** Show a caret at the end of the last block while the source is still arriving. Pass a message's status === \"streaming\" from ChatMessageList's renderContent. */\n streaming?: boolean;\n className?: string;\n}\n\nconst isExternal = (href: string) => /^(https?:)?\\/\\//i.test(href);\n\n/** Pull the code string and language out of the single <code> child react-markdown gives a <pre>. */\nfunction codeFromPre(children: ReactNode): { code: string; language?: string } {\n const only = Children.toArray(children).find(isValidElement) as ReactElement<{ className?: string; children?: ReactNode }> | undefined;\n const cls = only?.props.className ?? \"\";\n const language = /language-([\\w+-]+)/.exec(cls)?.[1];\n const raw = only ? only.props.children : children;\n const code = Children.toArray(raw)\n .map((c) => (typeof c === \"string\" || typeof c === \"number\" ? String(c) : \"\"))\n .join(\"\")\n .replace(/\\n$/, \"\");\n return { code, language };\n}\n\n/**\n * A table in its own frame, which scrolls sideways when the table is wider; with nothing in it to Tab to, the frame is\n * a Tab stop while it scrolls, so a keyboard can scroll it too (Sprint 25.30 item 2).\n */\nfunction TableFrame(props: ComponentProps<\"table\">) {\n const [frame, setFrame] = useState<HTMLDivElement | null>(null);\n useKeyboardScroll(frame, \"Table\", true, false, \"x\");\n return (\n <div ref={setFrame} className={cn(\"overflow-x-auto rounded-[var(--ds-radius-md)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\", FOCUS_INSET)}>\n <table className=\"w-full border-collapse text-sm\" {...props} />\n </div>\n );\n}\n\ntype P<T extends keyof React.JSX.IntrinsicElements> = ComponentProps<T> & { node?: unknown };\n\nconst components: Components = {\n p: ({ node: _n, ...props }: P<\"p\">) => <p {...props} />,\n a: ({ node: _n, href = \"#\", children, ...props }: P<\"a\">) => (\n <Link\n href={href}\n underline=\"always\"\n {...(isExternal(href) ? { target: \"_blank\", rel: \"noopener noreferrer\" } : {})}\n {...(props as Record<string, unknown>)}\n >\n {children}\n </Link>\n ),\n pre: ({ node: _n, children }: P<\"pre\">) => {\n const { code, language } = codeFromPre(children);\n return <CodeBlock code={code} language={language} />;\n },\n code: ({ node: _n, className, children, ...props }: P<\"code\">) => (\n <code\n className={cn(\n \"rounded-[var(--ds-radius-sm)] bg-[var(--ds-bg-muted)] px-ds-1 py-[1px] font-[family-name:var(--ds-font-mono)] text-[0.9em]\",\n className,\n )}\n {...props}\n >\n {children}\n </code>\n ),\n ul: ({ node: _n, ...props }: P<\"ul\">) => <ul className=\"list-disc space-y-ds-1 pl-ds-5\" {...props} />,\n ol: ({ node: _n, ...props }: P<\"ol\">) => <ol className=\"list-decimal space-y-ds-1 pl-ds-5\" {...props} />,\n li: ({ node: _n, ...props }: P<\"li\">) => <li {...props} />,\n h1: ({ node: _n, ...props }: P<\"h1\">) => <h3 className=\"text-base font-semibold text-[var(--ds-text-primary)]\" {...props} />,\n h2: ({ node: _n, ...props }: P<\"h2\">) => <h3 className=\"text-base font-semibold text-[var(--ds-text-primary)]\" {...props} />,\n h3: ({ node: _n, ...props }: P<\"h3\">) => <h4 className=\"text-sm font-semibold text-[var(--ds-text-primary)]\" {...props} />,\n h4: ({ node: _n, ...props }: P<\"h4\">) => <h4 className=\"text-sm font-semibold text-[var(--ds-text-primary)]\" {...props} />,\n h5: ({ node: _n, ...props }: P<\"h5\">) => <h5 className=\"text-sm font-medium text-[var(--ds-text-primary)]\" {...props} />,\n h6: ({ node: _n, ...props }: P<\"h6\">) => <h6 className=\"text-sm font-medium text-[var(--ds-text-secondary)]\" {...props} />,\n blockquote: ({ node: _n, ...props }: P<\"blockquote\">) => (\n <blockquote\n className=\"border-l-[length:calc(var(--ds-border-width)*2)] border-[var(--ds-border-default)] pl-ds-3 text-[var(--ds-text-secondary)]\"\n {...props}\n />\n ),\n hr: () => <Divider />,\n strong: ({ node: _n, ...props }: P<\"strong\">) => <strong className=\"font-semibold\" {...props} />,\n // Wide content scrolls inside its own container; the page never scrolls sideways.\n table: ({ node: _n, ...props }: P<\"table\">) => <TableFrame {...props} />,\n thead: ({ node: _n, ...props }: P<\"thead\">) => <thead className=\"bg-[var(--ds-bg-muted)]\" {...props} />,\n th: ({ node: _n, ...props }: P<\"th\">) => (\n <th className=\"px-ds-3 py-ds-2 text-left text-xs font-semibold uppercase tracking-wide text-[var(--ds-text-secondary)]\" {...props} />\n ),\n td: ({ node: _n, ...props }: P<\"td\">) => (\n <td className=\"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] px-ds-3 py-ds-2 align-top\" {...props} />\n ),\n img: ({ node: _n, alt = \"\", ...props }: P<\"img\">) => <img alt={alt} className=\"max-w-full rounded-[var(--ds-radius-md)]\" {...props} />,\n};\n\n/**\n * Renders markdown (GitHub flavour: tables, task lists, strikethrough) with\n * Gridsmith primitives: fenced code becomes CodeBlock, links become Link,\n * a rule becomes Divider, everything else is token-styled markup. Raw HTML is\n * not rendered — the source is untrusted by default. Memoised: an unchanged\n * message never re-parses; a streaming message re-parses only its own string.\n *\n * Lives on the `gridsmith-ui/chat` entry point (react-markdown and remark-gfm\n * are optional peers), so apps without a chat never load a markdown parser.\n */\n// The caret is a pseudo-element on the last block, so it sits at the end of the\n// last line of text instead of on a line of its own below a block element.\nconst STREAMING_CARET = cn(\n \"[&>:last-child]:after:content-['▍'] [&>:last-child]:after:ml-ds-0.5\",\n \"[&>:last-child]:after:text-[var(--ds-accent-ink)] [&>:last-child]:after:animate-pulse\",\n);\n\nconst Memoised = memo(function MarkdownContentInner({ children, streaming, className }: MarkdownContentProps) {\n return (\n <div\n className={cn(\"space-y-ds-4 text-sm leading-relaxed text-[var(--ds-text-primary)]\", streaming && STREAMING_CARET, className)}\n data-markdown=\"\"\n data-streaming={streaming || undefined}\n >\n <Markdown remarkPlugins={[remarkGfm]} components={components} skipHtml>\n {children}\n </Markdown>\n </div>\n );\n});\n\n// A plain function export so the registry extractor (which reads `export function`)\n// documents it; the memo above still skips re-parsing unchanged sources.\nexport function MarkdownContent(props: MarkdownContentProps) {\n return <Memoised {...props} />;\n}\n"]}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { useRef, useInsertionEffect, useEffect, useCallback, useState, useMemo, useLayoutEffect } from 'react';
|
|
2
|
+
import { useRef, useLayoutEffect, useInsertionEffect, useEffect, useCallback, useState, useMemo } from 'react';
|
|
4
3
|
import { flushSync } from 'react-dom';
|
|
5
4
|
|
|
5
|
+
// ../../showcase/src/lib/focus.ts
|
|
6
|
+
function useLatest(value) {
|
|
7
|
+
const ref = useRef(value);
|
|
8
|
+
useLayoutEffect(() => {
|
|
9
|
+
ref.current = value;
|
|
10
|
+
});
|
|
11
|
+
return ref;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// ../../showcase/src/lib/focus.ts
|
|
6
15
|
var FOCUSABLE = 'a[href], button:not(:disabled), input:not(:disabled), select:not(:disabled), textarea:not(:disabled), [tabindex]:not([tabindex="-1"]), [contenteditable]:not([contenteditable="false"])';
|
|
7
16
|
var FIELD = "input, select, textarea, [contenteditable='true']";
|
|
8
17
|
var CONTROL_ANCESTOR = 'a[href], button, summary, label, [role="button"], [role="link"], [role="option"], [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], [role="tab"], [role="treeitem"], [role="row"], [role="gridcell"], [role="checkbox"], [role="radio"], [role="switch"]';
|
|
@@ -55,10 +64,34 @@ function focusInitial(root, opts = {}) {
|
|
|
55
64
|
function useFocusBeforeOpen(open) {
|
|
56
65
|
const before = useRef(null);
|
|
57
66
|
useInsertionEffect(() => {
|
|
58
|
-
|
|
67
|
+
trackFocus();
|
|
68
|
+
if (!open) return;
|
|
69
|
+
const active = document.activeElement;
|
|
70
|
+
before.current = !active || active === document.body ? justLost() ?? active : active;
|
|
59
71
|
}, [open]);
|
|
60
72
|
return before;
|
|
61
73
|
}
|
|
74
|
+
var lastFocused = null;
|
|
75
|
+
var lastFocusedAt = 0;
|
|
76
|
+
var lastActedAt = 0;
|
|
77
|
+
var tracking = false;
|
|
78
|
+
function trackFocus() {
|
|
79
|
+
if (tracking || typeof document === "undefined") return;
|
|
80
|
+
tracking = true;
|
|
81
|
+
document.addEventListener("focusin", (e) => {
|
|
82
|
+
lastFocused = e.target instanceof Element ? e.target : null;
|
|
83
|
+
lastFocusedAt = performance.now();
|
|
84
|
+
}, true);
|
|
85
|
+
const acted = () => {
|
|
86
|
+
lastActedAt = performance.now();
|
|
87
|
+
};
|
|
88
|
+
for (const type of ["keydown", "pointerdown", "click"]) document.addEventListener(type, acted, true);
|
|
89
|
+
}
|
|
90
|
+
function justLost() {
|
|
91
|
+
const recent = lastActedAt >= lastFocusedAt && performance.now() - lastActedAt < 1e3;
|
|
92
|
+
return lastFocused && !lastFocused.isConnected && recent ? lastFocused : null;
|
|
93
|
+
}
|
|
94
|
+
trackFocus();
|
|
62
95
|
function pathAbove(to, from) {
|
|
63
96
|
const up = to.replace(/\/+$/, "");
|
|
64
97
|
return from.startsWith(`${up}/`) && from.replace(/\/+$/, "") !== up;
|
|
@@ -74,6 +107,64 @@ function deletedRow(before, now) {
|
|
|
74
107
|
for (let j = k; j < (refilled ? last : now.length); j++) if (now[j] !== before[j + 1]) return -1;
|
|
75
108
|
return k;
|
|
76
109
|
}
|
|
110
|
+
function focusForTheMoment(el) {
|
|
111
|
+
const own = el.getAttribute("tabindex");
|
|
112
|
+
if (own === null) el.setAttribute("tabindex", "-1");
|
|
113
|
+
el.focus();
|
|
114
|
+
if (document.activeElement !== el) {
|
|
115
|
+
if (own === null) el.removeAttribute("tabindex");
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
let ring = false;
|
|
119
|
+
try {
|
|
120
|
+
ring = el.matches(":focus-visible");
|
|
121
|
+
} catch {
|
|
122
|
+
}
|
|
123
|
+
const { outline, outlineOffset } = el.style;
|
|
124
|
+
if (ring) {
|
|
125
|
+
el.style.outline = "2px solid var(--ds-focus)";
|
|
126
|
+
el.style.outlineOffset = "2px";
|
|
127
|
+
}
|
|
128
|
+
el.addEventListener("blur", () => {
|
|
129
|
+
if (own === null) el.removeAttribute("tabindex");
|
|
130
|
+
if (ring) Object.assign(el.style, { outline, outlineOffset });
|
|
131
|
+
}, { once: true });
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
var HEADING = 'h1, h2, h3, h4, h5, h6, [role="heading"]';
|
|
135
|
+
var LAST_RESORT_MS = 200;
|
|
136
|
+
function placesOf(el) {
|
|
137
|
+
const places = [];
|
|
138
|
+
for (let c = el, box = el.parentElement; box && box !== document.body && box.parentElement && box.parentElement !== document.body; c = box, box = box.parentElement) {
|
|
139
|
+
places.push({ box, prev: c.previousElementSibling, next: c.nextElementSibling });
|
|
140
|
+
}
|
|
141
|
+
return places;
|
|
142
|
+
}
|
|
143
|
+
function landLastResort(places, closing) {
|
|
144
|
+
const counts = (el) => !closing?.contains(el);
|
|
145
|
+
const areas = [];
|
|
146
|
+
const at = places.findIndex((p) => p.box.isConnected);
|
|
147
|
+
if (at >= 0) {
|
|
148
|
+
const { box, prev, next } = places[at];
|
|
149
|
+
const kids = Array.from(box.children);
|
|
150
|
+
const from = prev?.parentElement === box ? kids.indexOf(prev) + 1 : 0;
|
|
151
|
+
const to = next?.parentElement === box ? kids.indexOf(next) : kids.length;
|
|
152
|
+
areas.push(kids.slice(from, Math.max(from, to)), ...places.slice(at).map((p) => [p.box]));
|
|
153
|
+
}
|
|
154
|
+
const main = document.querySelector('main, [role="main"]');
|
|
155
|
+
const mainCounts = !!main && counts(main) && isRendered(main);
|
|
156
|
+
if (mainCounts) areas.push([main]);
|
|
157
|
+
for (const area of areas) {
|
|
158
|
+
const stop = area.flatMap((a) => [...isTabStop(a) ? [a] : [], ...tabStops(a)]).find(counts);
|
|
159
|
+
if (stop) {
|
|
160
|
+
stop.focus();
|
|
161
|
+
if (document.activeElement === stop) return true;
|
|
162
|
+
}
|
|
163
|
+
const heading = area.flatMap((a) => [...a.matches(HEADING) ? [a] : [], ...a.querySelectorAll(HEADING)]).find((h) => h instanceof HTMLElement && isRendered(h) && counts(h));
|
|
164
|
+
if (heading && focusForTheMoment(heading)) return true;
|
|
165
|
+
}
|
|
166
|
+
return mainCounts && focusForTheMoment(main);
|
|
167
|
+
}
|
|
77
168
|
function rememberFocus(el, { ignoreRoute = false } = {}) {
|
|
78
169
|
const { href, pathname } = location;
|
|
79
170
|
const row = el.closest(ROW);
|
|
@@ -86,6 +177,7 @@ function rememberFocus(el, { ignoreRoute = false } = {}) {
|
|
|
86
177
|
const texts = rows.map((r) => r.textContent ?? "");
|
|
87
178
|
const keyOf = (r) => r?.getAttribute("data-row-key") ?? null;
|
|
88
179
|
const key = keyOf(row);
|
|
180
|
+
const places = placesOf(el);
|
|
89
181
|
const pageChanged = () => {
|
|
90
182
|
if (ignoreRoute) return false;
|
|
91
183
|
if (location.pathname !== pathname) return !pathAbove(location.pathname, pathname);
|
|
@@ -118,16 +210,27 @@ function rememberFocus(el, { ignoreRoute = false } = {}) {
|
|
|
118
210
|
return k >= 0 && k <= at ? list.children[Math.max(0, at - 1)] ?? void 0 : void 0;
|
|
119
211
|
};
|
|
120
212
|
const neighbour = () => inRow(byKey(keyOf(before)) ?? before) || inRow(byKey(keyOf(after)) ?? after) || !!list?.isConnected && land(tabStops(list)[0]);
|
|
213
|
+
const lastResort = () => {
|
|
214
|
+
setTimeout(() => {
|
|
215
|
+
if (typeof document === "undefined") return;
|
|
216
|
+
const active = document.activeElement;
|
|
217
|
+
if (active && active !== document.body && active.isConnected || pageChanged()) return;
|
|
218
|
+
landLastResort(places);
|
|
219
|
+
}, LAST_RESORT_MS);
|
|
220
|
+
return false;
|
|
221
|
+
};
|
|
121
222
|
let unwatch = null;
|
|
122
223
|
const watch = () => {
|
|
123
224
|
unwatch?.();
|
|
124
225
|
if (!list || typeof MutationObserver === "undefined") return;
|
|
125
|
-
const observer = new MutationObserver(() => {
|
|
226
|
+
const observer = new MutationObserver((changes) => {
|
|
126
227
|
if (el.isConnected) return;
|
|
127
228
|
const active = document.activeElement;
|
|
128
229
|
const dropped = !active || active === document.body || !active.isConnected;
|
|
129
230
|
stop();
|
|
130
|
-
if (dropped
|
|
231
|
+
if (!dropped || pageChanged()) return;
|
|
232
|
+
const fromList = changes.some((c) => c.target === list || c.target === list.parentNode);
|
|
233
|
+
if (!(fromList && neighbour())) lastResort();
|
|
131
234
|
});
|
|
132
235
|
const onFocusIn = (e) => {
|
|
133
236
|
if (e.target !== el) stop();
|
|
@@ -136,11 +239,12 @@ function rememberFocus(el, { ignoreRoute = false } = {}) {
|
|
|
136
239
|
function stop() {
|
|
137
240
|
observer.disconnect();
|
|
138
241
|
clearTimeout(timer);
|
|
139
|
-
document.removeEventListener("focusin", onFocusIn, true);
|
|
242
|
+
if (typeof document !== "undefined") document.removeEventListener("focusin", onFocusIn, true);
|
|
140
243
|
unwatch = null;
|
|
141
244
|
}
|
|
142
245
|
observer.observe(list, { childList: true });
|
|
143
246
|
if (list.parentNode) observer.observe(list.parentNode, { childList: true });
|
|
247
|
+
for (const { box } of places) observer.observe(box, { childList: true });
|
|
144
248
|
document.addEventListener("focusin", onFocusIn, true);
|
|
145
249
|
unwatch = stop;
|
|
146
250
|
};
|
|
@@ -154,7 +258,90 @@ function rememberFocus(el, { ignoreRoute = false } = {}) {
|
|
|
154
258
|
return true;
|
|
155
259
|
}
|
|
156
260
|
if (row && !row.isConnected && neighbour()) return true;
|
|
157
|
-
return land(fallback);
|
|
261
|
+
return land(fallback) || lastResort();
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function useFocusKeptInList(listRef) {
|
|
266
|
+
useEffect(() => {
|
|
267
|
+
if (typeof MutationObserver === "undefined") return;
|
|
268
|
+
let held = null;
|
|
269
|
+
let observer = null;
|
|
270
|
+
const forget = () => {
|
|
271
|
+
held = null;
|
|
272
|
+
observer?.disconnect();
|
|
273
|
+
observer = null;
|
|
274
|
+
};
|
|
275
|
+
const onFocusIn = (e) => {
|
|
276
|
+
const list = listRef.current;
|
|
277
|
+
const t = e.target;
|
|
278
|
+
if (!list || !(t instanceof HTMLElement) || !list.contains(t)) {
|
|
279
|
+
if (held) forget();
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
held = rememberFocus(t);
|
|
283
|
+
if (observer) return;
|
|
284
|
+
observer = new MutationObserver(() => {
|
|
285
|
+
const h = held;
|
|
286
|
+
if (!h || h.el.isConnected) return;
|
|
287
|
+
const active = document.activeElement;
|
|
288
|
+
forget();
|
|
289
|
+
if (!active || active === document.body || !active.isConnected) h.restore();
|
|
290
|
+
});
|
|
291
|
+
observer.observe(list, { childList: true, subtree: true });
|
|
292
|
+
};
|
|
293
|
+
const onFocusOut = (e) => {
|
|
294
|
+
if (!held || e.target !== held.el) return;
|
|
295
|
+
queueMicrotask(() => {
|
|
296
|
+
if (held?.el.isConnected && !listRef.current?.contains(document.activeElement)) forget();
|
|
297
|
+
});
|
|
298
|
+
};
|
|
299
|
+
document.addEventListener("focusin", onFocusIn, true);
|
|
300
|
+
document.addEventListener("focusout", onFocusOut, true);
|
|
301
|
+
return () => {
|
|
302
|
+
document.removeEventListener("focusin", onFocusIn, true);
|
|
303
|
+
document.removeEventListener("focusout", onFocusOut, true);
|
|
304
|
+
const h = held;
|
|
305
|
+
forget();
|
|
306
|
+
const active = document.activeElement;
|
|
307
|
+
if (h && !h.el.isConnected && (!active || active === document.body || !active.isConnected)) h.restore();
|
|
308
|
+
};
|
|
309
|
+
}, [listRef]);
|
|
310
|
+
}
|
|
311
|
+
var openers = /* @__PURE__ */ new WeakMap();
|
|
312
|
+
function rememberOpener(active, root) {
|
|
313
|
+
let own = active instanceof HTMLElement && active !== document.body && active.isConnected ? rememberFocus(active) : null;
|
|
314
|
+
const controller = !own && root?.id ? document.querySelector(`[aria-controls~="${CSS.escape(root.id)}"]`) : null;
|
|
315
|
+
if (controller) own = rememberFocus(controller);
|
|
316
|
+
let around = null;
|
|
317
|
+
for (let n = active; n && !around; n = n.parentElement) {
|
|
318
|
+
const opener = openers.get(n);
|
|
319
|
+
if (opener) around = { root: n, opener };
|
|
320
|
+
}
|
|
321
|
+
const back = own ?? around?.opener;
|
|
322
|
+
if (!back) {
|
|
323
|
+
if (!root) return null;
|
|
324
|
+
const places = placesOf(root);
|
|
325
|
+
const { pathname } = location;
|
|
326
|
+
return {
|
|
327
|
+
el: null,
|
|
328
|
+
restore() {
|
|
329
|
+
setTimeout(() => {
|
|
330
|
+
if (typeof document === "undefined") return;
|
|
331
|
+
const now = document.activeElement;
|
|
332
|
+
if (now && now !== document.body && now.isConnected && !root.contains(now) || location.pathname !== pathname && !pathAbove(location.pathname, pathname)) return;
|
|
333
|
+
landLastResort(places, root);
|
|
334
|
+
}, LAST_RESORT_MS);
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
if (root) openers.set(root, back);
|
|
340
|
+
return {
|
|
341
|
+
el: own?.el ?? null,
|
|
342
|
+
restore(fallback) {
|
|
343
|
+
if (own?.restore(fallback)) return true;
|
|
344
|
+
return !!around && !around.root.isConnected && around.opener.restore();
|
|
158
345
|
}
|
|
159
346
|
};
|
|
160
347
|
}
|
|
@@ -163,8 +350,7 @@ function useReturnFocus(open, root) {
|
|
|
163
350
|
const before = useFocusBeforeOpen(open);
|
|
164
351
|
useEffect(() => {
|
|
165
352
|
if (open) {
|
|
166
|
-
|
|
167
|
-
remembered.current = active2 instanceof HTMLElement && active2 !== document.body && active2.isConnected ? rememberFocus(active2) : null;
|
|
353
|
+
remembered.current = rememberOpener(before.current, root?.current);
|
|
168
354
|
return;
|
|
169
355
|
}
|
|
170
356
|
const r = remembered.current;
|
|
@@ -191,10 +377,14 @@ function rovingTabStop(items, isChecked, isDisabled = () => false) {
|
|
|
191
377
|
function focusAfterRemoval(items, index, fallback) {
|
|
192
378
|
(items[index - 1] ?? items[index] ?? fallback)?.focus();
|
|
193
379
|
}
|
|
194
|
-
function
|
|
380
|
+
function mayStop(root) {
|
|
381
|
+
const disabled = (el) => (el instanceof HTMLButtonElement || el instanceof HTMLInputElement || el instanceof HTMLSelectElement || el instanceof HTMLTextAreaElement) && el.disabled;
|
|
382
|
+
return Array.from(root.querySelectorAll(`${FOCUSABLE}, button:disabled, input:disabled, select:disabled, textarea:disabled`)).filter((el) => disabled(el) ? !(el instanceof HTMLInputElement && el.type === "hidden") : isTabStop(el)).sort((a, b) => a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1);
|
|
383
|
+
}
|
|
384
|
+
function focusAfterSelfRemoval(control, { item, group, to } = {}) {
|
|
195
385
|
const goes = item ?? control;
|
|
196
386
|
const within = group === void 0 ? goes.parentElement : group;
|
|
197
|
-
const stops = within ?
|
|
387
|
+
const stops = within ? mayStop(within).filter((el) => !goes.contains(el)) : [];
|
|
198
388
|
const before = stops.filter((el) => goes.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_PRECEDING).reverse();
|
|
199
389
|
const after = stops.filter((el) => goes.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING);
|
|
200
390
|
const stopsOf = (el) => [...isTabStop(el) ? [el] : [], ...tabStops(el)];
|
|
@@ -224,7 +414,8 @@ function focusAfterSelfRemoval(control, { item, group } = {}) {
|
|
|
224
414
|
within.focus();
|
|
225
415
|
return document.activeElement === within;
|
|
226
416
|
};
|
|
227
|
-
const
|
|
417
|
+
const landTo = (el) => land(el) || !!el && el.isConnected && !isTabStop(el) && isRendered(el) && focusForTheMoment(el);
|
|
418
|
+
const place = () => landTo(typeof to === "function" ? to() : to) || land(sameBefore) || before.some(land) || land(sameAfter) || after.some(land) || landOnGroup();
|
|
228
419
|
if (typeof MutationObserver === "undefined") return () => {
|
|
229
420
|
};
|
|
230
421
|
const observer = new MutationObserver(() => {
|
|
@@ -239,7 +430,7 @@ function focusAfterSelfRemoval(control, { item, group } = {}) {
|
|
|
239
430
|
function stop() {
|
|
240
431
|
observer.disconnect();
|
|
241
432
|
clearTimeout(timer);
|
|
242
|
-
document.removeEventListener("focusin", onFocusIn, true);
|
|
433
|
+
if (typeof document !== "undefined") document.removeEventListener("focusin", onFocusIn, true);
|
|
243
434
|
}
|
|
244
435
|
observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["disabled"] });
|
|
245
436
|
document.addEventListener("focusin", onFocusIn, true);
|
|
@@ -338,6 +529,7 @@ function usePopupFocus(open, { trigger, panel, close, tabExits, onTabOut, marked
|
|
|
338
529
|
const inPanel = active instanceof Node && !!panel.current?.contains(active);
|
|
339
530
|
const opener = active instanceof HTMLElement && active !== document.body && !inPanel ? active : trigger.current;
|
|
340
531
|
remembered.current = opener ? rememberFocus(opener) : null;
|
|
532
|
+
if (panel.current && remembered.current) openers.set(panel.current, remembered.current);
|
|
341
533
|
lastPress.current = null;
|
|
342
534
|
}, [open, trigger, panel, before]);
|
|
343
535
|
useEffect(() => {
|
|
@@ -517,12 +709,13 @@ function useGridKeyboard({ container, active, setActive, keyOf, move, onActivate
|
|
|
517
709
|
return { onKeyDown, tabIndexOf, focusActive, focus };
|
|
518
710
|
}
|
|
519
711
|
var ALWAYS_TOP = () => true;
|
|
520
|
-
function useFocusTrap(root, active, isTop = ALWAYS_TOP) {
|
|
712
|
+
function useFocusTrap(root, active, isTop = ALWAYS_TOP, also) {
|
|
521
713
|
useEffect(() => {
|
|
522
714
|
if (!active) return;
|
|
523
715
|
const onKeyDown = (e) => {
|
|
524
716
|
if (e.key !== "Tab" || e.defaultPrevented || !root.current || !isTop()) return;
|
|
525
|
-
const
|
|
717
|
+
const scope = [root.current, also?.current].filter((el) => !!el);
|
|
718
|
+
const focusable = scope.flatMap((el) => tabStops(el)).sort((a, b) => a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1);
|
|
526
719
|
if (focusable.length === 0) {
|
|
527
720
|
e.preventDefault();
|
|
528
721
|
return;
|
|
@@ -530,7 +723,7 @@ function useFocusTrap(root, active, isTop = ALWAYS_TOP) {
|
|
|
530
723
|
const first = focusable[0];
|
|
531
724
|
const last = focusable[focusable.length - 1];
|
|
532
725
|
const current = document.activeElement;
|
|
533
|
-
const inside = current instanceof Node &&
|
|
726
|
+
const inside = current instanceof Node && scope.some((el) => el.contains(current));
|
|
534
727
|
if (e.shiftKey) {
|
|
535
728
|
if (!inside || current === first) {
|
|
536
729
|
e.preventDefault();
|
|
@@ -543,7 +736,24 @@ function useFocusTrap(root, active, isTop = ALWAYS_TOP) {
|
|
|
543
736
|
};
|
|
544
737
|
document.addEventListener("keydown", onKeyDown);
|
|
545
738
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
546
|
-
}, [root, active, isTop]);
|
|
739
|
+
}, [root, active, isTop, also]);
|
|
740
|
+
}
|
|
741
|
+
function inertOutside(keep, within) {
|
|
742
|
+
const made = [];
|
|
743
|
+
const visit = (el) => {
|
|
744
|
+
for (const child of Array.from(el.children)) {
|
|
745
|
+
if (keep.includes(child)) continue;
|
|
746
|
+
if (keep.some((k) => child.contains(k))) visit(child);
|
|
747
|
+
else if (!child.hasAttribute("inert")) {
|
|
748
|
+
child.setAttribute("inert", "");
|
|
749
|
+
made.push(child);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
visit(within);
|
|
754
|
+
return () => {
|
|
755
|
+
for (const el of made) el.removeAttribute("inert");
|
|
756
|
+
};
|
|
547
757
|
}
|
|
548
758
|
function useNonModalDialog(root, active, onClose, isTop = ALWAYS_TOP) {
|
|
549
759
|
const onCloseRef = useLatest(onClose);
|
|
@@ -566,7 +776,80 @@ function useNonModalDialog(root, active, onClose, isTop = ALWAYS_TOP) {
|
|
|
566
776
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
567
777
|
}, [active, root, isTop, onCloseRef]);
|
|
568
778
|
}
|
|
779
|
+
var VIEWPORT_PADDING = 8;
|
|
780
|
+
function usePosition(triggerRef, floatingRef, open, options = {}) {
|
|
781
|
+
const { side = "bottom", align = "center", offset = 8, flip = true } = options;
|
|
782
|
+
const [pos, setPos] = useState({ top: 0, left: 0, placement: side });
|
|
783
|
+
const rafId = useRef(0);
|
|
784
|
+
const compute = useCallback(() => {
|
|
785
|
+
const trigger = triggerRef.current;
|
|
786
|
+
const floating = floatingRef.current;
|
|
787
|
+
if (!trigger || !floating) return;
|
|
788
|
+
const tRect = trigger.getBoundingClientRect();
|
|
789
|
+
const fRect = floating.getBoundingClientRect();
|
|
790
|
+
const vw = window.innerWidth;
|
|
791
|
+
const vh = window.innerHeight;
|
|
792
|
+
let placement = side;
|
|
793
|
+
if (flip) {
|
|
794
|
+
if (placement === "bottom" && tRect.bottom + offset + fRect.height > vh - VIEWPORT_PADDING && tRect.top - offset - fRect.height > VIEWPORT_PADDING) {
|
|
795
|
+
placement = "top";
|
|
796
|
+
} else if (placement === "top" && tRect.top - offset - fRect.height < VIEWPORT_PADDING && tRect.bottom + offset + fRect.height < vh - VIEWPORT_PADDING) {
|
|
797
|
+
placement = "bottom";
|
|
798
|
+
} else if (placement === "right" && tRect.right + offset + fRect.width > vw - VIEWPORT_PADDING && tRect.left - offset - fRect.width > VIEWPORT_PADDING) {
|
|
799
|
+
placement = "left";
|
|
800
|
+
} else if (placement === "left" && tRect.left - offset - fRect.width < VIEWPORT_PADDING && tRect.right + offset + fRect.width < vw - VIEWPORT_PADDING) {
|
|
801
|
+
placement = "right";
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
let top;
|
|
805
|
+
let left;
|
|
806
|
+
if (placement === "bottom" || placement === "top") {
|
|
807
|
+
top = placement === "bottom" ? tRect.bottom + offset : tRect.top - fRect.height - offset;
|
|
808
|
+
switch (align) {
|
|
809
|
+
case "start":
|
|
810
|
+
left = tRect.left;
|
|
811
|
+
break;
|
|
812
|
+
case "end":
|
|
813
|
+
left = tRect.right - fRect.width;
|
|
814
|
+
break;
|
|
815
|
+
default:
|
|
816
|
+
left = tRect.left + (tRect.width - fRect.width) / 2;
|
|
817
|
+
}
|
|
818
|
+
} else {
|
|
819
|
+
left = placement === "right" ? tRect.right + offset : tRect.left - fRect.width - offset;
|
|
820
|
+
switch (align) {
|
|
821
|
+
case "start":
|
|
822
|
+
top = tRect.top;
|
|
823
|
+
break;
|
|
824
|
+
case "end":
|
|
825
|
+
top = tRect.bottom - fRect.height;
|
|
826
|
+
break;
|
|
827
|
+
default:
|
|
828
|
+
top = tRect.top + (tRect.height - fRect.height) / 2;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
left = Math.max(VIEWPORT_PADDING, Math.min(left, vw - fRect.width - VIEWPORT_PADDING));
|
|
832
|
+
top = Math.max(VIEWPORT_PADDING, Math.min(top, vh - fRect.height - VIEWPORT_PADDING));
|
|
833
|
+
setPos((cur) => cur.top === top && cur.left === left && cur.placement === placement ? cur : { top, left, placement });
|
|
834
|
+
}, [triggerRef, floatingRef, side, align, offset, flip]);
|
|
835
|
+
useLayoutEffect(() => {
|
|
836
|
+
if (!open) return;
|
|
837
|
+
compute();
|
|
838
|
+
const onUpdate = () => {
|
|
839
|
+
cancelAnimationFrame(rafId.current);
|
|
840
|
+
rafId.current = requestAnimationFrame(compute);
|
|
841
|
+
};
|
|
842
|
+
window.addEventListener("scroll", onUpdate, true);
|
|
843
|
+
window.addEventListener("resize", onUpdate);
|
|
844
|
+
return () => {
|
|
845
|
+
cancelAnimationFrame(rafId.current);
|
|
846
|
+
window.removeEventListener("scroll", onUpdate, true);
|
|
847
|
+
window.removeEventListener("resize", onUpdate);
|
|
848
|
+
};
|
|
849
|
+
}, [open, compute]);
|
|
850
|
+
return pos;
|
|
851
|
+
}
|
|
569
852
|
|
|
570
|
-
export { CONTROL_ANCESTOR, FIELD, FOCUSABLE, OVERLAY_CLOSE_ATTR, ZOOM_KEYS, focusAfterRemoval, focusAfterSelfRemoval, focusInitial, isTabStop, rememberFocus, rovingTabStop, tabStops, useCloseOnFocusOut, useFocusBeforeOpen, useFocusLeave, useFocusTrap, useGridKeyboard, useNonModalDialog, useOverlayLayer, usePopupFocus, usePressMarks, useReturnFocus };
|
|
571
|
-
//# sourceMappingURL=chunk-
|
|
572
|
-
//# sourceMappingURL=chunk-
|
|
853
|
+
export { CONTROL_ANCESTOR, FIELD, FOCUSABLE, OVERLAY_CLOSE_ATTR, ZOOM_KEYS, focusAfterRemoval, focusAfterSelfRemoval, focusInitial, inertOutside, isTabStop, rememberFocus, rememberOpener, rovingTabStop, tabStops, useCloseOnFocusOut, useFocusBeforeOpen, useFocusKeptInList, useFocusLeave, useFocusTrap, useGridKeyboard, useLatest, useNonModalDialog, useOverlayLayer, usePopupFocus, usePosition, usePressMarks, useReturnFocus };
|
|
854
|
+
//# sourceMappingURL=chunk-4HJDOZ2M.js.map
|
|
855
|
+
//# sourceMappingURL=chunk-4HJDOZ2M.js.map
|