@shapesos/clay 0.9.0 → 0.11.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.
Files changed (74) hide show
  1. package/README.md +46 -1
  2. package/dist/artifacts.cjs +741 -0
  3. package/dist/artifacts.cjs.map +1 -0
  4. package/dist/artifacts.d.cts +56 -0
  5. package/dist/artifacts.d.ts +56 -0
  6. package/dist/artifacts.js +23 -0
  7. package/dist/artifacts.js.map +1 -0
  8. package/dist/blocks.cjs +1282 -0
  9. package/dist/blocks.cjs.map +1 -0
  10. package/dist/blocks.css +2 -0
  11. package/dist/blocks.d.cts +41 -0
  12. package/dist/blocks.d.ts +41 -0
  13. package/dist/blocks.js +31 -0
  14. package/dist/blocks.js.map +1 -0
  15. package/dist/button.d.cts +2 -2
  16. package/dist/button.d.ts +2 -2
  17. package/dist/chat.cjs +755 -281
  18. package/dist/chat.cjs.map +1 -1
  19. package/dist/chat.d.cts +31 -10
  20. package/dist/chat.d.ts +31 -10
  21. package/dist/chat.js +8 -3
  22. package/dist/chunk-BX5TCEPR.js +436 -0
  23. package/dist/chunk-BX5TCEPR.js.map +1 -0
  24. package/dist/chunk-JGMN6W72.js +12 -0
  25. package/dist/chunk-JGMN6W72.js.map +1 -0
  26. package/dist/{chunk-27GJUWVN.js → chunk-JJUIBBBU.js} +14 -8
  27. package/dist/chunk-JJUIBBBU.js.map +1 -0
  28. package/dist/chunk-L35M3OD5.js +99 -0
  29. package/dist/chunk-L35M3OD5.js.map +1 -0
  30. package/dist/chunk-MEJESPTZ.js +1 -0
  31. package/dist/chunk-MEJESPTZ.js.map +1 -0
  32. package/dist/chunk-MXOPG747.js +238 -0
  33. package/dist/chunk-MXOPG747.js.map +1 -0
  34. package/dist/{chunk-MLCRDVQ2.js → chunk-OBOXCBDL.js} +13 -5
  35. package/dist/chunk-OBOXCBDL.js.map +1 -0
  36. package/dist/chunk-OUW6PUEB.js +223 -0
  37. package/dist/chunk-OUW6PUEB.js.map +1 -0
  38. package/dist/{chunk-TDMJUF4A.js → chunk-WPQQVKWY.js} +4 -4
  39. package/dist/icon.cjs +12 -4
  40. package/dist/icon.cjs.map +1 -1
  41. package/dist/icon.d.cts +19 -6
  42. package/dist/icon.d.ts +19 -6
  43. package/dist/icon.js +1 -1
  44. package/dist/index.cjs +789 -273
  45. package/dist/index.cjs.map +1 -1
  46. package/dist/index.d.cts +7 -3
  47. package/dist/index.d.ts +7 -3
  48. package/dist/index.js +61 -21
  49. package/dist/lottie.d.cts +2 -2
  50. package/dist/lottie.d.ts +2 -2
  51. package/dist/table.cjs +142 -0
  52. package/dist/table.cjs.map +1 -0
  53. package/dist/table.d.cts +44 -0
  54. package/dist/table.d.ts +44 -0
  55. package/dist/table.js +24 -0
  56. package/dist/table.js.map +1 -0
  57. package/dist/text-area.d.cts +2 -2
  58. package/dist/text-area.d.ts +2 -2
  59. package/dist/text-area.js +2 -2
  60. package/dist/types-3Gzk7cRt.d.cts +121 -0
  61. package/dist/types-3Gzk7cRt.d.ts +121 -0
  62. package/dist/types-C9XX-Uhk.d.ts +68 -0
  63. package/dist/types-DuuRI4ll.d.cts +68 -0
  64. package/dist/utils.cjs +14 -7
  65. package/dist/utils.cjs.map +1 -1
  66. package/dist/utils.d.cts +18 -1
  67. package/dist/utils.d.ts +18 -1
  68. package/dist/utils.js +6 -4
  69. package/package.json +34 -4
  70. package/dist/chunk-27GJUWVN.js.map +0 -1
  71. package/dist/chunk-A77BGJH4.js +0 -458
  72. package/dist/chunk-A77BGJH4.js.map +0 -1
  73. package/dist/chunk-MLCRDVQ2.js.map +0 -1
  74. /package/dist/{chunk-TDMJUF4A.js.map → chunk-WPQQVKWY.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/blocks/index.ts","../src/components/blocks/types.ts","../src/components/artifacts/types.ts","../src/components/artifacts/table-artifact/table-artifact.tsx","../src/lib/utils.ts","../src/components/ai-elements/artifact.tsx","../node_modules/@tabler/icons-react/src/defaultAttributes.ts","../node_modules/@tabler/icons-react/src/createReactComponent.ts","../node_modules/@tabler/icons-react/src/icons/IconDownload.ts","../src/components/icon-button/icon-button.tsx","../src/components/icon/icon.tsx","../src/components/icon/icon-styles.ts","../src/components/icon-button/icon-button-styles.ts","../src/tokens/colors.ts","../src/components/ui/tooltip.tsx","../src/components/artifacts/artifact-download-button/artifact-download-button.tsx","../src/components/ui/table.tsx","../src/components/table/use-scroll-shadow.ts","../src/components/artifacts/table-artifact/table-artifact-styles.ts","../src/components/artifacts/table-artifact/table-artifact-content.constants.ts","../src/components/artifacts/table-artifact/table-artifact-content.utils.ts","../src/components/artifacts/table-artifact/table-artifact-content.tsx","../src/components/artifacts/table-artifact/use-table-artifact-data.ts","../src/components/artifacts/table-artifact/parse-csv.ts","../src/components/artifacts/table-artifact/validate.ts","../src/components/artifacts/table-artifact/to-clipboard-text.ts","../src/components/artifacts/artifact-services/table-artifact-service.ts","../src/components/artifacts/artifact-services/index.ts","../src/components/blocks/artifact-ref-block/artifact-ref-block.tsx","../src/components/blocks/block-services/artifact-ref-block-service.ts","../src/utils/markdown-to-plain-text.ts","../src/components/blocks/text-block/text-block.tsx","../src/components/blocks/scrollable-table/scrollable-table-styles.ts","../src/components/blocks/scrollable-table/scrollable-table.tsx","../src/components/blocks/text-block/sanitize.ts","../src/components/blocks/text-block/text-block-styles.ts","../src/tokens/typography.ts","../src/components/blocks/block-services/text-block-service.ts","../src/components/blocks/block-services/index.ts","../src/components/blocks/block/block.tsx","../src/components/blocks/block-context/block-context.tsx"],"sourcesContent":["export { Block } from \"./block\";\nexport { BlockContext, useBlockContext } from \"./block-context\";\nexport type { BlockContextValue } from \"./block-context\";\nexport { blockTypes } from \"./types\";\nexport type {\n ArtifactRefBlockRecord,\n BlockComponentProps,\n BlockRecord,\n BlockService,\n BlockType,\n TextBlockRecord,\n} from \"./types\";\nexport { BlockServices } from \"./block-services\";\nexport { ArtifactRefBlockService } from \"./block-services/artifact-ref-block-service\";\nexport { TextBlockService } from \"./block-services/text-block-service\";\nexport { ArtifactRefBlock } from \"./artifact-ref-block\";\n","import type { ComponentType } from \"react\";\n\nimport type { ArtifactRecord } from \"@/components/artifacts/types\";\n\n/** Block-type discriminator constants. Mirrors the wire shape from io-server / shapes-agent. */\nexport const blockTypes = {\n TEXT: \"TEXT\",\n ARTIFACT_REF: \"ARTIFACT_REF\",\n} as const;\n\n/** Discriminator for content blocks. */\nexport type BlockType = (typeof blockTypes)[keyof typeof blockTypes];\n\n/** Plain-text content block — rendered as Markdown. */\nexport interface TextBlockRecord {\n /** Block-type discriminator. */\n type: typeof blockTypes.TEXT;\n /** Type-specific data; kept as `payload` to match the wire shape 1:1. */\n payload: {\n /** The Markdown source for this text segment. */\n text: string;\n };\n}\n\n/**\n * Reference-to-an-artifact content block — dispatched to the per-type artifact component.\n *\n * The artifact-domain types (`ArtifactRecord`, `TableArtifactRecord`, etc.) live in\n * `@/components/artifacts/types` so the artifact layer can be consumed independently of the\n * block layer (e.g. by a future surface that renders an artifact outside chat). The block layer\n * imports them here to wrap an artifact in an `ARTIFACT_REF` block.\n */\nexport interface ArtifactRefBlockRecord {\n /** Block-type discriminator. */\n type: typeof blockTypes.ARTIFACT_REF;\n /** Type-specific data; kept as `payload` to match the wire shape 1:1. */\n payload: {\n /** The artifact's stable identifier, used for keying / future cross-message reuse. */\n artifactId: string;\n /** Inlined artifact metadata — clients fetch the underlying data via `artifact.protectedAsset.presignedUrl`. */\n artifact: ArtifactRecord;\n };\n}\n\n/** Discriminated union of all supported content blocks. Additive — new types extend this union. */\nexport type BlockRecord = TextBlockRecord | ArtifactRefBlockRecord;\n\n/** Props every concrete block component receives from the dispatcher. */\nexport interface BlockComponentProps<TBlock extends BlockRecord = BlockRecord> {\n /** The block to render. */\n block: TBlock;\n}\n\n/** Per-block-type service — registry entry that pairs a discriminator with its concrete component. */\nexport interface BlockService<TBlock extends BlockRecord = BlockRecord> {\n /** Discriminator value this service handles. */\n type: BlockType;\n /** React component that renders a block of this type. */\n Component: ComponentType<BlockComponentProps<TBlock>>;\n /**\n * Returns a plain-text or markdown string representation of this block suitable for clipboard\n * copy. Called by `copyMessageText` when the user clicks \"copy message\".\n *\n * - `TextBlockService`: returns `block.payload.text` verbatim (markdown preserved).\n * - `ArtifactRefBlockService`: delegates to `ArtifactServices[artifact.type].toClipboardText`.\n * Falls back to `[Artifact: <title>]` when the artifact type has no registered component.\n *\n * Optional so external `BlockService` implementors don't break on upgrade — when omitted, the\n * aggregator treats the block as contributing the empty string (silently skipped). Implementations\n * must be pure, synchronous functions — no async, no hooks, no side effects.\n */\n toClipboardText?: (block: TBlock) => string;\n}\n","/**\n * Artifact-domain types — wire-protocol shapes shared between artifact components, block-services, and\n * consumers. The block layer (`@/components/blocks`) imports these to define\n * `ArtifactRefBlockRecord`; the artifact components consume them directly.\n *\n * Mirrored from the agent / io-server contract — see the `chat-typed-content-blocks-and-artifacts`\n * plan, §6.4 (table contract).\n */\n\nimport type { ComponentType } from \"react\";\n\n/**\n * Artifact-type discriminator constants. Uppercase to match the server-side `artifactTypes`\n * constant — io-server stores `artifact.type === \"TABLE\"` (aligned with the GraphQL enum).\n */\nexport const artifactTypes = {\n TABLE: \"TABLE\",\n} as const;\n\n/** Discriminator for artifact types. Additive — new types extend this union. */\nexport type ArtifactType = (typeof artifactTypes)[keyof typeof artifactTypes];\n\n/**\n * A single column descriptor for a `TableArtifact`. Carries the ORDER and LABEL for the\n * rendered table — `key` selects a column from the CSV header; `label` overrides the rendered\n * header text. The CSV is always the source of truth for the data shape; clay never coerces,\n * reformats, or interprets cell values.\n */\nexport interface TableColumn {\n /** Matches a header in the CSV. Required. Used to project + order the CSV's columns. */\n key: string;\n /** Human-readable header text. Required. */\n label: string;\n /**\n * Accepted in the wire payload but not consulted by the renderer — every cell is rendered as\n * the raw CSV string (or empty for null). Format conversion is a server concern; if a column\n * needs to be \"Yes/No\" instead of \"true/false\", the server should emit it that way in the CSV.\n * Kept in the interface so callers that pass `type` (e.g. io-client) don't get a type error.\n */\n type?: \"string\" | \"number\" | \"date\" | \"boolean\";\n /**\n * Accepted in the wire payload but not consulted by the renderer — every column is left-aligned\n * by design. Kept in the interface for forward-compat; restore per-column alignment by editing\n * `table-artifact-content.tsx` if a future use case justifies it.\n */\n align?: \"left\" | \"center\" | \"right\";\n}\n\n/**\n * Optional stats embedded in `TableConfig` so clients can pre-render UI before fetching the\n * actual data payload (e.g. N loading shimmers sized to the eventual row count).\n *\n * Backward-compat: optional everywhere — older artifacts persisted before this field shipped\n * still validate. The renderer falls back to a single status-message line when `stats` is absent.\n */\nexport interface TableStats {\n /** Total number of rows in the materialised CSV. Lets the loading branch render shimmers. */\n rowCount: number;\n}\n\n/** Rendering config for a table artifact, stored at `artifact.config` (JSONB on the server). */\nexport interface TableConfig {\n /** Column descriptors in render order. */\n columns: TableColumn[];\n /** Optional metadata describing the underlying data — used for loading-state UI. */\n stats?: TableStats;\n}\n\n/**\n * A row inside a table artifact's parsed CSV. Every cell is the raw string from the CSV (or\n * `null` for the empty string). The renderer never coerces or interprets — type-aware formatting\n * is a server concern (the CSV's contents are what the user sees).\n */\nexport type TableRow = Record<string, string | null>;\n\n/** Common shape every artifact record carries. Discriminated by `type`. */\ninterface ArtifactBase<TType extends ArtifactType, TConfig> {\n /** Artifact-type discriminator. */\n type: TType;\n /** Human-readable label. Nullable when the artifact has no title. */\n title: string | null;\n /** Rendering config — shape varies per artifact type. */\n config: TConfig;\n /** Protected-asset metadata pointing to the underlying data payload. Null while the asset is unavailable. */\n protectedAsset: {\n /** Time-limited URL the renderer fetches the artifact's data from. */\n presignedUrl: string;\n } | null;\n}\n\n/** Concrete table artifact record. Future artifact types extend `ArtifactRecord` here. */\nexport type TableArtifactRecord = ArtifactBase<typeof artifactTypes.TABLE, TableConfig>;\n\n/**\n * Discriminated union of all supported artifacts. Single-member today; extension pattern:\n *\n * export type ArtifactRecord = TableArtifactRecord | ChartArtifactRecord;\n *\n * Every consumer that narrows on `artifact.type` must add the new branch here AND in the\n * `ArtifactServices` map (single source of truth for the type→component mapping). Older clay\n * versions that don't know about a new type silently render nothing — see `ArtifactRefBlock` guard.\n */\nexport type ArtifactRecord = TableArtifactRecord;\n\n/** Props every concrete artifact component receives from the dispatcher. */\nexport interface ArtifactServiceProps<TArtifact extends ArtifactRecord = ArtifactRecord> {\n /** The artifact metadata (config + presigned URL). */\n artifact: TArtifact;\n}\n\n/** Per-artifact-type service — registry entry that pairs a discriminator with its concrete component. */\nexport interface ArtifactService<TArtifact extends ArtifactRecord = ArtifactRecord> {\n /** Discriminator value this service handles. */\n type: ArtifactType;\n /** React component that renders an artifact of this type — composes ai-elements primitives\n * (`Artifact`, `ArtifactHeader`, `ArtifactTitle`, `ArtifactActions`, `ArtifactContent`) directly. */\n Component: ComponentType<ArtifactServiceProps<TArtifact>>;\n /**\n * Returns a plain-text / markdown string suitable for clipboard copy.\n *\n * Called by `ArtifactRefBlockService.toClipboardText` when the user copies a message that\n * contains this artifact. Must be pure and synchronous.\n *\n * Implementation notes per type:\n * - `table`: returns the artifact title as plain text (see `TableArtifactService`).\n * - Future types implement their own representation in a co-located `*-service.ts` file.\n */\n toClipboardText: (artifact: TArtifact) => string;\n}\n","import { useEffect, type ReactNode } from \"react\";\n\nimport {\n Artifact,\n ArtifactActions,\n ArtifactContent,\n ArtifactHeader,\n ArtifactTitle,\n} from \"@/components/ai-elements/artifact\";\nimport { ArtifactDownloadButton } from \"@/components/artifacts/artifact-download-button/artifact-download-button\";\nimport type { ArtifactServiceProps } from \"@/components/artifacts/types\";\nimport type { TableArtifactRecord } from \"@/components/artifacts/types\";\nimport { TableArtifactContent } from \"./table-artifact-content\";\nimport { StatusMessage } from \"./table-artifact-styles\";\nimport { useTableArtifactData } from \"./use-table-artifact-data\";\nimport { isValidTableConfig } from \"./validate\";\n\nconst TITLE_CLASSES = \"text-sm font-semibold text-foreground\";\n\n/**\n * Cap the body at ~10 rows × 48px (~480px). Long lists scroll inside the artifact so they\n * don't stretch the chat surface. Each artifact type declares its own sensible cap.\n */\nconst TABLE_MAX_BODY_HEIGHT = 480;\n\n/**\n * Cap on shimmer rows during loading. Approximates the visible viewport (`TABLE_MAX_BODY_HEIGHT`\n * ÷ 48px per row) so we don't render hundreds of placeholder DOM nodes for very large tables.\n */\nconst MAX_SHIMMER_ROWS = 10;\n\n/** User-facing copy for permanent server-side absence of the artifact's data (no presigned URL or malformed config). */\nconst MSG_UNAVAILABLE = \"Table data is unavailable.\";\n\n/**\n * Orchestrator for the `table`-typed artifact.\n *\n * Composes the ai-elements chrome primitives (`Artifact`, `ArtifactHeader`, `ArtifactTitle`,\n * `ArtifactActions`, `ArtifactContent`) directly around the table body (`TableArtifactContent`).\n * Download is handled via `ArtifactDownloadButton` — a shared utility component that applies the\n * safe-URL guard and renders nothing for non-http(s) schemes.\n */\nexport function TableArtifact({ artifact }: ArtifactServiceProps<TableArtifactRecord>): ReactNode {\n const validConfig = isValidTableConfig(artifact.config);\n const validColumns = validConfig ? artifact.config.columns : null;\n\n useEffect(() => {\n if (validConfig) return;\n console.warn(\"[clay] TableArtifact: malformed `config` — skipping render.\");\n }, [validConfig]);\n\n // Hook is always called (Rules of Hooks). Pass null URL when config is invalid so the hook\n // short-circuits at its `if (!presignedUrl) return UNAVAILABLE` path — no network fetch fires\n // for an artifact whose config shape can't be rendered.\n const data = useTableArtifactData(\n validConfig ? artifact.protectedAsset?.presignedUrl ?? null : null,\n validColumns ?? []\n );\n\n const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;\n\n if (!validConfig || !validColumns) {\n return (\n <Artifact className=\"shadow-none w-full rounded-2xl bg-background/70\">\n <ArtifactHeader className=\"bg-background/70\">\n {artifact.title ? <ArtifactTitle className={TITLE_CLASSES}>{artifact.title}</ArtifactTitle> : <span />}\n {presignedUrl ? (\n <ArtifactActions>\n <ArtifactDownloadButton href={presignedUrl} />\n </ArtifactActions>\n ) : null}\n </ArtifactHeader>\n <ArtifactContent className=\"p-0 overflow-auto\" style={{ maxHeight: TABLE_MAX_BODY_HEIGHT }}>\n <StatusMessage $tone=\"info\">{MSG_UNAVAILABLE}</StatusMessage>\n </ArtifactContent>\n </Artifact>\n );\n }\n\n return (\n // The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).\n // Disable the outer overflow container so only one scroll context exists — this prevents\n // double-scroll nesting and lets `useScrollShadow` find the correct scroll ancestor.\n <Artifact className=\"shadow-none w-full rounded-2xl bg-background/70\">\n <ArtifactHeader className=\"bg-background/70\">\n {artifact.title ? <ArtifactTitle className={TITLE_CLASSES}>{artifact.title}</ArtifactTitle> : <span />}\n <ArtifactActions>\n <ArtifactDownloadButton href={presignedUrl ?? \"\"} />\n </ArtifactActions>\n </ArtifactHeader>\n <ArtifactContent className=\"p-0 overflow-visible\" style={{ maxHeight: \"none\" }}>\n <TableArtifactContent\n columns={validColumns}\n data={data}\n knownRowCount={artifact.config.stats?.rowCount}\n maxShimmerRows={MAX_SHIMMER_ROWS}\n maxBodyHeight={TABLE_MAX_BODY_HEIGHT}\n unavailableMessage={MSG_UNAVAILABLE}\n />\n </ArtifactContent>\n </Artifact>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Combines class names using clsx and tailwind-merge — the standard shadcn/ui helper.\n * Tailwind classes that conflict (e.g. `p-2 p-4`) get merged so the last one wins.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import type { HTMLAttributes } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/* ------------------------------------------------------------------------------------------------\n * Originally vendored from `@vercel/ai-elements`'s `artifact` registry entry — see\n * https://elements.ai-sdk.dev/api/registry/artifact.json. Slimmed to the chrome primitives clay\n * actually composes (`Artifact`, `ArtifactHeader`, `ArtifactTitle`, `ArtifactActions`,\n * `ArtifactContent`). The original entry also shipped `ArtifactClose`, `ArtifactDescription`, and\n * `ArtifactAction` — all dependent on the shadcn `Button` primitive, none of which clay consumes.\n * Action buttons inside the artifact header use clay's `IconButton` (see `TableArtifact`'s\n * `ExportCsvButton`) instead of a generic shadcn Button, so the design system stays single-sourced.\n *\n * If a future ai-elements re-scaffold needs one of the dropped primitives back, re-add only the\n * piece consumers need and route its inner button through clay's `Button` / `IconButton` rather\n * than re-introducing the shadcn Button file.\n * ------------------------------------------------------------------------------------------------ */\n\nexport type ArtifactProps = HTMLAttributes<HTMLDivElement>;\n\nexport const Artifact = ({ className, ...props }: ArtifactProps) => (\n <div\n className={cn(\"flex flex-col overflow-hidden rounded-lg border bg-background shadow-sm\", className)}\n {...props}\n />\n);\n\nexport type ArtifactHeaderProps = HTMLAttributes<HTMLDivElement>;\n\nexport const ArtifactHeader = ({ className, ...props }: ArtifactHeaderProps) => (\n <div className={cn(\"flex items-center justify-between border-b bg-muted/50 px-4 py-3\", className)} {...props} />\n);\n\nexport type ArtifactTitleProps = HTMLAttributes<HTMLParagraphElement>;\n\nexport const ArtifactTitle = ({ className, ...props }: ArtifactTitleProps) => (\n <p className={cn(\"font-medium text-foreground text-sm\", className)} {...props} />\n);\n\nexport type ArtifactActionsProps = HTMLAttributes<HTMLDivElement>;\n\nexport const ArtifactActions = ({ className, ...props }: ArtifactActionsProps) => (\n <div className={cn(\"flex items-center gap-1\", className)} {...props} />\n);\n\nexport type ArtifactContentProps = HTMLAttributes<HTMLDivElement>;\n\nexport const ArtifactContent = ({ className, ...props }: ArtifactContentProps) => (\n <div className={cn(\"flex-1 overflow-auto p-4\", className)} {...props} />\n);\n","export default {\n outline: {\n xmlns: 'http://www.w3.org/2000/svg',\n width: 24,\n height: 24,\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n },\n filled: {\n xmlns: 'http://www.w3.org/2000/svg',\n width: 24,\n height: 24,\n viewBox: '0 0 24 24',\n fill: 'currentColor',\n stroke: 'none',\n },\n};\n","import { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes';\nimport type { IconNode, IconProps, Icon } from './types';\n\nconst createReactComponent = (\n type: 'outline' | 'filled',\n iconName: string,\n iconNamePascal: string,\n iconNode: IconNode,\n) => {\n const Component = forwardRef<SVGSVGElement, IconProps>(\n (\n { color = 'currentColor', size = 24, stroke = 2, title, className, children, ...rest }: IconProps,\n ref,\n ) =>\n createElement(\n 'svg',\n {\n ref,\n ...defaultAttributes[type],\n width: size,\n height: size,\n className: [`tabler-icon`, `tabler-icon-${iconName}`, className].join(' '),\n ...(type === 'filled'\n ? {\n fill: color,\n }\n : {\n strokeWidth: stroke,\n stroke: color,\n }),\n ...rest,\n },\n [\n title && createElement('title', { key: 'svg-title' }, title),\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...(Array.isArray(children) ? children : [children]),\n ],\n ),\n );\n\n Component.displayName = `${iconNamePascal}`;\n\n return Component;\n};\n\nexport default createReactComponent;\n","import createReactComponent from '../createReactComponent';\nimport { IconNode } from '../types';\n\nexport const __iconNode: IconNode = [[\"path\",{\"d\":\"M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2\",\"key\":\"svg-0\"}],[\"path\",{\"d\":\"M7 11l5 5l5 -5\",\"key\":\"svg-1\"}],[\"path\",{\"d\":\"M12 4l0 12\",\"key\":\"svg-2\"}]]\n\nconst IconDownload = createReactComponent('outline', 'download', 'Download', __iconNode);\n\nexport default IconDownload;","import { forwardRef } from \"react\";\n\nimport { Icon } from \"../icon/icon\";\nimport { Button } from \"./icon-button-styles\";\nimport type { IconButtonProps, IconButtonSize } from \"./types\";\n\nconst ICON_SIZE_BY_BUTTON_SIZE: Record<IconButtonSize, number> = {\n small: 16,\n medium: 20,\n};\n\n/** Ghost-style icon button. `forwardRef` + the rest-props spread so Radix `Slot`-based wrappers\n * (Tooltip, Popover, DropdownMenu) can attach refs and event handlers via `asChild`. */\nexport const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(function IconButton(\n {\n icon,\n size = \"small\",\n variant = \"short\",\n isSelected = false,\n disabled = false,\n onClick,\n className,\n id,\n as,\n \"aria-label\": ariaLabel,\n ...rest\n },\n ref\n) {\n // Only set `type=\"button\"` when rendering as a native button. Anchors (`as=\"a\"`) treat the\n // `type` attribute as a content-type hint for the linked resource — `type=\"button\"` on an\n // anchor is semantically wrong and shows up as an a11y / HTML-validation noise warning.\n const isNativeButton = as === undefined || as === \"button\";\n return (\n <Button\n ref={ref}\n className={className}\n id={id}\n as={as}\n $size={size}\n $variant={variant}\n $isSelected={isSelected}\n disabled={disabled}\n onClick={disabled ? undefined : onClick}\n aria-label={ariaLabel}\n {...(isNativeButton ? { type: \"button\" as const } : {})}\n {...rest}\n >\n <Icon icon={icon} size={ICON_SIZE_BY_BUTTON_SIZE[size]} />\n </Button>\n );\n});\n","import { forwardRef } from \"react\";\n\nimport { IconWrapper, getStrokeWidth } from \"./icon-styles\";\nimport type { IconProps } from \"./types\";\n\nconst DEFAULT_SIZE = 16;\n\nexport const Icon = forwardRef<HTMLSpanElement, IconProps>(function Icon(\n { icon: IconComponent, size = DEFAULT_SIZE, color, className, \"aria-label\": ariaLabel },\n ref\n) {\n return (\n <IconWrapper\n ref={ref}\n className={className}\n $color={color}\n aria-label={ariaLabel}\n role={ariaLabel ? \"img\" : undefined}\n >\n <IconComponent width={size} height={size} strokeWidth={getStrokeWidth(size)} />\n </IconWrapper>\n );\n});\n","import styled from \"styled-components\";\n\nexport const STROKE_WIDTH_BY_SIZE: Record<number, number> = {\n 12: 1.4,\n 14: 1.4,\n 16: 1.8,\n 18: 1.8,\n 20: 1.8,\n 24: 1.8,\n};\n\nexport const DEFAULT_STROKE_WIDTH = 1.8;\n\nexport function getStrokeWidth(size: number): number {\n return STROKE_WIDTH_BY_SIZE[size] ?? DEFAULT_STROKE_WIDTH;\n}\n\nexport const IconWrapper = styled.span<{ $color?: string }>`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: ${({ $color }) => $color ?? \"currentColor\"};\n flex-shrink: 0;\n`;\n","import styled from \"styled-components\";\n\nimport { colors } from \"../../tokens/colors\";\nimport type { IconButtonSize, IconButtonVariant } from \"./types\";\n\nconst PADDING: Record<IconButtonVariant, Record<IconButtonSize, string>> = {\n short: {\n small: \"4px\",\n medium: \"6px\",\n },\n long: {\n small: \"4px 6px\",\n medium: \"6px 10px\",\n },\n};\n\nconst BORDER_RADIUS: Record<IconButtonSize, number> = {\n small: 6,\n medium: 10,\n};\n\nexport const Button = styled.button<{\n $size: IconButtonSize;\n $variant: IconButtonVariant;\n $isSelected: boolean;\n}>`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: ${({ $size, $variant }) => PADDING[$variant][$size]};\n border: none;\n border-radius: ${({ $size }) => BORDER_RADIUS[$size]}px;\n background: ${({ $isSelected }) => ($isSelected ? colors[\"brown-40\"] : \"transparent\")};\n color: ${colors[\"brown-100\"]};\n cursor: pointer;\n transition: background-color 100ms ease;\n\n &:hover {\n background: ${({ $isSelected }) => ($isSelected ? colors[\"brown-40\"] : colors[\"brown-20\"])};\n }\n\n &:active {\n background: ${colors[\"brown-40\"]};\n }\n\n &:disabled {\n color: ${colors[\"brown-50\"]};\n background: transparent;\n cursor: not-allowed;\n }\n`;\n","export const colors = {\n // White\n white: \"#FFFFFF\",\n \"white-alpha-85\": \"rgba(255, 255, 255, 0.85)\",\n \"white-alpha-40\": \"rgba(255, 255, 255, 0.40)\",\n\n // Brown\n \"brown-10\": \"#FAF9F8\",\n \"brown-20\": \"#F5F3F0\",\n \"brown-30\": \"#EEEBE5\",\n \"brown-40\": \"#E6E2DA\",\n \"brown-50\": \"#CFCBC4\",\n \"brown-60\": \"#A19E99\",\n \"brown-70\": \"#73716D\",\n \"brown-80\": \"#5C5A57\",\n \"brown-90\": \"#2E2D2C\",\n \"brown-100\": \"#171716\",\n \"brown-alpha-12\": \"rgba(23, 23, 22, 0.12)\",\n \"brown-alpha-20\": \"rgba(23, 23, 22, 0.20)\",\n \"brown-alpha-55\": \"rgba(23, 23, 22, 0.55)\",\n \"brown-alpha-70\": \"rgba(23, 23, 22, 0.70)\",\n \"brown-alpha-80\": \"rgba(23, 23, 22, 0.80)\",\n \"brown-alpha-90\": \"rgba(23, 23, 22, 0.90)\",\n\n // Fuchsia\n \"fuchsia-50\": \"#FAF5FF\",\n \"fuchsia-300\": \"#F0ABFC\",\n \"fuchsia-500\": \"#D946EF\",\n \"fuchsia-600\": \"#C026D3\",\n \"fuchsia-800\": \"#86198F\",\n\n // Pink\n \"pink-50\": \"#FDF2F8\",\n \"pink-400\": \"#F472B6\",\n \"pink-600\": \"#DB2777\",\n \"pink-800\": \"#9D174D\",\n\n // Violet\n \"violet-50\": \"#F5F3FF\",\n \"violet-400\": \"#A78BFA\",\n \"violet-600\": \"#7C3AED\",\n \"violet-800\": \"#5B21B6\",\n\n // Indigo\n \"indigo-50\": \"#EEF2FF\",\n \"indigo-400\": \"#818CF8\",\n \"indigo-500\": \"#6366F1\",\n \"indigo-600\": \"#4F46E5\",\n \"indigo-800\": \"#3730A3\",\n\n // Cyan\n \"cyan-50\": \"#E7FEFF\",\n \"cyan-300\": \"#67E8F9\",\n \"cyan-600\": \"#0891B2\",\n \"cyan-900\": \"#164E63\",\n\n // Teal\n \"teal-50\": \"#EBFDF9\",\n \"teal-300\": \"#5EEAD4\",\n \"teal-600\": \"#0D9488\",\n\n // Rose\n \"rose-400\": \"#FB7185\",\n\n // Purple\n \"purple-400\": \"#C084FC\",\n\n // Blue\n \"blue-50\": \"#EFF6FF\",\n \"blue-100\": \"#DBEAFE\",\n \"blue-300\": \"#93C5FD\",\n \"blue-400\": \"#60A5FA\",\n \"blue-600\": \"#2563EB\",\n \"blue-800\": \"#1E40AF\",\n\n // Sky\n \"sky-300\": \"#7DD3FC\",\n\n // Green\n \"green-50\": \"#ECF9F0\",\n \"green-100\": \"#D4F1D9\",\n \"green-400\": \"#3DC269\",\n \"green-700\": \"#277C43\",\n \"green-800\": \"#1C5930\",\n\n // Orange\n \"orange-50\": \"#FFF7ED\",\n \"orange-100\": \"#FFEDD5\",\n \"orange-200\": \"#FED7AA\",\n \"orange-500\": \"#F97316\",\n \"orange-600\": \"#EA580C\",\n\n // Red\n \"red-50\": \"#FEF2F2\",\n \"red-100\": \"#FEE2E2\",\n \"red-200\": \"#FECACA\",\n \"red-400\": \"#F7776C\",\n \"red-500\": \"#EF4444\",\n \"red-600\": \"#DC2626\",\n} as const;\n\nexport type ColorToken = keyof typeof colors;\n","import * as React from \"react\";\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst TooltipProvider = TooltipPrimitive.Provider;\n\nconst Tooltip = TooltipPrimitive.Root;\n\nconst TooltipTrigger = TooltipPrimitive.Trigger;\n\nconst TooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-tooltip-content-transform-origin]\",\n className\n )}\n {...props}\n />\n));\nTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };\n","import { IconDownload } from \"@tabler/icons-react\";\nimport type { ReactNode } from \"react\";\n\nimport { IconButton } from \"@/components/icon-button/icon-button\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"@/components/ui/tooltip\";\n\n/** Props for `ArtifactDownloadButton`. */\nexport interface ArtifactDownloadButtonProps {\n /**\n * URL to download the artifact's underlying bytes. The button is an `<a href download>` so the\n * browser uses whatever filename the server supplies via `Content-Disposition`. No client-side\n * filename invention.\n *\n * Renders nothing when the URL is not a safe `http(s):` scheme — guards against `javascript:` or\n * `data:` URIs smuggled into `presignedUrl`.\n */\n href: string;\n}\n\n/**\n * Reusable download button for artifact headers. Anchor-based so the browser handles the download\n * natively (respects `Content-Disposition`, falls back to URL basename). `rel=\"noopener noreferrer\"`\n * defends against `window.opener` leakage if the browser opens the URL instead of downloading.\n *\n * Drop this inside `<ArtifactActions>` in any per-type artifact orchestrator.\n */\nexport function ArtifactDownloadButton({ href }: ArtifactDownloadButtonProps): ReactNode {\n if (!isSafeDownloadUrl(href)) return null;\n return (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <IconButton\n as=\"a\"\n href={href}\n download\n rel=\"noopener noreferrer\"\n icon={IconDownload}\n size=\"small\"\n aria-label=\"Download artifact\"\n />\n </TooltipTrigger>\n <TooltipContent>Download</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n}\n\n/**\n * Returns `true` only for `http:` and `https:` URLs. Rejects `javascript:`, `data:`, and any\n * other scheme that could execute code on click.\n */\nexport function isSafeDownloadUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === \"https:\" || parsed.protocol === \"http:\";\n } catch {\n return false;\n }\n}\n","import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/** Extension of shadcn's `Table` registry component: exposes `containerClassName` so callers can\n * override the wrapping `<div>`'s default `overflow-auto`. We need this for sticky-header support\n * (sticky uses the nearest overflow ancestor as its containing block — when the actual scroll\n * container is one level out, the inner overflow-auto needs to be neutralised with\n * `overflow-visible` so sticky aligns with the real scrolling parent). */\nconst Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement> & { containerClassName?: string }\n>(({ className, containerClassName, ...props }, ref) => (\n <div className={cn(\"relative w-full overflow-auto\", containerClassName)}>\n <table ref={ref} className={cn(\"w-full caption-bottom text-sm\", className)} {...props} />\n </div>\n));\nTable.displayName = \"Table\";\n\nconst TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => <thead ref={ref} className={cn(\"[&_tr]:border-b\", className)} {...props} />\n);\nTableHeader.displayName = \"TableHeader\";\n\nconst TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tbody ref={ref} className={cn(\"[&_tr:last-child]:border-0\", className)} {...props} />\n )\n);\nTableBody.displayName = \"TableBody\";\n\nconst TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tfoot ref={ref} className={cn(\"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\", className)} {...props} />\n )\n);\nTableFooter.displayName = \"TableFooter\";\n\nconst TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(\n ({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted\", className)}\n {...props}\n />\n )\n);\nTableRow.displayName = \"TableRow\";\n\nconst TableHead = React.forwardRef<HTMLTableCellElement, React.ThHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n \"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0\",\n className\n )}\n {...props}\n />\n )\n);\nTableHead.displayName = \"TableHead\";\n\nconst TableCell = React.forwardRef<HTMLTableCellElement, React.TdHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <td ref={ref} className={cn(\"p-4 align-middle [&:has([role=checkbox])]:pr-0\", className)} {...props} />\n )\n);\nTableCell.displayName = \"TableCell\";\n\nconst TableCaption = React.forwardRef<HTMLTableCaptionElement, React.HTMLAttributes<HTMLTableCaptionElement>>(\n ({ className, ...props }, ref) => (\n <caption ref={ref} className={cn(\"mt-4 text-sm text-muted-foreground\", className)} {...props} />\n )\n);\nTableCaption.displayName = \"TableCaption\";\n\nexport { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };\n","import { useEffect, useRef, useState, type RefObject } from \"react\";\n\n/**\n * Tracks whether a scroll container has scrolled past its top edge, for sticky-header shadow effects.\n *\n * Returns `targetRef` (attach to the scroll container itself or any element inside it) and\n * `isScrolled` (true once the container's `scrollTop > 0`). On mount the hook walks up the DOM\n * from the target to find the nearest overflow ancestor (or uses the target itself if it already\n * has `overflowY: auto | scroll`), then listens to its `scroll` event.\n *\n * Used to surface a subtle \"scroll lift\" shadow under sticky headers so users know there is\n * content hidden above.\n *\n * **Why a scroll listener and not a sentinel + IntersectionObserver:** an earlier version used a\n * 1px sentinel as the first child of the scroll container. The sentinel's height pushed the thead\n * down by one pixel in normal flow, and as soon as the user scrolled the thead snapped up to its\n * sticky position — a visible 1px jitter. A scroll listener has no layout footprint.\n *\n * `passive: true` so the listener doesn't block native scroll smoothness; we never call\n * `preventDefault`.\n */\nexport function useScrollShadow(): {\n targetRef: RefObject<HTMLDivElement | null>;\n isScrolled: boolean;\n} {\n const targetRef = useRef<HTMLDivElement>(null);\n const [isScrolled, setIsScrolled] = useState(false);\n\n useEffect(() => {\n const target = targetRef.current;\n if (!target) return;\n\n let scrollContainer: HTMLElement | null = target;\n while (scrollContainer) {\n const overflowY = getComputedStyle(scrollContainer).overflowY;\n if (overflowY === \"auto\" || overflowY === \"scroll\") break;\n scrollContainer = scrollContainer.parentElement;\n }\n if (!scrollContainer) return;\n\n setIsScrolled(scrollContainer.scrollTop > 0);\n\n const handleScroll = () => {\n if (!scrollContainer) return;\n setIsScrolled(scrollContainer.scrollTop > 0);\n };\n scrollContainer.addEventListener(\"scroll\", handleScroll, { passive: true });\n return () => scrollContainer.removeEventListener(\"scroll\", handleScroll);\n }, []);\n\n return { targetRef, isScrolled };\n}\n","import type { ReactNode } from \"react\";\n\nimport { createElement } from \"react\";\n\ninterface StatusMessageProps {\n /** Visual tone: \"error\" renders red copy, \"info\" renders muted brown copy. */\n $tone?: \"info\" | \"error\";\n children: ReactNode;\n}\n\n/**\n * Centred status copy rendered inside the artifact when there is no table to show\n * (loading without a known row count, error, or unavailable).\n * Uses Tailwind so it stays consistent with the rest of the artifact renderer.\n */\nexport function StatusMessage({ $tone, children }: StatusMessageProps): ReactNode {\n return createElement(\n \"div\",\n {\n className: `py-6 px-2 text-center text-sm font-medium leading-5 ${\n $tone === \"error\" ? \"text-red-600\" : \"text-brown-70\"\n }`,\n },\n children\n );\n}\n","/**\n * Discriminant constants for `TableArtifactDataState.status`.\n *\n * Use these instead of inline string literals so a typo is a compile-time error rather than a\n * silent wrong-branch at runtime.\n */\nexport const TABLE_STATUS = {\n LOADING: \"loading\",\n READY: \"ready\",\n ERROR: \"error\",\n UNAVAILABLE: \"unavailable\",\n} as const;\n","import type { TableColumn, TableRow as TableRowData } from \"@/components/artifacts/types\";\n\n/**\n * Returns a cell's rendered string. The CSV is the source of truth — clay never coerces or\n * reformats values. `null` / missing keys render as the empty cell. The value comes out as it\n * went in (whatever the server wrote into the CSV).\n */\nexport function formatCell(row: TableRowData, column: TableColumn): string {\n return row[column.key] ?? \"\";\n}\n\n/**\n * Header + body cell class strings. Alignment is uniformly left in chat-embedded artifact tables\n * by design (mixing right-aligned numerics with left-aligned text reads inconsistently); the\n * wire-type `column.align` is preserved for forward-compat but ignored at render time. See\n * `TableColumn.align` doc in `@/components/artifacts/types`.\n */\nexport const HEAD_CLASS = \"h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left\";\nexport const CELL_CLASS = \"p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left\";\n\n/**\n * Row tint matches the artifact card's frosted-glass scheme. The custom `border-b-brown-30`\n * overrides shadcn's row-default border (which inherits `--color-border` = brown-40) with the\n * lighter brown-30. Hover lifts to `bg-secondary` (opaque brown-20) for strong feedback against\n * the translucent base.\n */\nexport const ROW_CLASSES = \"border-b-brown-30 bg-background/70 hover:bg-secondary\";\n\n/**\n * Mount-time fade-in for data rows so the shimmer-to-data transition feels smooth (300ms ease-in\n * over `opacity: 0 → 1`). Shimmer rows keep `ROW_CLASSES` (no animate-in) so they remain in their\n * loading stillness while the pulse animation runs. `animate-in fade-in duration-300` is provided\n * by `tw-animate-css`.\n */\nexport const DATA_ROW_CLASSES = `${ROW_CLASSES} animate-in fade-in duration-300`;\n\n/** Layered drop-shadow for the scroll-lift effect on the sticky header. */\nexport const SCROLL_SHADOW = \"0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)\";\n","import { type ReactNode } from \"react\";\n\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, useScrollShadow } from \"@/components/table\";\nimport type { TableColumn, TableRow as TableRowData } from \"@/components/artifacts/types\";\nimport { StatusMessage } from \"./table-artifact-styles\";\nimport type { ArtifactTableProps, TableArtifactContentProps } from \"./table-artifact-content.types\";\nimport { TABLE_STATUS } from \"./table-artifact-content.constants\";\nimport {\n CELL_CLASS,\n DATA_ROW_CLASSES,\n formatCell,\n HEAD_CLASS,\n ROW_CLASSES,\n SCROLL_SHADOW,\n} from \"./table-artifact-content.utils\";\n\n/**\n * Bridges artifact data-states → shadcn's compound `Table` primitives.\n *\n * The four states render differently:\n *\n * - **loading w/ knownRowCount** → renders a sticky-header table with N shimmer rows so the\n * layout doesn't jump.\n * - **loading w/o knownRowCount** → renders the inline \"Loading table…\" status message.\n * - **error / unavailable** → renders an inline status message.\n * - **ready** → renders the full table with data rows and the scroll-lift\n * shadow on the sticky header.\n *\n * The shadcn primitives are composed directly here — no `Table` wrapper component sits in between.\n * Each row variant (header, data, shimmer, empty) is a small inline component below.\n */\nexport function TableArtifactContent({\n columns,\n data,\n knownRowCount,\n maxShimmerRows,\n maxBodyHeight,\n unavailableMessage,\n}: TableArtifactContentProps): ReactNode {\n if (data.status === TABLE_STATUS.ERROR) {\n // No retry hook today — copy intentionally drops the \"Please try again.\" that has nowhere\n // to land. Wire an `onRetry` callback into `ArtifactService` to re-mint a fresh\n // presigned URL before re-introducing the retry framing.\n return <StatusMessage $tone=\"error\">Couldn't load table data.</StatusMessage>;\n }\n if (data.status === TABLE_STATUS.UNAVAILABLE) {\n return <StatusMessage $tone=\"info\">{unavailableMessage}</StatusMessage>;\n }\n if (data.status === TABLE_STATUS.LOADING) {\n if (typeof knownRowCount === \"number\" && knownRowCount > 0) {\n const shimmerCount = Math.min(knownRowCount, maxShimmerRows);\n return (\n <ArtifactTable columns={columns} maxBodyHeight={maxBodyHeight}>\n {renderShimmerRows(columns, shimmerCount)}\n </ArtifactTable>\n );\n }\n return <StatusMessage $tone=\"info\">Loading table…</StatusMessage>;\n }\n // data.status === TABLE_STATUS.READY\n return (\n <ArtifactTable columns={columns} maxBodyHeight={maxBodyHeight}>\n {data.rows.length === 0 ? renderEmptyRow(columns.length) : renderDataRows(columns, data.rows)}\n </ArtifactTable>\n );\n}\n\n/**\n * Compound-table chrome shared between the loading-shimmer branch and the data/empty branch:\n * scroll container, sticky header, and the body slot. Caller passes the body rows.\n */\nfunction ArtifactTable({ columns, maxBodyHeight, children }: ArtifactTableProps): ReactNode {\n const { targetRef, isScrolled } = useScrollShadow();\n return (\n <div ref={targetRef} className=\"overscroll-none\" style={{ maxHeight: maxBodyHeight, overflowY: \"auto\" }}>\n <Table containerClassName=\"overflow-visible\">\n <TableHeader\n data-scrolled={isScrolled ? \"true\" : undefined}\n className=\"sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow\"\n style={isScrolled ? { boxShadow: SCROLL_SHADOW } : undefined}\n >\n <TableRow className=\"hover:bg-transparent\">\n {columns.map((column) => (\n <TableHead key={column.key} scope=\"col\" className={HEAD_CLASS}>\n {column.label}\n </TableHead>\n ))}\n </TableRow>\n </TableHeader>\n <TableBody>{children}</TableBody>\n </Table>\n </div>\n );\n}\n\nfunction renderShimmerRows(columns: TableColumn[], count: number): ReactNode {\n return Array.from({ length: count }).map((_, index) => (\n <TableRow key={`shimmer-${index}`} className={ROW_CLASSES} aria-hidden=\"true\">\n {columns.map((column) => (\n <TableCell key={column.key} className={CELL_CLASS}>\n <span className=\"block h-3 w-3/4 animate-pulse rounded bg-muted-foreground/20\" />\n </TableCell>\n ))}\n </TableRow>\n ));\n}\n\nfunction renderDataRows(columns: TableColumn[], rows: TableRowData[]): ReactNode {\n // `key={index}` is safe today because `rows` is a static fetch result — no sort, filter, or\n // streaming insertion. The moment row order can change (e.g. client-side sort feature), this\n // must switch to a stable per-row identity or React will reconcile incorrectly (inputs lose\n // focus, animations glitch). The data hook will need to surface a row-id at that point.\n return rows.map((row, index) => (\n <TableRow key={index} className={DATA_ROW_CLASSES}>\n {columns.map((column) => (\n <TableCell key={column.key} className={CELL_CLASS}>\n {formatCell(row, column)}\n </TableCell>\n ))}\n </TableRow>\n ));\n}\n\nfunction renderEmptyRow(colSpan: number): ReactNode {\n return (\n <TableRow className=\"hover:bg-transparent\">\n <TableCell colSpan={colSpan} className=\"py-6 text-center text-sm text-muted-foreground\">\n No rows to display.\n </TableCell>\n </TableRow>\n );\n}\n","import { useEffect, useMemo, useState } from \"react\";\n\nimport type { TableColumn, TableRow } from \"@/components/artifacts/types\";\nimport { parseCsv } from \"./parse-csv\";\n\n/**\n * Discriminator for the result returned by `useTableArtifactData`.\n *\n * - `loading` — fetch is in flight (or about to be).\n * - `ready` — payload fetched and parsed successfully.\n * - `error` — fetch or parse failed at runtime; user can retry.\n * - `unavailable` — the artifact has no presigned URL at all (permanent server-side state). Distinct\n * from `error` so the renderer can surface \"data is unavailable\" instead of a misleading \"try again\".\n */\nexport type TableArtifactDataState =\n | { status: \"loading\"; rows: null; error: null }\n | { status: \"ready\"; rows: TableRow[]; error: null }\n | { status: \"error\"; rows: null; error: Error }\n | { status: \"unavailable\"; rows: null; error: null };\n\nconst LOADING: TableArtifactDataState = { status: \"loading\", rows: null, error: null };\nconst UNAVAILABLE: TableArtifactDataState = { status: \"unavailable\", rows: null, error: null };\n\ninterface InternalState {\n /** The cache key the current `data` was fetched for; used to ignore stale data when inputs change. */\n cacheKey: string | null;\n /** The fetch result for `cacheKey`. */\n data: TableArtifactDataState;\n}\n\nconst INITIAL_INTERNAL: InternalState = { cacheKey: null, data: LOADING };\n\n/**\n * Builds a stable fingerprint string for a columns array so the effect only re-runs when the\n * column definitions actually change, not just when the array reference is replaced.\n */\nfunction columnsFingerprint(columns: TableColumn[]): string {\n return columns.map((c) => `${c.key}:${c.type ?? \"string\"}`).join(\"|\");\n}\n\n/**\n * Fetches a table artifact's data payload from a presigned URL and parses it as CSV.\n *\n * The server writes `text/csv` to the presigned URL (io-server PR #2096). This hook fetches with\n * `Accept: text/csv`, reads the body as text, and delegates to `parseCsv` for RFC 4180 parsing\n * and per-column type coercion (CSV strings → typed values per `column.type`).\n *\n * Returns `loading` while the request is in flight, `unavailable` synchronously when no URL is\n * supplied, `ready` on success, or `error` on a runtime failure (HTTP non-2xx, network, or parse\n * error). Parse errors are surfaced as `error` state — they are never thrown.\n *\n * In-flight requests are cancelled via `AbortController` when the URL or columns change, or the\n * consumer unmounts, so abandoned table loads don't keep consuming bandwidth.\n *\n * @param presignedUrl S3 presigned URL for the artifact's CSV file, or `null`/`undefined` when absent.\n * @param columns Column definitions from `TableConfig.columns` — used for per-cell type coercion.\n */\nexport function useTableArtifactData(\n presignedUrl: string | null | undefined,\n columns: TableColumn[]\n): TableArtifactDataState {\n // Stable fingerprint so the effect doesn't re-fire on referentially-new but content-equal column arrays.\n const colsKey = useMemo(() => columnsFingerprint(columns), [columns]);\n\n const cacheKey = presignedUrl ? `${presignedUrl}::${colsKey}` : null;\n\n const [state, setState] = useState<InternalState>(INITIAL_INTERNAL);\n\n useEffect(() => {\n if (!presignedUrl) return;\n\n const controller = new AbortController();\n\n fetch(presignedUrl, {\n signal: controller.signal,\n headers: { Accept: \"text/csv\" },\n // Presigned URLs are cross-origin S3 in production and don't need credentials. Explicit\n // omit so a same-origin URL (compromised payload, local dev) can't accidentally receive\n // session cookies or auth headers.\n credentials: \"omit\",\n })\n .then(async (response) => {\n if (!response.ok) throw new Error(`Failed to load table data (${response.status})`);\n return response.text();\n })\n .then((text) => {\n if (controller.signal.aborted) return;\n try {\n const rows = parseCsv(text, columns);\n setState({ cacheKey: `${presignedUrl}::${colsKey}`, data: { status: \"ready\", rows, error: null } });\n } catch (parseError: unknown) {\n console.error(\"[TableArtifact] CSV parse failed\", parseError);\n const err = parseError instanceof Error ? parseError : new Error(String(parseError));\n setState({ cacheKey: `${presignedUrl}::${colsKey}`, data: { status: \"error\", rows: null, error: err } });\n }\n })\n .catch((error: unknown) => {\n // Per the Fetch spec, `signal.aborted` is set before the promise rejects on abort, so this\n // guard catches every abort case driven by our `controller.abort()` cleanup.\n if (controller.signal.aborted) return;\n console.error(\"[TableArtifact] Fetch failed\", error);\n const err = error instanceof Error ? error : new Error(String(error));\n setState({ cacheKey: `${presignedUrl}::${colsKey}`, data: { status: \"error\", rows: null, error: err } });\n });\n\n return () => {\n controller.abort();\n };\n // `columns` is intentionally omitted from the dep array: `colsKey` is its stable fingerprint\n // (covers every observable change), and `columns` is validated config from a static payload\n // that cannot mutate between effect invocation and fetch resolution. If `columns` ever becomes\n // dynamic (e.g. a future column-reorder UI), this assumption breaks and the suppression must\n // be removed in favour of including `columns` directly.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [presignedUrl, colsKey]);\n\n if (!presignedUrl) return UNAVAILABLE;\n // While the in-flight URL/columns change, cached data belongs to a stale key — return loading until\n // the new fetch resolves. Avoids a synchronous setState() in the effect body (lint forbids that).\n if (state.cacheKey !== cacheKey) return LOADING;\n return state.data;\n}\n","import Papa from \"papaparse\";\n\nimport type { TableColumn, TableRow } from \"@/components/artifacts/types\";\n\n/**\n * Parses a CSV text payload fetched from a presigned URL into `TableRow[]`.\n *\n * Uses `Papa.parse` with `header: true` (first row is the header) and `skipEmptyLines: true`.\n * Every cell arrives as a string — the renderer NEVER coerces values to JS numbers / booleans /\n * dates. Format conversion is a server concern: if a column needs to be `\"Yes/No\"` or\n * `\"$1,234\"`, the server emits it that way in the CSV.\n *\n * Column projection rules:\n * - CSV header columns NOT in `columns[].key` are silently dropped.\n * - `columns[].key` values missing from the CSV header are silently omitted from row output —\n * client-side reconciliation warnings would let the client second-guess the server's contract.\n * Trust the CSV.\n *\n * Empty cells (`\"\"`) are returned as `null` so the renderer can distinguish \"missing value\"\n * from \"empty string\" downstream.\n *\n * @param text Raw CSV text (may start with a UTF-8 BOM which Papa strips automatically).\n * @param columns Column definitions from `TableConfig.columns`.\n * @returns Rows in source order, projected to the configured columns.\n */\nexport function parseCsv(text: string, columns: TableColumn[]): TableRow[] {\n const result = Papa.parse<Record<string, string>>(text, {\n header: true,\n skipEmptyLines: true,\n dynamicTyping: false,\n });\n\n const csvHeaders = new Set(result.meta?.fields ?? []);\n const presentColumns = columns.filter((col) => csvHeaders.has(col.key));\n\n return result.data.map((rawRow) => {\n const row: TableRow = {};\n for (const column of presentColumns) {\n const value = rawRow[column.key];\n row[column.key] = value === undefined || value === \"\" ? null : value;\n }\n return row;\n });\n}\n","import type { TableColumn, TableConfig } from \"@/components/artifacts/types\";\n\n/**\n * Returns true iff `config` carries the minimum-viable shape for rendering: a non-empty array\n * of columns where each has a non-empty `key` and a string `label`.\n *\n * Anything else is trusted to the server. The deprecated `type` / `align` wire fields are NOT\n * validated — clay doesn't act on them, so rejecting unknown values would punish servers\n * shipping fields clay was about to ignore anyway.\n */\nexport function isValidTableConfig(config: unknown): config is TableConfig {\n if (!config || typeof config !== \"object\") return false;\n const candidate = config as { columns?: unknown };\n if (!Array.isArray(candidate.columns)) return false;\n if (candidate.columns.length === 0) return false;\n return candidate.columns.every(isValidTableColumn);\n}\n\n/** Minimum-viable column shape: non-empty string `key` + string `label`. */\nfunction isValidTableColumn(column: unknown): column is TableColumn {\n if (!column || typeof column !== \"object\") return false;\n const candidate = column as Record<string, unknown>;\n if (typeof candidate.key !== \"string\" || candidate.key.length === 0) return false;\n if (typeof candidate.label !== \"string\") return false;\n return true;\n}\n","import type { TableArtifactRecord } from \"@/components/artifacts/types\";\n\n/**\n * Produces a plain-text clipboard representation of a table artifact.\n *\n * Returns the artifact title as plain text so that pasting into non-markdown-aware targets\n * (plain-text editors, terminal, spreadsheets) does not expose raw markdown syntax. This\n * matches the contract of `TextBlockService.toClipboardText`, which also strips markdown —\n * `useCopyToClipboard` writes the aggregated string verbatim, so every block type must\n * independently normalise to plain text.\n *\n * The presigned URL is intentionally omitted from the clipboard value: presigned URLs expire\n * quickly (typically 15 min–1 h) and are not useful when pasted as bare text. The Download\n * button in the artifact chrome is the canonical way to obtain the file.\n */\nexport function tableArtifactToClipboardText(artifact: TableArtifactRecord): string {\n const trimmedTitle = artifact.title?.trim();\n return trimmedTitle || \"Table\";\n}\n","import type { ArtifactService, TableArtifactRecord } from \"../types\";\nimport { artifactTypes } from \"../types\";\nimport { TableArtifact } from \"../table-artifact/table-artifact\";\nimport { tableArtifactToClipboardText } from \"../table-artifact/to-clipboard-text\";\n\nexport const TableArtifactService: ArtifactService<TableArtifactRecord> = {\n type: artifactTypes.TABLE,\n Component: TableArtifact,\n toClipboardText: tableArtifactToClipboardText,\n};\n","import type { ArtifactRecord, ArtifactService, ArtifactType } from \"../types\";\nimport { artifactTypes } from \"../types\";\nimport { TableArtifactService } from \"./table-artifact-service\";\n\n// `ArtifactService<TSpecific>` is invariant on `TSpecific` via React's `ComponentType`\n// (props are contravariant). Each service overlaps structurally with the base `ArtifactService`\n// enough for a direct `as ArtifactService` cast. The registry dispatches only by runtime\n// discriminator — `ArtifactServices[artifact.type]` always resolves to the matching concrete service.\n/**\n * Map of artifact services keyed by `artifact.type`.\n *\n * Adding a new artifact type = create a `*-service.ts` file (mirroring `block-services/`), then\n * add one entry here. The block-level dispatcher (`ArtifactRefBlock`) consumes this map to\n * render the concrete component; `artifactToClipboardText` consumes it for the clipboard contract.\n */\nexport const ArtifactServices: Record<ArtifactType, ArtifactService> = {\n [artifactTypes.TABLE]: TableArtifactService as ArtifactService,\n};\n\n/**\n * Returns a clipboard-friendly string for an artifact, delegating to the registered service's\n * `toClipboardText`. Falls back to `[Artifact: <title>]` when the artifact type has no registered\n * service (unknown type) so copy never silently produces an empty string.\n */\nexport function artifactToClipboardText(artifact: ArtifactRecord): string {\n const entry = ArtifactServices[artifact.type];\n if (!entry) {\n return `[Artifact: ${artifact.title ?? artifact.type}]`;\n }\n return entry.toClipboardText(artifact);\n}\n","import type { ReactNode } from \"react\";\n\nimport { ArtifactServices } from \"@/components/artifacts/artifact-services\";\nimport type { ArtifactRefBlockRecord, BlockComponentProps } from \"../types\";\n\n/**\n * Renders an `ARTIFACT_REF` block by dispatching the inlined artifact to its per-type component.\n *\n * This is the single bridge between the block layer and the artifact layer. It does the\n * `artifact.type → concrete component` lookup directly via the `ArtifactServices` map —\n * there is intentionally no separate `<ArtifactComponent>` JSX dispatcher in between.\n *\n * Unknown artifact types render as `null` (the map only contains types we know how to\n * render). Older clients receiving a future artifact type they don't yet support degrade\n * silently rather than crashing the chat.\n */\nexport function ArtifactRefBlock({ block }: BlockComponentProps<ArtifactRefBlockRecord>): ReactNode {\n const { artifact } = block.payload;\n const entry = ArtifactServices[artifact.type];\n if (!entry) return null;\n const { Component } = entry;\n return <Component artifact={artifact} />;\n}\n","import { artifactToClipboardText } from \"@/components/artifacts/artifact-services\";\nimport { ArtifactRefBlock } from \"../artifact-ref-block/artifact-ref-block\";\nimport { blockTypes } from \"../types\";\nimport type { ArtifactRefBlockRecord, BlockService } from \"../types\";\n\nexport const ArtifactRefBlockService: BlockService<ArtifactRefBlockRecord> = {\n type: blockTypes.ARTIFACT_REF,\n Component: ArtifactRefBlock,\n /**\n * Delegates to the registered artifact component's `toClipboardText`. Falls back to\n * `[Artifact: <title>]` via `artifactToClipboardText`'s own fallback when the artifact type\n * has no registered component, so copy never silently produces an empty string.\n */\n toClipboardText: (block) => artifactToClipboardText(block.payload.artifact),\n};\n","const PLACEHOLDER_PREFIX = \"\\u200B\\u200BIC\";\nconst PLACEHOLDER_SUFFIX = \"\\u200B\\u200B\";\nconst PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\\\d+)${PLACEHOLDER_SUFFIX}`, \"g\");\n\n/**\n * Strips only inline markdown marks (bold, italic, strikethrough) from a string.\n * Does not touch block-level syntax (headings, blockquotes, horizontal rules, links, images)\n * so values like `> 100`, `# items`, or `---` are preserved as-is.\n * @param text - The text to strip inline marks from.\n * @returns The text with inline marks removed.\n */\nexport function stripInlineMarks(text: string): string {\n return (\n text\n // Bold + italic\n .replace(/\\*{3}(.+?)\\*{3}/g, \"$1\")\n // Bold\n .replace(/\\*{2}(.+?)\\*{2}/g, \"$1\")\n .replace(/_{2}(.+?)_{2}/g, \"$1\")\n // Italic\n .replace(/\\*(.+?)\\*/g, \"$1\")\n .replace(/_(.+?)_/g, \"$1\")\n // Strikethrough\n .replace(/~~(.+?)~~/g, \"$1\")\n );\n}\n\n/**\n * Converts a Markdown string to plain text by stripping all formatting syntax.\n *\n * Handles headings, bold/italic/strikethrough, links, images, blockquotes, code blocks,\n * inline code, tables, and horizontal rules. Inline code content is preserved literally\n * (formatting inside backticks is not stripped).\n *\n * @param markdown - The Markdown source string.\n * @returns A plain-text string with all Markdown syntax removed.\n */\nexport function markdownToPlainText(markdown: string): string {\n if (!markdown) return \"\";\n\n // Protect inline code content from bold/italic stripping by replacing with placeholders\n const inlineCodeSnippets: string[] = [];\n let result = markdown\n // HTML comments (e.g. <!-- table-title: ... -->), including multiline and --!> variants\n .replace(/^<!--[\\s\\S]*?--!?>\\n?/gm, \"\")\n // Code blocks (must come first)\n .replace(/```[\\s\\S]*?```/g, \"\")\n // Inline code → placeholder\n .replace(/`([^`]+)`/g, (_match, code: string) => {\n inlineCodeSnippets.push(code);\n return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;\n })\n // Remove headings markers, keep text\n .replace(/^#{1,6}\\s+/gm, \"\")\n // Remove horizontal rules\n .replace(/^(?:---|\\*\\*\\*|___)\\s*$/gm, \"\");\n result = stripInlineMarks(result)\n // Images: ![alt](url) → alt (must come before links)\n .replace(/!\\[([^\\]]*)\\]\\([^)]+\\)/g, \"$1\")\n // Links: [text](url) → text\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, \"$1\")\n // Blockquote markers\n .replace(/^>\\s?/gm, \"\")\n // Table separator rows (|---|---|)\n .replace(/^\\|[-:\\s|]+\\|\\s*$/gm, \"\")\n // Table rows: | a | b | → a | b\n .replace(/^\\|\\s?/gm, \"\")\n .replace(/\\s?\\|$/gm, \"\")\n // Collapse multiple blank lines\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim();\n\n // Restore inline code content\n result = result.replace(PLACEHOLDER_REGEX, (_match, index: string) => inlineCodeSnippets[Number(index)]);\n\n return result;\n}\n","import type { ReactNode } from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkBreaks from \"remark-breaks\";\nimport remarkGfm from \"remark-gfm\";\n\nimport { ScrollableTable } from \"../scrollable-table/scrollable-table\";\nimport type { BlockComponentProps, TextBlockRecord } from \"../types\";\nimport { sanitize } from \"./sanitize\";\nimport { TextBlockWrapper } from \"./text-block-styles\";\n\nconst markdownComponents = {\n table: ((tableProps: { node?: unknown; children?: ReactNode }) => (\n <ScrollableTable {...tableProps} />\n )) as React.ComponentType<unknown>,\n};\n\n/** Renders a TEXT block as Markdown with GFM (tables, strikethrough) and line breaks. */\nexport function TextBlock({ block }: BlockComponentProps<TextBlockRecord>): ReactNode {\n return (\n <TextBlockWrapper>\n <ReactMarkdown remarkPlugins={[remarkGfm, remarkBreaks]} components={markdownComponents}>\n {sanitize(block.payload.text)}\n </ReactMarkdown>\n </TextBlockWrapper>\n );\n}\n","import styled from \"styled-components\";\n\nexport const TableContainer = styled.div`\n position: relative;\n margin-block: 8px 16px;\n`;\n\nexport const TableScroll = styled.div`\n width: 100%;\n overflow-x: auto;\n overflow-y: hidden;\n`;\n","import { type ReactNode } from \"react\";\n\nimport { TableContainer, TableScroll } from \"./scrollable-table-styles\";\n\n/** Props for the ScrollableTable component. */\ninterface ScrollableTableProps {\n /** Unused node prop from react-markdown. */\n node?: unknown;\n /** Table children elements. */\n children?: ReactNode;\n}\n\n/** Renders a markdown table inside a horizontally scrollable wrapper. Read-only — actions live on artifact-tables. */\nexport function ScrollableTable({ node: _node, ...props }: ScrollableTableProps): ReactNode {\n return (\n <TableContainer>\n <TableScroll>\n <table {...props} />\n </TableScroll>\n </TableContainer>\n );\n}\n","// Strips io-server's `<!-- table-title: ... -->` HTML-comment metadata before rendering.\n// The marker is emitted by the server's CSV-export pipeline so the export button can label\n// the file; it has no place in the visual output. If the server-side format changes\n// (prefix, spacing, closing-tag style), this filter silently stops matching and the\n// raw HTML comment leaks into rendered Markdown — keep this contract aligned with io-server.\nexport function sanitize(text: string): string {\n return text\n .split(\"\\n\")\n .filter((line) => {\n const t = line.trim();\n return !(t.startsWith(\"<!-- table-title:\") && t.endsWith(\"-->\"));\n })\n .join(\"\\n\");\n}\n","import styled from \"styled-components\";\n\nimport { colors } from \"@/tokens/colors\";\nimport { typographyMixin, typographyTypes } from \"@/tokens/typography\";\n\nexport const TextBlockWrapper = styled.div`\n ${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};\n color: ${colors[\"brown-100\"]};\n word-break: break-word;\n\n & h1 {\n ${typographyMixin(typographyTypes.GEIST_HEADING_S_BOLD)};\n margin-block: 20px;\n }\n\n & h2 {\n ${typographyMixin(typographyTypes.GEIST_BODY_L_SEMI_BOLD)};\n margin-block: 12px;\n }\n\n & h3,\n & h4,\n & h5,\n & h6 {\n ${typographyMixin(typographyTypes.GEIST_BODY_M_SEMI_BOLD)};\n margin-block: 8px;\n }\n\n & strong {\n ${typographyMixin(typographyTypes.GEIST_BODY_S_SEMI_BOLD)};\n }\n\n & p {\n margin-block: 0px;\n }\n\n & p + p {\n margin-block: 8px 0px;\n }\n\n & ul,\n & ol {\n margin-block: 16px;\n padding-left: 20px;\n }\n\n & li + li {\n margin-block: 4px;\n }\n\n & ol {\n list-style-type: decimal;\n }\n\n & ol ol {\n list-style-type: lower-alpha;\n }\n\n & ol ol ol {\n list-style-type: lower-roman;\n }\n\n & a {\n color: inherit;\n text-decoration-line: underline;\n text-decoration-style: dotted;\n text-decoration-thickness: auto;\n text-underline-offset: auto;\n text-underline-position: from-font;\n transition: color 75ms ease-in-out;\n\n &:hover {\n color: ${colors[\"blue-600\"]};\n }\n }\n\n & hr {\n border: none;\n border-top: 1px solid ${colors[\"brown-40\"]};\n margin-block: 20px;\n }\n\n & table {\n margin: 0;\n width: 100%;\n border-collapse: collapse;\n }\n\n & th,\n & td {\n border: none;\n border-bottom: 1px solid ${colors[\"brown-40\"]};\n text-align: left;\n }\n\n & th {\n ${typographyMixin(typographyTypes.GEIST_LABEL_CAPTION_MEDIUM)};\n padding: 8px;\n }\n\n & td {\n ${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};\n padding: 16px 8px;\n min-width: 150px;\n width: 1%;\n }\n\n & td strong {\n font-weight: inherit;\n font-size: inherit;\n line-height: inherit;\n }\n\n & blockquote {\n margin-block: 4px;\n margin-inline: 0px;\n padding-left: 16px;\n border-left: 4px solid ${colors[\"brown-40\"]};\n color: ${colors[\"brown-80\"]};\n }\n`;\n","/** Available font families in the Shapes.co design system. */\nexport const fontFamilies = {\n /** Geist — primary UI font for body text, labels, headings, and display. */\n GEIST: \"Geist\",\n /** Crimson Pro — editorial/serif font, always italic. Used for decorative headings and pull quotes. */\n CRIMSON_PRO: \"Crimson Pro\",\n} as const;\n\nexport const typographyTypes = {\n // Geist Label Caption (12px)\n GEIST_LABEL_CAPTION_REGULAR: \"GEIST_LABEL_CAPTION_REGULAR\",\n GEIST_LABEL_CAPTION_MEDIUM: \"GEIST_LABEL_CAPTION_MEDIUM\",\n GEIST_LABEL_CAPTION_SEMI_BOLD: \"GEIST_LABEL_CAPTION_SEMI_BOLD\",\n\n // Geist Body Extra Small (14px)\n GEIST_BODY_XS_REGULAR: \"GEIST_BODY_XS_REGULAR\",\n GEIST_BODY_XS_MEDIUM: \"GEIST_BODY_XS_MEDIUM\",\n GEIST_BODY_XS_BOLD: \"GEIST_BODY_XS_BOLD\",\n\n // Geist Body Small (16px)\n GEIST_BODY_S_REGULAR: \"GEIST_BODY_S_REGULAR\",\n GEIST_BODY_S_MEDIUM: \"GEIST_BODY_S_MEDIUM\",\n GEIST_BODY_S_SEMI_BOLD: \"GEIST_BODY_S_SEMI_BOLD\",\n GEIST_BODY_S_BOLD: \"GEIST_BODY_S_BOLD\",\n\n // Geist Body Medium (18px)\n GEIST_BODY_M_LIGHT: \"GEIST_BODY_M_LIGHT\",\n GEIST_BODY_M_REGULAR: \"GEIST_BODY_M_REGULAR\",\n GEIST_BODY_M_MEDIUM: \"GEIST_BODY_M_MEDIUM\",\n GEIST_BODY_M_SEMI_BOLD: \"GEIST_BODY_M_SEMI_BOLD\",\n\n // Geist Body Large (20px)\n GEIST_BODY_L_REGULAR: \"GEIST_BODY_L_REGULAR\",\n GEIST_BODY_L_MEDIUM: \"GEIST_BODY_L_MEDIUM\",\n GEIST_BODY_L_SEMI_BOLD: \"GEIST_BODY_L_SEMI_BOLD\",\n GEIST_BODY_L_BOLD: \"GEIST_BODY_L_BOLD\",\n\n // Geist Heading Small (24px)\n GEIST_HEADING_S_REGULAR: \"GEIST_HEADING_S_REGULAR\",\n GEIST_HEADING_S_MEDIUM: \"GEIST_HEADING_S_MEDIUM\",\n GEIST_HEADING_S_BOLD: \"GEIST_HEADING_S_BOLD\",\n\n // Geist Heading Medium (28px)\n GEIST_HEADING_M_BOLD: \"GEIST_HEADING_M_BOLD\",\n\n // Geist Heading Large (32px)\n GEIST_HEADING_L_REGULAR: \"GEIST_HEADING_L_REGULAR\",\n GEIST_HEADING_L_MEDIUM: \"GEIST_HEADING_L_MEDIUM\",\n GEIST_HEADING_L_SEMI_BOLD: \"GEIST_HEADING_L_SEMI_BOLD\",\n GEIST_HEADING_L_BOLD: \"GEIST_HEADING_L_BOLD\",\n\n // Geist Display Large (36px)\n GEIST_DISPLAY_L_MEDIUM: \"GEIST_DISPLAY_L_MEDIUM\",\n\n // Crimson Pro Body Small (16px)\n CRIMSON_PRO_BODY_S_LIGHT: \"CRIMSON_PRO_BODY_S_LIGHT\",\n\n // Crimson Pro Body Medium (18px)\n CRIMSON_PRO_BODY_M_LIGHT: \"CRIMSON_PRO_BODY_M_LIGHT\",\n\n // Crimson Pro Heading Medium (24px)\n CRIMSON_PRO_HEADING_M_MEDIUM: \"CRIMSON_PRO_HEADING_M_MEDIUM\",\n\n // Crimson Pro Display Extra Large (46px)\n CRIMSON_PRO_DISPLAY_XL_REGULAR: \"CRIMSON_PRO_DISPLAY_XL_REGULAR\",\n} as const;\n\n/** Union of all typography type string constants. Used as keys into `typographyStyles`. */\nexport type TypographyType = (typeof typographyTypes)[keyof typeof typographyTypes];\n\n/** CSS properties for a single typography type. All numeric values are in pixels. */\nexport interface TypographyStyle {\n /** Font family name (e.g., \"Geist\"). */\n fontFamily: string;\n /** Font size in pixels. */\n fontSize: number;\n /** Font weight (100–900). */\n fontWeight: number;\n /** Line height in pixels. */\n lineHeight: number;\n /** Letter spacing in pixels. Omitted when the font's default spacing is correct. */\n letterSpacing?: number;\n /** CSS font-style value (e.g., \"italic\"). Omitted for normal style. */\n fontStyle?: string;\n}\n\nexport const typographyStyles: Record<TypographyType, TypographyStyle> = {\n // Geist Label Caption (12px)\n [typographyTypes.GEIST_LABEL_CAPTION_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 12,\n fontWeight: 400,\n lineHeight: 16,\n },\n [typographyTypes.GEIST_LABEL_CAPTION_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 12,\n fontWeight: 500,\n lineHeight: 16,\n },\n [typographyTypes.GEIST_LABEL_CAPTION_SEMI_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 12,\n fontWeight: 600,\n lineHeight: 16,\n },\n\n // Geist Body Extra Small (14px)\n [typographyTypes.GEIST_BODY_XS_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 14,\n fontWeight: 400,\n lineHeight: 20,\n },\n [typographyTypes.GEIST_BODY_XS_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 14,\n fontWeight: 500,\n lineHeight: 20,\n },\n [typographyTypes.GEIST_BODY_XS_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 14,\n fontWeight: 600,\n lineHeight: 20,\n },\n\n // Geist Body Small (16px)\n [typographyTypes.GEIST_BODY_S_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 16,\n fontWeight: 400,\n lineHeight: 24,\n letterSpacing: -0.08,\n },\n [typographyTypes.GEIST_BODY_S_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 16,\n fontWeight: 500,\n lineHeight: 24,\n letterSpacing: -0.08,\n },\n [typographyTypes.GEIST_BODY_S_SEMI_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 16,\n fontWeight: 600,\n lineHeight: 24,\n letterSpacing: -0.08,\n },\n [typographyTypes.GEIST_BODY_S_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 16,\n fontWeight: 700,\n lineHeight: 24,\n letterSpacing: -0.08,\n },\n\n // Geist Body Medium (18px)\n [typographyTypes.GEIST_BODY_M_LIGHT]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 18,\n fontWeight: 300,\n lineHeight: 28,\n letterSpacing: -0.09,\n },\n [typographyTypes.GEIST_BODY_M_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 18,\n fontWeight: 400,\n lineHeight: 28,\n letterSpacing: -0.09,\n },\n [typographyTypes.GEIST_BODY_M_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 18,\n fontWeight: 500,\n lineHeight: 28,\n letterSpacing: -0.09,\n },\n [typographyTypes.GEIST_BODY_M_SEMI_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 18,\n fontWeight: 600,\n lineHeight: 28,\n letterSpacing: -0.09,\n },\n\n // Geist Body Large (20px)\n [typographyTypes.GEIST_BODY_L_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 20,\n fontWeight: 400,\n lineHeight: 30,\n letterSpacing: -0.2,\n },\n [typographyTypes.GEIST_BODY_L_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 20,\n fontWeight: 500,\n lineHeight: 30,\n letterSpacing: -0.2,\n },\n [typographyTypes.GEIST_BODY_L_SEMI_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 20,\n fontWeight: 600,\n lineHeight: 30,\n letterSpacing: -0.2,\n },\n [typographyTypes.GEIST_BODY_L_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 20,\n fontWeight: 700,\n lineHeight: 30,\n letterSpacing: -0.2,\n },\n\n // Geist Heading Small (24px)\n [typographyTypes.GEIST_HEADING_S_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 24,\n fontWeight: 400,\n lineHeight: 32,\n letterSpacing: -0.48,\n },\n [typographyTypes.GEIST_HEADING_S_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 24,\n fontWeight: 500,\n lineHeight: 32,\n letterSpacing: -0.48,\n },\n [typographyTypes.GEIST_HEADING_S_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 24,\n fontWeight: 700,\n lineHeight: 32,\n letterSpacing: -0.48,\n },\n\n // Geist Heading Medium (28px)\n [typographyTypes.GEIST_HEADING_M_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 28,\n fontWeight: 700,\n lineHeight: 36,\n letterSpacing: -0.6,\n },\n\n // Geist Heading Large (32px)\n [typographyTypes.GEIST_HEADING_L_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 32,\n fontWeight: 400,\n lineHeight: 40,\n letterSpacing: -0.64,\n },\n [typographyTypes.GEIST_HEADING_L_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 32,\n fontWeight: 500,\n lineHeight: 40,\n letterSpacing: -0.64,\n },\n [typographyTypes.GEIST_HEADING_L_SEMI_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 32,\n fontWeight: 600,\n lineHeight: 40,\n letterSpacing: -0.64,\n },\n [typographyTypes.GEIST_HEADING_L_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 32,\n fontWeight: 700,\n lineHeight: 40,\n letterSpacing: -0.64,\n },\n\n // Geist Display Large (36px)\n [typographyTypes.GEIST_DISPLAY_L_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 36,\n fontWeight: 500,\n lineHeight: 44,\n letterSpacing: -0.72,\n },\n\n // Crimson Pro Body Small (16px)\n [typographyTypes.CRIMSON_PRO_BODY_S_LIGHT]: {\n fontFamily: fontFamilies.CRIMSON_PRO,\n fontSize: 16,\n fontWeight: 300,\n lineHeight: 20,\n letterSpacing: -0.32,\n fontStyle: \"italic\",\n },\n\n // Crimson Pro Body Medium (18px)\n [typographyTypes.CRIMSON_PRO_BODY_M_LIGHT]: {\n fontFamily: fontFamilies.CRIMSON_PRO,\n fontSize: 18,\n fontWeight: 300,\n lineHeight: 28,\n letterSpacing: 0,\n fontStyle: \"italic\",\n },\n\n // Crimson Pro Heading Medium (24px)\n [typographyTypes.CRIMSON_PRO_HEADING_M_MEDIUM]: {\n fontFamily: fontFamilies.CRIMSON_PRO,\n fontSize: 24,\n fontWeight: 400,\n lineHeight: 32,\n letterSpacing: -0.48,\n fontStyle: \"italic\",\n },\n\n // Crimson Pro Display Extra Large (46px)\n [typographyTypes.CRIMSON_PRO_DISPLAY_XL_REGULAR]: {\n fontFamily: fontFamilies.CRIMSON_PRO,\n fontSize: 46,\n fontWeight: 400,\n lineHeight: 54,\n letterSpacing: -1.38,\n fontStyle: \"italic\",\n },\n};\n\n/**\n * Generates a CSS string for a given typography type, suitable for use in styled-components template literals.\n * @param type - The typography type constant (e.g., `typographyTypes.GEIST_BODY_S_REGULAR`).\n * @returns A semicolon-separated CSS string with font-family, font-size, font-weight, line-height, letter-spacing, and font-style.\n */\nexport function typographyMixin(type: TypographyType): string {\n const style = typographyStyles[type];\n return [\n `font-family: \"${style.fontFamily}\", sans-serif`,\n `font-size: ${style.fontSize}px`,\n `font-weight: ${style.fontWeight}`,\n `line-height: ${style.lineHeight}px`,\n `letter-spacing: ${style.letterSpacing != null ? `${style.letterSpacing}px` : \"inherit\"}`,\n `font-style: ${style.fontStyle ?? \"normal\"}`,\n ].join(\";\\n \");\n}\n","import { markdownToPlainText } from \"@/utils/markdown-to-plain-text\";\nimport { TextBlock } from \"../text-block/text-block\";\nimport { blockTypes } from \"../types\";\nimport type { BlockService, TextBlockRecord } from \"../types\";\n\nexport const TextBlockService: BlockService<TextBlockRecord> = {\n type: blockTypes.TEXT,\n Component: TextBlock,\n /**\n * Converts the block's markdown source to plain text so the final clipboard value is clean\n * when pasted into tools that don't render markdown. Each block type owns its own clipboard\n * conversion so `useCopyToClipboard` can write text verbatim without a second pass.\n */\n toClipboardText: (block) => markdownToPlainText(block.payload.text),\n};\n","import { blockTypes, type BlockService, type BlockType } from \"../types\";\nimport { ArtifactRefBlockService } from \"./artifact-ref-block-service\";\nimport { TextBlockService } from \"./text-block-service\";\n\n// `BlockService<TBlock>` is invariant on `TBlock` via React's `ComponentType` (props are\n// contravariant). The concrete services overlap structurally with the base `BlockService` type\n// enough for a direct `as BlockService` cast. The registry dispatches by runtime discriminator —\n// `BlockServices[block.type]` always resolves to the matching concrete service — so the cast is sound.\nexport const BlockServices: Record<BlockType, BlockService> = {\n [blockTypes.TEXT]: TextBlockService as BlockService,\n [blockTypes.ARTIFACT_REF]: ArtifactRefBlockService as BlockService,\n};\n","import type { ReactNode } from \"react\";\n\nimport { BlockServices } from \"../block-services\";\nimport type { BlockRecord } from \"../types\";\n\n/** Props for the Block dispatcher. */\ninterface BlockProps {\n /** The block to render. Dispatched to the registered concrete component for its `type`. */\n block: BlockRecord;\n}\n\n/** Dispatches a single block to its registered concrete component. Unknown types render as a no-op. */\nexport function Block({ block }: BlockProps): ReactNode {\n const service = BlockServices[block.type];\n if (!service) return null;\n const { Component } = service;\n return <Component block={block} />;\n}\n","import { createContext, useContext } from \"react\";\n\n/** Renderer-level concerns provided to descendants of any `Block`-rendering tree. */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- placeholder to preserve API while the surface area is scoped down\nexport interface BlockContextValue {}\n\nexport const BlockContext = createContext<BlockContextValue | null>(null);\n\n/** Returns the ambient block-rendering context. Returns an empty object outside a `<BlockContext.Provider>`. */\nexport function useBlockContext(): BlockContextValue {\n return useContext(BlockContext) ?? {};\n}\n"],"mappings":"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","names":["import_react","import_react","import_react","styled","import_jsx_runtime","Icon","import_styled_components","styled","import_jsx_runtime","IconButton","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_react","Papa","import_jsx_runtime","import_jsx_runtime","import_styled_components","styled","import_jsx_runtime","import_styled_components","styled","import_jsx_runtime","ReactMarkdown","remarkGfm","remarkBreaks","import_jsx_runtime","import_react"]}
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-sans:"Geist", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-serif:"Crimson Pro", Georgia, "Times New Roman", serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-500:#ef4444;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--radius-sm:calc(var(--radius) - 4px);--radius-md:calc(var(--radius) - 2px);--radius-lg:var(--radius);--radius-xl:calc(var(--radius) + 4px);--radius-2xl:1rem;--ease-in:cubic-bezier(.4, 0, 1, 1);--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--blur-lg:16px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:"Geist", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--default-mono-font-family:var(--font-mono);--color-brown-10:#faf9f8;--color-brown-20:#f5f3f0;--color-brown-30:#eeebe5;--color-brown-40:#e6e2da;--color-brown-60:#a19e99;--color-brown-70:#73716d;--color-brown-90:#2e2d2c;--color-brown-100:#171716;--color-background:var(--color-white);--color-foreground:var(--color-brown-100);--color-popover:var(--color-white);--color-muted:var(--color-brown-10);--color-border:var(--color-brown-40)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*,:after,:before{border-color:var(--color-border)}}@layer components;@layer utilities{.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.z-10{z-index:10}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mt-4{margin-top:calc(var(--spacing) * 4)}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline{display:inline}.table{display:table}.h-3{height:calc(var(--spacing) * 3)}.h-12{height:calc(var(--spacing) * 12)}.h-auto{height:auto}.w-3\/4{width:75%}.w-full{width:100%}.min-w-\[150px\]{min-width:150px}.flex-1{flex:1}.flex-shrink{flex-shrink:1}.caption-bottom{caption-side:bottom}.border-collapse{border-collapse:collapse}.origin-\[--radix-tooltip-content-transform-origin\]{transform-origin:--radix-tooltip-content-transform-origin}.animate-in{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.animate-pulse{animation:var(--animate-pulse)}.resize{resize:both}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.gap-1{gap:calc(var(--spacing) * 1)}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overscroll-none{overscroll-behavior:none}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-border{border-color:var(--color-brown-40)}.border-brown-alpha-12{border-color:#1717161f}.border-b-brown-30{border-bottom-color:#eeebe5}.bg-\[…\]{background-color:…}.bg-background{background-color:var(--color-white)}.bg-background\/70{background-color:#ffffffb3}@supports (color:color-mix(in lab, red, red)){.bg-background\/70{background-color:color-mix(in oklab, var(--color-white) 70%, transparent)}}.bg-brown-30{background-color:#eeebe5}.bg-brown-100{background-color:#171716}.bg-muted{background-color:var(--color-brown-10)}.bg-muted-foreground\/20{background-color:#73716d33}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\/20{background-color:color-mix(in oklab, var(--color-brown-70) 20%, transparent)}}.bg-muted\/50{background-color:#faf9f880}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab, var(--color-brown-10) 50%, transparent)}}.bg-popover{background-color:var(--color-white)}.bg-secondary{background-color:var(--color-brown-20)}.bg-white-alpha-85{background-color:#ffffffd9}.p-0{padding:calc(var(--spacing) * 0)}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-6{padding-block:calc(var(--spacing) * 6)}.text-center{text-align:center}.text-left{text-align:left}.align-middle{vertical-align:middle}.align-top{vertical-align:top}.font-sans{font-family:Geist,Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.font-serif{font-family:Crimson Pro,Georgia,Times New Roman,serif}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-brown-70{color:#73716d}.text-foreground{color:var(--color-brown-100)}.text-fuchsia-500{color:#d946ef}.text-muted-foreground{color:var(--color-brown-70)}.text-popover-foreground{color:var(--color-brown-100)}.text-red-600{color:#dc2626}.lowercase{text-transform:lowercase}.italic{font-style:italic}.accent-foreground{accent-color:var(--color-brown-100)}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.drop-shadow{--tw-drop-shadow-size:drop-shadow(0 1px 2px var(--tw-drop-shadow-color,#0000001a)) drop-shadow(0 1px 1px var(--tw-drop-shadow-color,#0000000f));--tw-drop-shadow:drop-shadow(0 1px 2px #0000001a) drop-shadow(0 1px 1px #0000000f);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-lg{--tw-backdrop-blur:blur(var(--blur-lg));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in{--tw-ease:var(--ease-in);transition-timing-function:var(--ease-in)}.fade-in-0{--tw-enter-opacity:0}.zoom-in-95{--tw-enter-scale:.95}.fade-in{--tw-enter-opacity:0}.running{animation-play-state:running}@media (hover:hover){.hover\:bg-muted\/50:hover{background-color:#faf9f880}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab, var(--color-brown-10) 50%, transparent)}}.hover\:bg-secondary:hover{background-color:var(--color-brown-20)}.hover\:bg-transparent:hover{background-color:#0000}}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y:calc(2*var(--spacing)*-1)}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x:calc(2*var(--spacing))}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x:calc(2*var(--spacing)*-1)}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y:calc(2*var(--spacing))}.data-\[state\=closed\]\:animate-out[data-state=closed]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale:.95}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:var(--color-brown-10)}.\[\&_tr\]\:border-b tr{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-style:var(--tw-border-style);border-width:0}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:calc(var(--spacing) * 0)}.\[\&\>tr\]\:last\:border-b-0>tr:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}:root{--radius:10px}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0));filter:blur(var(--tw-exit-blur,0))}}
@@ -0,0 +1,41 @@
1
+ import * as React from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { a as BlockRecord, c as BlockType, b as BlockService, A as ArtifactRefBlockRecord, T as TextBlockRecord, B as BlockComponentProps } from './types-DuuRI4ll.cjs';
4
+ export { d as blockTypes } from './types-DuuRI4ll.cjs';
5
+ import './types-3Gzk7cRt.cjs';
6
+
7
+ /** Props for the Block dispatcher. */
8
+ interface BlockProps {
9
+ /** The block to render. Dispatched to the registered concrete component for its `type`. */
10
+ block: BlockRecord;
11
+ }
12
+ /** Dispatches a single block to its registered concrete component. Unknown types render as a no-op. */
13
+ declare function Block({ block }: BlockProps): ReactNode;
14
+
15
+ /** Renderer-level concerns provided to descendants of any `Block`-rendering tree. */
16
+ interface BlockContextValue {
17
+ }
18
+ declare const BlockContext: React.Context<BlockContextValue | null>;
19
+ /** Returns the ambient block-rendering context. Returns an empty object outside a `<BlockContext.Provider>`. */
20
+ declare function useBlockContext(): BlockContextValue;
21
+
22
+ declare const BlockServices: Record<BlockType, BlockService>;
23
+
24
+ declare const ArtifactRefBlockService: BlockService<ArtifactRefBlockRecord>;
25
+
26
+ declare const TextBlockService: BlockService<TextBlockRecord>;
27
+
28
+ /**
29
+ * Renders an `ARTIFACT_REF` block by dispatching the inlined artifact to its per-type component.
30
+ *
31
+ * This is the single bridge between the block layer and the artifact layer. It does the
32
+ * `artifact.type → concrete component` lookup directly via the `ArtifactServices` map —
33
+ * there is intentionally no separate `<ArtifactComponent>` JSX dispatcher in between.
34
+ *
35
+ * Unknown artifact types render as `null` (the map only contains types we know how to
36
+ * render). Older clients receiving a future artifact type they don't yet support degrade
37
+ * silently rather than crashing the chat.
38
+ */
39
+ declare function ArtifactRefBlock({ block }: BlockComponentProps<ArtifactRefBlockRecord>): ReactNode;
40
+
41
+ export { ArtifactRefBlock, ArtifactRefBlockRecord, ArtifactRefBlockService, Block, BlockComponentProps, BlockContext, type BlockContextValue, BlockRecord, BlockService, BlockServices, BlockType, TextBlockRecord, TextBlockService, useBlockContext };
@@ -0,0 +1,41 @@
1
+ import * as React from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { a as BlockRecord, c as BlockType, b as BlockService, A as ArtifactRefBlockRecord, T as TextBlockRecord, B as BlockComponentProps } from './types-C9XX-Uhk.js';
4
+ export { d as blockTypes } from './types-C9XX-Uhk.js';
5
+ import './types-3Gzk7cRt.js';
6
+
7
+ /** Props for the Block dispatcher. */
8
+ interface BlockProps {
9
+ /** The block to render. Dispatched to the registered concrete component for its `type`. */
10
+ block: BlockRecord;
11
+ }
12
+ /** Dispatches a single block to its registered concrete component. Unknown types render as a no-op. */
13
+ declare function Block({ block }: BlockProps): ReactNode;
14
+
15
+ /** Renderer-level concerns provided to descendants of any `Block`-rendering tree. */
16
+ interface BlockContextValue {
17
+ }
18
+ declare const BlockContext: React.Context<BlockContextValue | null>;
19
+ /** Returns the ambient block-rendering context. Returns an empty object outside a `<BlockContext.Provider>`. */
20
+ declare function useBlockContext(): BlockContextValue;
21
+
22
+ declare const BlockServices: Record<BlockType, BlockService>;
23
+
24
+ declare const ArtifactRefBlockService: BlockService<ArtifactRefBlockRecord>;
25
+
26
+ declare const TextBlockService: BlockService<TextBlockRecord>;
27
+
28
+ /**
29
+ * Renders an `ARTIFACT_REF` block by dispatching the inlined artifact to its per-type component.
30
+ *
31
+ * This is the single bridge between the block layer and the artifact layer. It does the
32
+ * `artifact.type → concrete component` lookup directly via the `ArtifactServices` map —
33
+ * there is intentionally no separate `<ArtifactComponent>` JSX dispatcher in between.
34
+ *
35
+ * Unknown artifact types render as `null` (the map only contains types we know how to
36
+ * render). Older clients receiving a future artifact type they don't yet support degrade
37
+ * silently rather than crashing the chat.
38
+ */
39
+ declare function ArtifactRefBlock({ block }: BlockComponentProps<ArtifactRefBlockRecord>): ReactNode;
40
+
41
+ export { ArtifactRefBlock, ArtifactRefBlockRecord, ArtifactRefBlockService, Block, BlockComponentProps, BlockContext, type BlockContextValue, BlockRecord, BlockService, BlockServices, BlockType, TextBlockRecord, TextBlockService, useBlockContext };
package/dist/blocks.js ADDED
@@ -0,0 +1,31 @@
1
+ import {
2
+ BlockContext,
3
+ useBlockContext
4
+ } from "./chunk-JGMN6W72.js";
5
+ import {
6
+ ArtifactRefBlock,
7
+ ArtifactRefBlockService,
8
+ Block,
9
+ BlockServices,
10
+ TextBlockService,
11
+ blockTypes
12
+ } from "./chunk-MXOPG747.js";
13
+ import "./chunk-NMKKU2UG.js";
14
+ import "./chunk-SV24ONND.js";
15
+ import "./chunk-BX5TCEPR.js";
16
+ import "./chunk-L35M3OD5.js";
17
+ import "./chunk-OBOXCBDL.js";
18
+ import "./chunk-OLJIJYB5.js";
19
+ import "./chunk-JF3P66JF.js";
20
+ import "./chunk-5WRI5ZAA.js";
21
+ export {
22
+ ArtifactRefBlock,
23
+ ArtifactRefBlockService,
24
+ Block,
25
+ BlockContext,
26
+ BlockServices,
27
+ TextBlockService,
28
+ blockTypes,
29
+ useBlockContext
30
+ };
31
+ //# sourceMappingURL=blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/button.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react from 'react';
1
+ import * as React$1 from 'react';
2
2
  import { ComponentType, SVGProps } from 'react';
