@adea-ai/ui 0.105.0 → 0.106.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 +44 -8
- package/dist/components/composites/action-button/action-button.d.ts.map +1 -1
- package/dist/components/composites/action-button/action-button.js +6 -8
- package/dist/components/composites/action-button/action-button.js.map +1 -1
- package/dist/components/composites/appearance-editor/accent-swatch-groups.d.ts +16 -0
- package/dist/components/composites/appearance-editor/accent-swatch-groups.d.ts.map +1 -0
- package/dist/components/composites/appearance-editor/accent-swatch-groups.js +151 -0
- package/dist/components/composites/appearance-editor/accent-swatch-groups.js.map +1 -0
- package/dist/components/composites/appearance-editor/appearance-choices.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-choices.js +24 -84
- package/dist/components/composites/appearance-editor/appearance-choices.js.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-editor.d.ts +2 -2
- package/dist/components/composites/appearance-editor/appearance-editor.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-editor.js +25 -7
- package/dist/components/composites/appearance-editor/appearance-editor.js.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-types.d.ts +9 -0
- package/dist/components/composites/appearance-editor/appearance-types.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/font-settings-group.d.ts +10 -0
- package/dist/components/composites/appearance-editor/font-settings-group.d.ts.map +1 -0
- package/dist/components/composites/appearance-editor/font-settings-group.js +310 -0
- package/dist/components/composites/appearance-editor/font-settings-group.js.map +1 -0
- package/dist/components/composites/appearance-editor/index.d.ts +2 -0
- package/dist/components/composites/appearance-editor/index.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/index.js +3 -1
- package/dist/components/composites/update-dialog/update-dialog.js +2 -2
- package/dist/components/composites/update-dialog/update-dialog.js.map +1 -1
- package/dist/components/conversation/message-row.d.ts.map +1 -1
- package/dist/components/conversation/message-row.js +3 -3
- package/dist/components/conversation/message-row.js.map +1 -1
- package/dist/components/conversation/paste-token-editor.js +1 -1
- package/dist/components/conversation/paste-token-editor.js.map +1 -1
- package/dist/components/layout/side-rail/side-rail.js +2 -2
- package/dist/components/layout/side-rail/side-rail.js.map +1 -1
- package/dist/components/layout/top-bar/top-bar.js +1 -1
- package/dist/components/layout/top-bar/top-bar.js.map +1 -1
- package/dist/components/theme/appearance-panel.d.ts +1 -1
- package/dist/components/theme/appearance-panel.d.ts.map +1 -1
- package/dist/components/theme/appearance-panel.js +45 -105
- package/dist/components/theme/appearance-panel.js.map +1 -1
- package/dist/components/theme/theme-provider.d.ts +5 -2
- package/dist/components/theme/theme-provider.d.ts.map +1 -1
- package/dist/components/theme/theme-provider.js +38 -19
- package/dist/components/theme/theme-provider.js.map +1 -1
- package/dist/components/ui/code-block/code-block.d.ts +3 -3
- package/dist/components/ui/code-block/code-block.js +6 -6
- package/dist/components/ui/code-block/code-block.js.map +1 -1
- package/dist/components/ui/command/command.js +1 -1
- package/dist/components/ui/command/command.js.map +1 -1
- package/dist/components/ui/context-menu/context-menu.js +1 -1
- package/dist/components/ui/context-menu/context-menu.js.map +1 -1
- package/dist/components/ui/diff-block/diff-block.js +5 -5
- package/dist/components/ui/diff-block/diff-block.js.map +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu.js +101 -8
- package/dist/components/ui/dropdown-menu/dropdown-menu.js.map +1 -1
- package/dist/components/ui/kbd/kbd.js +1 -1
- package/dist/components/ui/kbd/kbd.js.map +1 -1
- package/dist/components/ui/menubar/menubar.js +1 -1
- package/dist/components/ui/menubar/menubar.js.map +1 -1
- package/dist/components/ui/typography/typography.d.ts +3 -5
- package/dist/components/ui/typography/typography.d.ts.map +1 -1
- package/dist/components/ui/typography/typography.js +6 -8
- package/dist/components/ui/typography/typography.js.map +1 -1
- package/dist/index.js +6 -3
- package/dist/lib/appearance-font-settings.d.ts +53 -0
- package/dist/lib/appearance-font-settings.d.ts.map +1 -0
- package/dist/lib/appearance-font-settings.js +160 -0
- package/dist/lib/appearance-font-settings.js.map +1 -0
- package/dist/lib/font-catalog.d.ts +72 -0
- package/dist/lib/font-catalog.d.ts.map +1 -0
- package/dist/lib/font-catalog.js +71 -0
- package/dist/lib/font-catalog.js.map +1 -0
- package/dist/lib/safe-script.d.ts +3 -0
- package/dist/lib/safe-script.d.ts.map +1 -0
- package/dist/lib/safe-script.js +9 -0
- package/dist/lib/safe-script.js.map +1 -0
- package/dist/lib/tokens.d.ts +2 -19
- package/dist/lib/tokens.d.ts.map +1 -1
- package/dist/lib/tokens.js +63 -39
- package/dist/lib/tokens.js.map +1 -1
- package/dist/r/appearance-editor.json +11 -0
- package/dist/r/lib.json +15 -0
- package/dist/r/registry.json +33 -0
- package/dist/r/src/components/composites/action-button/action-button.tsx +2 -1
- package/dist/r/src/components/composites/appearance-editor/accent-swatch-groups.tsx +147 -0
- package/dist/r/src/components/composites/appearance-editor/appearance-choices.tsx +17 -74
- package/dist/r/src/components/composites/appearance-editor/appearance-editor.tsx +19 -6
- package/dist/r/src/components/composites/appearance-editor/appearance-types.ts +9 -0
- package/dist/r/src/components/composites/appearance-editor/font-settings-group.tsx +350 -0
- package/dist/r/src/components/composites/appearance-editor/index.ts +19 -0
- package/dist/r/src/components/composites/update-dialog/update-dialog.tsx +2 -2
- package/dist/r/src/components/conversation/message-row.tsx +7 -3
- package/dist/r/src/components/conversation/paste-token-editor.tsx +1 -1
- package/dist/r/src/components/layout/side-rail/side-rail.tsx +3 -3
- package/dist/r/src/components/layout/top-bar/top-bar.tsx +1 -1
- package/dist/r/src/components/theme/appearance-panel.tsx +34 -83
- package/dist/r/src/components/theme/theme-provider.tsx +50 -20
- package/dist/r/src/components/ui/code-block/code-block.tsx +6 -6
- package/dist/r/src/components/ui/command/command.tsx +1 -1
- package/dist/r/src/components/ui/context-menu/context-menu.tsx +1 -1
- package/dist/r/src/components/ui/diff-block/diff-block.tsx +7 -7
- package/dist/r/src/components/ui/dropdown-menu/dropdown-menu.tsx +145 -7
- package/dist/r/src/components/ui/kbd/kbd.tsx +1 -1
- package/dist/r/src/components/ui/menubar/menubar.tsx +1 -1
- package/dist/r/src/components/ui/typography/typography.tsx +6 -8
- package/dist/r/src/lib/appearance-font-settings.ts +233 -0
- package/dist/r/src/lib/font-catalog.ts +80 -0
- package/dist/r/src/lib/safe-script.ts +7 -0
- package/dist/r/src/lib/tokens.ts +64 -59
- package/dist/r/src/styles/appearance-font-settings.css +110 -0
- package/dist/r/src/styles/fonts.css +4 -5
- package/dist/r/src/styles/globals.css +4 -1
- package/dist/r/src/styles/theme.css +14 -0
- package/dist/r/theme.json +5 -0
- package/dist/r/theming.json +2 -0
- package/package.json +2 -1
- package/registry.json +33 -0
- package/src/components/composites/action-button/action-button.tsx +2 -1
- package/src/components/composites/appearance-editor/accent-swatch-groups.tsx +147 -0
- package/src/components/composites/appearance-editor/appearance-choices.tsx +17 -74
- package/src/components/composites/appearance-editor/appearance-editor.tsx +19 -6
- package/src/components/composites/appearance-editor/appearance-types.ts +9 -0
- package/src/components/composites/appearance-editor/font-settings-group.tsx +350 -0
- package/src/components/composites/appearance-editor/index.ts +19 -0
- package/src/components/composites/update-dialog/update-dialog.tsx +2 -2
- package/src/components/conversation/message-row.tsx +7 -3
- package/src/components/conversation/paste-token-editor.tsx +1 -1
- package/src/components/layout/side-rail/side-rail.tsx +3 -3
- package/src/components/layout/top-bar/top-bar.tsx +1 -1
- package/src/components/theme/appearance-panel.tsx +34 -83
- package/src/components/theme/theme-provider.tsx +50 -20
- package/src/components/ui/code-block/code-block.tsx +6 -6
- package/src/components/ui/command/command.tsx +1 -1
- package/src/components/ui/context-menu/context-menu.tsx +1 -1
- package/src/components/ui/diff-block/diff-block.tsx +7 -7
- package/src/components/ui/dropdown-menu/dropdown-menu.tsx +145 -7
- package/src/components/ui/kbd/kbd.tsx +1 -1
- package/src/components/ui/menubar/menubar.tsx +1 -1
- package/src/components/ui/typography/typography.tsx +6 -8
- package/src/lib/appearance-font-settings.ts +233 -0
- package/src/lib/font-catalog.ts +80 -0
- package/src/lib/safe-script.ts +7 -0
- package/src/lib/tokens.ts +64 -59
- package/src/styles/appearance-font-settings.css +110 -0
- package/src/styles/fonts.css +4 -5
- package/src/styles/globals.css +4 -1
- package/src/styles/theme.css +14 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-block.js","names":["createMemo","createSignal","For","Show","splitProps","ComponentProps","JSX","Check","Copy","Button","cn","CodeBlockProps","Omit","code","language","highlight","Element","complete","title","actions","copyLabel","copiedLabel","lineHeight","showLineNumbers","tallThreshold","TALL_CODE_BLOCK_PX","copyText","text","Promise","navigator","clipboard","writeText","CodeBlock","props","local","rest","copied","setCopied","failed","setFailed","tall","setTall","label","regionLabel","lines","replace","split","copy","ok","setTimeout","Actions","_el$","_tmpl$","_$insert","_$createComponent","variant","size","aria-label","_$memo","undefined","onClick","children","when","fallback","_el$2","_tmpl$4","_el$3","firstChild","_el$4","_el$5","nextSibling","_$use","element","ref","observer","ResizeObserver","offsetHeight","observe","_$spread","_$mergeProps","class","_el$8","_tmpl$5","_el$9","each","line","index","_el$0","_tmpl$6","_el$1","_el$10","_$effect","_$p","_$setStyleProperty","_el$11","_tmpl$7","_tmpl$2","_el$7","_tmpl$3","_$setAttribute","InlineCode","_el$12","_tmpl$8","_$createComponent","_$memo","_$mergeProps","_$setStyleProperty","_$setAttribute"],"sources":["../../../../src/components/ui/code-block/code-block.tsx"],"sourcesContent":["import {\n createMemo,\n createSignal,\n For,\n Show,\n splitProps,\n type ComponentProps,\n type JSX,\n} from 'solid-js'\nimport { Check, Copy } from 'lucide-solid'\nimport { Button } from '../button'\nimport { cn } from '#lib/utils'\n\n/**\n * CodeBlock.\n *\n * A fenced block, rendered as a surface. The library ships no highlighter —\n * syntax colouring is a large dependency with its own theme format, and a\n * component that bundled one would force every consumer to pay for it. This\n * renders the block, its chrome, and its behaviour; a caller that wants\n * highlighting passes the result through `highlight`, which is the seam a\n * Shiki/Pierre/Prism integration plugs into.\n *\n * Four details are the reason this exists rather than a styled `<pre>`:\n *\n * **Copy confirms only on success.** `navigator.clipboard.writeText` rejects\n * outside a secure context, in a sandboxed frame, and when the document is not\n * focused. Flipping to a tick unconditionally confirms a copy that did not\n * happen, and the reader pastes something stale and does not know why. The\n * rejection is caught and the button reports the failure instead.\n *\n * **A tall block repeats its action row at the bottom.** Copying from a block\n * that is taller than the viewport otherwise costs a scroll back to the top and\n * another scroll down to where you were. The threshold is a fixed 480px rather\n * than viewport-relative so the behaviour does not change when the window is\n * resized.\n *\n * **The scroller is focusable and named.** A horizontally scrollable region has\n * to be reachable by keyboard — this is axe's `scrollable-region-focusable`, and\n * a region that scrolls but cannot be focused is a WCAG 2.1.1 failure. It is a\n * `region` with a label rather than a bare `tabindex`, so the tab stop announces\n * what it is.\n *\n * **Resolving a streaming block must not move the reader.** When `complete` is\n * false the block shows the code it has plus a generating indicator; the\n * indicator is inside the scroller's own box and does not add a line, because a\n * block that grows the moment its content resolves shifts everything below it.\n * If a caller's `highlight` changes the line box, that is the caller's height to\n * hold — `lineHeight` is a prop for exactly that reason.\n */\nexport type CodeBlockProps = Omit<ComponentProps<'div'>, 'children'> & {\n code: string\n /** The language, shown in the header and used as the region's label. */\n language?: string\n /** The code, transformed — highlighted HTML or a component. Omit for plain text. */\n highlight?: (code: string) => JSX.Element\n /** False while the block is still streaming. Adds a generating indicator. */\n complete?: boolean\n /** A filename or title, shown instead of the language. */\n title?: string\n /** Extra header controls, before the copy button. */\n actions?: JSX.Element\n /** Copy label. Override for a non-English application. */\n copyLabel?: string\n copiedLabel?: string\n /** Line height of the rendered code. Set it when `highlight` changes the box. */\n lineHeight?: string\n /** A line-number gutter. Off by default; a short snippet rarely needs one. */\n showLineNumbers?: boolean\n /** The height above which the action row is repeated below the block. */\n tallThreshold?: number\n}\n\n/** The height a block must exceed before its actions are repeated. */\nexport const TALL_CODE_BLOCK_PX = 480\n\n/**\n * Copy, reporting whether it worked. `navigator.clipboard` is absent in an\n * insecure context, and `writeText` rejects when the document is not focused —\n * both are normal in an embedded or iframed application, and neither should\n * silently look like success.\n */\nasync function copyText(text: string): Promise<boolean> {\n try {\n if (!navigator.clipboard) return false\n await navigator.clipboard.writeText(text)\n return true\n } catch {\n return false\n }\n}\n\nexport function CodeBlock(props: CodeBlockProps) {\n const [local, rest] = splitProps(props, [\n 'code',\n 'language',\n 'highlight',\n 'complete',\n 'title',\n 'actions',\n 'copyLabel',\n 'copiedLabel',\n 'lineHeight',\n 'showLineNumbers',\n 'tallThreshold',\n 'class',\n 'ref',\n ])\n\n const [copied, setCopied] = createSignal(false)\n const [failed, setFailed] = createSignal(false)\n const [tall, setTall] = createSignal(false)\n\n const label = () => local.title ?? local.language ?? 'code'\n const regionLabel = () => (local.language ? `${local.language} code` : 'code')\n const lines = createMemo(() => local.code.replace(/\\n$/, '').split('\\n'))\n\n const copy = async () => {\n const ok = await copyText(local.code)\n setCopied(ok)\n setFailed(!ok)\n if (ok) setTimeout(() => setCopied(false), 1500)\n }\n\n const Actions = () => (\n <div class=\"flex items-center gap-1 opacity-0 transition-opacity group-focus-within/code:opacity-100 group-hover/code:opacity-100\">\n {local.actions}\n <Button\n variant=\"ghost\"\n size=\"icon-2xs\"\n aria-label={copied() ? (local.copiedLabel ?? 'Copied') : (local.copyLabel ?? 'Copy code')}\n title={failed() ? 'Copying is unavailable in this context' : undefined}\n onClick={() => void copy()}\n >\n <Show when={copied()} fallback={<Copy aria-hidden=\"true\" />}>\n <Check aria-hidden=\"true\" />\n </Show>\n </Button>\n </div>\n )\n\n return (\n <div\n class={cn('group/code overflow-hidden rounded-xl border border-border bg-card', local.class)}\n {...rest}\n ref={(element) => {\n // Composed rather than replaced: a caller's ref must survive.\n if (typeof local.ref === 'function') local.ref(element)\n else if (local.ref) local.ref = element\n // Measured rather than assumed: the caller controls the content, so only\n // the rendered box can say whether the action row has scrolled away.\n const observer = new ResizeObserver(() => {\n setTall(element.offsetHeight > (local.tallThreshold ?? TALL_CODE_BLOCK_PX))\n })\n observer.observe(element)\n }}\n >\n <div class=\"flex items-center justify-between gap-2 px-3 py-1\">\n <span class=\"truncate font-mono text-xs text-muted-foreground\">{label()}</span>\n <Actions />\n </div>\n <div\n class=\"scroll-fade overflow-x-auto\"\n // A region that scrolls must be focusable, and a tab stop needs a name.\n tabindex=\"0\"\n role=\"region\"\n aria-label={regionLabel()}\n >\n <Show\n when={local.highlight}\n fallback={\n <pre class=\"m-0 px-3 py-2\" style={{ 'line-height': local.lineHeight ?? '1.5' }}>\n <code class=\"font-mono text-xs\">\n <Show when={local.showLineNumbers} fallback={local.code.replace(/\\n$/, '')}>\n <For each={lines()}>\n {(line, index) => (\n <span class=\"grid grid-cols-[3ch_1fr] gap-3\">\n <span\n class=\"text-right text-muted-foreground select-none\"\n aria-hidden=\"true\"\n >\n {index() + 1}\n </span>\n <span>{line || ' '}</span>\n </span>\n )}\n </For>\n </Show>\n </code>\n </pre>\n }\n >\n {(highlight) => <div class=\"px-3 py-2\">{highlight()(local.code)}</div>}\n </Show>\n {/*\n In the scroller's box, and a single line: the indicator must not add\n height when it disappears, or a streaming block shifts everything below\n it as it resolves.\n */}\n <Show when={!local.complete}>\n <p class=\"px-3 pb-2 text-xs text-muted-foreground italic\">Generating…</p>\n </Show>\n </div>\n <Show when={tall()}>\n <div\n data-code-block-footer=\"\"\n class=\"flex items-center justify-end border-t border-transparent px-3 py-1 transition-colors group-focus-within/code:border-border group-hover/code:border-border\"\n >\n <Actions />\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * InlineCode.\n *\n * The `code` inside a sentence. It is a component rather than a class because it\n * has to hold three properties at once: it must not break the line's rhythm\n * (`font-size: 0.9em`, so it tracks the surrounding text), it must wrap rather\n * than overflow a narrow column (`overflow-wrap: anywhere` — an identifier with\n * no spaces is one long token), and it must be legible against whatever surface\n * it lands on, which is why the fill is a token and not a fixed grey.\n */\nexport function InlineCode(props: ComponentProps<'code'>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <code\n class={cn(\n 'rounded-sm bg-muted px-[0.4em] py-[0.15em] font-mono text-[0.9em] text-foreground [overflow-wrap:anywhere]',\n local.class\n )}\n {...rest}\n />\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"code-block.js","names":["createMemo","createSignal","For","Show","splitProps","ComponentProps","JSX","Check","Copy","Button","cn","CodeBlockProps","Omit","code","language","highlight","Element","complete","title","actions","copyLabel","copiedLabel","lineHeight","showLineNumbers","tallThreshold","TALL_CODE_BLOCK_PX","copyText","text","Promise","navigator","clipboard","writeText","CodeBlock","props","local","rest","copied","setCopied","failed","setFailed","tall","setTall","label","regionLabel","lines","replace","split","copy","ok","setTimeout","Actions","_el$","_tmpl$","_$insert","_$createComponent","variant","size","aria-label","_$memo","undefined","onClick","children","when","fallback","_el$2","_tmpl$4","_el$3","firstChild","_el$4","_el$5","nextSibling","_$use","element","ref","observer","ResizeObserver","offsetHeight","observe","_$spread","_$mergeProps","class","_el$8","_tmpl$5","_el$9","each","line","index","_el$0","_tmpl$6","_el$1","_el$10","_$effect","_$p","_$setStyleProperty","_el$11","_tmpl$7","_tmpl$2","_el$7","_tmpl$3","_$setAttribute","InlineCode","_el$12","_tmpl$8","_$createComponent","_$memo","_$mergeProps","_$setStyleProperty","_$setAttribute"],"sources":["../../../../src/components/ui/code-block/code-block.tsx"],"sourcesContent":["import {\n createMemo,\n createSignal,\n For,\n Show,\n splitProps,\n type ComponentProps,\n type JSX,\n} from 'solid-js'\nimport { Check, Copy } from 'lucide-solid'\nimport { Button } from '../button'\nimport { cn } from '#lib/utils'\n\n/**\n * CodeBlock.\n *\n * A fenced block, rendered as a surface. The library ships no highlighter —\n * syntax colouring is a large dependency with its own theme format, and a\n * component that bundled one would force every consumer to pay for it. This\n * renders the block, its chrome, and its behaviour; a caller that wants\n * highlighting passes the result through `highlight`, which is the seam a\n * Shiki/Pierre/Prism integration plugs into.\n *\n * Four details are the reason this exists rather than a styled `<pre>`:\n *\n * **Copy confirms only on success.** `navigator.clipboard.writeText` rejects\n * outside a secure context, in a sandboxed frame, and when the document is not\n * focused. Flipping to a tick unconditionally confirms a copy that did not\n * happen, and the reader pastes something stale and does not know why. The\n * rejection is caught and the button reports the failure instead.\n *\n * **A tall block repeats its action row at the bottom.** Copying from a block\n * that is taller than the viewport otherwise costs a scroll back to the top and\n * another scroll down to where you were. The threshold is a fixed 480px rather\n * than viewport-relative so the behaviour does not change when the window is\n * resized.\n *\n * **The scroller is focusable and named.** A horizontally scrollable region has\n * to be reachable by keyboard — this is axe's `scrollable-region-focusable`, and\n * a region that scrolls but cannot be focused is a WCAG 2.1.1 failure. It is a\n * `region` with a label rather than a bare `tabindex`, so the tab stop announces\n * what it is.\n *\n * **Resolving a streaming block must not move the reader.** When `complete` is\n * false the block shows the code it has plus a generating indicator; the\n * indicator is inside the scroller's own box and does not add a line, because a\n * block that grows the moment its content resolves shifts everything below it.\n * If a caller's `highlight` changes the line box, that is the caller's height to\n * hold — `lineHeight` is a prop for exactly that reason.\n */\nexport type CodeBlockProps = Omit<ComponentProps<'div'>, 'children'> & {\n code: string\n /** The language, shown in the header and used as the region's label. */\n language?: string\n /** The code, transformed — highlighted HTML or a component. Omit for plain text. */\n highlight?: (code: string) => JSX.Element\n /** False while the block is still streaming. Adds a generating indicator. */\n complete?: boolean\n /** A filename or title, shown instead of the language. */\n title?: string\n /** Extra header controls, before the copy button. */\n actions?: JSX.Element\n /** Copy label. Override for a non-English application. */\n copyLabel?: string\n copiedLabel?: string\n /** Line height of the rendered code. Set it when `highlight` changes the box. */\n lineHeight?: string\n /** A line-number gutter. Off by default; a short snippet rarely needs one. */\n showLineNumbers?: boolean\n /** The height above which the action row is repeated below the block. */\n tallThreshold?: number\n}\n\n/** The height a block must exceed before its actions are repeated. */\nexport const TALL_CODE_BLOCK_PX = 480\n\n/**\n * Copy, reporting whether it worked. `navigator.clipboard` is absent in an\n * insecure context, and `writeText` rejects when the document is not focused —\n * both are normal in an embedded or iframed application, and neither should\n * silently look like success.\n */\nasync function copyText(text: string): Promise<boolean> {\n try {\n if (!navigator.clipboard) return false\n await navigator.clipboard.writeText(text)\n return true\n } catch {\n return false\n }\n}\n\nexport function CodeBlock(props: CodeBlockProps) {\n const [local, rest] = splitProps(props, [\n 'code',\n 'language',\n 'highlight',\n 'complete',\n 'title',\n 'actions',\n 'copyLabel',\n 'copiedLabel',\n 'lineHeight',\n 'showLineNumbers',\n 'tallThreshold',\n 'class',\n 'ref',\n ])\n\n const [copied, setCopied] = createSignal(false)\n const [failed, setFailed] = createSignal(false)\n const [tall, setTall] = createSignal(false)\n\n const label = () => local.title ?? local.language ?? 'code'\n const regionLabel = () => (local.language ? `${local.language} code` : 'code')\n const lines = createMemo(() => local.code.replace(/\\n$/, '').split('\\n'))\n\n const copy = async () => {\n const ok = await copyText(local.code)\n setCopied(ok)\n setFailed(!ok)\n if (ok) setTimeout(() => setCopied(false), 1500)\n }\n\n const Actions = () => (\n <div class=\"flex items-center gap-1 opacity-0 transition-opacity group-focus-within/code:opacity-100 group-hover/code:opacity-100\">\n {local.actions}\n <Button\n variant=\"ghost\"\n size=\"icon-2xs\"\n aria-label={copied() ? (local.copiedLabel ?? 'Copied') : (local.copyLabel ?? 'Copy code')}\n title={failed() ? 'Copying is unavailable in this context' : undefined}\n onClick={() => void copy()}\n >\n <Show when={copied()} fallback={<Copy aria-hidden=\"true\" />}>\n <Check aria-hidden=\"true\" />\n </Show>\n </Button>\n </div>\n )\n\n return (\n <div\n class={cn('group/code overflow-hidden rounded-xl border border-border bg-card', local.class)}\n {...rest}\n ref={(element) => {\n // Composed rather than replaced: a caller's ref must survive.\n if (typeof local.ref === 'function') local.ref(element)\n else if (local.ref) local.ref = element\n // Measured rather than assumed: the caller controls the content, so only\n // the rendered box can say whether the action row has scrolled away.\n const observer = new ResizeObserver(() => {\n setTall(element.offsetHeight > (local.tallThreshold ?? TALL_CODE_BLOCK_PX))\n })\n observer.observe(element)\n }}\n >\n <div class=\"flex items-center justify-between gap-2 px-3 py-1\">\n <span class=\"truncate font-code text-code text-muted-foreground\">{label()}</span>\n <Actions />\n </div>\n <div\n class=\"scroll-fade overflow-x-auto\"\n // A region that scrolls must be focusable, and a tab stop needs a name.\n tabindex=\"0\"\n role=\"region\"\n aria-label={regionLabel()}\n >\n <Show\n when={local.highlight}\n fallback={\n <pre class=\"m-0 px-3 py-2\" style={{ 'line-height': local.lineHeight ?? '1.5' }}>\n <code class=\"font-code text-code\">\n <Show when={local.showLineNumbers} fallback={local.code.replace(/\\n$/, '')}>\n <For each={lines()}>\n {(line, index) => (\n <span class=\"grid grid-cols-[3ch_1fr] gap-3\">\n <span\n class=\"text-right text-muted-foreground select-none\"\n aria-hidden=\"true\"\n >\n {index() + 1}\n </span>\n <span>{line || ' '}</span>\n </span>\n )}\n </For>\n </Show>\n </code>\n </pre>\n }\n >\n {(highlight) => <div class=\"px-3 py-2\">{highlight()(local.code)}</div>}\n </Show>\n {/*\n In the scroller's box, and a single line: the indicator must not add\n height when it disappears, or a streaming block shifts everything below\n it as it resolves.\n */}\n <Show when={!local.complete}>\n <p class=\"px-3 pb-2 text-xs text-muted-foreground italic\">Generating…</p>\n </Show>\n </div>\n <Show when={tall()}>\n <div\n data-code-block-footer=\"\"\n class=\"flex items-center justify-end border-t border-transparent px-3 py-1 transition-colors group-focus-within/code:border-border group-hover/code:border-border\"\n >\n <Actions />\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * InlineCode.\n *\n * The `code` inside a sentence. It is a component rather than a class because it\n * has to hold three properties at once: it uses the shared code family and size\n * preference, and it wraps rather than overflows a narrow column\n * (`overflow-wrap: anywhere` — an identifier with\n * no spaces is one long token), and it must be legible against whatever surface\n * it lands on, which is why the fill is a token and not a fixed grey.\n */\nexport function InlineCode(props: ComponentProps<'code'>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <code\n class={cn(\n 'rounded-sm bg-muted px-[0.4em] py-[0.15em] font-code text-code text-foreground [overflow-wrap:anywhere]',\n local.class\n )}\n {...rest}\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0EA,IAAayB,qBAAqB;;;;;;;AAQlC,eAAeC,SAASC,MAAgC;CACtD,IAAI;EACF,IAAI,CAACE,UAAUC,WAAW,OAAO;EACjC,MAAMD,UAAUC,UAAUC,UAAUJ,IAAI;EACxC,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgBK,UAAUC,OAAuB;CAC/C,MAAM,CAACC,OAAOC,QAAQ/B,WAAW6B,OAAO;EACtC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAAK,CACN;CAED,MAAM,CAACG,QAAQC,aAAapC,aAAa,KAAK;CAC9C,MAAM,CAACqC,QAAQC,aAAatC,aAAa,KAAK;CAC9C,MAAM,CAACuC,MAAMC,WAAWxC,aAAa,KAAK;CAE1C,MAAMyC,cAAcR,MAAMhB,SAASgB,MAAMpB,YAAY;CACrD,MAAM6B,oBAAqBT,MAAMpB,WAAW,GAAGoB,MAAMpB,SAAQ,SAAU;CACvE,MAAM8B,QAAQ5C,iBAAiBkC,MAAMrB,KAAKgC,QAAQ,OAAO,EAAE,CAAC,CAACC,MAAM,IAAI,CAAC;CAExE,MAAMC,OAAO,YAAY;EACvB,MAAMC,KAAK,MAAMtB,SAASQ,MAAMrB,IAAI;EACpCwB,UAAUW,EAAE;EACZT,UAAU,CAACS,EAAE;EACb,IAAIA,IAAIC,iBAAiBZ,UAAU,KAAK,GAAG,IAAI;CACjD;CAEA,MAAMa,uBAAU;EAAA,IAAAC,OAAAC,OAAA;EAAAC,OAAAF,YAEXjB,MAAMf,SAAO,IAAA;EAAAkC,OAAAF,MAAAG,gBACb7C,QAAM;GACL8C,SAAO;GACPC,MAAI;GAAA,KAAA,gBAAA;IAAA,OACQE,WAAA,CAAA,CAAAtB,OAAO,CAAC,CAAA,CAAA,IAAIF,MAAMb,eAAe,WAAaa,MAAMd,aAAa;GAAY;GAAA,IACzFF,QAAK;IAAA,OAAEoB,OAAO,IAAI,2CAA2CqB,KAAAA;GAAS;GACtEC,eAAe,KAAKb,KAAK;GAAC,IAAAc,WAAA;IAAA,OAAAP,gBAEzBnD,MAAI;KAAA,IAAC2D,OAAI;MAAA,OAAE1B,OAAO;KAAC;KAAA,IAAE2B,WAAQ;MAAA,OAAAT,gBAAG9C,MAAI,EAAA,eAAA,OAAA,CAAA;KAAA;KAAA,IAAAqD,WAAA;MAAA,OAAAP,gBAClC/C,OAAK,EAAA,eAAA,OAAA,CAAA;KAAA;IAAA,CAAA;GAAA;EAAA,CAAA,GAAA,IAAA;EAAA,OAAA4C;CAAA,EAAA,CAAA;CAMd,cAAA;EAAA,IAAAa,QAAAC,QAAA,GAAAC,QAAAF,MAAAG,YAAAC,QAAAF,MAAAC,YAAAE,QAAAH,MAAAI;EAAAC,KAIUC,YAAY;GAEhB,IAAI,OAAOtC,MAAMuC,QAAQ,YAAYvC,MAAMuC,IAAID,OAAO;QACjD,IAAItC,MAAMuC,KAAKvC,MAAMuC,MAAMD;GAMhCE,IAHqBC,qBAAqB;IACxClC,QAAQ+B,QAAQI,gBAAgB1C,MAAMV,iBAAAA,IAAoC;GAC5E,CACAkD,CAAAA,CAASG,QAAQL,OAAO;EAC1B,GAACR,KAAA;EAAAc,OAAAd,OAAAe,WAAA,EAAA,KAAA,WAAA;GAAA,OAZMrE,GAAG,sEAAsEwB,MAAM8C,KAAK;EAAC,EAAA,GACxF7C,IAAI,GAAA,OAAA,IAAA;EAAAkB,OAAAe,OAc4D1B,KAAK;EAAAW,OAAAa,OAAAZ,gBACtEJ,SAAO,CAAA,CAAA,GAAA,IAAA;EAAAG,OAAAgB,OAAAf,gBASPnD,MAAI;GAAA,IACH2D,OAAI;IAAA,OAAE5B,MAAMnB;GAAS;GAAA,IACrBgD,WAAQ;IAAA,cAAA;KAAA,IAAAkB,QAAAC,QAAA,GAAAC,QAAAF,MAAAd;KAAAd,OAAA8B,OAAA7B,gBAGDnD,MAAI;MAAA,IAAC2D,OAAI;OAAA,OAAE5B,MAAMX;MAAe;MAAA,IAAEwC,WAAQ;OAAA,OAAE7B,MAAMrB,KAAKgC,QAAQ,OAAO,EAAE;MAAC;MAAA,IAAAgB,WAAA;OAAA,OAAAP,gBACvEpD,KAAG;QAAA,IAACkF,OAAI;SAAA,OAAExC,MAAM;QAAC;QAAAiB,WACdwB,MAAMC,iBAAK;SAAA,IAAAC,QAAAC,QAAA,GAAAC,QAAAF,MAAApB,YAAAuB,SAAAD,MAAAnB;SAAAjB,OAAAoC,aAMNH,MAAM,IAAI,CAAC;SAAAjC,OAAAqC,QAEPL,QAAQ,GAAG;SAAA,OAAAE;QAAA,EAAA,CAAA;OAErB,CAAA;MAAA;KAAA,CAAA,CAAA;KAAAI,QAAAC,QAAAC,iBAAAZ,OAAA,eAd0C/C,MAAMZ,cAAc,KAAK,CAAA;KAAA,OAAA2D;IAAA,EAAA,CAAA;GAAA;GAAApB,WAqB5E9C,qBAAS;IAAA,IAAA+E,SAAAC,QAAA;IAAA1C,OAAAyC,cAA6B/E,UAAU,CAAC,CAACmB,MAAMrB,IAAI,CAAC;IAAA,OAAAiF;GAAA,EAAA,CAAA;EAAO,CAAA,GAAA,IAAA;EAAAzC,OAAAgB,OAAAf,gBAOvEnD,MAAI;GAAA,IAAC2D,OAAI;IAAA,OAAE,CAAC5B,MAAMjB;GAAQ;GAAA,IAAA4C,WAAA;IAAA,OAAAmC,QAAA;GAAA;EAAA,CAAA,GAAA,IAAA;EAAA3C,OAAAW,OAAAV,gBAI5BnD,MAAI;GAAA,IAAC2D,OAAI;IAAA,OAAEtB,KAAK;GAAC;GAAA,IAAAqB,WAAA;IAAA,IAAAoC,QAAAC,QAAA;IAAA7C,OAAA4C,OAAA3C,gBAKbJ,SAAO,CAAA,CAAA,CAAA;IAAA,OAAA+C;GAAA;EAAA,CAAA,GAAA,IAAA;EAAAN,aAAAQ,aAAA9B,OAAA,cA1CE1B,YAAY,CAAC,CAAA;EAAA,OAAAqB;CAAA,EAAA,CAAA;AA+CjC;;;;;;;;;;;AAYA,SAAgBoC,WAAWnE,OAA+B;CACxD,MAAM,CAACC,OAAOC,QAAQ/B,WAAW6B,OAAO,CAAC,OAAO,CAAC;CAEjD,cAAA;EAAA,IAAAoE,SAAAC,QAAA;EAAAxB,OAAAuB,QAAAtB,WAAA,EAAA,KAAA,WAAA;GAAA,OAEWrE,GACL,2GACAwB,MAAM8C,KACR;EAAC,EAAA,GACG7C,IAAI,GAAA,OAAA,KAAA;EAAA,OAAAkE;CAAA,EAAA,CAAA;AAGd"}
|
|
@@ -191,7 +191,7 @@ function CommandShortcut(props) {
|
|
|
191
191
|
return (() => {
|
|
192
192
|
var _el$3 = _tmpl$3();
|
|
193
193
|
insert(_el$3, () => props.children);
|
|
194
|
-
effect(() => className(_el$3, cn("text-muted-foreground ms-auto font-
|
|
194
|
+
effect(() => className(_el$3, cn("text-muted-foreground ms-auto font-code text-code tracking-widest group-data-[selected=true]/command-item:text-foreground", props.class)));
|
|
195
195
|
return _el$3;
|
|
196
196
|
})();
|
|
197
197
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.js","names":["CommandDialog","CmdkDialog","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandInput","CmdkInput","CommandItem","CmdkItem","CommandList","CmdkList","CommandLoading","CmdkLoading","CommandRoot","CmdkRoot","CommandSeparator","CmdkSeparator","useCommandState","Dialog","KobalteDialog","Search","ComponentProps","createEffect","createSignal","splitProps","createDialogFocusRestoration","menuItem","cn","commandItem","replace","Command","props","local","rest","_$createComponent","_$mergeProps","class","CommandDialogProps","Pick","Content","dialogProps","commandProps","isOpen","setIsOpen","open","defaultOpen","undefined","focus","onCloseAutoFocus","onOpenAutoFocus","onOpenChange","children","Portal","mount","container","Overlay","overlayClassName","aria-label","label","role","contentClassName","_el$","_tmpl$","_$insert","wrapper","setWrapper","HTMLDivElement","resultCount","state","filtered","count","root","selector","querySelector","setAttribute","_el$2","_tmpl$2","_$use","CommandShortcut","_el$3","_tmpl$3","_$effect","_$className","_$createComponent","CmdkRoot","_$mergeProps","KobalteDialog","CommandInput","CmdkInput","CommandList","CmdkList","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandItem","CmdkItem","CommandSeparator","CmdkSeparator","CommandLoading","CmdkLoading","_$className"],"sources":["../../../../src/components/ui/command/command.tsx"],"sourcesContent":["import {\n CommandDialog as CmdkDialog,\n CommandEmpty as CmdkEmpty,\n CommandGroup as CmdkGroup,\n CommandInput as CmdkInput,\n CommandItem as CmdkItem,\n CommandList as CmdkList,\n CommandLoading as CmdkLoading,\n CommandRoot as CmdkRoot,\n CommandSeparator as CmdkSeparator,\n useCommandState,\n} from 'cmdk-solid'\nimport { Dialog as KobalteDialog } from '@kobalte/core/dialog'\nimport { Search } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { createEffect, createSignal, splitProps } from 'solid-js'\nimport { createDialogFocusRestoration } from '../dialog/dialog'\nimport { menuItem } from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n// cmdk emits data-disabled=\"false\" on enabled items, unlike the presence-only\n// attributes Kobalte menu rows use. Apply those shared disabled styles only when\n// cmdk's value is true.\nconst commandItem = menuItem\n .replace('data-[disabled]:pointer-events-none', '')\n .replace('data-[disabled]:text-muted-foreground', '')\n\n/**\n * Command.\n *\n * The command palette: a filtered list of everything the user can do, ranked\n * by fuzzy match. It is the one place in an app where a keyboard-first surface\n * is the *primary* one, so it carries rules the rest of the system does not:\n *\n * - Every item must be reachable by typing its name. If a user has to\n * remember which group it lives in, the palette has failed at its job.\n * - Groups exist for reading, not for navigation. The ranking crosses them.\n * - The empty state is not an apology — it should offer the closest thing\n * the app could guess, or say plainly that nothing matched.\n *\n * cmdk-solid supplies the filter, the scoring, the `aria-activedescendant`\n * wiring and the arrow-key navigation.\n */\nexport function Command(props: ComponentProps<typeof CmdkRoot>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkRoot\n class={cn(\n 'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-xl',\n local.class\n )}\n {...rest}\n />\n )\n}\n\ntype CommandDialogProps = ComponentProps<typeof CmdkDialog> &\n Pick<ComponentProps<typeof KobalteDialog.Content>, 'onCloseAutoFocus' | 'onOpenAutoFocus'>\n\nexport function CommandDialog(props: CommandDialogProps) {\n // cmdk-solid's Dialog does not forward Content autofocus props: unknown\n // props fall through to its Command root. Compose Kobalte's dialog surface\n // here so Escape and other close paths can restore focus to the real opener.\n // Preserve the shared wrapper's `class` contract on the dialog surface;\n // `contentClassName` adds to it, while the nested Command keeps its own API.\n const [local, dialogProps, commandProps] = splitProps(\n props,\n [\n 'class',\n 'contentClassName',\n 'overlayClassName',\n 'container',\n 'onCloseAutoFocus',\n 'onOpenAutoFocus',\n ],\n [\n 'open',\n 'defaultOpen',\n 'onOpenChange',\n 'id',\n 'modal',\n 'preventScroll',\n 'forceMount',\n 'translations',\n ]\n )\n const [isOpen, setIsOpen] = createSignal(dialogProps.open ?? dialogProps.defaultOpen ?? false)\n\n createEffect(() => {\n if (dialogProps.open !== undefined) setIsOpen(dialogProps.open)\n })\n\n const focus = createDialogFocusRestoration({\n open: isOpen,\n onCloseAutoFocus: local.onCloseAutoFocus,\n onOpenAutoFocus: local.onOpenAutoFocus,\n })\n\n return (\n <KobalteDialog\n {...dialogProps}\n onOpenChange={(open) => {\n setIsOpen(open)\n dialogProps.onOpenChange?.(open)\n }}\n >\n <KobalteDialog.Portal mount={local.container}>\n <KobalteDialog.Overlay cmdk-overlay=\"\" class={local.overlayClassName} />\n <KobalteDialog.Content\n aria-label={commandProps.label}\n cmdk-dialog=\"\"\n role=\"dialog\"\n class={cn(\n 'bg-popover text-popover-foreground fixed top-1/3 left-1/2 z-(--z-dialog) w-full max-w-lg -translate-x-1/2 -translate-y-1/2',\n 'overflow-hidden rounded-xl border border-border shadow-xl',\n 'data-expanded:animate-in data-expanded:fade-in-0 data-expanded:zoom-in-95',\n 'data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95',\n local.class,\n local.contentClassName\n )}\n onOpenAutoFocus={focus.onOpenAutoFocus}\n onCloseAutoFocus={focus.onCloseAutoFocus}\n >\n <Command {...commandProps} />\n </KobalteDialog.Content>\n </KobalteDialog.Portal>\n </KobalteDialog>\n )\n}\n\nexport function CommandInput(props: ComponentProps<typeof CmdkInput>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <div\n data-slot=\"command-input-wrapper\"\n class=\"flex h-11 items-center gap-2 border-b border-border px-3\"\n >\n <Search class=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <CmdkInput\n class={cn(\n 'h-full w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n </div>\n )\n}\n\n/**\n * The scrolling list.\n *\n * Two DOM corrections, and both are deliberate. cmdk builds a `role=\"listbox\"`\n * whose children include two elements ARIA does not allow there:\n *\n * - a bare `<div cmdk-list-sizer>` with no role, wrapped around every group;\n * - a `<div cmdk-separator role=\"separator\">`, and `separator` is a menu and\n * toolbar role — inside a listbox the only owned elements may be `option`\n * and `group`.\n *\n * Both are pure presentation: the sizer is layout, and the separator is a\n * hairline between groups that the groups already structure. `role=\"presentation\"`\n * is their accurate role rather than a workaround — each is flattened out of the\n * accessibility tree, and the options inside are reached exactly as before.\n *\n * Written onto the mounted nodes rather than through props, because cmdk owns\n * this markup and does not forward a `ref`; in an effect rather than `onMount`,\n * because cmdk renders the sizer with the first item, after the list itself.\n */\nexport function CommandList(props: ComponentProps<typeof CmdkList>) {\n const [local, rest] = splitProps(props, ['class'])\n const [wrapper, setWrapper] = createSignal<HTMLDivElement>()\n const resultCount = useCommandState((state) => state.filtered.count)\n\n createEffect(() => {\n const root = wrapper()\n if (!root) return\n for (const selector of ['[cmdk-list-sizer]', '[cmdk-separator]']) {\n root.querySelector(selector)?.setAttribute('role', 'presentation')\n }\n\n /*\n * A `listbox` must own at least one `option`, so a listbox with nothing in it\n * is invalid ARIA — which is what a search with no matches produces. When\n * there are no results the list is inert, so it becomes presentational and\n * the empty message carries the information instead. It keeps its `id`, so\n * the input's `aria-controls` still resolves.\n */\n root\n .querySelector('[cmdk-list]')\n ?.setAttribute('role', resultCount() > 0 ? 'listbox' : 'presentation')\n })\n\n return (\n <div ref={setWrapper} class=\"contents\">\n <CmdkList\n class={cn('max-h-80 scroll-py-1 overflow-y-auto overflow-x-hidden p-1', local.class)}\n {...rest}\n />\n </div>\n )\n}\n\nexport function CommandEmpty(props: ComponentProps<typeof CmdkEmpty>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkEmpty\n /*\n * A status rather than plain text: when the list is presentational, this is\n * the only thing that tells a screen reader the search matched nothing.\n */\n role=\"status\"\n class={cn('text-muted-foreground py-8 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function CommandGroup(props: ComponentProps<typeof CmdkGroup>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkGroup\n class={cn(\n 'text-foreground overflow-hidden p-1',\n '[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-2xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:tracking-wide [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:uppercase',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandItem(props: ComponentProps<typeof CmdkItem>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkItem\n class={cn(\n commandItem,\n 'data-[disabled=true]:pointer-events-none data-[disabled=true]:text-muted-foreground',\n 'group/command-item text-popover-foreground data-[selected=true]:bg-card data-[selected=true]:text-popover-foreground',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandSeparator(props: ComponentProps<typeof CmdkSeparator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <CmdkSeparator class={cn('bg-border -mx-1 my-1 h-px', local.class)} {...rest} />\n}\n\nexport function CommandLoading(props: ComponentProps<typeof CmdkLoading>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <CmdkLoading\n class={cn('text-muted-foreground py-6 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\n/** The keyboard hint a palette item usually carries. */\nexport function CommandShortcut(props: {\n class?: string\n children?: ComponentProps<'span'>['children']\n}) {\n return (\n <span\n class={cn(\n 'text-muted-foreground ms-auto font-mono text-2xs tracking-widest group-data-[selected=true]/command-item:text-foreground',\n props.class\n )}\n >\n {props.children}\n </span>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"command.js","names":["CommandDialog","CmdkDialog","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandInput","CmdkInput","CommandItem","CmdkItem","CommandList","CmdkList","CommandLoading","CmdkLoading","CommandRoot","CmdkRoot","CommandSeparator","CmdkSeparator","useCommandState","Dialog","KobalteDialog","Search","ComponentProps","createEffect","createSignal","splitProps","createDialogFocusRestoration","menuItem","cn","commandItem","replace","Command","props","local","rest","_$createComponent","_$mergeProps","class","CommandDialogProps","Pick","Content","dialogProps","commandProps","isOpen","setIsOpen","open","defaultOpen","undefined","focus","onCloseAutoFocus","onOpenAutoFocus","onOpenChange","children","Portal","mount","container","Overlay","overlayClassName","aria-label","label","role","contentClassName","_el$","_tmpl$","_$insert","wrapper","setWrapper","HTMLDivElement","resultCount","state","filtered","count","root","selector","querySelector","setAttribute","_el$2","_tmpl$2","_$use","CommandShortcut","_el$3","_tmpl$3","_$effect","_$className","_$createComponent","CmdkRoot","_$mergeProps","KobalteDialog","CommandInput","CmdkInput","CommandList","CmdkList","CommandEmpty","CmdkEmpty","CommandGroup","CmdkGroup","CommandItem","CmdkItem","CommandSeparator","CmdkSeparator","CommandLoading","CmdkLoading","_$className"],"sources":["../../../../src/components/ui/command/command.tsx"],"sourcesContent":["import {\n CommandDialog as CmdkDialog,\n CommandEmpty as CmdkEmpty,\n CommandGroup as CmdkGroup,\n CommandInput as CmdkInput,\n CommandItem as CmdkItem,\n CommandList as CmdkList,\n CommandLoading as CmdkLoading,\n CommandRoot as CmdkRoot,\n CommandSeparator as CmdkSeparator,\n useCommandState,\n} from 'cmdk-solid'\nimport { Dialog as KobalteDialog } from '@kobalte/core/dialog'\nimport { Search } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { createEffect, createSignal, splitProps } from 'solid-js'\nimport { createDialogFocusRestoration } from '../dialog/dialog'\nimport { menuItem } from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n// cmdk emits data-disabled=\"false\" on enabled items, unlike the presence-only\n// attributes Kobalte menu rows use. Apply those shared disabled styles only when\n// cmdk's value is true.\nconst commandItem = menuItem\n .replace('data-[disabled]:pointer-events-none', '')\n .replace('data-[disabled]:text-muted-foreground', '')\n\n/**\n * Command.\n *\n * The command palette: a filtered list of everything the user can do, ranked\n * by fuzzy match. It is the one place in an app where a keyboard-first surface\n * is the *primary* one, so it carries rules the rest of the system does not:\n *\n * - Every item must be reachable by typing its name. If a user has to\n * remember which group it lives in, the palette has failed at its job.\n * - Groups exist for reading, not for navigation. The ranking crosses them.\n * - The empty state is not an apology — it should offer the closest thing\n * the app could guess, or say plainly that nothing matched.\n *\n * cmdk-solid supplies the filter, the scoring, the `aria-activedescendant`\n * wiring and the arrow-key navigation.\n */\nexport function Command(props: ComponentProps<typeof CmdkRoot>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkRoot\n class={cn(\n 'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-xl',\n local.class\n )}\n {...rest}\n />\n )\n}\n\ntype CommandDialogProps = ComponentProps<typeof CmdkDialog> &\n Pick<ComponentProps<typeof KobalteDialog.Content>, 'onCloseAutoFocus' | 'onOpenAutoFocus'>\n\nexport function CommandDialog(props: CommandDialogProps) {\n // cmdk-solid's Dialog does not forward Content autofocus props: unknown\n // props fall through to its Command root. Compose Kobalte's dialog surface\n // here so Escape and other close paths can restore focus to the real opener.\n // Preserve the shared wrapper's `class` contract on the dialog surface;\n // `contentClassName` adds to it, while the nested Command keeps its own API.\n const [local, dialogProps, commandProps] = splitProps(\n props,\n [\n 'class',\n 'contentClassName',\n 'overlayClassName',\n 'container',\n 'onCloseAutoFocus',\n 'onOpenAutoFocus',\n ],\n [\n 'open',\n 'defaultOpen',\n 'onOpenChange',\n 'id',\n 'modal',\n 'preventScroll',\n 'forceMount',\n 'translations',\n ]\n )\n const [isOpen, setIsOpen] = createSignal(dialogProps.open ?? dialogProps.defaultOpen ?? false)\n\n createEffect(() => {\n if (dialogProps.open !== undefined) setIsOpen(dialogProps.open)\n })\n\n const focus = createDialogFocusRestoration({\n open: isOpen,\n onCloseAutoFocus: local.onCloseAutoFocus,\n onOpenAutoFocus: local.onOpenAutoFocus,\n })\n\n return (\n <KobalteDialog\n {...dialogProps}\n onOpenChange={(open) => {\n setIsOpen(open)\n dialogProps.onOpenChange?.(open)\n }}\n >\n <KobalteDialog.Portal mount={local.container}>\n <KobalteDialog.Overlay cmdk-overlay=\"\" class={local.overlayClassName} />\n <KobalteDialog.Content\n aria-label={commandProps.label}\n cmdk-dialog=\"\"\n role=\"dialog\"\n class={cn(\n 'bg-popover text-popover-foreground fixed top-1/3 left-1/2 z-(--z-dialog) w-full max-w-lg -translate-x-1/2 -translate-y-1/2',\n 'overflow-hidden rounded-xl border border-border shadow-xl',\n 'data-expanded:animate-in data-expanded:fade-in-0 data-expanded:zoom-in-95',\n 'data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95',\n local.class,\n local.contentClassName\n )}\n onOpenAutoFocus={focus.onOpenAutoFocus}\n onCloseAutoFocus={focus.onCloseAutoFocus}\n >\n <Command {...commandProps} />\n </KobalteDialog.Content>\n </KobalteDialog.Portal>\n </KobalteDialog>\n )\n}\n\nexport function CommandInput(props: ComponentProps<typeof CmdkInput>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <div\n data-slot=\"command-input-wrapper\"\n class=\"flex h-11 items-center gap-2 border-b border-border px-3\"\n >\n <Search class=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <CmdkInput\n class={cn(\n 'h-full w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n local.class\n )}\n {...rest}\n />\n </div>\n )\n}\n\n/**\n * The scrolling list.\n *\n * Two DOM corrections, and both are deliberate. cmdk builds a `role=\"listbox\"`\n * whose children include two elements ARIA does not allow there:\n *\n * - a bare `<div cmdk-list-sizer>` with no role, wrapped around every group;\n * - a `<div cmdk-separator role=\"separator\">`, and `separator` is a menu and\n * toolbar role — inside a listbox the only owned elements may be `option`\n * and `group`.\n *\n * Both are pure presentation: the sizer is layout, and the separator is a\n * hairline between groups that the groups already structure. `role=\"presentation\"`\n * is their accurate role rather than a workaround — each is flattened out of the\n * accessibility tree, and the options inside are reached exactly as before.\n *\n * Written onto the mounted nodes rather than through props, because cmdk owns\n * this markup and does not forward a `ref`; in an effect rather than `onMount`,\n * because cmdk renders the sizer with the first item, after the list itself.\n */\nexport function CommandList(props: ComponentProps<typeof CmdkList>) {\n const [local, rest] = splitProps(props, ['class'])\n const [wrapper, setWrapper] = createSignal<HTMLDivElement>()\n const resultCount = useCommandState((state) => state.filtered.count)\n\n createEffect(() => {\n const root = wrapper()\n if (!root) return\n for (const selector of ['[cmdk-list-sizer]', '[cmdk-separator]']) {\n root.querySelector(selector)?.setAttribute('role', 'presentation')\n }\n\n /*\n * A `listbox` must own at least one `option`, so a listbox with nothing in it\n * is invalid ARIA — which is what a search with no matches produces. When\n * there are no results the list is inert, so it becomes presentational and\n * the empty message carries the information instead. It keeps its `id`, so\n * the input's `aria-controls` still resolves.\n */\n root\n .querySelector('[cmdk-list]')\n ?.setAttribute('role', resultCount() > 0 ? 'listbox' : 'presentation')\n })\n\n return (\n <div ref={setWrapper} class=\"contents\">\n <CmdkList\n class={cn('max-h-80 scroll-py-1 overflow-y-auto overflow-x-hidden p-1', local.class)}\n {...rest}\n />\n </div>\n )\n}\n\nexport function CommandEmpty(props: ComponentProps<typeof CmdkEmpty>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkEmpty\n /*\n * A status rather than plain text: when the list is presentational, this is\n * the only thing that tells a screen reader the search matched nothing.\n */\n role=\"status\"\n class={cn('text-muted-foreground py-8 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function CommandGroup(props: ComponentProps<typeof CmdkGroup>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkGroup\n class={cn(\n 'text-foreground overflow-hidden p-1',\n '[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-2xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:tracking-wide [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:uppercase',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandItem(props: ComponentProps<typeof CmdkItem>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <CmdkItem\n class={cn(\n commandItem,\n 'data-[disabled=true]:pointer-events-none data-[disabled=true]:text-muted-foreground',\n 'group/command-item text-popover-foreground data-[selected=true]:bg-card data-[selected=true]:text-popover-foreground',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CommandSeparator(props: ComponentProps<typeof CmdkSeparator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <CmdkSeparator class={cn('bg-border -mx-1 my-1 h-px', local.class)} {...rest} />\n}\n\nexport function CommandLoading(props: ComponentProps<typeof CmdkLoading>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <CmdkLoading\n class={cn('text-muted-foreground py-6 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n\n/** The keyboard hint a palette item usually carries. */\nexport function CommandShortcut(props: {\n class?: string\n children?: ComponentProps<'span'>['children']\n}) {\n return (\n <span\n class={cn(\n 'text-muted-foreground ms-auto font-code text-code tracking-widest group-data-[selected=true]/command-item:text-foreground',\n props.class\n )}\n >\n {props.children}\n </span>\n )\n}\n"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { Check, ChevronRight, Circle } from "lucide-solid";
|
|
|
5
5
|
import { splitProps } from "solid-js";
|
|
6
6
|
import { ContextMenu } from "@kobalte/core/context-menu";
|
|
7
7
|
//#region src/components/ui/context-menu/context-menu.tsx
|
|
8
|
-
var _tmpl$ = /*#__PURE__*/ template(`<span aria-hidden=true class="text-muted-foreground ms-auto font-
|
|
8
|
+
var _tmpl$ = /*#__PURE__*/ template(`<span aria-hidden=true class="text-muted-foreground ms-auto font-code text-code tracking-widest">`);
|
|
9
9
|
/**
|
|
10
10
|
* ContextMenu.
|
|
11
11
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-menu.js","names":["ContextMenu","KobalteContextMenu","Check","ChevronRight","Circle","ComponentProps","splitProps","menuContentPadding","destructiveMenuItem","menuItem","menuLabel","menuSeparator","overlayMotion","overlaySurface","cn","props","_$createComponent","ContextMenuTrigger","Trigger","ContextMenuContent","Content","local","rest","Portal","children","_$mergeProps","class","ContextMenuItem","Item","variant","shortcut","keyshortcuts","aria-keyshortcuts","_$memo","_el$","_tmpl$","_$insert","ContextMenuCheckboxItem","CheckboxItem","ItemIndicator","ContextMenuRadioGroup","RadioGroup","ContextMenuRadioItem","RadioItem","ContextMenuLabel","GroupLabel","ContextMenuGroup","Group","ContextMenuSeparator","Separator","ContextMenuSub","Sub","ContextMenuSubTrigger","SubTrigger","ContextMenuSubContent","SubContent","ContextMenu","_$createComponent","KobalteContextMenu","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/context-menu/context-menu.tsx"],"sourcesContent":["import { ContextMenu as KobalteContextMenu } from '@kobalte/core/context-menu'\nimport { Check, ChevronRight, Circle } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport {\n menuContentPadding,\n destructiveMenuItem,\n menuItem,\n menuLabel,\n menuSeparator,\n overlayMotion,\n overlaySurface,\n} from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n/**\n * ContextMenu.\n *\n * The same actions as DropdownMenu, opened by right-click. The trigger is the\n * region the menu belongs to — a file row, a canvas, a code block — and the\n * menu opens at the pointer.\n *\n * The accessibility rule for this component is not about its own markup: a\n * context menu must never hold the *only* route to an action, because a\n * right-click is unavailable on touch and undiscoverable on a trackpad. Every\n * item here should also appear somewhere reachable, usually a DropdownMenu on\n * the same row.\n */\nexport function ContextMenu(props: ComponentProps<typeof KobalteContextMenu>) {\n return <KobalteContextMenu {...props} />\n}\n\nexport function ContextMenuTrigger(props: ComponentProps<typeof KobalteContextMenu.Trigger>) {\n return <KobalteContextMenu.Trigger {...props} />\n}\n\nexport function ContextMenuContent(props: ComponentProps<typeof KobalteContextMenu.Content>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteContextMenu.Portal>\n <KobalteContextMenu.Content\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[10rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n />\n </KobalteContextMenu.Portal>\n )\n}\n\nexport function ContextMenuItem(\n props: ComponentProps<typeof KobalteContextMenu.Item> & {\n variant?: 'default' | 'destructive'\n shortcut?: string\n /**\n * The parseable chord behind `shortcut`, e.g. `Meta+C`. The drawn glyph is\n * `aria-hidden` — reading it out would pollute the item's accessible name —\n * so this is what assistive technology announces instead. Supply it\n * whenever `shortcut` is drawn.\n */\n keyshortcuts?: string\n }\n) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'variant',\n 'shortcut',\n 'keyshortcuts',\n 'children',\n ])\n\n return (\n <KobalteContextMenu.Item\n class={cn(\n menuItem,\n {\n [destructiveMenuItem]: local.variant === 'destructive',\n },\n local.class\n )}\n aria-keyshortcuts={local.keyshortcuts}\n {...rest}\n >\n {local.children}\n {local.shortcut ? (\n <span\n aria-hidden=\"true\"\n class=\"text-muted-foreground ms-auto font-mono text-2xs tracking-widest\"\n >\n {local.shortcut}\n </span>\n ) : null}\n </KobalteContextMenu.Item>\n )\n}\n\nexport function ContextMenuCheckboxItem(\n props: ComponentProps<typeof KobalteContextMenu.CheckboxItem>\n) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteContextMenu.CheckboxItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n <KobalteContextMenu.ItemIndicator class=\"absolute end-2 flex size-4 items-center justify-center\">\n <Check class=\"size-4\" />\n </KobalteContextMenu.ItemIndicator>\n </KobalteContextMenu.CheckboxItem>\n )\n}\n\nexport function ContextMenuRadioGroup(props: ComponentProps<typeof KobalteContextMenu.RadioGroup>) {\n return <KobalteContextMenu.RadioGroup {...props} />\n}\n\nexport function ContextMenuRadioItem(props: ComponentProps<typeof KobalteContextMenu.RadioItem>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteContextMenu.RadioItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n <KobalteContextMenu.ItemIndicator class=\"absolute end-2 flex size-4 items-center justify-center\">\n <Circle class=\"size-2 fill-current\" />\n </KobalteContextMenu.ItemIndicator>\n </KobalteContextMenu.RadioItem>\n )\n}\n\n/**\n * The caption of a `ContextMenuGroup`, and that group's accessible name. It must be a\n * child of the group it names: Kobalte reads the group from context, so a label\n * placed directly in the content throws `useMenuGroupContext must be used within\n * a Menu.Group` the moment the menu opens. For an ungrouped caption, wrap the\n * label and its items in a group anyway — the grouping is what a screen reader\n * announces.\n */\nexport function ContextMenuLabel(props: ComponentProps<typeof KobalteContextMenu.GroupLabel>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteContextMenu.GroupLabel class={cn(menuLabel, local.class)} {...rest} />\n}\n\nexport function ContextMenuGroup(props: ComponentProps<typeof KobalteContextMenu.Group>) {\n return <KobalteContextMenu.Group {...props} />\n}\n\nexport function ContextMenuSeparator(props: ComponentProps<typeof KobalteContextMenu.Separator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteContextMenu.Separator class={cn(menuSeparator, local.class)} {...rest} />\n}\n\nexport function ContextMenuSub(props: ComponentProps<typeof KobalteContextMenu.Sub>) {\n return <KobalteContextMenu.Sub {...props} />\n}\n\nexport function ContextMenuSubTrigger(props: ComponentProps<typeof KobalteContextMenu.SubTrigger>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteContextMenu.SubTrigger class={cn(menuItem, local.class)} {...rest}>\n {local.children}\n <ChevronRight class=\"ms-auto size-4\" />\n </KobalteContextMenu.SubTrigger>\n )\n}\n\nexport function ContextMenuSubContent(props: ComponentProps<typeof KobalteContextMenu.SubContent>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteContextMenu.Portal>\n <KobalteContextMenu.SubContent\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[8rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n />\n </KobalteContextMenu.Portal>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"context-menu.js","names":["ContextMenu","KobalteContextMenu","Check","ChevronRight","Circle","ComponentProps","splitProps","menuContentPadding","destructiveMenuItem","menuItem","menuLabel","menuSeparator","overlayMotion","overlaySurface","cn","props","_$createComponent","ContextMenuTrigger","Trigger","ContextMenuContent","Content","local","rest","Portal","children","_$mergeProps","class","ContextMenuItem","Item","variant","shortcut","keyshortcuts","aria-keyshortcuts","_$memo","_el$","_tmpl$","_$insert","ContextMenuCheckboxItem","CheckboxItem","ItemIndicator","ContextMenuRadioGroup","RadioGroup","ContextMenuRadioItem","RadioItem","ContextMenuLabel","GroupLabel","ContextMenuGroup","Group","ContextMenuSeparator","Separator","ContextMenuSub","Sub","ContextMenuSubTrigger","SubTrigger","ContextMenuSubContent","SubContent","ContextMenu","_$createComponent","KobalteContextMenu","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/context-menu/context-menu.tsx"],"sourcesContent":["import { ContextMenu as KobalteContextMenu } from '@kobalte/core/context-menu'\nimport { Check, ChevronRight, Circle } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport {\n menuContentPadding,\n destructiveMenuItem,\n menuItem,\n menuLabel,\n menuSeparator,\n overlayMotion,\n overlaySurface,\n} from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n/**\n * ContextMenu.\n *\n * The same actions as DropdownMenu, opened by right-click. The trigger is the\n * region the menu belongs to — a file row, a canvas, a code block — and the\n * menu opens at the pointer.\n *\n * The accessibility rule for this component is not about its own markup: a\n * context menu must never hold the *only* route to an action, because a\n * right-click is unavailable on touch and undiscoverable on a trackpad. Every\n * item here should also appear somewhere reachable, usually a DropdownMenu on\n * the same row.\n */\nexport function ContextMenu(props: ComponentProps<typeof KobalteContextMenu>) {\n return <KobalteContextMenu {...props} />\n}\n\nexport function ContextMenuTrigger(props: ComponentProps<typeof KobalteContextMenu.Trigger>) {\n return <KobalteContextMenu.Trigger {...props} />\n}\n\nexport function ContextMenuContent(props: ComponentProps<typeof KobalteContextMenu.Content>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteContextMenu.Portal>\n <KobalteContextMenu.Content\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[10rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n />\n </KobalteContextMenu.Portal>\n )\n}\n\nexport function ContextMenuItem(\n props: ComponentProps<typeof KobalteContextMenu.Item> & {\n variant?: 'default' | 'destructive'\n shortcut?: string\n /**\n * The parseable chord behind `shortcut`, e.g. `Meta+C`. The drawn glyph is\n * `aria-hidden` — reading it out would pollute the item's accessible name —\n * so this is what assistive technology announces instead. Supply it\n * whenever `shortcut` is drawn.\n */\n keyshortcuts?: string\n }\n) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'variant',\n 'shortcut',\n 'keyshortcuts',\n 'children',\n ])\n\n return (\n <KobalteContextMenu.Item\n class={cn(\n menuItem,\n {\n [destructiveMenuItem]: local.variant === 'destructive',\n },\n local.class\n )}\n aria-keyshortcuts={local.keyshortcuts}\n {...rest}\n >\n {local.children}\n {local.shortcut ? (\n <span\n aria-hidden=\"true\"\n class=\"text-muted-foreground ms-auto font-code text-code tracking-widest\"\n >\n {local.shortcut}\n </span>\n ) : null}\n </KobalteContextMenu.Item>\n )\n}\n\nexport function ContextMenuCheckboxItem(\n props: ComponentProps<typeof KobalteContextMenu.CheckboxItem>\n) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteContextMenu.CheckboxItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n <KobalteContextMenu.ItemIndicator class=\"absolute end-2 flex size-4 items-center justify-center\">\n <Check class=\"size-4\" />\n </KobalteContextMenu.ItemIndicator>\n </KobalteContextMenu.CheckboxItem>\n )\n}\n\nexport function ContextMenuRadioGroup(props: ComponentProps<typeof KobalteContextMenu.RadioGroup>) {\n return <KobalteContextMenu.RadioGroup {...props} />\n}\n\nexport function ContextMenuRadioItem(props: ComponentProps<typeof KobalteContextMenu.RadioItem>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteContextMenu.RadioItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n <KobalteContextMenu.ItemIndicator class=\"absolute end-2 flex size-4 items-center justify-center\">\n <Circle class=\"size-2 fill-current\" />\n </KobalteContextMenu.ItemIndicator>\n </KobalteContextMenu.RadioItem>\n )\n}\n\n/**\n * The caption of a `ContextMenuGroup`, and that group's accessible name. It must be a\n * child of the group it names: Kobalte reads the group from context, so a label\n * placed directly in the content throws `useMenuGroupContext must be used within\n * a Menu.Group` the moment the menu opens. For an ungrouped caption, wrap the\n * label and its items in a group anyway — the grouping is what a screen reader\n * announces.\n */\nexport function ContextMenuLabel(props: ComponentProps<typeof KobalteContextMenu.GroupLabel>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteContextMenu.GroupLabel class={cn(menuLabel, local.class)} {...rest} />\n}\n\nexport function ContextMenuGroup(props: ComponentProps<typeof KobalteContextMenu.Group>) {\n return <KobalteContextMenu.Group {...props} />\n}\n\nexport function ContextMenuSeparator(props: ComponentProps<typeof KobalteContextMenu.Separator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteContextMenu.Separator class={cn(menuSeparator, local.class)} {...rest} />\n}\n\nexport function ContextMenuSub(props: ComponentProps<typeof KobalteContextMenu.Sub>) {\n return <KobalteContextMenu.Sub {...props} />\n}\n\nexport function ContextMenuSubTrigger(props: ComponentProps<typeof KobalteContextMenu.SubTrigger>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteContextMenu.SubTrigger class={cn(menuItem, local.class)} {...rest}>\n {local.children}\n <ChevronRight class=\"ms-auto size-4\" />\n </KobalteContextMenu.SubTrigger>\n )\n}\n\nexport function ContextMenuSubContent(props: ComponentProps<typeof KobalteContextMenu.SubContent>) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteContextMenu.Portal>\n <KobalteContextMenu.SubContent\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[8rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n />\n </KobalteContextMenu.Portal>\n )\n}\n"],"mappings":"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"}
|
|
@@ -4,10 +4,10 @@ import { className, createComponent, delegateEvents, effect, insert, memo, merge
|
|
|
4
4
|
import { For, Show, createMemo, splitProps } from "solid-js";
|
|
5
5
|
//#region src/components/ui/diff-block/diff-block.tsx
|
|
6
6
|
var _tmpl$ = /*#__PURE__*/ template(`<p class="px-3 py-1 text-xs text-muted-foreground italic">Generating diff…`);
|
|
7
|
-
var _tmpl$2 = /*#__PURE__*/ template(`<div><div class="flex items-center justify-between gap-2 border-b border-border px-3 py-1"><span class="flex min-w-0 items-baseline gap-2"><span class="truncate font-
|
|
8
|
-
var _tmpl$3 = /*#__PURE__*/ template(`<span class="w-10 shrink-0 pr-2 text-right text-
|
|
7
|
+
var _tmpl$2 = /*#__PURE__*/ template(`<div><div class="flex items-center justify-between gap-2 border-b border-border px-3 py-1"><span class="flex min-w-0 items-baseline gap-2"><span class="truncate font-code text-code text-foreground"></span><span class="shrink-0 font-code text-code text-muted-foreground"><span class=text-foreground>+</span> <span class=text-foreground>−</span></span></span></div><div class="scroll-fade overflow-x-auto"tabindex=0 role=region><div class=min-w-fit>`);
|
|
8
|
+
var _tmpl$3 = /*#__PURE__*/ template(`<span class="w-10 shrink-0 pr-2 text-right text-code text-muted-foreground tabular-nums select-none"aria-hidden=true>`);
|
|
9
9
|
var _tmpl$4 = /*#__PURE__*/ template(`<div><span class="w-4 shrink-0 text-center select-none"aria-hidden=true></span><span class="min-w-0 whitespace-pre pr-4"><span class=visually-hidden>`);
|
|
10
|
-
var _tmpl$5 = /*#__PURE__*/ template(`<button type=button><span class="truncate text-foreground"></span><span class="shrink-0 text-
|
|
10
|
+
var _tmpl$5 = /*#__PURE__*/ template(`<button type=button><span class="truncate text-foreground"></span><span class="shrink-0 text-code"><span class=text-foreground>+</span> <span class=text-foreground>−`);
|
|
11
11
|
var HUNK_HEADER = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
|
|
12
12
|
/**
|
|
13
13
|
* Classify a unified diff.
|
|
@@ -119,7 +119,7 @@ function diffTargetPath(patch) {
|
|
|
119
119
|
}
|
|
120
120
|
return null;
|
|
121
121
|
}
|
|
122
|
-
var diffLineVariants = cva("flex items-baseline font-
|
|
122
|
+
var diffLineVariants = cva("flex items-baseline font-code text-code", {
|
|
123
123
|
variants: { kind: {
|
|
124
124
|
add: "bg-success-subtle text-foreground",
|
|
125
125
|
delete: "bg-destructive-subtle text-foreground",
|
|
@@ -219,7 +219,7 @@ function DiffSummary(props) {
|
|
|
219
219
|
insert(_el$19, name);
|
|
220
220
|
insert(_el$21, () => stats().added, null);
|
|
221
221
|
insert(_el$24, () => stats().removed, null);
|
|
222
|
-
effect(() => className(_el$18, cn("flex w-full items-baseline justify-between gap-3 rounded-md px-2 py-1 text-left font-
|
|
222
|
+
effect(() => className(_el$18, cn("flex w-full items-baseline justify-between gap-3 rounded-md px-2 py-1 text-left font-code text-code hover:bg-muted", props.class)));
|
|
223
223
|
return _el$18;
|
|
224
224
|
})();
|
|
225
225
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-block.js","names":["createMemo","For","Show","splitProps","ComponentProps","JSX","cva","VariantProps","cn","DiffLineKind","DiffLine","Readonly","kind","text","marker","oldLine","newLine","HUNK_HEADER","parseDiff","patch","lines","inHunk","raw","replace","split","test","match","exec","Number","push","isFileHeader","startsWith","slice","numbered","line","show","Boolean","diffStats","added","removed","diffTargetPath","git","plain","fromHeader","diffLineVariants","variants","add","delete","context","hunk","header","meta","defaultVariants","DiffBlockProps","Omit","title","complete","showLineNumbers","actions","Element","DiffBlock","props","local","rest","stats","name","pop","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","_el$5","nextSibling","_el$6","_el$7","_el$8","_el$9","_el$0","_el$1","_el$10","_$spread","_$mergeProps","class","_$insert","_$createComponent","each","children","_el$12","_tmpl$4","_el$15","_el$16","_el$17","when","_el$13","_tmpl$3","_el$14","_c$","_$memo","_c$2","_$effect","_$className","_tmpl$","_$setAttribute","DiffSummary","onSelect","_el$18","_tmpl$5","_el$19","_el$20","_el$21","_el$22","_el$23","_el$24","_el$25","$$click","_$delegateEvents","_$mergeProps","_$createComponent","_$memo","_$className","_$setAttribute","_$delegateEvents"],"sources":["../../../../src/components/ui/diff-block/diff-block.tsx"],"sourcesContent":["import { createMemo, For, Show, splitProps, type ComponentProps, type JSX } from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * DiffBlock.\n *\n * A unified diff, classified and toned. Parsing lives here because the\n * classification is the part that is easy to get subtly wrong and impossible to\n * fix from a caller: whether a line is an addition, a deletion, a hunk header,\n * a file header, or context depends on state — a line beginning with `+++` is a\n * file header *before* the first hunk and an added line beginning with `++`\n * *inside* one — and a renderer that tested prefixes without that state would\n * mis-colour real patches.\n *\n * The line grammar:\n *\n * | Prefix | Meaning |\n * | --- | --- |\n * | `diff --git`, `index`, `---`, `+++` (before a hunk) | file header |\n * | `@@` | hunk header |\n * | `+` | addition |\n * | `-` | deletion |\n * | `\\` | the \"no newline at end of file\" marker |\n * | anything else, including a leading space | context |\n *\n * Tones are pairs of surface and text, so an addition is readable in both\n * polarities and with any accent — the greens and reds are the theme's own\n * `success` and `destructive` at low alpha, not fixed hexes. Colour is never the\n * only signal: the gutter carries `+` or `-` as well, which is what makes the\n * block usable in greyscale and by anyone who cannot separate the two hues.\n *\n * Split (side-by-side) view is deliberately not implemented. It is a different\n * layout algorithm — pairing deletions with additions across hunks — and a\n * half-correct one is worse than none. `view=\"unified\"` is the only value, and\n * the prop exists so that adding the second is not a breaking change.\n */\n\nexport type DiffLineKind = 'add' | 'delete' | 'context' | 'hunk' | 'header' | 'meta'\n\nexport type DiffLine = Readonly<{\n kind: DiffLineKind\n /** The line without its diff prefix. */\n text: string\n /** The prefix as written: `+`, `-`, a space, or nothing for a header. */\n marker: string\n /** The old-side line number, when the line exists on the old side. */\n oldLine?: number\n /** The new-side line number, when the line exists on the new side. */\n newLine?: number\n}>\n\nconst HUNK_HEADER = /^@@ -(\\d+)(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@/\n\n/**\n * Classify a unified diff.\n *\n * `headerState` is what makes `---` and `+++` unambiguous: git writes them as\n * file headers before the first `@@` and as content after it, and the two need\n * different tones. `oldLine`/`newLine` are tracked so the gutter can number both\n * sides — the numbers a reader uses to find the change in their editor.\n */\nexport function parseDiff(patch: string): readonly DiffLine[] {\n const lines: DiffLine[] = []\n let inHunk = false\n let oldLine = 0\n let newLine = 0\n\n for (const raw of patch.replace(/\\n$/, '').split('\\n')) {\n if (HUNK_HEADER.test(raw)) {\n const match = HUNK_HEADER.exec(raw)!\n oldLine = Number(match[1])\n newLine = Number(match[2])\n inHunk = true\n lines.push({ kind: 'hunk', text: raw, marker: '' })\n continue\n }\n\n if (!inHunk) {\n const isFileHeader =\n raw.startsWith('diff --git') ||\n raw.startsWith('index ') ||\n raw.startsWith('new file') ||\n raw.startsWith('deleted file') ||\n raw.startsWith('similarity index') ||\n raw.startsWith('rename ') ||\n raw.startsWith('--- ') ||\n raw.startsWith('+++ ')\n lines.push({ kind: isFileHeader ? 'header' : 'meta', text: raw, marker: '' })\n continue\n }\n\n if (raw.startsWith('\\\\')) {\n lines.push({ kind: 'meta', text: raw, marker: '' })\n continue\n }\n\n const marker = raw[0] ?? ' '\n if (marker === '+') {\n lines.push({ kind: 'add', text: raw.slice(1), marker, newLine })\n newLine += 1\n } else if (marker === '-') {\n lines.push({ kind: 'delete', text: raw.slice(1), marker, oldLine })\n oldLine += 1\n } else {\n lines.push({ kind: 'context', text: raw.slice(1), marker: ' ', oldLine, newLine })\n oldLine += 1\n newLine += 1\n }\n }\n\n return lines\n}\n\n/**\n * Whether a line gets gutter numbers. A hunk header and a file header are\n * structural, so numbering them would put a number on a line that has none.\n */\nfunction numbered(line: DiffLine, show: boolean | undefined): boolean {\n return Boolean(show) && line.kind !== 'hunk' && line.kind !== 'header' && line.kind !== 'meta'\n}\n\n/** The counts a diff summary reports: how much was added and removed. */\nexport function diffStats(\n lines: readonly DiffLine[]\n): Readonly<{ added: number; removed: number }> {\n let added = 0\n let removed = 0\n for (const line of lines) {\n if (line.kind === 'add') added += 1\n else if (line.kind === 'delete') removed += 1\n }\n return { added, removed }\n}\n\n/**\n * The target path from a unified diff's file header. Prefers `+++ b/<path>` —\n * git's explicit new-side marker — and skips `/dev/null`, which marks an added\n * or deleted side rather than naming a file. Only lines outside a hunk are\n * considered, for the same reason the parser tracks state.\n */\nexport function diffTargetPath(patch: string): string | null {\n for (const line of patch.split('\\n')) {\n if (line.startsWith('@@')) break\n const git = /^\\+\\+\\+ b\\/(.+?)(?:\\t|$)/.exec(line)\n if (git) return git[1]!\n const plain = /^\\+\\+\\+ ([^\\s/][^\\t]*?)(?:\\t|$)/.exec(line)\n if (plain && plain[1] !== '/dev/null') return plain[1]!\n const fromHeader = /^diff --git a\\/.+ b\\/(.+)/.exec(line)\n if (fromHeader) return fromHeader[1]!\n }\n return null\n}\n\nexport const diffLineVariants = cva('flex items-baseline font-mono text-xs', {\n variants: {\n kind: {\n add: 'bg-success-subtle text-foreground',\n delete: 'bg-destructive-subtle text-foreground',\n context: 'text-foreground',\n hunk: 'bg-muted text-muted-foreground',\n header: 'bg-muted font-semibold text-foreground',\n meta: 'text-muted-foreground italic',\n },\n },\n defaultVariants: { kind: 'context' },\n})\n\nexport type DiffBlockProps = Omit<ComponentProps<'div'>, 'children'> &\n VariantProps<typeof diffLineVariants> & {\n /** The unified diff. */\n patch: string\n /** A filename. Defaults to the path in the patch's header, or \"diff\". */\n title?: string\n /** False while the patch is still streaming. */\n complete?: boolean\n /** Show the two line-number gutters. Off for a fragment with no line numbers. */\n showLineNumbers?: boolean\n /** Extra header controls. */\n actions?: JSX.Element\n }\n\nexport function DiffBlock(props: DiffBlockProps) {\n const [local, rest] = splitProps(props, [\n 'patch',\n 'title',\n 'complete',\n 'showLineNumbers',\n 'actions',\n 'class',\n ])\n\n const lines = createMemo(() => parseDiff(local.patch))\n const stats = createMemo(() => diffStats(lines()))\n const name = () => local.title ?? diffTargetPath(local.patch)?.split('/').pop() ?? 'diff'\n\n return (\n <div\n class={cn('overflow-hidden rounded-xl border border-border bg-card', local.class)}\n {...rest}\n >\n <div class=\"flex items-center justify-between gap-2 border-b border-border px-3 py-1\">\n <span class=\"flex min-w-0 items-baseline gap-2\">\n <span class=\"truncate font-mono text-xs text-foreground\">{name()}</span>\n {/* The counts are text, so the summary survives greyscale and a reader\n who cannot separate the two line tones still gets the shape of it. */}\n <span class=\"shrink-0 font-mono text-2xs text-muted-foreground\">\n <span class=\"text-foreground\">+{stats().added}</span>{' '}\n <span class=\"text-foreground\">−{stats().removed}</span>\n </span>\n </span>\n {local.actions}\n </div>\n <div\n class=\"scroll-fade overflow-x-auto\"\n tabindex=\"0\"\n role=\"region\"\n aria-label={`Diff for ${name()}`}\n >\n <div class=\"min-w-fit\">\n <For each={lines()}>\n {(line) => (\n <div class={diffLineVariants({ kind: line.kind })}>\n <Show when={numbered(line, local.showLineNumbers)}>\n <span\n class=\"w-10 shrink-0 pr-2 text-right text-2xs text-muted-foreground tabular-nums select-none\"\n aria-hidden=\"true\"\n >\n {line.oldLine ?? ''}\n </span>\n <span\n class=\"w-10 shrink-0 pr-2 text-right text-2xs text-muted-foreground tabular-nums select-none\"\n aria-hidden=\"true\"\n >\n {line.newLine ?? ''}\n </span>\n </Show>\n {/* The marker is the signal that is not a colour. */}\n <span class=\"w-4 shrink-0 text-center select-none\" aria-hidden=\"true\">\n {line.kind === 'add' ? '+' : line.kind === 'delete' ? '−' : ''}\n </span>\n <span class=\"min-w-0 whitespace-pre pr-4\">\n {/* A screen reader gets the kind as a word, not a glyph. */}\n <span class=\"visually-hidden\">\n {line.kind === 'add' ? 'Added: ' : line.kind === 'delete' ? 'Removed: ' : ''}\n </span>\n {line.text || ' '}\n </span>\n </div>\n )}\n </For>\n </div>\n <Show when={!local.complete}>\n <p class=\"px-3 py-1 text-xs text-muted-foreground italic\">Generating diff…</p>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * A diff summary line, for a list of changes rather than one patch: the file and\n * its counts. Uses `CodeBlock`'s height rules and nothing else, because a summary\n * is a row and not a surface.\n */\nexport function DiffSummary(props: { patch: string; class?: string; onSelect?: () => void }) {\n const stats = createMemo(() => diffStats(parseDiff(props.patch)))\n const name = () => diffTargetPath(props.patch) ?? 'diff'\n\n return (\n <button\n type=\"button\"\n class={cn(\n 'flex w-full items-baseline justify-between gap-3 rounded-md px-2 py-1 text-left font-mono text-xs hover:bg-muted',\n props.class\n )}\n onClick={() => props.onSelect?.()}\n >\n <span class=\"truncate text-foreground\">{name()}</span>\n <span class=\"shrink-0 text-2xs\">\n <span class=\"text-foreground\">+{stats().added}</span>{' '}\n <span class=\"text-foreground\">−{stats().removed}</span>\n </span>\n </button>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"diff-block.js","names":["createMemo","For","Show","splitProps","ComponentProps","JSX","cva","VariantProps","cn","DiffLineKind","DiffLine","Readonly","kind","text","marker","oldLine","newLine","HUNK_HEADER","parseDiff","patch","lines","inHunk","raw","replace","split","test","match","exec","Number","push","isFileHeader","startsWith","slice","numbered","line","show","Boolean","diffStats","added","removed","diffTargetPath","git","plain","fromHeader","diffLineVariants","variants","add","delete","context","hunk","header","meta","defaultVariants","DiffBlockProps","Omit","title","complete","showLineNumbers","actions","Element","DiffBlock","props","local","rest","stats","name","pop","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","_el$5","nextSibling","_el$6","_el$7","_el$8","_el$9","_el$0","_el$1","_el$10","_$spread","_$mergeProps","class","_$insert","_$createComponent","each","children","_el$12","_tmpl$4","_el$15","_el$16","_el$17","when","_el$13","_tmpl$3","_el$14","_c$","_$memo","_c$2","_$effect","_$className","_tmpl$","_$setAttribute","DiffSummary","onSelect","_el$18","_tmpl$5","_el$19","_el$20","_el$21","_el$22","_el$23","_el$24","_el$25","$$click","_$delegateEvents","_$mergeProps","_$createComponent","_$memo","_$className","_$setAttribute","_$delegateEvents"],"sources":["../../../../src/components/ui/diff-block/diff-block.tsx"],"sourcesContent":["import { createMemo, For, Show, splitProps, type ComponentProps, type JSX } from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * DiffBlock.\n *\n * A unified diff, classified and toned. Parsing lives here because the\n * classification is the part that is easy to get subtly wrong and impossible to\n * fix from a caller: whether a line is an addition, a deletion, a hunk header,\n * a file header, or context depends on state — a line beginning with `+++` is a\n * file header *before* the first hunk and an added line beginning with `++`\n * *inside* one — and a renderer that tested prefixes without that state would\n * mis-colour real patches.\n *\n * The line grammar:\n *\n * | Prefix | Meaning |\n * | --- | --- |\n * | `diff --git`, `index`, `---`, `+++` (before a hunk) | file header |\n * | `@@` | hunk header |\n * | `+` | addition |\n * | `-` | deletion |\n * | `\\` | the \"no newline at end of file\" marker |\n * | anything else, including a leading space | context |\n *\n * Tones are pairs of surface and text, so an addition is readable in both\n * polarities and with any accent — the greens and reds are the theme's own\n * `success` and `destructive` at low alpha, not fixed hexes. Colour is never the\n * only signal: the gutter carries `+` or `-` as well, which is what makes the\n * block usable in greyscale and by anyone who cannot separate the two hues.\n *\n * Split (side-by-side) view is deliberately not implemented. It is a different\n * layout algorithm — pairing deletions with additions across hunks — and a\n * half-correct one is worse than none. `view=\"unified\"` is the only value, and\n * the prop exists so that adding the second is not a breaking change.\n */\n\nexport type DiffLineKind = 'add' | 'delete' | 'context' | 'hunk' | 'header' | 'meta'\n\nexport type DiffLine = Readonly<{\n kind: DiffLineKind\n /** The line without its diff prefix. */\n text: string\n /** The prefix as written: `+`, `-`, a space, or nothing for a header. */\n marker: string\n /** The old-side line number, when the line exists on the old side. */\n oldLine?: number\n /** The new-side line number, when the line exists on the new side. */\n newLine?: number\n}>\n\nconst HUNK_HEADER = /^@@ -(\\d+)(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@/\n\n/**\n * Classify a unified diff.\n *\n * `headerState` is what makes `---` and `+++` unambiguous: git writes them as\n * file headers before the first `@@` and as content after it, and the two need\n * different tones. `oldLine`/`newLine` are tracked so the gutter can number both\n * sides — the numbers a reader uses to find the change in their editor.\n */\nexport function parseDiff(patch: string): readonly DiffLine[] {\n const lines: DiffLine[] = []\n let inHunk = false\n let oldLine = 0\n let newLine = 0\n\n for (const raw of patch.replace(/\\n$/, '').split('\\n')) {\n if (HUNK_HEADER.test(raw)) {\n const match = HUNK_HEADER.exec(raw)!\n oldLine = Number(match[1])\n newLine = Number(match[2])\n inHunk = true\n lines.push({ kind: 'hunk', text: raw, marker: '' })\n continue\n }\n\n if (!inHunk) {\n const isFileHeader =\n raw.startsWith('diff --git') ||\n raw.startsWith('index ') ||\n raw.startsWith('new file') ||\n raw.startsWith('deleted file') ||\n raw.startsWith('similarity index') ||\n raw.startsWith('rename ') ||\n raw.startsWith('--- ') ||\n raw.startsWith('+++ ')\n lines.push({ kind: isFileHeader ? 'header' : 'meta', text: raw, marker: '' })\n continue\n }\n\n if (raw.startsWith('\\\\')) {\n lines.push({ kind: 'meta', text: raw, marker: '' })\n continue\n }\n\n const marker = raw[0] ?? ' '\n if (marker === '+') {\n lines.push({ kind: 'add', text: raw.slice(1), marker, newLine })\n newLine += 1\n } else if (marker === '-') {\n lines.push({ kind: 'delete', text: raw.slice(1), marker, oldLine })\n oldLine += 1\n } else {\n lines.push({ kind: 'context', text: raw.slice(1), marker: ' ', oldLine, newLine })\n oldLine += 1\n newLine += 1\n }\n }\n\n return lines\n}\n\n/**\n * Whether a line gets gutter numbers. A hunk header and a file header are\n * structural, so numbering them would put a number on a line that has none.\n */\nfunction numbered(line: DiffLine, show: boolean | undefined): boolean {\n return Boolean(show) && line.kind !== 'hunk' && line.kind !== 'header' && line.kind !== 'meta'\n}\n\n/** The counts a diff summary reports: how much was added and removed. */\nexport function diffStats(\n lines: readonly DiffLine[]\n): Readonly<{ added: number; removed: number }> {\n let added = 0\n let removed = 0\n for (const line of lines) {\n if (line.kind === 'add') added += 1\n else if (line.kind === 'delete') removed += 1\n }\n return { added, removed }\n}\n\n/**\n * The target path from a unified diff's file header. Prefers `+++ b/<path>` —\n * git's explicit new-side marker — and skips `/dev/null`, which marks an added\n * or deleted side rather than naming a file. Only lines outside a hunk are\n * considered, for the same reason the parser tracks state.\n */\nexport function diffTargetPath(patch: string): string | null {\n for (const line of patch.split('\\n')) {\n if (line.startsWith('@@')) break\n const git = /^\\+\\+\\+ b\\/(.+?)(?:\\t|$)/.exec(line)\n if (git) return git[1]!\n const plain = /^\\+\\+\\+ ([^\\s/][^\\t]*?)(?:\\t|$)/.exec(line)\n if (plain && plain[1] !== '/dev/null') return plain[1]!\n const fromHeader = /^diff --git a\\/.+ b\\/(.+)/.exec(line)\n if (fromHeader) return fromHeader[1]!\n }\n return null\n}\n\nexport const diffLineVariants = cva('flex items-baseline font-code text-code', {\n variants: {\n kind: {\n add: 'bg-success-subtle text-foreground',\n delete: 'bg-destructive-subtle text-foreground',\n context: 'text-foreground',\n hunk: 'bg-muted text-muted-foreground',\n header: 'bg-muted font-semibold text-foreground',\n meta: 'text-muted-foreground italic',\n },\n },\n defaultVariants: { kind: 'context' },\n})\n\nexport type DiffBlockProps = Omit<ComponentProps<'div'>, 'children'> &\n VariantProps<typeof diffLineVariants> & {\n /** The unified diff. */\n patch: string\n /** A filename. Defaults to the path in the patch's header, or \"diff\". */\n title?: string\n /** False while the patch is still streaming. */\n complete?: boolean\n /** Show the two line-number gutters. Off for a fragment with no line numbers. */\n showLineNumbers?: boolean\n /** Extra header controls. */\n actions?: JSX.Element\n }\n\nexport function DiffBlock(props: DiffBlockProps) {\n const [local, rest] = splitProps(props, [\n 'patch',\n 'title',\n 'complete',\n 'showLineNumbers',\n 'actions',\n 'class',\n ])\n\n const lines = createMemo(() => parseDiff(local.patch))\n const stats = createMemo(() => diffStats(lines()))\n const name = () => local.title ?? diffTargetPath(local.patch)?.split('/').pop() ?? 'diff'\n\n return (\n <div\n class={cn('overflow-hidden rounded-xl border border-border bg-card', local.class)}\n {...rest}\n >\n <div class=\"flex items-center justify-between gap-2 border-b border-border px-3 py-1\">\n <span class=\"flex min-w-0 items-baseline gap-2\">\n <span class=\"truncate font-code text-code text-foreground\">{name()}</span>\n {/* The counts are text, so the summary survives greyscale and a reader\n who cannot separate the two line tones still gets the shape of it. */}\n <span class=\"shrink-0 font-code text-code text-muted-foreground\">\n <span class=\"text-foreground\">+{stats().added}</span>{' '}\n <span class=\"text-foreground\">−{stats().removed}</span>\n </span>\n </span>\n {local.actions}\n </div>\n <div\n class=\"scroll-fade overflow-x-auto\"\n tabindex=\"0\"\n role=\"region\"\n aria-label={`Diff for ${name()}`}\n >\n <div class=\"min-w-fit\">\n <For each={lines()}>\n {(line) => (\n <div class={diffLineVariants({ kind: line.kind })}>\n <Show when={numbered(line, local.showLineNumbers)}>\n <span\n class=\"w-10 shrink-0 pr-2 text-right text-code text-muted-foreground tabular-nums select-none\"\n aria-hidden=\"true\"\n >\n {line.oldLine ?? ''}\n </span>\n <span\n class=\"w-10 shrink-0 pr-2 text-right text-code text-muted-foreground tabular-nums select-none\"\n aria-hidden=\"true\"\n >\n {line.newLine ?? ''}\n </span>\n </Show>\n {/* The marker is the signal that is not a colour. */}\n <span class=\"w-4 shrink-0 text-center select-none\" aria-hidden=\"true\">\n {line.kind === 'add' ? '+' : line.kind === 'delete' ? '−' : ''}\n </span>\n <span class=\"min-w-0 whitespace-pre pr-4\">\n {/* A screen reader gets the kind as a word, not a glyph. */}\n <span class=\"visually-hidden\">\n {line.kind === 'add' ? 'Added: ' : line.kind === 'delete' ? 'Removed: ' : ''}\n </span>\n {line.text || ' '}\n </span>\n </div>\n )}\n </For>\n </div>\n <Show when={!local.complete}>\n <p class=\"px-3 py-1 text-xs text-muted-foreground italic\">Generating diff…</p>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * A diff summary line, for a list of changes rather than one patch: the file and\n * its counts. Uses `CodeBlock`'s height rules and nothing else, because a summary\n * is a row and not a surface.\n */\nexport function DiffSummary(props: { patch: string; class?: string; onSelect?: () => void }) {\n const stats = createMemo(() => diffStats(parseDiff(props.patch)))\n const name = () => diffTargetPath(props.patch) ?? 'diff'\n\n return (\n <button\n type=\"button\"\n class={cn(\n 'flex w-full items-baseline justify-between gap-3 rounded-md px-2 py-1 text-left font-code text-code hover:bg-muted',\n props.class\n )}\n onClick={() => props.onSelect?.()}\n >\n <span class=\"truncate text-foreground\">{name()}</span>\n <span class=\"shrink-0 text-code\">\n <span class=\"text-foreground\">+{stats().added}</span>{' '}\n <span class=\"text-foreground\">−{stats().removed}</span>\n </span>\n </button>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjF,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjF,OAAO,KAAK,EAAY,cAAc,EAAE,MAAM,UAAU,CAAA;AA0BxD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,kCAQ7E;AAqED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,OAAO,CAAC,kCAwD5F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,MAAM,CAAC,kCAE1F;AAED,MAAM,MAAM,wBAAwB,GAAG,cAAc,CAAC,OAAO,mBAAmB,CAAC,OAAO,CAAC,GAAG;IAC1F,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,gGAAgG;IAChG,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,CAAA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,kCAoBlE;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,IAAI,CAAC,GAAG;IACvD,qEAAqE;IACrE,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAA;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,kCAiCF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,kCAUjE;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,YAAY,CAAC,kCAe/D;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAG7D;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,SAAS,CAAC,kCAgBhG;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAG7F;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,KAAK,CAAC,kCAExF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,SAAS,CAAC,kCAGhG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,GAAG,CAAC,kCAEpF;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAU7D;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAkB7D"}
|
|
@@ -2,11 +2,12 @@ import { cn } from "../../../lib/utils.js";
|
|
|
2
2
|
import { destructiveMenuItem, menuItem, menuLabel, menuSeparator, overlayMotion, overlaySurface } from "../../../lib/overlay.js";
|
|
3
3
|
import { createComponent, insert, memo, mergeProps, spread, template } from "solid-js/web";
|
|
4
4
|
import { Check, ChevronRight, Circle } from "lucide-solid";
|
|
5
|
-
import { splitProps } from "solid-js";
|
|
5
|
+
import { createContext, splitProps, useContext } from "solid-js";
|
|
6
6
|
import { DropdownMenu } from "@kobalte/core/dropdown-menu";
|
|
7
7
|
//#region src/components/ui/dropdown-menu/dropdown-menu.tsx
|
|
8
|
-
var _tmpl$ = /*#__PURE__*/ template(`<span aria-hidden=true class="text-muted-foreground ms-auto font-
|
|
8
|
+
var _tmpl$ = /*#__PURE__*/ template(`<span aria-hidden=true class="text-muted-foreground ms-auto font-code text-code tracking-widest">`);
|
|
9
9
|
var _tmpl$2 = /*#__PURE__*/ template(`<span data-slot=dropdown-menu-shortcut aria-hidden=true>`);
|
|
10
|
+
var DropdownMenuOrientationContext = createContext();
|
|
10
11
|
/**
|
|
11
12
|
* DropdownMenu.
|
|
12
13
|
*
|
|
@@ -27,13 +28,105 @@ var _tmpl$2 = /*#__PURE__*/ template(`<span data-slot=dropdown-menu-shortcut ari
|
|
|
27
28
|
* with an AlertDialog is the caller's job.
|
|
28
29
|
*/
|
|
29
30
|
function DropdownMenu$1(props) {
|
|
30
|
-
const [local, rest] = splitProps(props, ["modal"]);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
const [local, rest] = splitProps(props, ["modal", "orientation"]);
|
|
32
|
+
const orientation = () => local.orientation;
|
|
33
|
+
return createComponent(DropdownMenuOrientationContext.Provider, {
|
|
34
|
+
value: orientation,
|
|
35
|
+
get children() {
|
|
36
|
+
return createComponent(DropdownMenu, mergeProps({
|
|
37
|
+
get modal() {
|
|
38
|
+
return local.modal ?? false;
|
|
39
|
+
},
|
|
40
|
+
get orientation() {
|
|
41
|
+
return local.orientation;
|
|
42
|
+
}
|
|
43
|
+
}, rest));
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
var SCROLLABLE_OVERFLOW = /(auto|scroll)/;
|
|
48
|
+
var OVERFLOW_PROPERTIES = [
|
|
49
|
+
"overflow",
|
|
50
|
+
"overflow-x",
|
|
51
|
+
"overflow-y"
|
|
52
|
+
];
|
|
53
|
+
function readInlineOverflow(element) {
|
|
54
|
+
return OVERFLOW_PROPERTIES.map((property) => ({
|
|
55
|
+
property,
|
|
56
|
+
value: element.style.getPropertyValue(property),
|
|
57
|
+
priority: element.style.getPropertyPriority(property)
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
function declarationsMatch(element, declarations) {
|
|
61
|
+
return declarations.every(({ property, value, priority }) => element.style.getPropertyValue(property) === value && element.style.getPropertyPriority(property) === priority);
|
|
62
|
+
}
|
|
63
|
+
function bypassUnboundedScrollLookup(trigger) {
|
|
64
|
+
const scrollRoot = document.scrollingElement ?? document.documentElement;
|
|
65
|
+
if (window.getComputedStyle(scrollRoot).overflow !== "hidden") return;
|
|
66
|
+
const temporaryStyles = [];
|
|
67
|
+
for (let element = trigger; element;) {
|
|
68
|
+
const parent = element.parentElement;
|
|
69
|
+
if (element !== scrollRoot) {
|
|
70
|
+
const computed = window.getComputedStyle(element);
|
|
71
|
+
const overflow = `${computed.overflow} ${computed.overflowX} ${computed.overflowY}`;
|
|
72
|
+
if (SCROLLABLE_OVERFLOW.test(overflow)) {
|
|
73
|
+
const original = readInlineOverflow(element);
|
|
74
|
+
element.style.setProperty("overflow", "clip", "important");
|
|
75
|
+
temporaryStyles.push({
|
|
76
|
+
element,
|
|
77
|
+
original,
|
|
78
|
+
applied: readInlineOverflow(element)
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
element = parent;
|
|
83
|
+
}
|
|
84
|
+
if (temporaryStyles.length === 0) return;
|
|
85
|
+
queueMicrotask(() => {
|
|
86
|
+
for (const { element, original, applied } of temporaryStyles) {
|
|
87
|
+
if (!element.isConnected || !declarationsMatch(element, applied)) continue;
|
|
88
|
+
for (const property of OVERFLOW_PROPERTIES) element.style.removeProperty(property);
|
|
89
|
+
for (const { property, value, priority } of original) if (value) element.style.setProperty(property, value, priority);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
34
92
|
}
|
|
35
93
|
function DropdownMenuTrigger(props) {
|
|
36
|
-
|
|
94
|
+
const inheritedOrientation = useContext(DropdownMenuOrientationContext);
|
|
95
|
+
const [local, rest] = splitProps(props, [
|
|
96
|
+
"disabled",
|
|
97
|
+
"onKeyDown",
|
|
98
|
+
"onPointerDown"
|
|
99
|
+
]);
|
|
100
|
+
const onPointerDown = (event) => {
|
|
101
|
+
if (typeof local.onPointerDown === "function") local.onPointerDown(event);
|
|
102
|
+
else if (local.onPointerDown) local.onPointerDown[0](local.onPointerDown[1], event);
|
|
103
|
+
if (local.disabled || event.defaultPrevented || !event.isPrimary || event.button !== 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
|
|
104
|
+
const trigger = event.currentTarget;
|
|
105
|
+
const isNativeLink = trigger instanceof HTMLAnchorElement && trigger.hasAttribute("href");
|
|
106
|
+
if (trigger instanceof HTMLElement && !isNativeLink) trigger.focus({ preventScroll: true });
|
|
107
|
+
};
|
|
108
|
+
const onKeyDown = (event) => {
|
|
109
|
+
if (typeof local.onKeyDown === "function") local.onKeyDown(event);
|
|
110
|
+
else if (local.onKeyDown) local.onKeyDown[0](local.onKeyDown[1], event);
|
|
111
|
+
if (local.disabled) return;
|
|
112
|
+
const trigger = event.currentTarget;
|
|
113
|
+
if (!(trigger instanceof HTMLElement)) return;
|
|
114
|
+
const menubarOrientation = trigger.closest("[role=\"menubar\"]")?.getAttribute("aria-orientation");
|
|
115
|
+
if (![
|
|
116
|
+
"Enter",
|
|
117
|
+
" ",
|
|
118
|
+
(inheritedOrientation?.() ?? (menubarOrientation === "vertical" ? "vertical" : "horizontal")) === "horizontal" ? "ArrowDown" : "ArrowRight"
|
|
119
|
+
].includes(event.key)) return;
|
|
120
|
+
if (trigger instanceof HTMLAnchorElement && trigger.hasAttribute("href") && (event.key === "Enter" || event.key === " ")) return;
|
|
121
|
+
bypassUnboundedScrollLookup(trigger);
|
|
122
|
+
};
|
|
123
|
+
return createComponent(DropdownMenu.Trigger, mergeProps(rest, {
|
|
124
|
+
get disabled() {
|
|
125
|
+
return local.disabled;
|
|
126
|
+
},
|
|
127
|
+
onPointerDown,
|
|
128
|
+
onKeyDown
|
|
129
|
+
}));
|
|
37
130
|
}
|
|
38
131
|
function DropdownMenuPortal(props) {
|
|
39
132
|
return createComponent(DropdownMenu.Portal, props);
|
|
@@ -100,7 +193,7 @@ function DropdownMenuShortcut(props) {
|
|
|
100
193
|
return (() => {
|
|
101
194
|
var _el$2 = _tmpl$2();
|
|
102
195
|
spread(_el$2, mergeProps({ get ["class"]() {
|
|
103
|
-
return cn("text-muted-foreground ms-auto font-
|
|
196
|
+
return cn("text-muted-foreground ms-auto font-code text-code tracking-widest", local.class);
|
|
104
197
|
} }, rest), false, false);
|
|
105
198
|
return _el$2;
|
|
106
199
|
})();
|