3
3
 
4
4
  /** Available visual style variants for the Button component. */
@@ -57,6 +57,6 @@ interface ButtonProps {
57
57
  }
58
58
 
59
59
  /** A versatile button component with multiple variants and sizes. */
60
- declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
60
+ declare const Button: React$1.ForwardRefExoticComponent<ButtonProps & React$1.RefAttributes<HTMLButtonElement>>;
61
61
 
62
62
  export { BUTTON_INTENT, BUTTON_SIZE, BUTTON_VARIANT, Button, type ButtonIntent, type ButtonProps, type ButtonSize, type ButtonVariant, ICON_POSITION, type IconPosition };
package/dist/button.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react from 'react';
1
+ import * as React$1 from 'react';
2
2
  import { ComponentType, SVGProps } from 'react';
3
3
 
4
4
  /** Available visual style variants for the Button component. */
@@ -57,6 +57,6 @@ interface ButtonProps {
57
57
  }
58
58
 
59
59
  /** A versatile button component with multiple variants and sizes. */
60
- declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
60
+ declare const Button: React$1.ForwardRefExoticComponent<ButtonProps & React$1.RefAttributes<HTMLButtonElement>>;
61
61
 
62
62
  export { BUTTON_INTENT, BUTTON_SIZE, BUTTON_VARIANT, Button, type ButtonIntent, type ButtonProps, type ButtonSize, type ButtonVariant, ICON_POSITION, type IconPosition };