@hex-core/components 1.8.1 → 1.10.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 (158) hide show
  1. package/dist/_tsup-dts-rollup.d.ts +855 -18
  2. package/dist/accordion.js.map +1 -1
  3. package/dist/alert-dialog.js.map +1 -1
  4. package/dist/alert.js.map +1 -1
  5. package/dist/arc.js.map +1 -1
  6. package/dist/attachment.js.map +1 -1
  7. package/dist/audio-player.js.map +1 -1
  8. package/dist/audio-waveform.js.map +1 -1
  9. package/dist/auth-forgot-password.d.ts +2 -0
  10. package/dist/auth-forgot-password.js +400 -0
  11. package/dist/auth-forgot-password.js.map +1 -0
  12. package/dist/auth-reset-password.d.ts +2 -0
  13. package/dist/auth-reset-password.js +323 -0
  14. package/dist/auth-reset-password.js.map +1 -0
  15. package/dist/auth-sign-in-split.d.ts +3 -0
  16. package/dist/auth-sign-in-split.js +443 -0
  17. package/dist/auth-sign-in-split.js.map +1 -0
  18. package/dist/auth-sign-up-card.d.ts +3 -0
  19. package/dist/auth-sign-up-card.js +590 -0
  20. package/dist/auth-sign-up-card.js.map +1 -0
  21. package/dist/auth-verify-email.d.ts +2 -0
  22. package/dist/auth-verify-email.js +339 -0
  23. package/dist/auth-verify-email.js.map +1 -0
  24. package/dist/auth-verify-otp.d.ts +2 -0
  25. package/dist/auth-verify-otp.js +349 -0
  26. package/dist/auth-verify-otp.js.map +1 -0
  27. package/dist/avatar.js.map +1 -1
  28. package/dist/badge.js.map +1 -1
  29. package/dist/branch.d.ts +2 -0
  30. package/dist/branch.js +136 -0
  31. package/dist/branch.js.map +1 -0
  32. package/dist/breadcrumb.js.map +1 -1
  33. package/dist/button.js.map +1 -1
  34. package/dist/calendar.js.map +1 -1
  35. package/dist/canvas.js.map +1 -1
  36. package/dist/card.js.map +1 -1
  37. package/dist/chain-of-thought.d.ts +3 -0
  38. package/dist/chain-of-thought.js +119 -0
  39. package/dist/chain-of-thought.js.map +1 -0
  40. package/dist/checkbox.js.map +1 -1
  41. package/dist/chord.js.map +1 -1
  42. package/dist/citation.js.map +1 -1
  43. package/dist/cloze.js.map +1 -1
  44. package/dist/cluster.js.map +1 -1
  45. package/dist/code-block-copy.js.map +1 -1
  46. package/dist/code-block.js.map +1 -1
  47. package/dist/color-picker.js.map +1 -1
  48. package/dist/combobox.js.map +1 -1
  49. package/dist/command.js.map +1 -1
  50. package/dist/compare-table.js.map +1 -1
  51. package/dist/composer.js.map +1 -1
  52. package/dist/container.js.map +1 -1
  53. package/dist/context-menu.js.map +1 -1
  54. package/dist/conversation.d.ts +3 -0
  55. package/dist/conversation.js +358 -0
  56. package/dist/conversation.js.map +1 -0
  57. package/dist/data-table.js.map +1 -1
  58. package/dist/date-picker.js.map +1 -1
  59. package/dist/deck.js.map +1 -1
  60. package/dist/dendrogram.js.map +1 -1
  61. package/dist/diagram.js.map +1 -1
  62. package/dist/dialog.js.map +1 -1
  63. package/dist/drawer.js.map +1 -1
  64. package/dist/dropdown-menu.js.map +1 -1
  65. package/dist/dropzone.js.map +1 -1
  66. package/dist/empty.js.map +1 -1
  67. package/dist/error-state.js.map +1 -1
  68. package/dist/file-tree.js.map +1 -1
  69. package/dist/flashcard.js.map +1 -1
  70. package/dist/flowchart.js.map +1 -1
  71. package/dist/form.js.map +1 -1
  72. package/dist/funnel.js.map +1 -1
  73. package/dist/gantt.js.map +1 -1
  74. package/dist/grid.js.map +1 -1
  75. package/dist/hover-card.js.map +1 -1
  76. package/dist/image-occlusion.js.map +1 -1
  77. package/dist/index.d.ts +40 -0
  78. package/dist/index.js +4839 -2813
  79. package/dist/index.js.map +1 -1
  80. package/dist/inline-citation.d.ts +2 -0
  81. package/dist/inline-citation.js +108 -0
  82. package/dist/inline-citation.js.map +1 -0
  83. package/dist/input-otp.js.map +1 -1
  84. package/dist/input.js.map +1 -1
  85. package/dist/label.js.map +1 -1
  86. package/dist/loading-indicator.js.map +1 -1
  87. package/dist/loading.js.map +1 -1
  88. package/dist/markdown.d.ts +1 -0
  89. package/dist/markdown.js +784 -4
  90. package/dist/markdown.js.map +1 -1
  91. package/dist/matrix.js.map +1 -1
  92. package/dist/menubar.js.map +1 -1
  93. package/dist/message-actions.js.map +1 -1
  94. package/dist/message-list.js.map +1 -1
  95. package/dist/message.js.map +1 -1
  96. package/dist/mind-map.js.map +1 -1
  97. package/dist/multi-combobox.js.map +1 -1
  98. package/dist/navigation-menu.js.map +1 -1
  99. package/dist/org-chart.js.map +1 -1
  100. package/dist/pagination.js.map +1 -1
  101. package/dist/plan.d.ts +3 -0
  102. package/dist/plan.js +183 -0
  103. package/dist/plan.js.map +1 -0
  104. package/dist/popover.js.map +1 -1
  105. package/dist/progress.js.map +1 -1
  106. package/dist/pyramid.js.map +1 -1
  107. package/dist/quiz.js.map +1 -1
  108. package/dist/radio-group.js.map +1 -1
  109. package/dist/reasoning.js.map +1 -1
  110. package/dist/resizable.js.map +1 -1
  111. package/dist/sankey.js.map +1 -1
  112. package/dist/schemas.d.ts +8 -0
  113. package/dist/schemas.js +774 -17
  114. package/dist/schemas.js.map +1 -1
  115. package/dist/scroll-area.js.map +1 -1
  116. package/dist/select.js.map +1 -1
  117. package/dist/separator.js.map +1 -1
  118. package/dist/sequence.js.map +1 -1
  119. package/dist/sheet.js.map +1 -1
  120. package/dist/shimmer.d.ts +2 -0
  121. package/dist/shimmer.js +39 -0
  122. package/dist/shimmer.js.map +1 -0
  123. package/dist/sidebar.js.map +1 -1
  124. package/dist/skeleton.js.map +1 -1
  125. package/dist/slider.js.map +1 -1
  126. package/dist/sources.d.ts +3 -0
  127. package/dist/sources.js +164 -0
  128. package/dist/sources.js.map +1 -0
  129. package/dist/spaced-repetition.js.map +1 -1
  130. package/dist/spacer.js.map +1 -1
  131. package/dist/speech-recognition.js.map +1 -1
  132. package/dist/stack.js.map +1 -1
  133. package/dist/stepper.js.map +1 -1
  134. package/dist/suggestion.js.map +1 -1
  135. package/dist/sunburst.js.map +1 -1
  136. package/dist/switch.js.map +1 -1
  137. package/dist/table.js.map +1 -1
  138. package/dist/tabs.js.map +1 -1
  139. package/dist/tag.js.map +1 -1
  140. package/dist/task.d.ts +3 -0
  141. package/dist/task.js +189 -0
  142. package/dist/task.js.map +1 -0
  143. package/dist/terminal.js +11 -0
  144. package/dist/terminal.js.map +1 -1
  145. package/dist/textarea.js.map +1 -1
  146. package/dist/time-axis.js.map +1 -1
  147. package/dist/time-picker.js.map +1 -1
  148. package/dist/timeline.js.map +1 -1
  149. package/dist/toggle-group.js.map +1 -1
  150. package/dist/toggle.js.map +1 -1
  151. package/dist/tool-call.js +5 -6
  152. package/dist/tool-call.js.map +1 -1
  153. package/dist/toolbar.js.map +1 -1
  154. package/dist/tooltip.js.map +1 -1
  155. package/dist/tree-map.js.map +1 -1
  156. package/dist/tree.js.map +1 -1
  157. package/dist/venn.js.map +1 -1
  158. package/package.json +9 -4
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/components/breadcrumb/breadcrumb.tsx"],"names":[],"mappings":"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","file":"breadcrumb.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/** Root nav landmark for breadcrumb navigation. */\nconst Breadcrumb = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<\"nav\">>(\n\t(props, ref) => <nav ref={ref} aria-label=\"breadcrumb\" {...props} />,\n);\nBreadcrumb.displayName = \"Breadcrumb\";\n\n/** Ordered list of breadcrumb items. */\nconst BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<\"ol\">>(\n\t({ className, ...props }, ref) => (\n\t\t<ol\n\t\t\tref={ref}\n\t\t\tclassName={cn(\n\t\t\t\t\"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-[var(--gap-sm,0.5rem)].5\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nBreadcrumbList.displayName = \"BreadcrumbList\";\n\n/** A single breadcrumb list item. */\nconst BreadcrumbItem = React.forwardRef<HTMLLIElement, React.ComponentPropsWithoutRef<\"li\">>(\n\t({ className, ...props }, ref) => (\n\t\t<li\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"inline-flex items-center gap-1.5\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nBreadcrumbItem.displayName = \"BreadcrumbItem\";\n\n/** A link inside a breadcrumb item. Use asChild to render e.g. Next.js Link. */\nconst BreadcrumbLink = React.forwardRef<\n\tHTMLAnchorElement,\n\tReact.ComponentPropsWithoutRef<\"a\"> & { asChild?: boolean }\n>(({ asChild, className, ...props }, ref) => {\n\tconst Comp = asChild ? Slot : \"a\";\n\treturn (\n\t\t<Comp\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"transition-all duration-[var(--duration-normal,200ms)] ease-out hover:text-foreground\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n});\nBreadcrumbLink.displayName = \"BreadcrumbLink\";\n\n/** The final breadcrumb (current page). Not interactive. */\nconst BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentPropsWithoutRef<\"span\">>(\n\t({ className, ...props }, ref) => (\n\t\t<span\n\t\t\tref={ref}\n\t\t\trole=\"link\"\n\t\t\taria-disabled=\"true\"\n\t\t\taria-current=\"page\"\n\t\t\tclassName={cn(\"font-normal text-foreground\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nBreadcrumbPage.displayName = \"BreadcrumbPage\";\n\n/**\n * Visual separator between breadcrumb items (chevron by default).\n * @returns An li rendering a decorative chevron icon\n */\nfunction BreadcrumbSeparator({\n\tchildren,\n\tclassName,\n\t...props\n}: React.ComponentProps<\"li\">) {\n\treturn (\n\t\t<li role=\"presentation\" aria-hidden=\"true\" className={cn(\"[&>svg]:h-3.5 [&>svg]:w-3.5\", className)} {...props}>\n\t\t\t{children ?? (\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<polyline points=\"9 18 15 12 9 6\" />\n\t\t\t\t</svg>\n\t\t\t)}\n\t\t</li>\n\t);\n}\n\n/**\n * Ellipsis for truncated breadcrumb trails.\n * @returns A span containing a decorative SVG (aria-hidden) plus a sr-only \"More pages\" label for AT.\n */\nfunction BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<\"span\">) {\n\t// Wrapper stays reachable by AT; only the decorative SVG is aria-hidden so the\n\t// sr-only \"More pages\" label actually reaches screen readers.\n\treturn (\n\t\t<span\n\t\t\tclassName={cn(\"flex h-[var(--control-height-sm,2.25rem)] w-[var(--control-height-sm,2.25rem)] items-center justify-center\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<svg\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tclassName=\"h-4 w-4\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"1\" />\n\t\t\t\t<circle cx=\"19\" cy=\"12\" r=\"1\" />\n\t\t\t\t<circle cx=\"5\" cy=\"12\" r=\"1\" />\n\t\t\t</svg>\n\t\t\t<span className=\"sr-only\">More pages</span>\n\t\t</span>\n\t);\n}\n\nexport {\n\tBreadcrumb,\n\tBreadcrumbList,\n\tBreadcrumbItem,\n\tBreadcrumbLink,\n\tBreadcrumbPage,\n\tBreadcrumbSeparator,\n\tBreadcrumbEllipsis,\n};\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/breadcrumb/breadcrumb.tsx"],"names":[],"mappings":"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","file":"breadcrumb.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n\nconst SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"mailto:\"] as const;\n\n/**\n * Allowlist a URL for use as an `<a href>` against untrusted input.\n *\n * Returns the raw string when it's `http(s):` / `mailto:` / a relative\n * URL (no scheme); returns `undefined` otherwise. Defends against\n * `javascript:` / `data:` / `vbscript:` injection from streamed model\n * output or third-party JSON payloads that flow into citation chips.\n *\n * Inside a Markdown render path, `rehype-sanitize` already strips\n * `javascript:` from inline-link hrefs — but it does NOT introspect\n * JSON nested inside attribute values (e.g. `<sources data='[…]'/>`),\n * so the components that consume that data must guard themselves.\n *\n * @param raw - The candidate URL, or `undefined` when none was supplied.\n * @returns The URL when safe to render, otherwise `undefined`.\n */\nexport function safeUrl(raw: string | undefined): string | undefined {\n\tif (raw === undefined || raw === \"\") return undefined;\n\t// Relative URLs have no scheme — `new URL(relative)` throws without a base,\n\t// so a thrown URL means either malformed input OR a relative path. Treat\n\t// \"throws + does not contain a colon\" as a relative path (safe).\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(raw);\n\t} catch {\n\t\treturn raw.includes(\":\") ? undefined : raw;\n\t}\n\treturn SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : undefined;\n}\n","\"use client\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/** Root nav landmark for breadcrumb navigation. */\nconst Breadcrumb = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<\"nav\">>(\n\t(props, ref) => <nav ref={ref} aria-label=\"breadcrumb\" {...props} />,\n);\nBreadcrumb.displayName = \"Breadcrumb\";\n\n/** Ordered list of breadcrumb items. */\nconst BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<\"ol\">>(\n\t({ className, ...props }, ref) => (\n\t\t<ol\n\t\t\tref={ref}\n\t\t\tclassName={cn(\n\t\t\t\t\"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-[var(--gap-sm,0.5rem)].5\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nBreadcrumbList.displayName = \"BreadcrumbList\";\n\n/** A single breadcrumb list item. */\nconst BreadcrumbItem = React.forwardRef<HTMLLIElement, React.ComponentPropsWithoutRef<\"li\">>(\n\t({ className, ...props }, ref) => (\n\t\t<li\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"inline-flex items-center gap-1.5\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nBreadcrumbItem.displayName = \"BreadcrumbItem\";\n\n/** A link inside a breadcrumb item. Use asChild to render e.g. Next.js Link. */\nconst BreadcrumbLink = React.forwardRef<\n\tHTMLAnchorElement,\n\tReact.ComponentPropsWithoutRef<\"a\"> & { asChild?: boolean }\n>(({ asChild, className, ...props }, ref) => {\n\tconst Comp = asChild ? Slot : \"a\";\n\treturn (\n\t\t<Comp\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"transition-all duration-[var(--duration-normal,200ms)] ease-out hover:text-foreground\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n});\nBreadcrumbLink.displayName = \"BreadcrumbLink\";\n\n/** The final breadcrumb (current page). Not interactive. */\nconst BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentPropsWithoutRef<\"span\">>(\n\t({ className, ...props }, ref) => (\n\t\t<span\n\t\t\tref={ref}\n\t\t\trole=\"link\"\n\t\t\taria-disabled=\"true\"\n\t\t\taria-current=\"page\"\n\t\t\tclassName={cn(\"font-normal text-foreground\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nBreadcrumbPage.displayName = \"BreadcrumbPage\";\n\n/**\n * Visual separator between breadcrumb items (chevron by default).\n * @returns An li rendering a decorative chevron icon\n */\nfunction BreadcrumbSeparator({\n\tchildren,\n\tclassName,\n\t...props\n}: React.ComponentProps<\"li\">) {\n\treturn (\n\t\t<li role=\"presentation\" aria-hidden=\"true\" className={cn(\"[&>svg]:h-3.5 [&>svg]:w-3.5\", className)} {...props}>\n\t\t\t{children ?? (\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<polyline points=\"9 18 15 12 9 6\" />\n\t\t\t\t</svg>\n\t\t\t)}\n\t\t</li>\n\t);\n}\n\n/**\n * Ellipsis for truncated breadcrumb trails.\n * @returns A span containing a decorative SVG (aria-hidden) plus a sr-only \"More pages\" label for AT.\n */\nfunction BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<\"span\">) {\n\t// Wrapper stays reachable by AT; only the decorative SVG is aria-hidden so the\n\t// sr-only \"More pages\" label actually reaches screen readers.\n\treturn (\n\t\t<span\n\t\t\tclassName={cn(\"flex h-[var(--control-height-sm,2.25rem)] w-[var(--control-height-sm,2.25rem)] items-center justify-center\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<svg\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tclassName=\"h-4 w-4\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"1\" />\n\t\t\t\t<circle cx=\"19\" cy=\"12\" r=\"1\" />\n\t\t\t\t<circle cx=\"5\" cy=\"12\" r=\"1\" />\n\t\t\t</svg>\n\t\t\t<span className=\"sr-only\">More pages</span>\n\t\t</span>\n\t);\n}\n\nexport {\n\tBreadcrumb,\n\tBreadcrumbList,\n\tBreadcrumbItem,\n\tBreadcrumbLink,\n\tBreadcrumbPage,\n\tBreadcrumbSeparator,\n\tBreadcrumbEllipsis,\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/button/button-variants.ts","../src/primitives/button/button.tsx"],"names":[],"mappings":"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","file":"button.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","import { type VariantProps, cva } from \"class-variance-authority\";\n\n/**\n * CVA variants for the Button component.\n *\n * Lives in its own module so RSC-safe consumers (`Pagination`, future\n * link-styled buttons in static layouts) can import variants without\n * pulling in the full `Button` runtime — `Button` itself is client-only\n * because of `Slot` + `forwardRef` + the loading spinner. Splitting the\n * variants out keeps `dist/pagination.js` free of `@radix-ui/react-slot`.\n */\nexport const buttonVariants = cva(\n\t[\n\t\t\"inline-flex items-center justify-center gap-[var(--gap-sm,0.5rem)] whitespace-nowrap rounded-md text-sm font-medium\",\n\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\"disabled:pointer-events-none disabled:opacity-50\",\n\t\t\"active:scale-[0.98]\",\n\t\t\"[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n\t].join(\" \"),\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: [\n\t\t\t\t\t\"bg-primary text-primary-foreground\",\n\t\t\t\t\t\"shadow-sm shadow-primary/20\",\n\t\t\t\t\t\"hover:bg-primary/90 hover:shadow-md hover:shadow-primary/25\",\n\t\t\t\t].join(\" \"),\n\t\t\t\tdestructive: [\n\t\t\t\t\t\"bg-destructive text-destructive-foreground\",\n\t\t\t\t\t\"shadow-sm shadow-destructive/20\",\n\t\t\t\t\t\"hover:bg-destructive/90 hover:shadow-md hover:shadow-destructive/25\",\n\t\t\t\t].join(\" \"),\n\t\t\t\toutline: [\n\t\t\t\t\t\"border border-input bg-background\",\n\t\t\t\t\t\"shadow-sm inset-ring-1 inset-ring-foreground/[0.06]\",\n\t\t\t\t\t\"hover:bg-accent hover:text-accent-foreground hover:shadow-md hover:inset-ring-foreground/12\",\n\t\t\t\t].join(\" \"),\n\t\t\t\tsecondary: [\n\t\t\t\t\t\"bg-secondary text-secondary-foreground\",\n\t\t\t\t\t\"shadow-sm inset-ring-1 inset-ring-foreground/[0.08]\",\n\t\t\t\t\t\"hover:bg-secondary/80 hover:shadow-md hover:inset-ring-foreground/15\",\n\t\t\t\t].join(\" \"),\n\t\t\t\tghost: \"hover:bg-accent hover:text-accent-foreground\",\n\t\t\t\tlink: \"text-primary underline-offset-4 hover:underline\",\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault:\n\t\t\t\t\t\"h-[var(--control-height-md,2.5rem)] px-[var(--space-4,1rem)] py-[var(--space-2,0.5rem)]\",\n\t\t\t\tsm: \"h-[var(--control-height-sm,2.25rem)] rounded-md px-[var(--space-3,0.75rem)]\",\n\t\t\t\tlg: \"h-[var(--control-height-lg,2.75rem)] rounded-md px-[var(--space-8,2rem)] text-base\",\n\t\t\t\ticon: \"h-[var(--control-height-md,2.5rem)] w-[var(--control-height-md,2.5rem)]\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: \"default\",\n\t\t\tsize: \"default\",\n\t\t},\n\t},\n);\n\nexport type ButtonVariantsProps = VariantProps<typeof buttonVariants>;\n","\"use client\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\nimport { type ButtonVariantsProps, buttonVariants } from \"./button-variants.js\";\n\nexport interface ButtonProps\n\textends React.ButtonHTMLAttributes<HTMLButtonElement>,\n\t\tButtonVariantsProps {\n\tasChild?: boolean;\n\tloading?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n\t(\n\t\t{ className, variant, size, asChild = false, loading = false, children, disabled, ...props },\n\t\tref,\n\t) => {\n\t\tconst Comp = asChild ? Slot : \"button\";\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tclassName={cn(buttonVariants({ variant, size, className }))}\n\t\t\t\tref={ref}\n\t\t\t\tdisabled={disabled || loading}\n\t\t\t\taria-busy={loading || undefined}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{loading ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\tclassName=\"animate-spin h-4 w-4\"\n\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\tclassName=\"opacity-25\"\n\t\t\t\t\t\t\t\tcx=\"12\"\n\t\t\t\t\t\t\t\tcy=\"12\"\n\t\t\t\t\t\t\t\tr=\"10\"\n\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\tstrokeWidth=\"4\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\tclassName=\"opacity-75\"\n\t\t\t\t\t\t\t\tfill=\"currentColor\"\n\t\t\t\t\t\t\t\td=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\tchildren\n\t\t\t\t)}\n\t\t\t</Comp>\n\t\t);\n\t},\n);\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/button/button-variants.ts","../src/primitives/button/button.tsx"],"names":[],"mappings":"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","file":"button.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n\nconst SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"mailto:\"] as const;\n\n/**\n * Allowlist a URL for use as an `<a href>` against untrusted input.\n *\n * Returns the raw string when it's `http(s):` / `mailto:` / a relative\n * URL (no scheme); returns `undefined` otherwise. Defends against\n * `javascript:` / `data:` / `vbscript:` injection from streamed model\n * output or third-party JSON payloads that flow into citation chips.\n *\n * Inside a Markdown render path, `rehype-sanitize` already strips\n * `javascript:` from inline-link hrefs — but it does NOT introspect\n * JSON nested inside attribute values (e.g. `<sources data='[…]'/>`),\n * so the components that consume that data must guard themselves.\n *\n * @param raw - The candidate URL, or `undefined` when none was supplied.\n * @returns The URL when safe to render, otherwise `undefined`.\n */\nexport function safeUrl(raw: string | undefined): string | undefined {\n\tif (raw === undefined || raw === \"\") return undefined;\n\t// Relative URLs have no scheme — `new URL(relative)` throws without a base,\n\t// so a thrown URL means either malformed input OR a relative path. Treat\n\t// \"throws + does not contain a colon\" as a relative path (safe).\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(raw);\n\t} catch {\n\t\treturn raw.includes(\":\") ? undefined : raw;\n\t}\n\treturn SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : undefined;\n}\n","import { type VariantProps, cva } from \"class-variance-authority\";\n\n/**\n * CVA variants for the Button component.\n *\n * Lives in its own module so RSC-safe consumers (`Pagination`, future\n * link-styled buttons in static layouts) can import variants without\n * pulling in the full `Button` runtime — `Button` itself is client-only\n * because of `Slot` + `forwardRef` + the loading spinner. Splitting the\n * variants out keeps `dist/pagination.js` free of `@radix-ui/react-slot`.\n */\nexport const buttonVariants = cva(\n\t[\n\t\t\"inline-flex items-center justify-center gap-[var(--gap-sm,0.5rem)] whitespace-nowrap rounded-md text-sm font-medium\",\n\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\"disabled:pointer-events-none disabled:opacity-50\",\n\t\t\"active:scale-[0.98]\",\n\t\t\"[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n\t].join(\" \"),\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: [\n\t\t\t\t\t\"bg-primary text-primary-foreground\",\n\t\t\t\t\t\"shadow-sm shadow-primary/20\",\n\t\t\t\t\t\"hover:bg-primary/90 hover:shadow-md hover:shadow-primary/25\",\n\t\t\t\t].join(\" \"),\n\t\t\t\tdestructive: [\n\t\t\t\t\t\"bg-destructive text-destructive-foreground\",\n\t\t\t\t\t\"shadow-sm shadow-destructive/20\",\n\t\t\t\t\t\"hover:bg-destructive/90 hover:shadow-md hover:shadow-destructive/25\",\n\t\t\t\t].join(\" \"),\n\t\t\t\toutline: [\n\t\t\t\t\t\"border border-input bg-background\",\n\t\t\t\t\t\"shadow-sm inset-ring-1 inset-ring-foreground/[0.06]\",\n\t\t\t\t\t\"hover:bg-accent hover:text-accent-foreground hover:shadow-md hover:inset-ring-foreground/12\",\n\t\t\t\t].join(\" \"),\n\t\t\t\tsecondary: [\n\t\t\t\t\t\"bg-secondary text-secondary-foreground\",\n\t\t\t\t\t\"shadow-sm inset-ring-1 inset-ring-foreground/[0.08]\",\n\t\t\t\t\t\"hover:bg-secondary/80 hover:shadow-md hover:inset-ring-foreground/15\",\n\t\t\t\t].join(\" \"),\n\t\t\t\tghost: \"hover:bg-accent hover:text-accent-foreground\",\n\t\t\t\tlink: \"text-primary underline-offset-4 hover:underline\",\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault:\n\t\t\t\t\t\"h-[var(--control-height-md,2.5rem)] px-[var(--space-4,1rem)] py-[var(--space-2,0.5rem)]\",\n\t\t\t\tsm: \"h-[var(--control-height-sm,2.25rem)] rounded-md px-[var(--space-3,0.75rem)]\",\n\t\t\t\tlg: \"h-[var(--control-height-lg,2.75rem)] rounded-md px-[var(--space-8,2rem)] text-base\",\n\t\t\t\ticon: \"h-[var(--control-height-md,2.5rem)] w-[var(--control-height-md,2.5rem)]\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: \"default\",\n\t\t\tsize: \"default\",\n\t\t},\n\t},\n);\n\nexport type ButtonVariantsProps = VariantProps<typeof buttonVariants>;\n","\"use client\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\nimport { type ButtonVariantsProps, buttonVariants } from \"./button-variants.js\";\n\nexport interface ButtonProps\n\textends React.ButtonHTMLAttributes<HTMLButtonElement>,\n\t\tButtonVariantsProps {\n\tasChild?: boolean;\n\tloading?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n\t(\n\t\t{ className, variant, size, asChild = false, loading = false, children, disabled, ...props },\n\t\tref,\n\t) => {\n\t\tconst Comp = asChild ? Slot : \"button\";\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tclassName={cn(buttonVariants({ variant, size, className }))}\n\t\t\t\tref={ref}\n\t\t\t\tdisabled={disabled || loading}\n\t\t\t\taria-busy={loading || undefined}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{loading ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\tclassName=\"animate-spin h-4 w-4\"\n\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\tclassName=\"opacity-25\"\n\t\t\t\t\t\t\t\tcx=\"12\"\n\t\t\t\t\t\t\t\tcy=\"12\"\n\t\t\t\t\t\t\t\tr=\"10\"\n\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\tstrokeWidth=\"4\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\tclassName=\"opacity-75\"\n\t\t\t\t\t\t\t\tfill=\"currentColor\"\n\t\t\t\t\t\t\t\td=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\tchildren\n\t\t\t\t)}\n\t\t\t</Comp>\n\t\t);\n\t},\n);\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/components/calendar/calendar.tsx"],"names":[],"mappings":"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","file":"calendar.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { DayPicker } from \"react-day-picker\";\nimport { cn } from \"../../lib/utils.js\";\n\n/*\n * react-day-picker v9 renders each caption-layout dropdown as:\n * <span class=\"rdp-dropdown_root\">\n * <select class=\"rdp-dropdown\">…</select>\n * <span aria-hidden=\"true\">{label}<chevron/></span>\n * </span>\n * The library expects the consumer's theme to layer the native <select>\n * transparently over the visible label span. Without that overlay both\n * elements paint side-by-side and the month/year labels duplicate. We use a\n * plain <style> block (rather than Tailwind arbitrary variants) because the\n * `_` in the rdp class names trips up Tailwind's underscore-as-space rule and\n * RDP v9's ClassNames merger doesn't run user classes for these keys.\n */\nconst RDP_DROPDOWN_OVERLAY_CSS = `\n.rdp-dropdowns {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tgap: var(--gap-sm, 0.5rem);\n\tfont-size: 0.875rem;\n\tfont-weight: 500;\n}\n.rdp-dropdown_root {\n\tposition: relative;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: var(--space-1, 0.25rem);\n\tborder-radius: 0.375rem;\n\tpadding: var(--space-1, 0.25rem) var(--space-2, 0.5rem);\n\ttransition: background-color var(--duration-normal, 200ms) ease-out;\n}\n.rdp-dropdown_root:hover {\n\tbackground-color: hsl(var(--accent));\n}\n.rdp-dropdown_root:has(:focus-visible) {\n\toutline: 2px solid hsl(var(--ring));\n\toutline-offset: 2px;\n}\n.rdp-dropdown {\n\tposition: absolute;\n\tinset: 0;\n\tz-index: 10;\n\twidth: 100%;\n\theight: 100%;\n\tcursor: pointer;\n\tappearance: none;\n\tbackground: transparent;\n\tborder: 0;\n\topacity: 0;\n}\n.rdp-dropdown:disabled {\n\tcursor: not-allowed;\n}\n`;\n\n/**\n * Calendar date grid built on react-day-picker v9. Forwards all DayPicker\n * props. Pair `mode` + `selected` + `onSelect` for selection control;\n * pass `captionLayout=\"dropdown\"` with `startMonth`/`endMonth` for\n * native year-dropdown navigation.\n * @returns A themed react-day-picker instance with our dropdown overlay CSS.\n */\nfunction Calendar({\n\tclassName,\n\tclassNames,\n\tshowOutsideDays = true,\n\t...props\n}: React.ComponentProps<typeof DayPicker>) {\n\treturn (\n\t\t<>\n\t\t\t<style\n\t\t\t\t// Single static stylesheet; React inlines once per page\n\t\t\t\t// regardless of Calendar instance count.\n\t\t\t\tdangerouslySetInnerHTML={{ __html: RDP_DROPDOWN_OVERLAY_CSS }}\n\t\t\t/>\n\t\t<DayPicker\n\t\t\tshowOutsideDays={showOutsideDays}\n\t\t\tclassName={cn(\"relative p-[var(--space-3,0.75rem)]\", className)}\n\t\t\tclassNames={{\n\t\t\t\tmonths: \"flex flex-col sm:flex-row gap-[var(--gap-md,1rem)]\",\n\t\t\t\tmonth: \"flex flex-col gap-[var(--gap-md,1rem)]\",\n\t\t\t\tmonth_caption: \"flex h-7 items-center justify-center\",\n\t\t\t\tcaption_label: \"text-sm font-medium\",\n\t\t\t\tnav: \"absolute inset-x-3 top-3 z-10 flex items-center justify-between pointer-events-none [&>button]:pointer-events-auto\",\n\t\t\t\tbutton_previous: cn(\n\t\t\t\t\t\"inline-flex h-7 w-7 items-center justify-center rounded-md border border-foreground/[0.08] bg-transparent p-0 opacity-60 transition-all duration-[var(--duration-normal,200ms)] ease-out hover:opacity-100 disabled:pointer-events-none disabled:opacity-30\",\n\t\t\t\t),\n\t\t\t\tbutton_next: cn(\n\t\t\t\t\t\"inline-flex h-7 w-7 items-center justify-center rounded-md border border-foreground/[0.08] bg-transparent p-0 opacity-60 transition-all duration-[var(--duration-normal,200ms)] ease-out hover:opacity-100 disabled:pointer-events-none disabled:opacity-30\",\n\t\t\t\t),\n\t\t\t\tmonth_grid: \"w-full border-collapse space-y-1\",\n\t\t\t\tweekdays: \"flex\",\n\t\t\t\tweekday: \"text-muted-foreground rounded-md w-[var(--control-height-sm,2.25rem)] font-normal text-[0.8rem]\",\n\t\t\t\tweek: \"flex w-full mt-[var(--space-2,0.5rem)]\",\n\t\t\t\tday: \"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].range-end)]:rounded-r-md [&:has([aria-selected].range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md\",\n\t\t\t\tday_button:\n\t\t\t\t\t\"inline-flex h-[var(--control-height-sm,2.25rem)] w-[var(--control-height-sm,2.25rem)] items-center justify-center rounded-md p-0 text-sm font-normal transition-all duration-[var(--duration-normal,200ms)] ease-out hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 aria-selected:opacity-100\",\n\t\t\t\tselected:\n\t\t\t\t\t\"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground\",\n\t\t\t\ttoday: \"bg-accent text-accent-foreground\",\n\t\t\t\toutside:\n\t\t\t\t\t\"day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground\",\n\t\t\t\tdisabled: \"text-muted-foreground opacity-50\",\n\t\t\t\trange_start: \"day-range-start range-start\",\n\t\t\t\trange_end: \"day-range-end range-end\",\n\t\t\t\trange_middle:\n\t\t\t\t\t\"aria-selected:bg-accent aria-selected:text-accent-foreground rounded-none\",\n\t\t\t\thidden: \"invisible\",\n\t\t\t\t...classNames,\n\t\t\t}}\n\t\t\tcomponents={{\n\t\t\t\tChevron: ({ orientation, className: chevronClassName }) => {\n\t\t\t\t\tconst rotation =\n\t\t\t\t\t\torientation === \"left\"\n\t\t\t\t\t\t\t? \"rotate-90\"\n\t\t\t\t\t\t\t: orientation === \"right\"\n\t\t\t\t\t\t\t\t? \"-rotate-90\"\n\t\t\t\t\t\t\t\t: orientation === \"up\"\n\t\t\t\t\t\t\t\t\t? \"rotate-180\"\n\t\t\t\t\t\t\t\t\t: \"\";\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\tclassName={cn(\"h-4 w-4\", rotation, chevronClassName)}\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<polyline points=\"6 9 12 15 18 9\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t}}\n\t\t\t{...props}\n\t\t/>\n\t\t</>\n\t);\n}\nCalendar.displayName = \"Calendar\";\n\nexport { Calendar };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/calendar/calendar.tsx"],"names":[],"mappings":"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","file":"calendar.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n\nconst SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"mailto:\"] as const;\n\n/**\n * Allowlist a URL for use as an `<a href>` against untrusted input.\n *\n * Returns the raw string when it's `http(s):` / `mailto:` / a relative\n * URL (no scheme); returns `undefined` otherwise. Defends against\n * `javascript:` / `data:` / `vbscript:` injection from streamed model\n * output or third-party JSON payloads that flow into citation chips.\n *\n * Inside a Markdown render path, `rehype-sanitize` already strips\n * `javascript:` from inline-link hrefs — but it does NOT introspect\n * JSON nested inside attribute values (e.g. `<sources data='[…]'/>`),\n * so the components that consume that data must guard themselves.\n *\n * @param raw - The candidate URL, or `undefined` when none was supplied.\n * @returns The URL when safe to render, otherwise `undefined`.\n */\nexport function safeUrl(raw: string | undefined): string | undefined {\n\tif (raw === undefined || raw === \"\") return undefined;\n\t// Relative URLs have no scheme — `new URL(relative)` throws without a base,\n\t// so a thrown URL means either malformed input OR a relative path. Treat\n\t// \"throws + does not contain a colon\" as a relative path (safe).\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(raw);\n\t} catch {\n\t\treturn raw.includes(\":\") ? undefined : raw;\n\t}\n\treturn SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : undefined;\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { DayPicker } from \"react-day-picker\";\nimport { cn } from \"../../lib/utils.js\";\n\n/*\n * react-day-picker v9 renders each caption-layout dropdown as:\n * <span class=\"rdp-dropdown_root\">\n * <select class=\"rdp-dropdown\">…</select>\n * <span aria-hidden=\"true\">{label}<chevron/></span>\n * </span>\n * The library expects the consumer's theme to layer the native <select>\n * transparently over the visible label span. Without that overlay both\n * elements paint side-by-side and the month/year labels duplicate. We use a\n * plain <style> block (rather than Tailwind arbitrary variants) because the\n * `_` in the rdp class names trips up Tailwind's underscore-as-space rule and\n * RDP v9's ClassNames merger doesn't run user classes for these keys.\n */\nconst RDP_DROPDOWN_OVERLAY_CSS = `\n.rdp-dropdowns {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tgap: var(--gap-sm, 0.5rem);\n\tfont-size: 0.875rem;\n\tfont-weight: 500;\n}\n.rdp-dropdown_root {\n\tposition: relative;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: var(--space-1, 0.25rem);\n\tborder-radius: 0.375rem;\n\tpadding: var(--space-1, 0.25rem) var(--space-2, 0.5rem);\n\ttransition: background-color var(--duration-normal, 200ms) ease-out;\n}\n.rdp-dropdown_root:hover {\n\tbackground-color: hsl(var(--accent));\n}\n.rdp-dropdown_root:has(:focus-visible) {\n\toutline: 2px solid hsl(var(--ring));\n\toutline-offset: 2px;\n}\n.rdp-dropdown {\n\tposition: absolute;\n\tinset: 0;\n\tz-index: 10;\n\twidth: 100%;\n\theight: 100%;\n\tcursor: pointer;\n\tappearance: none;\n\tbackground: transparent;\n\tborder: 0;\n\topacity: 0;\n}\n.rdp-dropdown:disabled {\n\tcursor: not-allowed;\n}\n`;\n\n/**\n * Calendar date grid built on react-day-picker v9. Forwards all DayPicker\n * props. Pair `mode` + `selected` + `onSelect` for selection control;\n * pass `captionLayout=\"dropdown\"` with `startMonth`/`endMonth` for\n * native year-dropdown navigation.\n * @returns A themed react-day-picker instance with our dropdown overlay CSS.\n */\nfunction Calendar({\n\tclassName,\n\tclassNames,\n\tshowOutsideDays = true,\n\t...props\n}: React.ComponentProps<typeof DayPicker>) {\n\treturn (\n\t\t<>\n\t\t\t<style\n\t\t\t\t// Single static stylesheet; React inlines once per page\n\t\t\t\t// regardless of Calendar instance count.\n\t\t\t\tdangerouslySetInnerHTML={{ __html: RDP_DROPDOWN_OVERLAY_CSS }}\n\t\t\t/>\n\t\t<DayPicker\n\t\t\tshowOutsideDays={showOutsideDays}\n\t\t\tclassName={cn(\"relative p-[var(--space-3,0.75rem)]\", className)}\n\t\t\tclassNames={{\n\t\t\t\tmonths: \"flex flex-col sm:flex-row gap-[var(--gap-md,1rem)]\",\n\t\t\t\tmonth: \"flex flex-col gap-[var(--gap-md,1rem)]\",\n\t\t\t\tmonth_caption: \"flex h-7 items-center justify-center\",\n\t\t\t\tcaption_label: \"text-sm font-medium\",\n\t\t\t\tnav: \"absolute inset-x-3 top-3 z-10 flex items-center justify-between pointer-events-none [&>button]:pointer-events-auto\",\n\t\t\t\tbutton_previous: cn(\n\t\t\t\t\t\"inline-flex h-7 w-7 items-center justify-center rounded-md border border-foreground/[0.08] bg-transparent p-0 opacity-60 transition-all duration-[var(--duration-normal,200ms)] ease-out hover:opacity-100 disabled:pointer-events-none disabled:opacity-30\",\n\t\t\t\t),\n\t\t\t\tbutton_next: cn(\n\t\t\t\t\t\"inline-flex h-7 w-7 items-center justify-center rounded-md border border-foreground/[0.08] bg-transparent p-0 opacity-60 transition-all duration-[var(--duration-normal,200ms)] ease-out hover:opacity-100 disabled:pointer-events-none disabled:opacity-30\",\n\t\t\t\t),\n\t\t\t\tmonth_grid: \"w-full border-collapse space-y-1\",\n\t\t\t\tweekdays: \"flex\",\n\t\t\t\tweekday: \"text-muted-foreground rounded-md w-[var(--control-height-sm,2.25rem)] font-normal text-[0.8rem]\",\n\t\t\t\tweek: \"flex w-full mt-[var(--space-2,0.5rem)]\",\n\t\t\t\tday: \"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].range-end)]:rounded-r-md [&:has([aria-selected].range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md\",\n\t\t\t\tday_button:\n\t\t\t\t\t\"inline-flex h-[var(--control-height-sm,2.25rem)] w-[var(--control-height-sm,2.25rem)] items-center justify-center rounded-md p-0 text-sm font-normal transition-all duration-[var(--duration-normal,200ms)] ease-out hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 aria-selected:opacity-100\",\n\t\t\t\tselected:\n\t\t\t\t\t\"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground\",\n\t\t\t\ttoday: \"bg-accent text-accent-foreground\",\n\t\t\t\toutside:\n\t\t\t\t\t\"day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground\",\n\t\t\t\tdisabled: \"text-muted-foreground opacity-50\",\n\t\t\t\trange_start: \"day-range-start range-start\",\n\t\t\t\trange_end: \"day-range-end range-end\",\n\t\t\t\trange_middle:\n\t\t\t\t\t\"aria-selected:bg-accent aria-selected:text-accent-foreground rounded-none\",\n\t\t\t\thidden: \"invisible\",\n\t\t\t\t...classNames,\n\t\t\t}}\n\t\t\tcomponents={{\n\t\t\t\tChevron: ({ orientation, className: chevronClassName }) => {\n\t\t\t\t\tconst rotation =\n\t\t\t\t\t\torientation === \"left\"\n\t\t\t\t\t\t\t? \"rotate-90\"\n\t\t\t\t\t\t\t: orientation === \"right\"\n\t\t\t\t\t\t\t\t? \"-rotate-90\"\n\t\t\t\t\t\t\t\t: orientation === \"up\"\n\t\t\t\t\t\t\t\t\t? \"rotate-180\"\n\t\t\t\t\t\t\t\t\t: \"\";\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\tclassName={cn(\"h-4 w-4\", rotation, chevronClassName)}\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<polyline points=\"6 9 12 15 18 9\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t}}\n\t\t\t{...props}\n\t\t/>\n\t\t</>\n\t);\n}\nCalendar.displayName = \"Calendar\";\n\nexport { Calendar };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/ai/canvas/canvas.tsx"],"names":[],"mappings":";;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;AC0CA,SAAS,MAAA,CAAO;AAAA,EACf,KAAA;AAAA,EACA,KAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA,GAAe,KAAA;AAAA,EACf,cAAA,GAAiB,KAAA;AAAA,EACjB,OAAA,GAAU,IAAA;AAAA,EACV,QAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAG;AACJ,CAAA,EAAgB;AAGf,EAAA,MAAM,CAAC,EAAA,EAAI,KAAK,CAAA,GAAU,eAA4C,IAAI,CAAA;AAE1E,EAAM,gBAAU,MAAM;AACrB,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,KAAK,OAAO,WAAW,CAAA,CAAE,IAAA,CAAK,CAAC,GAAA,KAAQ;AACtC,MAAA,IAAI,CAAC,SAAA,EAAW,KAAA,CAAM,GAAG,CAAA;AAAA,IAC1B,CAAC,CAAA;AACD,IAAA,OAAO,MAAM;AACZ,MAAA,SAAA,GAAY,IAAA;AAAA,IACb,CAAA;AAAA,EACD,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,IAAI,CAAC,EAAA,EAAI;AACR,IAAA,uBACC,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAG,IAAA;AAAA,QACJ,yBAAA,EAAuB,IAAA;AAAA,QACvB,SAAA,EAAW,EAAA,CAAG,2BAAA,EAA6B,SAAS,CAAA;AAAA,QACpD,WAAA,EAAU;AAAA;AAAA,KACX;AAAA,EAEF;AAEA,EAAA,MAAM,EAAE,SAAA,EAAW,UAAA,EAAY,QAAA,EAAS,GAAI,EAAA;AAE5C,EAAA,uBACC,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAG,IAAA;AAAA,MACJ,iBAAA,EAAe,IAAA;AAAA,MACf,SAAA,EAAW,EAAA,CAAG,eAAA,EAAiB,SAAS,CAAA;AAAA,MAExC,QAAA,kBAAA,IAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACA,KAAA;AAAA,UACA,KAAA;AAAA,UACA,aAAA;AAAA,UACA,aAAA;AAAA,UACA,SAAA;AAAA,UACA,OAAA;AAAA,UAEC,QAAA,EAAA;AAAA,YAAA,CAAC,cAAA,wBAAmB,UAAA,EAAA,EAAW,CAAA;AAAA,YAC/B,CAAC,YAAA,oBAAgB,GAAA,CAAC,QAAA,EAAA,EAAS,CAAA;AAAA,YAC3B;AAAA;AAAA;AAAA;AACF;AAAA,GACD;AAEF","file":"canvas.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Headless node-graph canvas backed by reactflow. Renders an interactive\n * graph of agent steps, workflow nodes, RAG document refs — anywhere your\n * AI app needs to visualize relationships.\n *\n * Controlled: pass `nodes` and `edges`; receive change events. Reactflow's\n * default Background + Controls are rendered automatically; pass `children`\n * to add Panels, MiniMap, or custom overlays.\n *\n * Heavy peer: requires `reactflow` (~80 KB gzip). The hex-core CLI's `add`\n * flow prompts before installing.\n *\n * @example\n * import \"reactflow/dist/style.css\"; // once in your app entry\n * <Canvas\n * nodes={[{ id: \"1\", position: { x: 0, y: 0 }, data: { label: \"Agent\" } }]}\n * edges={[]}\n * onNodesChange={onNodesChange}\n * onEdgesChange={onEdgesChange}\n * />\n */\nexport interface CanvasProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"children\" | \"onError\"> {\n\t/** Node objects passed to ReactFlow. See reactflow docs for shape. */\n\tnodes: import(\"reactflow\").Node[];\n\t/** Edge objects passed to ReactFlow. */\n\tedges: import(\"reactflow\").Edge[];\n\t/** Forwarded to ReactFlow.onNodesChange. */\n\tonNodesChange?: import(\"reactflow\").OnNodesChange;\n\t/** Forwarded to ReactFlow.onEdgesChange. */\n\tonEdgesChange?: import(\"reactflow\").OnEdgesChange;\n\t/** Forwarded to ReactFlow.onConnect (fires when user wires two nodes). */\n\tonConnect?: import(\"reactflow\").OnConnect;\n\t/** Hide the bottom-left zoom/pan/fit controls. Default false (visible). */\n\thideControls?: boolean;\n\t/** Hide the dotted background. Default false (visible). */\n\thideBackground?: boolean;\n\t/** Auto-fit the view to all nodes on first render. Default true. */\n\tfitView?: boolean;\n\t/** Slot for MiniMap, Panel, or custom overlays rendered inside ReactFlow. */\n\tchildren?: React.ReactNode;\n}\n\n/**\n * Renders a ReactFlow graph with sensible defaults.\n * @param props - Controlled nodes/edges + interaction handlers\n * @returns A div containing the ReactFlow canvas\n */\nfunction Canvas({\n\tnodes,\n\tedges,\n\tonNodesChange,\n\tonEdgesChange,\n\tonConnect,\n\thideControls = false,\n\thideBackground = false,\n\tfitView = true,\n\tchildren,\n\tclassName,\n\t...rest\n}: CanvasProps) {\n\t// Lazy-loaded reactflow modules. Held in state so a re-render kicks in\n\t// once the dynamic import resolves; until then we render a placeholder.\n\tconst [rf, setRf] = React.useState<typeof import(\"reactflow\") | null>(null);\n\n\tReact.useEffect(() => {\n\t\tlet cancelled = false;\n\t\tvoid import(\"reactflow\").then((mod) => {\n\t\t\tif (!cancelled) setRf(mod);\n\t\t});\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, []);\n\n\tif (!rf) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\t{...rest}\n\t\t\t\tdata-hex-canvas-loading\n\t\t\t\tclassName={cn(\"h-full w-full bg-muted/20\", className)}\n\t\t\t\taria-busy=\"true\"\n\t\t\t/>\n\t\t);\n\t}\n\n\tconst { ReactFlow, Background, Controls } = rf;\n\n\treturn (\n\t\t<div\n\t\t\t{...rest}\n\t\t\tdata-hex-canvas\n\t\t\tclassName={cn(\"h-full w-full\", className)}\n\t\t>\n\t\t\t<ReactFlow\n\t\t\t\tnodes={nodes}\n\t\t\t\tedges={edges}\n\t\t\t\tonNodesChange={onNodesChange}\n\t\t\t\tonEdgesChange={onEdgesChange}\n\t\t\t\tonConnect={onConnect}\n\t\t\t\tfitView={fitView}\n\t\t\t>\n\t\t\t\t{!hideBackground && <Background />}\n\t\t\t\t{!hideControls && <Controls />}\n\t\t\t\t{children}\n\t\t\t</ReactFlow>\n\t\t</div>\n\t);\n}\n\nexport { Canvas };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/ai/canvas/canvas.tsx"],"names":[],"mappings":";;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;AC0CA,SAAS,MAAA,CAAO;AAAA,EACf,KAAA;AAAA,EACA,KAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA,GAAe,KAAA;AAAA,EACf,cAAA,GAAiB,KAAA;AAAA,EACjB,OAAA,GAAU,IAAA;AAAA,EACV,QAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAG;AACJ,CAAA,EAAgB;AAGf,EAAA,MAAM,CAAC,EAAA,EAAI,KAAK,CAAA,GAAU,eAA4C,IAAI,CAAA;AAE1E,EAAM,gBAAU,MAAM;AACrB,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,KAAK,OAAO,WAAW,CAAA,CAAE,IAAA,CAAK,CAAC,GAAA,KAAQ;AACtC,MAAA,IAAI,CAAC,SAAA,EAAW,KAAA,CAAM,GAAG,CAAA;AAAA,IAC1B,CAAC,CAAA;AACD,IAAA,OAAO,MAAM;AACZ,MAAA,SAAA,GAAY,IAAA;AAAA,IACb,CAAA;AAAA,EACD,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,IAAI,CAAC,EAAA,EAAI;AACR,IAAA,uBACC,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAG,IAAA;AAAA,QACJ,yBAAA,EAAuB,IAAA;AAAA,QACvB,SAAA,EAAW,EAAA,CAAG,2BAAA,EAA6B,SAAS,CAAA;AAAA,QACpD,WAAA,EAAU;AAAA;AAAA,KACX;AAAA,EAEF;AAEA,EAAA,MAAM,EAAE,SAAA,EAAW,UAAA,EAAY,QAAA,EAAS,GAAI,EAAA;AAE5C,EAAA,uBACC,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAG,IAAA;AAAA,MACJ,iBAAA,EAAe,IAAA;AAAA,MACf,SAAA,EAAW,EAAA,CAAG,eAAA,EAAiB,SAAS,CAAA;AAAA,MAExC,QAAA,kBAAA,IAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACA,KAAA;AAAA,UACA,KAAA;AAAA,UACA,aAAA;AAAA,UACA,aAAA;AAAA,UACA,SAAA;AAAA,UACA,OAAA;AAAA,UAEC,QAAA,EAAA;AAAA,YAAA,CAAC,cAAA,wBAAmB,UAAA,EAAA,EAAW,CAAA;AAAA,YAC/B,CAAC,YAAA,oBAAgB,GAAA,CAAC,QAAA,EAAA,EAAS,CAAA;AAAA,YAC3B;AAAA;AAAA;AAAA;AACF;AAAA,GACD;AAEF","file":"canvas.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n\nconst SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"mailto:\"] as const;\n\n/**\n * Allowlist a URL for use as an `<a href>` against untrusted input.\n *\n * Returns the raw string when it's `http(s):` / `mailto:` / a relative\n * URL (no scheme); returns `undefined` otherwise. Defends against\n * `javascript:` / `data:` / `vbscript:` injection from streamed model\n * output or third-party JSON payloads that flow into citation chips.\n *\n * Inside a Markdown render path, `rehype-sanitize` already strips\n * `javascript:` from inline-link hrefs — but it does NOT introspect\n * JSON nested inside attribute values (e.g. `<sources data='[…]'/>`),\n * so the components that consume that data must guard themselves.\n *\n * @param raw - The candidate URL, or `undefined` when none was supplied.\n * @returns The URL when safe to render, otherwise `undefined`.\n */\nexport function safeUrl(raw: string | undefined): string | undefined {\n\tif (raw === undefined || raw === \"\") return undefined;\n\t// Relative URLs have no scheme — `new URL(relative)` throws without a base,\n\t// so a thrown URL means either malformed input OR a relative path. Treat\n\t// \"throws + does not contain a colon\" as a relative path (safe).\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(raw);\n\t} catch {\n\t\treturn raw.includes(\":\") ? undefined : raw;\n\t}\n\treturn SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : undefined;\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Headless node-graph canvas backed by reactflow. Renders an interactive\n * graph of agent steps, workflow nodes, RAG document refs — anywhere your\n * AI app needs to visualize relationships.\n *\n * Controlled: pass `nodes` and `edges`; receive change events. Reactflow's\n * default Background + Controls are rendered automatically; pass `children`\n * to add Panels, MiniMap, or custom overlays.\n *\n * Heavy peer: requires `reactflow` (~80 KB gzip). The hex-core CLI's `add`\n * flow prompts before installing.\n *\n * @example\n * import \"reactflow/dist/style.css\"; // once in your app entry\n * <Canvas\n * nodes={[{ id: \"1\", position: { x: 0, y: 0 }, data: { label: \"Agent\" } }]}\n * edges={[]}\n * onNodesChange={onNodesChange}\n * onEdgesChange={onEdgesChange}\n * />\n */\nexport interface CanvasProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"children\" | \"onError\"> {\n\t/** Node objects passed to ReactFlow. See reactflow docs for shape. */\n\tnodes: import(\"reactflow\").Node[];\n\t/** Edge objects passed to ReactFlow. */\n\tedges: import(\"reactflow\").Edge[];\n\t/** Forwarded to ReactFlow.onNodesChange. */\n\tonNodesChange?: import(\"reactflow\").OnNodesChange;\n\t/** Forwarded to ReactFlow.onEdgesChange. */\n\tonEdgesChange?: import(\"reactflow\").OnEdgesChange;\n\t/** Forwarded to ReactFlow.onConnect (fires when user wires two nodes). */\n\tonConnect?: import(\"reactflow\").OnConnect;\n\t/** Hide the bottom-left zoom/pan/fit controls. Default false (visible). */\n\thideControls?: boolean;\n\t/** Hide the dotted background. Default false (visible). */\n\thideBackground?: boolean;\n\t/** Auto-fit the view to all nodes on first render. Default true. */\n\tfitView?: boolean;\n\t/** Slot for MiniMap, Panel, or custom overlays rendered inside ReactFlow. */\n\tchildren?: React.ReactNode;\n}\n\n/**\n * Renders a ReactFlow graph with sensible defaults.\n * @param props - Controlled nodes/edges + interaction handlers\n * @returns A div containing the ReactFlow canvas\n */\nfunction Canvas({\n\tnodes,\n\tedges,\n\tonNodesChange,\n\tonEdgesChange,\n\tonConnect,\n\thideControls = false,\n\thideBackground = false,\n\tfitView = true,\n\tchildren,\n\tclassName,\n\t...rest\n}: CanvasProps) {\n\t// Lazy-loaded reactflow modules. Held in state so a re-render kicks in\n\t// once the dynamic import resolves; until then we render a placeholder.\n\tconst [rf, setRf] = React.useState<typeof import(\"reactflow\") | null>(null);\n\n\tReact.useEffect(() => {\n\t\tlet cancelled = false;\n\t\tvoid import(\"reactflow\").then((mod) => {\n\t\t\tif (!cancelled) setRf(mod);\n\t\t});\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, []);\n\n\tif (!rf) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\t{...rest}\n\t\t\t\tdata-hex-canvas-loading\n\t\t\t\tclassName={cn(\"h-full w-full bg-muted/20\", className)}\n\t\t\t\taria-busy=\"true\"\n\t\t\t/>\n\t\t);\n\t}\n\n\tconst { ReactFlow, Background, Controls } = rf;\n\n\treturn (\n\t\t<div\n\t\t\t{...rest}\n\t\t\tdata-hex-canvas\n\t\t\tclassName={cn(\"h-full w-full\", className)}\n\t\t>\n\t\t\t<ReactFlow\n\t\t\t\tnodes={nodes}\n\t\t\t\tedges={edges}\n\t\t\t\tonNodesChange={onNodesChange}\n\t\t\t\tonEdgesChange={onEdgesChange}\n\t\t\t\tonConnect={onConnect}\n\t\t\t\tfitView={fitView}\n\t\t\t>\n\t\t\t\t{!hideBackground && <Background />}\n\t\t\t\t{!hideControls && <Controls />}\n\t\t\t\t{children}\n\t\t\t</ReactFlow>\n\t\t</div>\n\t);\n}\n\nexport { Canvas };\n"]}
package/dist/card.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/components/card/card.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACHA,IAAM,IAAA,GAAa,KAAA,CAAA,UAAA;AAAA,EAClB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACV,yEAAA;AAAA,QACA,2EAAA;AAAA,QACA,iBAAA;AAAA,QACA;AAAA,OACD;AAAA,MACC,GAAG;AAAA;AAAA;AAGP;AACA,IAAA,CAAK,WAAA,GAAc,MAAA;AAGnB,IAAM,UAAA,GAAmB,KAAA,CAAA,UAAA;AAAA,EACxB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,qDAAA,EAAuD,SAAS,CAAA;AAAA,MAC7E,GAAG;AAAA;AAAA;AAGP;AACA,UAAA,CAAW,WAAA,GAAc,YAAA;AAGzB,IAAM,SAAA,GAAkB,KAAA,CAAA,UAAA;AAAA,EACvB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,oDAAA,EAAsD,SAAS,CAAA;AAAA,MAC5E,GAAG;AAAA;AAAA;AAGP;AACA,SAAA,CAAU,WAAA,GAAc,WAAA;AAGxB,IAAM,kBAAwB,KAAA,CAAA,UAAA,CAG5B,CAAC,EAAE,SAAA,EAAW,GAAG,OAAM,EAAG,GAAA,yBAC1B,GAAA,EAAA,EAAE,GAAA,EAAU,WAAW,EAAA,CAAG,+BAAA,EAAiC,SAAS,CAAA,EAAI,GAAG,OAAO,CACnF;AACD,eAAA,CAAgB,WAAA,GAAc,iBAAA;AAG9B,IAAM,WAAA,GAAoB,KAAA,CAAA,UAAA;AAAA,EACzB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,WAAW,EAAA,CAAG,gCAAA,EAAkC,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO;AAExF;AACA,WAAA,CAAY,WAAA,GAAc,aAAA;AAG1B,IAAM,UAAA,GAAmB,KAAA,CAAA,UAAA;AAAA,EACxB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,kDAAA,EAAoD,SAAS,CAAA;AAAA,MAC1E,GAAG;AAAA;AAAA;AAGP;AACA,UAAA,CAAW,WAAA,GAAc,YAAA","file":"card.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n// Card consumes tokens --space-6, --space-4, --duration-normal.\n// Fallbacks match Tailwind defaults for consumers without a theme loaded.\n\n/** A container card with subtle shadow and border. */\nconst Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={cn(\n\t\t\t\t\"rounded-lg border border-foreground/[0.08] bg-card text-card-foreground\",\n\t\t\t\t\"shadow-sm transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\"hover:shadow-md\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCard.displayName = \"Card\";\n\n/** The header section of a Card. */\nconst CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"flex flex-col space-y-1.5 p-[var(--space-6,1.5rem)]\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCardHeader.displayName = \"CardHeader\";\n\n/** The title element inside a CardHeader. */\nconst CardTitle = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<h3\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"text-2xl font-semibold leading-none tracking-tight\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCardTitle.displayName = \"CardTitle\";\n\n/** A description element inside a CardHeader. */\nconst CardDescription = React.forwardRef<\n\tHTMLParagraphElement,\n\tReact.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n\t<p ref={ref} className={cn(\"text-sm text-muted-foreground\", className)} {...props} />\n));\nCardDescription.displayName = \"CardDescription\";\n\n/** The main content area of a Card. */\nconst CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div ref={ref} className={cn(\"p-[var(--space-6,1.5rem)] pt-0\", className)} {...props} />\n\t),\n);\nCardContent.displayName = \"CardContent\";\n\n/** The footer section of a Card. */\nconst CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"flex items-center p-[var(--space-6,1.5rem)] pt-0\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCardFooter.displayName = \"CardFooter\";\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/card/card.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACHA,IAAM,IAAA,GAAa,KAAA,CAAA,UAAA;AAAA,EAClB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACV,yEAAA;AAAA,QACA,2EAAA;AAAA,QACA,iBAAA;AAAA,QACA;AAAA,OACD;AAAA,MACC,GAAG;AAAA;AAAA;AAGP;AACA,IAAA,CAAK,WAAA,GAAc,MAAA;AAGnB,IAAM,UAAA,GAAmB,KAAA,CAAA,UAAA;AAAA,EACxB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,qDAAA,EAAuD,SAAS,CAAA;AAAA,MAC7E,GAAG;AAAA;AAAA;AAGP;AACA,UAAA,CAAW,WAAA,GAAc,YAAA;AAGzB,IAAM,SAAA,GAAkB,KAAA,CAAA,UAAA;AAAA,EACvB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,oDAAA,EAAsD,SAAS,CAAA;AAAA,MAC5E,GAAG;AAAA;AAAA;AAGP;AACA,SAAA,CAAU,WAAA,GAAc,WAAA;AAGxB,IAAM,kBAAwB,KAAA,CAAA,UAAA,CAG5B,CAAC,EAAE,SAAA,EAAW,GAAG,OAAM,EAAG,GAAA,yBAC1B,GAAA,EAAA,EAAE,GAAA,EAAU,WAAW,EAAA,CAAG,+BAAA,EAAiC,SAAS,CAAA,EAAI,GAAG,OAAO,CACnF;AACD,eAAA,CAAgB,WAAA,GAAc,iBAAA;AAG9B,IAAM,WAAA,GAAoB,KAAA,CAAA,UAAA;AAAA,EACzB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,WAAW,EAAA,CAAG,gCAAA,EAAkC,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO;AAExF;AACA,WAAA,CAAY,WAAA,GAAc,aAAA;AAG1B,IAAM,UAAA,GAAmB,KAAA,CAAA,UAAA;AAAA,EACxB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,kDAAA,EAAoD,SAAS,CAAA;AAAA,MAC1E,GAAG;AAAA;AAAA;AAGP;AACA,UAAA,CAAW,WAAA,GAAc,YAAA","file":"card.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n\nconst SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"mailto:\"] as const;\n\n/**\n * Allowlist a URL for use as an `<a href>` against untrusted input.\n *\n * Returns the raw string when it's `http(s):` / `mailto:` / a relative\n * URL (no scheme); returns `undefined` otherwise. Defends against\n * `javascript:` / `data:` / `vbscript:` injection from streamed model\n * output or third-party JSON payloads that flow into citation chips.\n *\n * Inside a Markdown render path, `rehype-sanitize` already strips\n * `javascript:` from inline-link hrefs — but it does NOT introspect\n * JSON nested inside attribute values (e.g. `<sources data='[…]'/>`),\n * so the components that consume that data must guard themselves.\n *\n * @param raw - The candidate URL, or `undefined` when none was supplied.\n * @returns The URL when safe to render, otherwise `undefined`.\n */\nexport function safeUrl(raw: string | undefined): string | undefined {\n\tif (raw === undefined || raw === \"\") return undefined;\n\t// Relative URLs have no scheme — `new URL(relative)` throws without a base,\n\t// so a thrown URL means either malformed input OR a relative path. Treat\n\t// \"throws + does not contain a colon\" as a relative path (safe).\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(raw);\n\t} catch {\n\t\treturn raw.includes(\":\") ? undefined : raw;\n\t}\n\treturn SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : undefined;\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n// Card consumes tokens --space-6, --space-4, --duration-normal.\n// Fallbacks match Tailwind defaults for consumers without a theme loaded.\n\n/** A container card with subtle shadow and border. */\nconst Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={cn(\n\t\t\t\t\"rounded-lg border border-foreground/[0.08] bg-card text-card-foreground\",\n\t\t\t\t\"shadow-sm transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\"hover:shadow-md\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCard.displayName = \"Card\";\n\n/** The header section of a Card. */\nconst CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"flex flex-col space-y-1.5 p-[var(--space-6,1.5rem)]\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCardHeader.displayName = \"CardHeader\";\n\n/** The title element inside a CardHeader. */\nconst CardTitle = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<h3\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"text-2xl font-semibold leading-none tracking-tight\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCardTitle.displayName = \"CardTitle\";\n\n/** A description element inside a CardHeader. */\nconst CardDescription = React.forwardRef<\n\tHTMLParagraphElement,\n\tReact.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n\t<p ref={ref} className={cn(\"text-sm text-muted-foreground\", className)} {...props} />\n));\nCardDescription.displayName = \"CardDescription\";\n\n/** The main content area of a Card. */\nconst CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div ref={ref} className={cn(\"p-[var(--space-6,1.5rem)] pt-0\", className)} {...props} />\n\t),\n);\nCardContent.displayName = \"CardContent\";\n\n/** The footer section of a Card. */\nconst CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"flex items-center p-[var(--space-6,1.5rem)] pt-0\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCardFooter.displayName = \"CardFooter\";\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };\n"]}
@@ -0,0 +1,3 @@
1
+ export { ChainOfThoughtProps_alias_1 as ChainOfThoughtProps } from './_tsup-dts-rollup.js';
2
+ export { ChainOfThoughtStep_alias_1 as ChainOfThoughtStep } from './_tsup-dts-rollup.js';
3
+ export { ChainOfThought_alias_1 as ChainOfThought } from './_tsup-dts-rollup.js';
@@ -0,0 +1,119 @@
1
+ "use client";
2
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
3
+ import { clsx } from 'clsx';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+ function Reasoning({
11
+ children,
12
+ defaultOpen = false,
13
+ durationMs,
14
+ label,
15
+ className
16
+ }) {
17
+ const headerLabel = label ?? (typeof durationMs === "number" ? formatThoughtFor(durationMs) : "Thinking");
18
+ return /* @__PURE__ */ jsxs(
19
+ CollapsiblePrimitive.Root,
20
+ {
21
+ defaultOpen,
22
+ className: cn("overflow-hidden rounded-md border-l-2 border-foreground/15 bg-muted/20", className),
23
+ children: [
24
+ /* @__PURE__ */ jsxs(
25
+ CollapsiblePrimitive.Trigger,
26
+ {
27
+ className: cn(
28
+ "group flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-muted-foreground",
29
+ "transition-all duration-[var(--duration-normal,200ms)] ease-out",
30
+ "hover:text-foreground",
31
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
32
+ ),
33
+ children: [
34
+ /* @__PURE__ */ jsx(SparkleGlyph, {}),
35
+ /* @__PURE__ */ jsx("span", { className: "font-medium italic", children: headerLabel }),
36
+ /* @__PURE__ */ jsx(Chevron, {})
37
+ ]
38
+ }
39
+ ),
40
+ /* @__PURE__ */ jsx(CollapsiblePrimitive.Content, { className: "overflow-hidden border-t border-foreground/[0.06] px-3 py-2 text-sm text-muted-foreground", children })
41
+ ]
42
+ }
43
+ );
44
+ }
45
+ function formatThoughtFor(ms) {
46
+ if (ms < 1e3) return `Thought for ${ms}ms`;
47
+ const seconds = ms / 1e3;
48
+ const formatted = seconds >= 10 ? Math.round(seconds).toString() : seconds.toFixed(1);
49
+ return `Thought for ${formatted}s`;
50
+ }
51
+ function SparkleGlyph() {
52
+ return /* @__PURE__ */ jsx(
53
+ "svg",
54
+ {
55
+ "aria-hidden": true,
56
+ viewBox: "0 0 16 16",
57
+ width: "12",
58
+ height: "12",
59
+ fill: "none",
60
+ stroke: "currentColor",
61
+ strokeWidth: "1.5",
62
+ strokeLinecap: "round",
63
+ strokeLinejoin: "round",
64
+ className: "shrink-0",
65
+ children: /* @__PURE__ */ jsx("path", { d: "M8 1.5l1.5 4 4 1.5-4 1.5L8 12.5 6.5 8.5l-4-1.5 4-1.5L8 1.5z" })
66
+ }
67
+ );
68
+ }
69
+ function Chevron() {
70
+ return /* @__PURE__ */ jsx(
71
+ "svg",
72
+ {
73
+ "aria-hidden": true,
74
+ viewBox: "0 0 16 16",
75
+ width: "12",
76
+ height: "12",
77
+ fill: "none",
78
+ stroke: "currentColor",
79
+ strokeWidth: "1.5",
80
+ strokeLinecap: "round",
81
+ strokeLinejoin: "round",
82
+ className: "ml-auto shrink-0 transition-transform duration-200 group-data-[state=open]:rotate-180",
83
+ children: /* @__PURE__ */ jsx("path", { d: "M4 6l4 4 4-4" })
84
+ }
85
+ );
86
+ }
87
+ function ChainOfThought({
88
+ steps,
89
+ finalAnswer,
90
+ label = "Chain of thought",
91
+ defaultOpen = false,
92
+ className
93
+ }) {
94
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
95
+ /* @__PURE__ */ jsx(Reasoning, { label, defaultOpen, children: /* @__PURE__ */ jsx("ol", { className: "my-0 ml-0 flex list-none flex-col gap-3 pl-0", children: steps.map((step, index) => /* @__PURE__ */ jsxs(
96
+ "li",
97
+ {
98
+ className: "flex flex-col gap-1 text-sm before:content-none",
99
+ children: [
100
+ /* @__PURE__ */ jsx(Row, { term: "Thought", value: step.thought }),
101
+ step.action ? /* @__PURE__ */ jsx(Row, { term: "Action", value: step.action }) : null,
102
+ step.observation ? /* @__PURE__ */ jsx(Row, { term: "Observation", value: step.observation }) : null
103
+ ]
104
+ },
105
+ index
106
+ )) }) }),
107
+ finalAnswer ? /* @__PURE__ */ jsx("div", { children: finalAnswer }) : null
108
+ ] });
109
+ }
110
+ function Row({ term, value }) {
111
+ return /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
112
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: term }),
113
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 text-foreground", children: value })
114
+ ] });
115
+ }
116
+
117
+ export { ChainOfThought };
118
+ //# sourceMappingURL=chain-of-thought.js.map
119
+ //# sourceMappingURL=chain-of-thought.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/ai/reasoning/reasoning.tsx","../src/ai/chain-of-thought/chain-of-thought.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"chain-of-thought.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n\nconst SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"mailto:\"] as const;\n\n/**\n * Allowlist a URL for use as an `<a href>` against untrusted input.\n *\n * Returns the raw string when it's `http(s):` / `mailto:` / a relative\n * URL (no scheme); returns `undefined` otherwise. Defends against\n * `javascript:` / `data:` / `vbscript:` injection from streamed model\n * output or third-party JSON payloads that flow into citation chips.\n *\n * Inside a Markdown render path, `rehype-sanitize` already strips\n * `javascript:` from inline-link hrefs — but it does NOT introspect\n * JSON nested inside attribute values (e.g. `<sources data='[…]'/>`),\n * so the components that consume that data must guard themselves.\n *\n * @param raw - The candidate URL, or `undefined` when none was supplied.\n * @returns The URL when safe to render, otherwise `undefined`.\n */\nexport function safeUrl(raw: string | undefined): string | undefined {\n\tif (raw === undefined || raw === \"\") return undefined;\n\t// Relative URLs have no scheme — `new URL(relative)` throws without a base,\n\t// so a thrown URL means either malformed input OR a relative path. Treat\n\t// \"throws + does not contain a colon\" as a relative path (safe).\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(raw);\n\t} catch {\n\t\treturn raw.includes(\":\") ? undefined : raw;\n\t}\n\treturn SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : undefined;\n}\n","\"use client\";\n\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Collapsible \"thinking\" block. Designed for Anthropic-style reasoning\n * traces or Chain-of-Thought scratchpads — content the user can optionally\n * inspect without it dominating the response. Header shows a label and the\n * thinking duration if provided.\n *\n * Headless on content: pass any `children`. Pair with `Markdown` if the\n * reasoning is markdown-formatted.\n *\n * @example\n * <Reasoning durationMs={4200}>\n * <Markdown>{thinking}</Markdown>\n * </Reasoning>\n */\nexport interface ReasoningProps {\n\tchildren: React.ReactNode;\n\tdefaultOpen?: boolean;\n\t/** Time spent thinking, in milliseconds. Renders as \"Thought for 4.2s\". */\n\tdurationMs?: number;\n\t/** Override the default \"Thinking\" / \"Thought for X\" label. */\n\tlabel?: string;\n\tclassName?: string;\n}\n\n/**\n * Renders a collapsible thinking-trace block.\n * @param props - children + optional duration\n * @returns A Collapsible with a labelled header and content body\n */\nfunction Reasoning({\n\tchildren,\n\tdefaultOpen = false,\n\tdurationMs,\n\tlabel,\n\tclassName,\n}: ReasoningProps) {\n\tconst headerLabel =\n\t\tlabel ?? (typeof durationMs === \"number\" ? formatThoughtFor(durationMs) : \"Thinking\");\n\n\treturn (\n\t\t<CollapsiblePrimitive.Root\n\t\t\tdefaultOpen={defaultOpen}\n\t\t\tclassName={cn(\"overflow-hidden rounded-md border-l-2 border-foreground/15 bg-muted/20\", className)}\n\t\t>\n\t\t\t<CollapsiblePrimitive.Trigger\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"group flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-muted-foreground\",\n\t\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\t\"hover:text-foreground\",\n\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<SparkleGlyph />\n\t\t\t\t<span className=\"font-medium italic\">{headerLabel}</span>\n\t\t\t\t<Chevron />\n\t\t\t</CollapsiblePrimitive.Trigger>\n\t\t\t<CollapsiblePrimitive.Content className=\"overflow-hidden border-t border-foreground/[0.06] px-3 py-2 text-sm text-muted-foreground\">\n\t\t\t\t{children}\n\t\t\t</CollapsiblePrimitive.Content>\n\t\t</CollapsiblePrimitive.Root>\n\t);\n}\n\nfunction formatThoughtFor(ms: number): string {\n\tif (ms < 1000) return `Thought for ${ms}ms`;\n\tconst seconds = ms / 1000;\n\tconst formatted = seconds >= 10 ? Math.round(seconds).toString() : seconds.toFixed(1);\n\treturn `Thought for ${formatted}s`;\n}\n\nfunction SparkleGlyph() {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\twidth=\"12\"\n\t\t\theight=\"12\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"1.5\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName=\"shrink-0\"\n\t\t>\n\t\t\t<path d=\"M8 1.5l1.5 4 4 1.5-4 1.5L8 12.5 6.5 8.5l-4-1.5 4-1.5L8 1.5z\" />\n\t\t</svg>\n\t);\n}\n\nfunction Chevron() {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\twidth=\"12\"\n\t\t\theight=\"12\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"1.5\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName=\"ml-auto shrink-0 transition-transform duration-200 group-data-[state=open]:rotate-180\"\n\t\t>\n\t\t\t<path d=\"M4 6l4 4 4-4\" />\n\t\t</svg>\n\t);\n}\n\nexport { Reasoning };\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Reasoning } from \"../reasoning/reasoning.js\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Structured reasoning trace following the canonical ReAct shape — each\n * step has a `thought`, an optional `action`, and an optional\n * `observation`. The final answer renders below the trace.\n *\n * Distinct from `<Reasoning>`: Reasoning is unstructured prose;\n * `<ChainOfThought>` enforces the per-step structure agents emit when\n * doing tool-augmented reasoning. Internally composes `<Reasoning>` for\n * the collapsible shell so the visual rhythm matches.\n *\n * @example\n * <ChainOfThought\n * steps={[\n * {\n * thought: \"Need to look up the auth module\",\n * action: \"read auth.ts\",\n * observation: \"200 lines, uses bcrypt + jwt\",\n * },\n * { thought: \"The bug is on line 42 — missing salt rounds.\" },\n * ]}\n * finalAnswer={<Markdown>{summary}</Markdown>}\n * />\n */\nexport interface ChainOfThoughtProps {\n\t/** Ordered ReAct steps. */\n\tsteps: ChainOfThoughtStep[];\n\t/** Optional final answer rendered beneath the trace. */\n\tfinalAnswer?: React.ReactNode;\n\t/** Header label for the collapsible. Defaults to \"Chain of thought\". */\n\tlabel?: string;\n\t/** Whether the trace is expanded by default. */\n\tdefaultOpen?: boolean;\n\tclassName?: string;\n}\n\n/** A single ReAct step. */\nexport interface ChainOfThoughtStep {\n\t/** What the model is thinking right now. Required — every step has a thought. */\n\tthought: React.ReactNode;\n\t/** Optional action the model is about to take (e.g. \"read auth.ts\"). */\n\taction?: React.ReactNode;\n\t/** Optional observation returned by the action. */\n\tobservation?: React.ReactNode;\n}\n\n/**\n * Render a structured reasoning trace + optional final answer.\n * @param props - The ordered steps and optional final answer.\n * @returns A Reasoning collapsible wrapping per-step rows, then the final answer.\n */\nfunction ChainOfThought({\n\tsteps,\n\tfinalAnswer,\n\tlabel = \"Chain of thought\",\n\tdefaultOpen = false,\n\tclassName,\n}: ChainOfThoughtProps) {\n\treturn (\n\t\t<div className={cn(\"flex flex-col gap-2\", className)}>\n\t\t\t<Reasoning label={label} defaultOpen={defaultOpen}>\n\t\t\t\t<ol className=\"my-0 ml-0 flex list-none flex-col gap-3 pl-0\">\n\t\t\t\t\t{steps.map((step, index) => (\n\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t * Index keys are correct here: ReAct steps are\n\t\t\t\t\t\t\t * append-only during a turn, never reordered or\n\t\t\t\t\t\t\t * spliced out, so the index uniquely identifies\n\t\t\t\t\t\t\t * each step for the lifetime of the render.\n\t\t\t\t\t\t\t *\n\t\t\t\t\t\t\t * `before:content-none` defeats Tailwind\n\t\t\t\t\t\t\t * Typography's default `<li>::before` markers\n\t\t\t\t\t\t\t * when this card lands inside a `prose` block.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\tclassName=\"flex flex-col gap-1 text-sm before:content-none\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Row term=\"Thought\" value={step.thought} />\n\t\t\t\t\t\t\t{step.action ? <Row term=\"Action\" value={step.action} /> : null}\n\t\t\t\t\t\t\t{step.observation ? (\n\t\t\t\t\t\t\t\t<Row term=\"Observation\" value={step.observation} />\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ol>\n\t\t\t</Reasoning>\n\t\t\t{finalAnswer ? <div>{finalAnswer}</div> : null}\n\t\t</div>\n\t);\n}\n\ninterface RowProps {\n\tterm: string;\n\tvalue: React.ReactNode;\n}\n\nfunction Row({ term, value }: RowProps) {\n\treturn (\n\t\t<div className=\"flex gap-2\">\n\t\t\t<span className=\"shrink-0 text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n\t\t\t\t{term}\n\t\t\t</span>\n\t\t\t<span className=\"min-w-0 flex-1 text-foreground\">{value}</span>\n\t\t</div>\n\t);\n}\n\nexport { ChainOfThought };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/checkbox/checkbox.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACEA,IAAM,QAAA,GAAiB,iBAGrB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC3B,GAAA;AAAA,EAAmB,iBAAA,CAAA,IAAA;AAAA,EAAlB;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,uDAAA;AAAA,MACA,iEAAA;AAAA,MACA,qDAAA;AAAA,MACA,sCAAA;AAAA,MACA,qGAAA;AAAA,MACA,iDAAA;AAAA,MACA,kHAAA;AAAA,MACA,oIAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG,KAAA;AAAA,IAEJ,+BAAmB,iBAAA,CAAA,SAAA,EAAlB,EAA4B,SAAA,EAAW,EAAA,CAAG,+CAA+C,CAAA,EAGzF,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACA,KAAA,EAAM,4BAAA;AAAA,UACN,OAAA,EAAQ,WAAA;AAAA,UACR,IAAA,EAAK,MAAA;AAAA,UACL,MAAA,EAAO,cAAA;AAAA,UACP,WAAA,EAAY,GAAA;AAAA,UACZ,aAAA,EAAc,OAAA;AAAA,UACd,cAAA,EAAe,OAAA;AAAA,UACf,SAAA,EAAU,qDAAA;AAAA,UACV,aAAA,EAAY,MAAA;AAAA,UAEZ,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAS,MAAA,EAAO,gBAAA,EAAiB;AAAA;AAAA,OACnC;AAAA,sBACA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACA,KAAA,EAAM,4BAAA;AAAA,UACN,OAAA,EAAQ,WAAA;AAAA,UACR,IAAA,EAAK,MAAA;AAAA,UACL,MAAA,EAAO,cAAA;AAAA,UACP,WAAA,EAAY,GAAA;AAAA,UACZ,aAAA,EAAc,OAAA;AAAA,UACd,cAAA,EAAe,OAAA;AAAA,UACf,SAAA,EAAU,2DAAA;AAAA,UACV,aAAA,EAAY,MAAA;AAAA,UAEZ,QAAA,kBAAA,GAAA,CAAC,UAAK,EAAA,EAAG,GAAA,EAAI,IAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK;AAAA;AAAA;AACtC,KAAA,EACD;AAAA;AACD,CACA;AACD,QAAA,CAAS,WAAA,GAAc,UAAA","file":"checkbox.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * An accessible checkbox component built on Radix UI.\n * Supports checked, unchecked, and indeterminate states with smooth animations.\n */\nexport type CheckboxProps = React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>;\n\nconst Checkbox = React.forwardRef<\n\tReact.ComponentRef<typeof CheckboxPrimitive.Root>,\n\tCheckboxProps\n>(({ className, ...props }, ref) => (\n\t<CheckboxPrimitive.Root\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"group h-4 w-4 shrink-0 rounded-sm border border-input\",\n\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\"shadow-sm inset-ring-1 inset-ring-foreground/[0.06]\",\n\t\t\t\"hover:border-ring/50 hover:shadow-md\",\n\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\"data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground\",\n\t\t\t\"data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t<CheckboxPrimitive.Indicator className={cn(\"flex items-center justify-center text-current\")}>\n\t\t\t{/* ✓ when checked; dash when indeterminate. The Root has `group`, so each icon\n\t\t\t shows only when the Root's data-state matches. */}\n\t\t\t<svg\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"3\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tclassName=\"hidden h-3.5 w-3.5 group-data-[state=checked]:block\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t\t</svg>\n\t\t\t<svg\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"3\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tclassName=\"hidden h-3.5 w-3.5 group-data-[state=indeterminate]:block\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n\t\t\t</svg>\n\t\t</CheckboxPrimitive.Indicator>\n\t</CheckboxPrimitive.Root>\n));\nCheckbox.displayName = \"Checkbox\";\n\nexport { Checkbox };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/checkbox/checkbox.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACEA,IAAM,QAAA,GAAiB,iBAGrB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC3B,GAAA;AAAA,EAAmB,iBAAA,CAAA,IAAA;AAAA,EAAlB;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,uDAAA;AAAA,MACA,iEAAA;AAAA,MACA,qDAAA;AAAA,MACA,sCAAA;AAAA,MACA,qGAAA;AAAA,MACA,iDAAA;AAAA,MACA,kHAAA;AAAA,MACA,oIAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG,KAAA;AAAA,IAEJ,+BAAmB,iBAAA,CAAA,SAAA,EAAlB,EAA4B,SAAA,EAAW,EAAA,CAAG,+CAA+C,CAAA,EAGzF,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACA,KAAA,EAAM,4BAAA;AAAA,UACN,OAAA,EAAQ,WAAA;AAAA,UACR,IAAA,EAAK,MAAA;AAAA,UACL,MAAA,EAAO,cAAA;AAAA,UACP,WAAA,EAAY,GAAA;AAAA,UACZ,aAAA,EAAc,OAAA;AAAA,UACd,cAAA,EAAe,OAAA;AAAA,UACf,SAAA,EAAU,qDAAA;AAAA,UACV,aAAA,EAAY,MAAA;AAAA,UAEZ,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAS,MAAA,EAAO,gBAAA,EAAiB;AAAA;AAAA,OACnC;AAAA,sBACA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACA,KAAA,EAAM,4BAAA;AAAA,UACN,OAAA,EAAQ,WAAA;AAAA,UACR,IAAA,EAAK,MAAA;AAAA,UACL,MAAA,EAAO,cAAA;AAAA,UACP,WAAA,EAAY,GAAA;AAAA,UACZ,aAAA,EAAc,OAAA;AAAA,UACd,cAAA,EAAe,OAAA;AAAA,UACf,SAAA,EAAU,2DAAA;AAAA,UACV,aAAA,EAAY,MAAA;AAAA,UAEZ,QAAA,kBAAA,GAAA,CAAC,UAAK,EAAA,EAAG,GAAA,EAAI,IAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK;AAAA;AAAA;AACtC,KAAA,EACD;AAAA;AACD,CACA;AACD,QAAA,CAAS,WAAA,GAAc,UAAA","file":"checkbox.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n\nconst SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"mailto:\"] as const;\n\n/**\n * Allowlist a URL for use as an `<a href>` against untrusted input.\n *\n * Returns the raw string when it's `http(s):` / `mailto:` / a relative\n * URL (no scheme); returns `undefined` otherwise. Defends against\n * `javascript:` / `data:` / `vbscript:` injection from streamed model\n * output or third-party JSON payloads that flow into citation chips.\n *\n * Inside a Markdown render path, `rehype-sanitize` already strips\n * `javascript:` from inline-link hrefs — but it does NOT introspect\n * JSON nested inside attribute values (e.g. `<sources data='[…]'/>`),\n * so the components that consume that data must guard themselves.\n *\n * @param raw - The candidate URL, or `undefined` when none was supplied.\n * @returns The URL when safe to render, otherwise `undefined`.\n */\nexport function safeUrl(raw: string | undefined): string | undefined {\n\tif (raw === undefined || raw === \"\") return undefined;\n\t// Relative URLs have no scheme — `new URL(relative)` throws without a base,\n\t// so a thrown URL means either malformed input OR a relative path. Treat\n\t// \"throws + does not contain a colon\" as a relative path (safe).\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(raw);\n\t} catch {\n\t\treturn raw.includes(\":\") ? undefined : raw;\n\t}\n\treturn SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : undefined;\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * An accessible checkbox component built on Radix UI.\n * Supports checked, unchecked, and indeterminate states with smooth animations.\n */\nexport type CheckboxProps = React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>;\n\nconst Checkbox = React.forwardRef<\n\tReact.ComponentRef<typeof CheckboxPrimitive.Root>,\n\tCheckboxProps\n>(({ className, ...props }, ref) => (\n\t<CheckboxPrimitive.Root\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"group h-4 w-4 shrink-0 rounded-sm border border-input\",\n\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\"shadow-sm inset-ring-1 inset-ring-foreground/[0.06]\",\n\t\t\t\"hover:border-ring/50 hover:shadow-md\",\n\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\"data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground\",\n\t\t\t\"data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t<CheckboxPrimitive.Indicator className={cn(\"flex items-center justify-center text-current\")}>\n\t\t\t{/* ✓ when checked; dash when indeterminate. The Root has `group`, so each icon\n\t\t\t shows only when the Root's data-state matches. */}\n\t\t\t<svg\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"3\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tclassName=\"hidden h-3.5 w-3.5 group-data-[state=checked]:block\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t\t</svg>\n\t\t\t<svg\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"3\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tclassName=\"hidden h-3.5 w-3.5 group-data-[state=indeterminate]:block\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n\t\t\t</svg>\n\t\t</CheckboxPrimitive.Indicator>\n\t</CheckboxPrimitive.Root>\n));\nCheckbox.displayName = \"Checkbox\";\n\nexport { Checkbox };\n"]}
package/dist/chord.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/chart-palette.ts","../src/lib/utils.ts","../src/artifacts/chord/chord.tsx"],"names":[],"mappings":"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","file":"chord.js","sourcesContent":["/**\n * Categorical chart palette for diagram primitives that encode categorical\n * data (sunburst, treemap, sankey, chord, funnel, pyramid, venn, matrix).\n * Cycled by an integer key — node index, leaf index, depth-1 ancestor, etc.\n *\n * The values reach into `--chart-1` through `--chart-6`, the dedicated\n * diagram-encoding tokens added in `@hex-core/tokens` 1.4. Each token has a\n * `var(--primary)` fallback so consumers on theme presets that haven't been\n * updated to ship `--chart-N` (or who run a custom theme without the chart\n * family) still see a coherent monochrome rendering instead of black SVG\n * fills.\n *\n * Why a chart palette and not the semantic tokens: `--primary`, `--accent`,\n * `--secondary`, and `--muted` collapse to a single hue family in the\n * default monochrome theme — adjacent segments of a chart end up\n * indistinguishable. Chart tokens are tuned for perceptual differentiation.\n */\nexport const CHART_PALETTE = [\n\t\"hsl(var(--chart-1, var(--primary)))\",\n\t\"hsl(var(--chart-2, var(--primary)))\",\n\t\"hsl(var(--chart-3, var(--primary)))\",\n\t\"hsl(var(--chart-4, var(--primary)))\",\n\t\"hsl(var(--chart-5, var(--primary)))\",\n\t\"hsl(var(--chart-6, var(--primary)))\",\n] as const;\n\n/**\n * Return the chart hue at a stable index. Cycles modulo `CHART_PALETTE.length`\n * so the caller doesn't have to range-check.\n *\n * @param index - Integer key (node index, leaf index, depth-1 ancestor index, …).\n * @returns A `hsl(var(...))` string suitable for SVG `fill` / `stroke`.\n */\nexport function pickChartHue(index: number): string {\n\tconst safe = ((index % CHART_PALETTE.length) + CHART_PALETTE.length) % CHART_PALETTE.length;\n\t// `safe` is provably 0..CHART_PALETTE.length-1 — the assertion documents that.\n\treturn CHART_PALETTE[safe] as string;\n}\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { pickChartHue } from \"../../lib/chart-palette.js\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Chord diagram. Nodes sit on a ring; ribbons inside the ring encode\n * weighted bidirectional relationships between them. Common for\n * trade flows, migration, hyperlink graphs, citation networks —\n * anywhere \"A relates to B with weight w\" matters at scale.\n *\n * Heavy peers: requires `d3-chord` (~3 KB gzip) and `d3-shape` (~6 KB\n * gzip, already in the artifacts/ family). The hex-core CLI's `add`\n * flow prompts before installing.\n *\n * @example\n * <Chord\n * nodes={[\"A\", \"B\", \"C\", \"D\"].map((id) => ({ id, label: id }))}\n * matrix={[\n * [0, 5, 8, 1],\n * [3, 0, 2, 4],\n * [6, 0, 0, 7],\n * [2, 1, 9, 0],\n * ]}\n * />\n */\nexport type ChordNode = {\n\tid: string;\n\tlabel: string;\n};\n\n/**\n * Payload fired to `onChordHover`. `sourceValue` is the i→j flow;\n * `targetValue` is the j→i flow. They differ for asymmetric matrices and\n * are equal for symmetric ones.\n */\nexport type ChordHoverPayload = {\n\tsource: ChordNode;\n\ttarget: ChordNode;\n\tsourceValue: number;\n\ttargetValue: number;\n};\n\nexport interface ChordProps extends Omit<React.SVGAttributes<SVGSVGElement>, \"children\"> {\n\t/** Nodes (as ring segments). Order matches matrix rows/columns. */\n\tnodes: ChordNode[];\n\t/** Square N×N matrix of weights. matrix[i][j] = flow from node i to node j. */\n\tmatrix: number[][];\n\t/** Pixel size of the rendered SVG (it's square). Default 480. */\n\tsize?: number;\n\t/** Pixel padding between adjacent ring segments. Default 0.04 (radians, d3 convention). */\n\tpadAngle?: number;\n\t/** Fired when a ribbon is hovered (or hover ends, with `null`). */\n\tonChordHover?: (chord: ChordHoverPayload | null) => void;\n\t/** Fired when a node arc is clicked. */\n\tonNodeClick?: (node: ChordNode) => void;\n}\n\ninterface LaidOutArc {\n\tnode: ChordNode;\n\tdepth: number;\n\td: string;\n\tlabelX: number;\n\tlabelY: number;\n\tlabelAngle: number;\n}\n\ninterface LaidOutChord {\n\tsource: ChordNode;\n\ttarget: ChordNode;\n\tsourceValue: number;\n\ttargetValue: number;\n\td: string;\n\t/** Index of the source node — ribbons inherit the source arc's hue\n\t * so the eye can trace \"where did this flow originate\". */\n\tsourceIdx: number;\n}\n\ntype D3ChordMod = typeof import(\"d3-chord\");\ntype D3ShapeMod = typeof import(\"d3-shape\");\n\nfunction Chord({\n\tnodes,\n\tmatrix,\n\tsize = 480,\n\tpadAngle = 0.04,\n\tonChordHover,\n\tonNodeClick,\n\tclassName,\n\t...rest\n}: ChordProps) {\n\tconst [d3c, setD3c] = React.useState<D3ChordMod | null>(null);\n\tconst [d3s, setD3s] = React.useState<D3ShapeMod | null>(null);\n\tconst [importError, setImportError] = React.useState(false);\n\n\tReact.useEffect(() => {\n\t\tlet cancelled = false;\n\t\tvoid Promise.all([import(\"d3-chord\"), import(\"d3-shape\")]).then(\n\t\t\t([c, s]) => {\n\t\t\t\tif (cancelled) return;\n\t\t\t\tsetD3c(c);\n\t\t\t\tsetD3s(s);\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tif (!cancelled) setImportError(true);\n\t\t\t},\n\t\t);\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, []);\n\n\tconst laidOut = React.useMemo(() => {\n\t\tif (!d3c || !d3s) return null;\n\t\treturn layout(d3c, d3s, nodes, matrix, size, padAngle);\n\t}, [d3c, d3s, nodes, matrix, size, padAngle]);\n\n\tif (importError) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tdata-hex-chord-error\n\t\t\t\trole=\"alert\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"inline-flex items-center justify-center rounded-md border border-destructive/40 bg-destructive/5 p-3 text-sm text-destructive\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tstyle={{ width: size, height: size }}\n\t\t\t>\n\t\t\t\tInstall <code className=\"mx-1\">d3-chord</code> to view this chord diagram.\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (!laidOut) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tdata-hex-chord-loading\n\t\t\t\taria-busy=\"true\"\n\t\t\t\taria-label=\"Loading chord diagram\"\n\t\t\t\tclassName={cn(\"inline-block bg-muted/20\", className)}\n\t\t\t\tstyle={{ width: size, height: size }}\n\t\t\t/>\n\t\t);\n\t}\n\n\tconst { arcs, chords } = laidOut;\n\tconst desc = `Chord diagram with ${nodes.length} node${nodes.length === 1 ? \"\" : \"s\"} and ${chords.length} ribbon${chords.length === 1 ? \"\" : \"s\"}`;\n\tconst radius = size / 2;\n\n\treturn (\n\t\t<svg\n\t\t\t{...rest}\n\t\t\tdata-hex-chord\n\t\t\trole=\"img\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox={`${-radius} ${-radius} ${size} ${size}`}\n\t\t\tclassName={cn(\"block\", className)}\n\t\t>\n\t\t\t<title>Chord diagram</title>\n\t\t\t<desc>{desc}</desc>\n\t\t\t<g data-hex-chord-ribbons>\n\t\t\t\t{chords.map((c, i) => {\n\t\t\t\t\tconst interactive = Boolean(onChordHover);\n\t\t\t\t\tconst payload: ChordHoverPayload = {\n\t\t\t\t\t\tsource: c.source,\n\t\t\t\t\t\ttarget: c.target,\n\t\t\t\t\t\tsourceValue: c.sourceValue,\n\t\t\t\t\t\ttargetValue: c.targetValue,\n\t\t\t\t\t};\n\t\t\t\t\tconst fireHover = (chord: ChordHoverPayload | null) => onChordHover?.(chord);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tkey={`${c.source.id}-${c.target.id}-${i}`}\n\t\t\t\t\t\t\tdata-hex-chord-ribbon\n\t\t\t\t\t\t\td={c.d}\n\t\t\t\t\t\t\tfill={pickChartHue(c.sourceIdx)}\n\t\t\t\t\t\t\tfillOpacity={0.55}\n\t\t\t\t\t\t\tstroke=\"hsl(var(--background))\"\n\t\t\t\t\t\t\tstrokeWidth={0.5}\n\t\t\t\t\t\t\trole={interactive ? \"button\" : undefined}\n\t\t\t\t\t\t\ttabIndex={interactive ? 0 : undefined}\n\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\tinteractive\n\t\t\t\t\t\t\t\t\t? `Flow from ${c.source.label} to ${c.target.label}, value ${c.sourceValue}; reverse value ${c.targetValue}`\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tcursor: interactive ? \"pointer\" : undefined,\n\t\t\t\t\t\t\t\ttransition: \"fill-opacity 120ms ease\",\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonMouseEnter={interactive ? () => fireHover(payload) : undefined}\n\t\t\t\t\t\t\tonMouseLeave={interactive ? () => fireHover(null) : undefined}\n\t\t\t\t\t\t\tonFocus={interactive ? () => fireHover(payload) : undefined}\n\t\t\t\t\t\t\tonBlur={interactive ? () => fireHover(null) : undefined}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</g>\n\t\t\t<g data-hex-chord-arcs>\n\t\t\t\t{arcs.map((a) => {\n\t\t\t\t\tconst interactive = Boolean(onNodeClick);\n\t\t\t\t\tconst handleActivate = () => onNodeClick?.(a.node);\n\t\t\t\t\tconst flip = a.labelAngle > Math.PI / 2 && a.labelAngle < (3 * Math.PI) / 2;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<g\n\t\t\t\t\t\t\tkey={a.node.id}\n\t\t\t\t\t\t\tdata-hex-chord-arc\n\t\t\t\t\t\t\tdata-depth={a.depth}\n\t\t\t\t\t\t\trole={interactive ? \"button\" : undefined}\n\t\t\t\t\t\t\ttabIndex={interactive ? 0 : undefined}\n\t\t\t\t\t\t\taria-label={interactive ? a.node.label : undefined}\n\t\t\t\t\t\t\tstyle={interactive ? { cursor: \"pointer\" } : undefined}\n\t\t\t\t\t\t\tonClick={interactive ? handleActivate : undefined}\n\t\t\t\t\t\t\tonKeyDown={interactive ? (e) => activateOnKey(e, handleActivate) : undefined}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\td={a.d}\n\t\t\t\t\t\t\t\tfill={pickChartHue(a.depth)}\n\t\t\t\t\t\t\t\tstroke=\"hsl(var(--background))\"\n\t\t\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\tx={a.labelX}\n\t\t\t\t\t\t\t\ty={a.labelY}\n\t\t\t\t\t\t\t\ttextAnchor={flip ? \"end\" : \"start\"}\n\t\t\t\t\t\t\t\tdy=\"0.35em\"\n\t\t\t\t\t\t\t\ttransform={\n\t\t\t\t\t\t\t\t\tflip\n\t\t\t\t\t\t\t\t\t\t? `rotate(${(a.labelAngle * 180) / Math.PI - 270} ${a.labelX} ${a.labelY})`\n\t\t\t\t\t\t\t\t\t\t: `rotate(${(a.labelAngle * 180) / Math.PI - 90} ${a.labelX} ${a.labelY})`\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tfontSize={11}\n\t\t\t\t\t\t\t\tfill=\"hsl(var(--foreground))\"\n\t\t\t\t\t\t\t\tstyle={{ pointerEvents: \"none\" }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{a.node.label}\n\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t</g>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</g>\n\t\t</svg>\n\t);\n}\n\nfunction layout(\n\td3c: D3ChordMod,\n\td3s: D3ShapeMod,\n\tnodes: ChordNode[],\n\tmatrix: number[][],\n\tsize: number,\n\tpadAngle: number,\n): { arcs: LaidOutArc[]; chords: LaidOutChord[] } {\n\t// Reserve margin for label text scaled by the longest label, so words\n\t// like \"Americas\" / \"Manufacturing\" don't clip against the SVG edge.\n\t// 6 px/char + 16 px slack — empirically fits 12-char labels at fontSize 11.\n\tconst longestLabel = nodes.reduce((m, n) => Math.max(m, n.label.length), 0);\n\tconst labelMargin = Math.max(40, longestLabel * 6 + 16);\n\tconst radius = size / 2 - labelMargin;\n\tconst innerRadius = radius - 12;\n\tconst outerRadius = radius;\n\n\t// d3.descending lives in d3-array — inline the comparator to avoid pulling\n\t// another peer dep just for one helper.\n\tconst chordGen = d3c\n\t\t.chord()\n\t\t.padAngle(padAngle)\n\t\t.sortSubgroups((a, b) => (a < b ? 1 : a > b ? -1 : 0));\n\tconst result = chordGen(matrix);\n\n\tconst arc = d3s.arc().innerRadius(innerRadius).outerRadius(outerRadius);\n\t// `ribbon()` is exported from d3-chord, not d3-shape.\n\tconst ribbon = d3c.ribbon().radius(innerRadius);\n\n\tconst arcs: LaidOutArc[] = result.groups.map((g) => {\n\t\tconst node = nodes[g.index] ?? { id: `_${g.index}`, label: `Set ${g.index}` };\n\t\tconst midAngle = (g.startAngle + g.endAngle) / 2;\n\t\tconst labelRadius = outerRadius + 6;\n\t\treturn {\n\t\t\tnode,\n\t\t\tdepth: g.index,\n\t\t\td: arc({ startAngle: g.startAngle, endAngle: g.endAngle, innerRadius, outerRadius }) ?? \"\",\n\t\t\tlabelX: labelRadius * Math.sin(midAngle),\n\t\t\tlabelY: -labelRadius * Math.cos(midAngle),\n\t\t\tlabelAngle: midAngle,\n\t\t};\n\t});\n\n\t// Satisfies @types/d3-chord@3.0.6's `RibbonSubgroup.radius` requirement;\n\t// runtime ignores per-subgroup radius when the generator's `.radius()`\n\t// is set, so this spread is purely a typing accommodation.\n\tconst buildRibbonInput = (c: typeof result[number]) => ({\n\t\tsource: { ...c.source, radius: innerRadius },\n\t\ttarget: { ...c.target, radius: innerRadius },\n\t});\n\n\tconst chords: LaidOutChord[] = result\n\t\t// Drop chord pairs where both directions have zero flow — d3-chord\n\t\t// emits placeholder pairs for them which would otherwise render as\n\t\t// invisible-but-event-firing ribbons.\n\t\t.filter((c) => c.source.value > 0 || c.target.value > 0)\n\t\t.map((c) => ({\n\t\t\tsource: nodes[c.source.index] ?? { id: `_${c.source.index}`, label: `Set ${c.source.index}` },\n\t\t\ttarget: nodes[c.target.index] ?? { id: `_${c.target.index}`, label: `Set ${c.target.index}` },\n\t\t\tsourceValue: c.source.value,\n\t\t\ttargetValue: c.target.value,\n\t\t\td: ribbon(buildRibbonInput(c)) ?? \"\",\n\t\t\tsourceIdx: c.source.index,\n\t\t}));\n\n\treturn { arcs, chords };\n}\n\nfunction activateOnKey(e: React.KeyboardEvent, fn: () => void): void {\n\tif (e.key === \"Enter\" || e.key === \" \") {\n\t\te.preventDefault();\n\t\tfn();\n\t}\n}\n\nexport { Chord };\n"]}
1
+ {"version":3,"sources":["../src/lib/chart-palette.ts","../src/lib/utils.ts","../src/artifacts/chord/chord.tsx"],"names":[],"mappings":"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","file":"chord.js","sourcesContent":["/**\n * Categorical chart palette for diagram primitives that encode categorical\n * data (sunburst, treemap, sankey, chord, funnel, pyramid, venn, matrix).\n * Cycled by an integer key — node index, leaf index, depth-1 ancestor, etc.\n *\n * The values reach into `--chart-1` through `--chart-6`, the dedicated\n * diagram-encoding tokens added in `@hex-core/tokens` 1.4. Each token has a\n * `var(--primary)` fallback so consumers on theme presets that haven't been\n * updated to ship `--chart-N` (or who run a custom theme without the chart\n * family) still see a coherent monochrome rendering instead of black SVG\n * fills.\n *\n * Why a chart palette and not the semantic tokens: `--primary`, `--accent`,\n * `--secondary`, and `--muted` collapse to a single hue family in the\n * default monochrome theme — adjacent segments of a chart end up\n * indistinguishable. Chart tokens are tuned for perceptual differentiation.\n */\nexport const CHART_PALETTE = [\n\t\"hsl(var(--chart-1, var(--primary)))\",\n\t\"hsl(var(--chart-2, var(--primary)))\",\n\t\"hsl(var(--chart-3, var(--primary)))\",\n\t\"hsl(var(--chart-4, var(--primary)))\",\n\t\"hsl(var(--chart-5, var(--primary)))\",\n\t\"hsl(var(--chart-6, var(--primary)))\",\n] as const;\n\n/**\n * Return the chart hue at a stable index. Cycles modulo `CHART_PALETTE.length`\n * so the caller doesn't have to range-check.\n *\n * @param index - Integer key (node index, leaf index, depth-1 ancestor index, …).\n * @returns A `hsl(var(...))` string suitable for SVG `fill` / `stroke`.\n */\nexport function pickChartHue(index: number): string {\n\tconst safe = ((index % CHART_PALETTE.length) + CHART_PALETTE.length) % CHART_PALETTE.length;\n\t// `safe` is provably 0..CHART_PALETTE.length-1 — the assertion documents that.\n\treturn CHART_PALETTE[safe] as string;\n}\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n\nconst SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"mailto:\"] as const;\n\n/**\n * Allowlist a URL for use as an `<a href>` against untrusted input.\n *\n * Returns the raw string when it's `http(s):` / `mailto:` / a relative\n * URL (no scheme); returns `undefined` otherwise. Defends against\n * `javascript:` / `data:` / `vbscript:` injection from streamed model\n * output or third-party JSON payloads that flow into citation chips.\n *\n * Inside a Markdown render path, `rehype-sanitize` already strips\n * `javascript:` from inline-link hrefs — but it does NOT introspect\n * JSON nested inside attribute values (e.g. `<sources data='[…]'/>`),\n * so the components that consume that data must guard themselves.\n *\n * @param raw - The candidate URL, or `undefined` when none was supplied.\n * @returns The URL when safe to render, otherwise `undefined`.\n */\nexport function safeUrl(raw: string | undefined): string | undefined {\n\tif (raw === undefined || raw === \"\") return undefined;\n\t// Relative URLs have no scheme — `new URL(relative)` throws without a base,\n\t// so a thrown URL means either malformed input OR a relative path. Treat\n\t// \"throws + does not contain a colon\" as a relative path (safe).\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(raw);\n\t} catch {\n\t\treturn raw.includes(\":\") ? undefined : raw;\n\t}\n\treturn SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : undefined;\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { pickChartHue } from \"../../lib/chart-palette.js\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Chord diagram. Nodes sit on a ring; ribbons inside the ring encode\n * weighted bidirectional relationships between them. Common for\n * trade flows, migration, hyperlink graphs, citation networks —\n * anywhere \"A relates to B with weight w\" matters at scale.\n *\n * Heavy peers: requires `d3-chord` (~3 KB gzip) and `d3-shape` (~6 KB\n * gzip, already in the artifacts/ family). The hex-core CLI's `add`\n * flow prompts before installing.\n *\n * @example\n * <Chord\n * nodes={[\"A\", \"B\", \"C\", \"D\"].map((id) => ({ id, label: id }))}\n * matrix={[\n * [0, 5, 8, 1],\n * [3, 0, 2, 4],\n * [6, 0, 0, 7],\n * [2, 1, 9, 0],\n * ]}\n * />\n */\nexport type ChordNode = {\n\tid: string;\n\tlabel: string;\n};\n\n/**\n * Payload fired to `onChordHover`. `sourceValue` is the i→j flow;\n * `targetValue` is the j→i flow. They differ for asymmetric matrices and\n * are equal for symmetric ones.\n */\nexport type ChordHoverPayload = {\n\tsource: ChordNode;\n\ttarget: ChordNode;\n\tsourceValue: number;\n\ttargetValue: number;\n};\n\nexport interface ChordProps extends Omit<React.SVGAttributes<SVGSVGElement>, \"children\"> {\n\t/** Nodes (as ring segments). Order matches matrix rows/columns. */\n\tnodes: ChordNode[];\n\t/** Square N×N matrix of weights. matrix[i][j] = flow from node i to node j. */\n\tmatrix: number[][];\n\t/** Pixel size of the rendered SVG (it's square). Default 480. */\n\tsize?: number;\n\t/** Pixel padding between adjacent ring segments. Default 0.04 (radians, d3 convention). */\n\tpadAngle?: number;\n\t/** Fired when a ribbon is hovered (or hover ends, with `null`). */\n\tonChordHover?: (chord: ChordHoverPayload | null) => void;\n\t/** Fired when a node arc is clicked. */\n\tonNodeClick?: (node: ChordNode) => void;\n}\n\ninterface LaidOutArc {\n\tnode: ChordNode;\n\tdepth: number;\n\td: string;\n\tlabelX: number;\n\tlabelY: number;\n\tlabelAngle: number;\n}\n\ninterface LaidOutChord {\n\tsource: ChordNode;\n\ttarget: ChordNode;\n\tsourceValue: number;\n\ttargetValue: number;\n\td: string;\n\t/** Index of the source node — ribbons inherit the source arc's hue\n\t * so the eye can trace \"where did this flow originate\". */\n\tsourceIdx: number;\n}\n\ntype D3ChordMod = typeof import(\"d3-chord\");\ntype D3ShapeMod = typeof import(\"d3-shape\");\n\nfunction Chord({\n\tnodes,\n\tmatrix,\n\tsize = 480,\n\tpadAngle = 0.04,\n\tonChordHover,\n\tonNodeClick,\n\tclassName,\n\t...rest\n}: ChordProps) {\n\tconst [d3c, setD3c] = React.useState<D3ChordMod | null>(null);\n\tconst [d3s, setD3s] = React.useState<D3ShapeMod | null>(null);\n\tconst [importError, setImportError] = React.useState(false);\n\n\tReact.useEffect(() => {\n\t\tlet cancelled = false;\n\t\tvoid Promise.all([import(\"d3-chord\"), import(\"d3-shape\")]).then(\n\t\t\t([c, s]) => {\n\t\t\t\tif (cancelled) return;\n\t\t\t\tsetD3c(c);\n\t\t\t\tsetD3s(s);\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tif (!cancelled) setImportError(true);\n\t\t\t},\n\t\t);\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, []);\n\n\tconst laidOut = React.useMemo(() => {\n\t\tif (!d3c || !d3s) return null;\n\t\treturn layout(d3c, d3s, nodes, matrix, size, padAngle);\n\t}, [d3c, d3s, nodes, matrix, size, padAngle]);\n\n\tif (importError) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tdata-hex-chord-error\n\t\t\t\trole=\"alert\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"inline-flex items-center justify-center rounded-md border border-destructive/40 bg-destructive/5 p-3 text-sm text-destructive\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tstyle={{ width: size, height: size }}\n\t\t\t>\n\t\t\t\tInstall <code className=\"mx-1\">d3-chord</code> to view this chord diagram.\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (!laidOut) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tdata-hex-chord-loading\n\t\t\t\taria-busy=\"true\"\n\t\t\t\taria-label=\"Loading chord diagram\"\n\t\t\t\tclassName={cn(\"inline-block bg-muted/20\", className)}\n\t\t\t\tstyle={{ width: size, height: size }}\n\t\t\t/>\n\t\t);\n\t}\n\n\tconst { arcs, chords } = laidOut;\n\tconst desc = `Chord diagram with ${nodes.length} node${nodes.length === 1 ? \"\" : \"s\"} and ${chords.length} ribbon${chords.length === 1 ? \"\" : \"s\"}`;\n\tconst radius = size / 2;\n\n\treturn (\n\t\t<svg\n\t\t\t{...rest}\n\t\t\tdata-hex-chord\n\t\t\trole=\"img\"\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox={`${-radius} ${-radius} ${size} ${size}`}\n\t\t\tclassName={cn(\"block\", className)}\n\t\t>\n\t\t\t<title>Chord diagram</title>\n\t\t\t<desc>{desc}</desc>\n\t\t\t<g data-hex-chord-ribbons>\n\t\t\t\t{chords.map((c, i) => {\n\t\t\t\t\tconst interactive = Boolean(onChordHover);\n\t\t\t\t\tconst payload: ChordHoverPayload = {\n\t\t\t\t\t\tsource: c.source,\n\t\t\t\t\t\ttarget: c.target,\n\t\t\t\t\t\tsourceValue: c.sourceValue,\n\t\t\t\t\t\ttargetValue: c.targetValue,\n\t\t\t\t\t};\n\t\t\t\t\tconst fireHover = (chord: ChordHoverPayload | null) => onChordHover?.(chord);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tkey={`${c.source.id}-${c.target.id}-${i}`}\n\t\t\t\t\t\t\tdata-hex-chord-ribbon\n\t\t\t\t\t\t\td={c.d}\n\t\t\t\t\t\t\tfill={pickChartHue(c.sourceIdx)}\n\t\t\t\t\t\t\tfillOpacity={0.55}\n\t\t\t\t\t\t\tstroke=\"hsl(var(--background))\"\n\t\t\t\t\t\t\tstrokeWidth={0.5}\n\t\t\t\t\t\t\trole={interactive ? \"button\" : undefined}\n\t\t\t\t\t\t\ttabIndex={interactive ? 0 : undefined}\n\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\tinteractive\n\t\t\t\t\t\t\t\t\t? `Flow from ${c.source.label} to ${c.target.label}, value ${c.sourceValue}; reverse value ${c.targetValue}`\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tcursor: interactive ? \"pointer\" : undefined,\n\t\t\t\t\t\t\t\ttransition: \"fill-opacity 120ms ease\",\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonMouseEnter={interactive ? () => fireHover(payload) : undefined}\n\t\t\t\t\t\t\tonMouseLeave={interactive ? () => fireHover(null) : undefined}\n\t\t\t\t\t\t\tonFocus={interactive ? () => fireHover(payload) : undefined}\n\t\t\t\t\t\t\tonBlur={interactive ? () => fireHover(null) : undefined}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</g>\n\t\t\t<g data-hex-chord-arcs>\n\t\t\t\t{arcs.map((a) => {\n\t\t\t\t\tconst interactive = Boolean(onNodeClick);\n\t\t\t\t\tconst handleActivate = () => onNodeClick?.(a.node);\n\t\t\t\t\tconst flip = a.labelAngle > Math.PI / 2 && a.labelAngle < (3 * Math.PI) / 2;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<g\n\t\t\t\t\t\t\tkey={a.node.id}\n\t\t\t\t\t\t\tdata-hex-chord-arc\n\t\t\t\t\t\t\tdata-depth={a.depth}\n\t\t\t\t\t\t\trole={interactive ? \"button\" : undefined}\n\t\t\t\t\t\t\ttabIndex={interactive ? 0 : undefined}\n\t\t\t\t\t\t\taria-label={interactive ? a.node.label : undefined}\n\t\t\t\t\t\t\tstyle={interactive ? { cursor: \"pointer\" } : undefined}\n\t\t\t\t\t\t\tonClick={interactive ? handleActivate : undefined}\n\t\t\t\t\t\t\tonKeyDown={interactive ? (e) => activateOnKey(e, handleActivate) : undefined}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\td={a.d}\n\t\t\t\t\t\t\t\tfill={pickChartHue(a.depth)}\n\t\t\t\t\t\t\t\tstroke=\"hsl(var(--background))\"\n\t\t\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\tx={a.labelX}\n\t\t\t\t\t\t\t\ty={a.labelY}\n\t\t\t\t\t\t\t\ttextAnchor={flip ? \"end\" : \"start\"}\n\t\t\t\t\t\t\t\tdy=\"0.35em\"\n\t\t\t\t\t\t\t\ttransform={\n\t\t\t\t\t\t\t\t\tflip\n\t\t\t\t\t\t\t\t\t\t? `rotate(${(a.labelAngle * 180) / Math.PI - 270} ${a.labelX} ${a.labelY})`\n\t\t\t\t\t\t\t\t\t\t: `rotate(${(a.labelAngle * 180) / Math.PI - 90} ${a.labelX} ${a.labelY})`\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tfontSize={11}\n\t\t\t\t\t\t\t\tfill=\"hsl(var(--foreground))\"\n\t\t\t\t\t\t\t\tstyle={{ pointerEvents: \"none\" }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{a.node.label}\n\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t</g>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</g>\n\t\t</svg>\n\t);\n}\n\nfunction layout(\n\td3c: D3ChordMod,\n\td3s: D3ShapeMod,\n\tnodes: ChordNode[],\n\tmatrix: number[][],\n\tsize: number,\n\tpadAngle: number,\n): { arcs: LaidOutArc[]; chords: LaidOutChord[] } {\n\t// Reserve margin for label text scaled by the longest label, so words\n\t// like \"Americas\" / \"Manufacturing\" don't clip against the SVG edge.\n\t// 6 px/char + 16 px slack — empirically fits 12-char labels at fontSize 11.\n\tconst longestLabel = nodes.reduce((m, n) => Math.max(m, n.label.length), 0);\n\tconst labelMargin = Math.max(40, longestLabel * 6 + 16);\n\tconst radius = size / 2 - labelMargin;\n\tconst innerRadius = radius - 12;\n\tconst outerRadius = radius;\n\n\t// d3.descending lives in d3-array — inline the comparator to avoid pulling\n\t// another peer dep just for one helper.\n\tconst chordGen = d3c\n\t\t.chord()\n\t\t.padAngle(padAngle)\n\t\t.sortSubgroups((a, b) => (a < b ? 1 : a > b ? -1 : 0));\n\tconst result = chordGen(matrix);\n\n\tconst arc = d3s.arc().innerRadius(innerRadius).outerRadius(outerRadius);\n\t// `ribbon()` is exported from d3-chord, not d3-shape.\n\tconst ribbon = d3c.ribbon().radius(innerRadius);\n\n\tconst arcs: LaidOutArc[] = result.groups.map((g) => {\n\t\tconst node = nodes[g.index] ?? { id: `_${g.index}`, label: `Set ${g.index}` };\n\t\tconst midAngle = (g.startAngle + g.endAngle) / 2;\n\t\tconst labelRadius = outerRadius + 6;\n\t\treturn {\n\t\t\tnode,\n\t\t\tdepth: g.index,\n\t\t\td: arc({ startAngle: g.startAngle, endAngle: g.endAngle, innerRadius, outerRadius }) ?? \"\",\n\t\t\tlabelX: labelRadius * Math.sin(midAngle),\n\t\t\tlabelY: -labelRadius * Math.cos(midAngle),\n\t\t\tlabelAngle: midAngle,\n\t\t};\n\t});\n\n\t// Satisfies @types/d3-chord@3.0.6's `RibbonSubgroup.radius` requirement;\n\t// runtime ignores per-subgroup radius when the generator's `.radius()`\n\t// is set, so this spread is purely a typing accommodation.\n\tconst buildRibbonInput = (c: typeof result[number]) => ({\n\t\tsource: { ...c.source, radius: innerRadius },\n\t\ttarget: { ...c.target, radius: innerRadius },\n\t});\n\n\tconst chords: LaidOutChord[] = result\n\t\t// Drop chord pairs where both directions have zero flow — d3-chord\n\t\t// emits placeholder pairs for them which would otherwise render as\n\t\t// invisible-but-event-firing ribbons.\n\t\t.filter((c) => c.source.value > 0 || c.target.value > 0)\n\t\t.map((c) => ({\n\t\t\tsource: nodes[c.source.index] ?? { id: `_${c.source.index}`, label: `Set ${c.source.index}` },\n\t\t\ttarget: nodes[c.target.index] ?? { id: `_${c.target.index}`, label: `Set ${c.target.index}` },\n\t\t\tsourceValue: c.source.value,\n\t\t\ttargetValue: c.target.value,\n\t\t\td: ribbon(buildRibbonInput(c)) ?? \"\",\n\t\t\tsourceIdx: c.source.index,\n\t\t}));\n\n\treturn { arcs, chords };\n}\n\nfunction activateOnKey(e: React.KeyboardEvent, fn: () => void): void {\n\tif (e.key === \"Enter\" || e.key === \" \") {\n\t\te.preventDefault();\n\t\tfn();\n\t}\n}\n\nexport { Chord };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/ai/citation/citation.tsx"],"names":[],"mappings":";;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACyBA,SAAS,QAAA,CAAS,EAAE,KAAA,EAAO,GAAA,EAAK,MAAM,KAAA,EAAO,SAAA,EAAW,UAAS,EAAkB;AAClF,EAAA,MAAM,WAAA,GAAc,EAAA;AAAA,IACnB,qGAAA;AAAA,IACA,iEAAA;AAAA,IACA;AAAA,GACD;AAEA,EAAA,MAAM,uBACL,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,IAAA,OAAO,KAAA,KAAU,QAAA,mBACjB,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,2DAAA,EAA4D,QAAA,EAAA;AAAA,MAAA,GAAA;AAAA,MAAE,KAAA;AAAA,MAAM;AAAA,KAAA,EAAC,CAAA,uBAEpF,QAAA,EAAA,EAAS,CAAA;AAAA,oBAEX,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0BAAA,EAA4B,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IACjD,OAAO,IAAA,KAAS,QAAA,mBAChB,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,uBAAA,EAAwB,QAAA,EAAA;AAAA,MAAA,IAAA;AAAA,MAAG;AAAA,KAAA,EAAK,CAAA,GAC7C,IAAA;AAAA,IACH;AAAA,GAAA,EACF,CAAA;AAGD,EAAA,IAAI,GAAA,EAAK;AACR,IAAA,uBACC,GAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACA,IAAA,EAAM,GAAA;AAAA,QACN,MAAA,EAAO,QAAA;AAAA,QACP,GAAA,EAAI,qBAAA;AAAA,QACJ,SAAA,EAAW,EAAA;AAAA,UACV,WAAA;AAAA,UACA,kEAAA;AAAA,UACA;AAAA,SACD;AAAA,QAEC,QAAA,EAAA;AAAA;AAAA,KACF;AAAA,EAEF;AAEA,EAAA,uBAAO,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,WAAA,EAAc,QAAA,EAAA,IAAA,EAAK,CAAA;AAC5C;AAEA,SAAS,QAAA,GAAW;AACnB,EAAA,uBACC,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,aAAA,EAAW,IAAA;AAAA,MACX,OAAA,EAAQ,WAAA;AAAA,MACR,KAAA,EAAM,IAAA;AAAA,MACN,MAAA,EAAO,IAAA;AAAA,MACP,IAAA,EAAK,MAAA;AAAA,MACL,MAAA,EAAO,cAAA;AAAA,MACP,WAAA,EAAY,KAAA;AAAA,MACZ,aAAA,EAAc,OAAA;AAAA,MACd,cAAA,EAAe,OAAA;AAAA,MACf,SAAA,EAAU,gCAAA;AAAA,MAEV,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,wFAAA,EAAyF,CAAA;AAAA,wBACjG,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,cAAA,EAAe;AAAA;AAAA;AAAA,GACxB;AAEF","file":"citation.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Source attribution chip — renders a citation for a RAG hit, search\n * result, or any external reference the assistant pulled from. Becomes a\n * clickable anchor when `url` is provided; otherwise a static span.\n *\n * @example\n * <Citation title=\"auth-overview.md\" url={src.url} page={3} />\n * @example\n * <Cluster gap=\"xs\">\n * {sources.map((s, i) => (\n * <Citation key={s.id} title={s.title} url={s.url} index={i + 1} />\n * ))}\n * </Cluster>\n */\nexport interface CitationProps {\n\ttitle: string;\n\turl?: string;\n\tpage?: number;\n\t/** Numeric index for inline footnote-style display (e.g. \"[1] auth.md\"). */\n\tindex?: number;\n\tclassName?: string;\n\tchildren?: React.ReactNode;\n}\n\n/**\n * Renders a source citation chip. Uses an `<a>` when `url` is set so the\n * chip is keyboard-focusable + opens in a new tab; falls back to a\n * non-interactive span otherwise.\n *\n * @param props - title + optional url, page, index\n * @returns An anchor or span styled as a chip\n */\nfunction Citation({ title, url, page, index, className, children }: CitationProps) {\n\tconst baseClasses = cn(\n\t\t\"inline-flex items-center gap-1.5 rounded-md border border-foreground/15 bg-card px-2 py-0.5 text-xs\",\n\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\tclassName,\n\t);\n\n\tconst body = (\n\t\t<>\n\t\t\t{typeof index === \"number\" ? (\n\t\t\t\t<span className=\"font-mono text-[10px] font-semibold text-muted-foreground\">[{index}]</span>\n\t\t\t) : (\n\t\t\t\t<DocGlyph />\n\t\t\t)}\n\t\t\t<span className=\"truncate text-foreground\">{title}</span>\n\t\t\t{typeof page === \"number\" ? (\n\t\t\t\t<span className=\"text-muted-foreground\">p.{page}</span>\n\t\t\t) : null}\n\t\t\t{children}\n\t\t</>\n\t);\n\n\tif (url) {\n\t\treturn (\n\t\t\t<a\n\t\t\t\thref={url}\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\trel=\"noreferrer noopener\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\tbaseClasses,\n\t\t\t\t\t\"hover:border-foreground/30 hover:bg-secondary/40 hover:shadow-sm\",\n\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{body}\n\t\t\t</a>\n\t\t);\n\t}\n\n\treturn <span className={baseClasses}>{body}</span>;\n}\n\nfunction DocGlyph() {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\twidth=\"11\"\n\t\t\theight=\"11\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"1.5\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName=\"shrink-0 text-muted-foreground\"\n\t\t>\n\t\t\t<path d=\"M9 1.5H4.5A1.5 1.5 0 0 0 3 3v10a1.5 1.5 0 0 0 1.5 1.5h7A1.5 1.5 0 0 0 13 13V5.5L9 1.5z\" />\n\t\t\t<path d=\"M9 1.5V5.5h4\" />\n\t\t</svg>\n\t);\n}\n\nexport { Citation };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/ai/citation/citation.tsx"],"names":[],"mappings":";;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACyBA,SAAS,QAAA,CAAS,EAAE,KAAA,EAAO,GAAA,EAAK,MAAM,KAAA,EAAO,SAAA,EAAW,UAAS,EAAkB;AAClF,EAAA,MAAM,WAAA,GAAc,EAAA;AAAA,IACnB,qGAAA;AAAA,IACA,iEAAA;AAAA,IACA;AAAA,GACD;AAEA,EAAA,MAAM,uBACL,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,IAAA,OAAO,KAAA,KAAU,QAAA,mBACjB,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,2DAAA,EAA4D,QAAA,EAAA;AAAA,MAAA,GAAA;AAAA,MAAE,KAAA;AAAA,MAAM;AAAA,KAAA,EAAC,CAAA,uBAEpF,QAAA,EAAA,EAAS,CAAA;AAAA,oBAEX,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0BAAA,EAA4B,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IACjD,OAAO,IAAA,KAAS,QAAA,mBAChB,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,uBAAA,EAAwB,QAAA,EAAA;AAAA,MAAA,IAAA;AAAA,MAAG;AAAA,KAAA,EAAK,CAAA,GAC7C,IAAA;AAAA,IACH;AAAA,GAAA,EACF,CAAA;AAGD,EAAA,IAAI,GAAA,EAAK;AACR,IAAA,uBACC,GAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACA,IAAA,EAAM,GAAA;AAAA,QACN,MAAA,EAAO,QAAA;AAAA,QACP,GAAA,EAAI,qBAAA;AAAA,QACJ,SAAA,EAAW,EAAA;AAAA,UACV,WAAA;AAAA,UACA,kEAAA;AAAA,UACA;AAAA,SACD;AAAA,QAEC,QAAA,EAAA;AAAA;AAAA,KACF;AAAA,EAEF;AAEA,EAAA,uBAAO,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,WAAA,EAAc,QAAA,EAAA,IAAA,EAAK,CAAA;AAC5C;AAEA,SAAS,QAAA,GAAW;AACnB,EAAA,uBACC,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,aAAA,EAAW,IAAA;AAAA,MACX,OAAA,EAAQ,WAAA;AAAA,MACR,KAAA,EAAM,IAAA;AAAA,MACN,MAAA,EAAO,IAAA;AAAA,MACP,IAAA,EAAK,MAAA;AAAA,MACL,MAAA,EAAO,cAAA;AAAA,MACP,WAAA,EAAY,KAAA;AAAA,MACZ,aAAA,EAAc,OAAA;AAAA,MACd,cAAA,EAAe,OAAA;AAAA,MACf,SAAA,EAAU,gCAAA;AAAA,MAEV,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,wFAAA,EAAyF,CAAA;AAAA,wBACjG,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,cAAA,EAAe;AAAA;AAAA;AAAA,GACxB;AAEF","file":"citation.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n\nconst SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"mailto:\"] as const;\n\n/**\n * Allowlist a URL for use as an `<a href>` against untrusted input.\n *\n * Returns the raw string when it's `http(s):` / `mailto:` / a relative\n * URL (no scheme); returns `undefined` otherwise. Defends against\n * `javascript:` / `data:` / `vbscript:` injection from streamed model\n * output or third-party JSON payloads that flow into citation chips.\n *\n * Inside a Markdown render path, `rehype-sanitize` already strips\n * `javascript:` from inline-link hrefs — but it does NOT introspect\n * JSON nested inside attribute values (e.g. `<sources data='[…]'/>`),\n * so the components that consume that data must guard themselves.\n *\n * @param raw - The candidate URL, or `undefined` when none was supplied.\n * @returns The URL when safe to render, otherwise `undefined`.\n */\nexport function safeUrl(raw: string | undefined): string | undefined {\n\tif (raw === undefined || raw === \"\") return undefined;\n\t// Relative URLs have no scheme — `new URL(relative)` throws without a base,\n\t// so a thrown URL means either malformed input OR a relative path. Treat\n\t// \"throws + does not contain a colon\" as a relative path (safe).\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(raw);\n\t} catch {\n\t\treturn raw.includes(\":\") ? undefined : raw;\n\t}\n\treturn SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : undefined;\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Source attribution chip — renders a citation for a RAG hit, search\n * result, or any external reference the assistant pulled from. Becomes a\n * clickable anchor when `url` is provided; otherwise a static span.\n *\n * @example\n * <Citation title=\"auth-overview.md\" url={src.url} page={3} />\n * @example\n * <Cluster gap=\"xs\">\n * {sources.map((s, i) => (\n * <Citation key={s.id} title={s.title} url={s.url} index={i + 1} />\n * ))}\n * </Cluster>\n */\nexport interface CitationProps {\n\ttitle: string;\n\turl?: string;\n\tpage?: number;\n\t/** Numeric index for inline footnote-style display (e.g. \"[1] auth.md\"). */\n\tindex?: number;\n\tclassName?: string;\n\tchildren?: React.ReactNode;\n}\n\n/**\n * Renders a source citation chip. Uses an `<a>` when `url` is set so the\n * chip is keyboard-focusable + opens in a new tab; falls back to a\n * non-interactive span otherwise.\n *\n * @param props - title + optional url, page, index\n * @returns An anchor or span styled as a chip\n */\nfunction Citation({ title, url, page, index, className, children }: CitationProps) {\n\tconst baseClasses = cn(\n\t\t\"inline-flex items-center gap-1.5 rounded-md border border-foreground/15 bg-card px-2 py-0.5 text-xs\",\n\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\tclassName,\n\t);\n\n\tconst body = (\n\t\t<>\n\t\t\t{typeof index === \"number\" ? (\n\t\t\t\t<span className=\"font-mono text-[10px] font-semibold text-muted-foreground\">[{index}]</span>\n\t\t\t) : (\n\t\t\t\t<DocGlyph />\n\t\t\t)}\n\t\t\t<span className=\"truncate text-foreground\">{title}</span>\n\t\t\t{typeof page === \"number\" ? (\n\t\t\t\t<span className=\"text-muted-foreground\">p.{page}</span>\n\t\t\t) : null}\n\t\t\t{children}\n\t\t</>\n\t);\n\n\tif (url) {\n\t\treturn (\n\t\t\t<a\n\t\t\t\thref={url}\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\trel=\"noreferrer noopener\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\tbaseClasses,\n\t\t\t\t\t\"hover:border-foreground/30 hover:bg-secondary/40 hover:shadow-sm\",\n\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{body}\n\t\t\t</a>\n\t\t);\n\t}\n\n\treturn <span className={baseClasses}>{body}</span>;\n}\n\nfunction DocGlyph() {\n\treturn (\n\t\t<svg\n\t\t\taria-hidden\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\twidth=\"11\"\n\t\t\theight=\"11\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"1.5\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName=\"shrink-0 text-muted-foreground\"\n\t\t>\n\t\t\t<path d=\"M9 1.5H4.5A1.5 1.5 0 0 0 3 3v10a1.5 1.5 0 0 0 1.5 1.5h7A1.5 1.5 0 0 0 13 13V5.5L9 1.5z\" />\n\t\t\t<path d=\"M9 1.5V5.5h4\" />\n\t\t</svg>\n\t);\n}\n\nexport { Citation };\n"]}
package/dist/cloze.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/artifacts/cloze/cloze.tsx"],"names":[],"mappings":";;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACiCA,IAAM,cAAA,GAAiB,mBAAA;AAEvB,SAAS,UAAU,KAAA,EAAmF;AACrG,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM;AAClC,IAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,CAAA;AAClC,IAAA,MAAM,KAAK,CAAA,CAAE,EAAA,IAAM,CAAA,EAAG,cAAc,GAAG,UAAU,CAAA,CAAA;AACjD,IAAA,MAAM,MAAuB,EAAE,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAQ,IAAI,UAAA,EAAW;AAChE,IAAA,UAAA,EAAA;AACA,IAAA,OAAO,GAAA;AAAA,EACR,CAAC,CAAA;AACD,EAAA,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,UAAA,EAAW;AACvC;AAEA,SAAS,KAAA,CAAM,EAAE,KAAA,EAAO,UAAA,GAAa,SAAS,QAAA,EAAU,SAAA,EAAW,GAAG,IAAA,EAAK,EAAe;AACzF,EAAA,MAAM,EAAE,SAAA,EAAW,KAAA,EAAM,GAAU,KAAA,CAAA,OAAA,CAAQ,MAAM,SAAA,CAAU,KAAK,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAC1E,EAAA,MAAM,CAAC,UAAU,WAAW,CAAA,GAAU,eAAsB,sBAAM,IAAI,KAAK,CAAA;AAC3E,EAAA,MAAM,WAAA,GAAoB,aAAO,QAAQ,CAAA;AACzC,EAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AAEtB,EAAA,MAAM,MAAA,GAAe,KAAA,CAAA,WAAA,CAAY,CAAC,IAAA,KAAsB;AACvD,IAAA,WAAA,CAAY,IAAI,CAAA;AAChB,IAAA,WAAA,CAAY,OAAA,GAAU,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,EACvC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,WAAA,GAAoB,KAAA,CAAA,WAAA;AAAA,IACzB,CAAC,EAAA,KAAe;AACf,MAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,QAAQ,CAAA;AAC7B,MAAA,IAAI,KAAK,GAAA,CAAI,EAAE,CAAA,EAAG,IAAA,CAAK,OAAO,EAAE,CAAA;AAAA,WAC3B,IAAA,CAAK,IAAI,EAAE,CAAA;AAChB,MAAA,MAAA,CAAO,IAAI,CAAA;AAAA,IACZ,CAAA;AAAA,IACA,CAAC,UAAU,MAAM;AAAA,GAClB;AAEA,EAAA,MAAM,WAAA,GAAc,KAAA,GAAQ,CAAA,IAAK,QAAA,CAAS,IAAA,KAAS,KAAA;AAEnD,EAAA,MAAM,SAAA,GAAkB,kBAAY,MAAM;AACzC,IAAA,IAAI,WAAA,EAAa;AAChB,MAAA,MAAA,iBAAO,IAAI,KAAK,CAAA;AAAA,IACjB,CAAA,MAAO;AACN,MAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,MAAA,KAAA,MAAW,CAAA,IAAK,WAAW,IAAI,OAAO,MAAM,QAAA,EAAU,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA;AACnE,MAAA,MAAA,CAAO,IAAI,CAAA;AAAA,IACZ;AAAA,EACD,CAAA,EAAG,CAAC,WAAA,EAAa,SAAA,EAAW,MAAM,CAAC,CAAA;AAEnC,EAAA,uBACC,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAG,IAAA;AAAA,MACJ,gBAAA,EAAc,IAAA;AAAA,MACd,mBAAA,EAAmB,WAAA;AAAA,MACnB,SAAA,EAAW,EAAA,CAAG,2BAAA,EAA6B,SAAS,CAAA;AAAA,MAEpD,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,OAAE,qBAAA,EAAmB,IAAA,EACpB,oBAAU,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AACxB,UAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,uBAAO,GAAA,CAAO,gBAAN,EAA+B,QAAA,EAAA,CAAA,EAAA,EAAX,CAAA,EAAA,EAAK,CAAC,CAAA,CAAO,CAAA;AACpE,UAAA,MAAM,UAAA,GAAa,QAAA,CAAS,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA;AACpC,UAAA,uBACC,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cAEA,IAAA,EAAK,QAAA;AAAA,cACL,sBAAA,EAAoB,IAAA;AAAA,cACpB,iBAAe,CAAA,CAAE,EAAA;AAAA,cACjB,eAAA,EAAe,UAAA;AAAA,cACf,cAAA,EAAc,UAAA;AAAA,cACd,YAAA,EACC,UAAA,GACG,CAAA,MAAA,EAAS,CAAA,CAAE,aAAa,CAAC,CAAA,WAAA,EAAc,CAAA,CAAE,MAAM,wBAC/C,CAAA,MAAA,EAAS,CAAA,CAAE,UAAA,GAAa,CAAC,OAAO,KAAK,CAAA,qBAAA,CAAA;AAAA,cAEzC,OAAA,EAAS,MAAM,WAAA,CAAY,CAAA,CAAE,EAAE,CAAA;AAAA,cAC/B,SAAA,EAAW,EAAA;AAAA,gBACV,0IAAA;AAAA,gBACA,aACG,iGAAA,GACA;AAAA,eACJ;AAAA,cAIC,QAAA,EAAA,CAAA,CAAE;AAAA,aAAA;AAAA,YArBE,CAAA,CAAE;AAAA,WAsBR;AAAA,QAEF,CAAC,CAAA,EACF,CAAA;AAAA,QACC,eAAe,KAAA,IAAS,KAAA,GAAQ,oBAChC,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,MAAA,EACd,QAAA,kBAAA,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACA,IAAA,EAAK,QAAA;AAAA,YACL,2BAAA,EAAyB,IAAA;AAAA,YACzB,YAAA,EAAY,cAAc,iBAAA,GAAoB,mBAAA;AAAA,YAC9C,OAAA,EAAS,SAAA;AAAA,YACT,SAAA,EAAU,gLAAA;AAAA,YAET,wBAAc,UAAA,GAAa;AAAA;AAAA,WAE9B,CAAA,GACG;AAAA;AAAA;AAAA,GACL;AAEF","file":"cloze.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Cloze deletion — text with hidden segments the learner reveals one at\n * a time (or all at once). Each `{ hidden }` token in the `parts` array\n * renders as a redacted span; click / Enter / Space reveals just that\n * blank.\n *\n * Pure HTML; no heavy peer. Pair with Deck (artifacts/deck) to flow\n * through a sequence of cloze cards, or with SpacedRepetition for\n * confidence rating.\n *\n * @example\n * <Cloze parts={[\n * \"The mitochondria is the \",\n * { hidden: \"powerhouse\" },\n * \" of the cell.\",\n * ]} />\n */\nexport type ClozePart = string | { hidden: string; id?: string };\n\nexport interface ClozeProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"children\" | \"onReveal\"> {\n\t/** Mixed array: string fragments + { hidden } cloze tokens. */\n\tparts: ClozePart[];\n\t/** \"click\" reveals one blank at a time; \"all\" additionally surfaces a \"Reveal all\" toggle. Default \"click\". */\n\trevealMode?: \"click\" | \"all\";\n\t/** Fired with the cumulative set of revealed blank ids on every reveal change. */\n\tonReveal?: (revealedIds: string[]) => void;\n}\n\ninterface NormalizedBlank {\n\thidden: string;\n\tid: string;\n\tblankIndex: number;\n}\n\n// Namespace auto-ids with a prefix that's vanishingly unlikely to collide\n// with consumer-supplied explicit ids. Without this, `[{hidden:'a'},\n// {hidden:'b'}]` (auto-numbered \"blank-0\", \"blank-1\") would silently\n// alias with a future `{hidden:'c', id:'blank-1'}`.\nconst AUTO_ID_PREFIX = \"__hex_cloze_auto_\";\n\nfunction normalize(parts: ClozePart[]): { fragments: Array<string | NormalizedBlank>; total: number } {\n\tlet blankIndex = 0;\n\tconst fragments = parts.map((p) => {\n\t\tif (typeof p === \"string\") return p;\n\t\tconst id = p.id ?? `${AUTO_ID_PREFIX}${blankIndex}`;\n\t\tconst out: NormalizedBlank = { hidden: p.hidden, id, blankIndex };\n\t\tblankIndex++;\n\t\treturn out;\n\t});\n\treturn { fragments, total: blankIndex };\n}\n\nfunction Cloze({ parts, revealMode = \"click\", onReveal, className, ...rest }: ClozeProps) {\n\tconst { fragments, total } = React.useMemo(() => normalize(parts), [parts]);\n\tconst [revealed, setRevealed] = React.useState<Set<string>>(() => new Set());\n\tconst onRevealRef = React.useRef(onReveal);\n\tonRevealRef.current = onReveal;\n\n\tconst update = React.useCallback((next: Set<string>) => {\n\t\tsetRevealed(next);\n\t\tonRevealRef.current?.(Array.from(next));\n\t}, []);\n\n\tconst toggleBlank = React.useCallback(\n\t\t(id: string) => {\n\t\t\tconst next = new Set(revealed);\n\t\t\tif (next.has(id)) next.delete(id);\n\t\t\telse next.add(id);\n\t\t\tupdate(next);\n\t\t},\n\t\t[revealed, update],\n\t);\n\n\tconst allRevealed = total > 0 && revealed.size === total;\n\n\tconst toggleAll = React.useCallback(() => {\n\t\tif (allRevealed) {\n\t\t\tupdate(new Set());\n\t\t} else {\n\t\t\tconst next = new Set<string>();\n\t\t\tfor (const f of fragments) if (typeof f !== \"string\") next.add(f.id);\n\t\t\tupdate(next);\n\t\t}\n\t}, [allRevealed, fragments, update]);\n\n\treturn (\n\t\t<div\n\t\t\t{...rest}\n\t\t\tdata-hex-cloze\n\t\t\tdata-all-revealed={allRevealed}\n\t\t\tclassName={cn(\"text-base leading-relaxed\", className)}\n\t\t>\n\t\t\t<p data-hex-cloze-text>\n\t\t\t\t{fragments.map((f, i) => {\n\t\t\t\t\tif (typeof f === \"string\") return <React.Fragment key={`s-${i}`}>{f}</React.Fragment>;\n\t\t\t\t\tconst isRevealed = revealed.has(f.id);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={f.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tdata-hex-cloze-blank\n\t\t\t\t\t\t\tdata-blank-id={f.id}\n\t\t\t\t\t\t\tdata-revealed={isRevealed}\n\t\t\t\t\t\t\taria-pressed={isRevealed}\n\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\tisRevealed\n\t\t\t\t\t\t\t\t\t? `Blank ${f.blankIndex + 1} revealed: ${f.hidden}. Activate to hide.`\n\t\t\t\t\t\t\t\t\t: `Blank ${f.blankIndex + 1} of ${total}. Activate to reveal.`\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonClick={() => toggleBlank(f.id)}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"mx-0.5 inline-block rounded px-1.5 py-0 align-baseline transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n\t\t\t\t\t\t\t\tisRevealed\n\t\t\t\t\t\t\t\t\t? \"bg-primary/10 text-foreground underline decoration-primary decoration-dotted underline-offset-4\"\n\t\t\t\t\t\t\t\t\t: \"select-none bg-muted text-transparent\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{/* Always render the hidden text so the visual width matches\n\t\t\t\t\t\t\t once revealed; transparent text when hidden. */}\n\t\t\t\t\t\t\t{f.hidden}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</p>\n\t\t\t{revealMode === \"all\" && total > 0 ? (\n\t\t\t\t<div className=\"mt-3\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tdata-hex-cloze-toggle-all\n\t\t\t\t\t\taria-label={allRevealed ? \"Hide all blanks\" : \"Reveal all blanks\"}\n\t\t\t\t\t\tonClick={toggleAll}\n\t\t\t\t\t\tclassName=\"rounded-md border bg-background px-3 py-1 text-xs font-medium text-foreground transition-colors hover:bg-muted focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{allRevealed ? \"Hide all\" : \"Reveal all\"}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n\nexport { Cloze };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/artifacts/cloze/cloze.tsx"],"names":[],"mappings":"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","file":"cloze.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n\nconst SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"mailto:\"] as const;\n\n/**\n * Allowlist a URL for use as an `<a href>` against untrusted input.\n *\n * Returns the raw string when it's `http(s):` / `mailto:` / a relative\n * URL (no scheme); returns `undefined` otherwise. Defends against\n * `javascript:` / `data:` / `vbscript:` injection from streamed model\n * output or third-party JSON payloads that flow into citation chips.\n *\n * Inside a Markdown render path, `rehype-sanitize` already strips\n * `javascript:` from inline-link hrefs — but it does NOT introspect\n * JSON nested inside attribute values (e.g. `<sources data='[…]'/>`),\n * so the components that consume that data must guard themselves.\n *\n * @param raw - The candidate URL, or `undefined` when none was supplied.\n * @returns The URL when safe to render, otherwise `undefined`.\n */\nexport function safeUrl(raw: string | undefined): string | undefined {\n\tif (raw === undefined || raw === \"\") return undefined;\n\t// Relative URLs have no scheme — `new URL(relative)` throws without a base,\n\t// so a thrown URL means either malformed input OR a relative path. Treat\n\t// \"throws + does not contain a colon\" as a relative path (safe).\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(raw);\n\t} catch {\n\t\treturn raw.includes(\":\") ? undefined : raw;\n\t}\n\treturn SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : undefined;\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * Cloze deletion — text with hidden segments the learner reveals one at\n * a time (or all at once). Each `{ hidden }` token in the `parts` array\n * renders as a redacted span; click / Enter / Space reveals just that\n * blank.\n *\n * Pure HTML; no heavy peer. Pair with Deck (artifacts/deck) to flow\n * through a sequence of cloze cards, or with SpacedRepetition for\n * confidence rating.\n *\n * @example\n * <Cloze parts={[\n * \"The mitochondria is the \",\n * { hidden: \"powerhouse\" },\n * \" of the cell.\",\n * ]} />\n */\nexport type ClozePart = string | { hidden: string; id?: string };\n\nexport interface ClozeProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"children\" | \"onReveal\"> {\n\t/** Mixed array: string fragments + { hidden } cloze tokens. */\n\tparts: ClozePart[];\n\t/** \"click\" reveals one blank at a time; \"all\" additionally surfaces a \"Reveal all\" toggle. Default \"click\". */\n\trevealMode?: \"click\" | \"all\";\n\t/** Fired with the cumulative set of revealed blank ids on every reveal change. */\n\tonReveal?: (revealedIds: string[]) => void;\n}\n\ninterface NormalizedBlank {\n\thidden: string;\n\tid: string;\n\tblankIndex: number;\n}\n\n// Namespace auto-ids with a prefix that's vanishingly unlikely to collide\n// with consumer-supplied explicit ids. Without this, `[{hidden:'a'},\n// {hidden:'b'}]` (auto-numbered \"blank-0\", \"blank-1\") would silently\n// alias with a future `{hidden:'c', id:'blank-1'}`.\nconst AUTO_ID_PREFIX = \"__hex_cloze_auto_\";\n\nfunction normalize(parts: ClozePart[]): { fragments: Array<string | NormalizedBlank>; total: number } {\n\tlet blankIndex = 0;\n\tconst fragments = parts.map((p) => {\n\t\tif (typeof p === \"string\") return p;\n\t\tconst id = p.id ?? `${AUTO_ID_PREFIX}${blankIndex}`;\n\t\tconst out: NormalizedBlank = { hidden: p.hidden, id, blankIndex };\n\t\tblankIndex++;\n\t\treturn out;\n\t});\n\treturn { fragments, total: blankIndex };\n}\n\nfunction Cloze({ parts, revealMode = \"click\", onReveal, className, ...rest }: ClozeProps) {\n\tconst { fragments, total } = React.useMemo(() => normalize(parts), [parts]);\n\tconst [revealed, setRevealed] = React.useState<Set<string>>(() => new Set());\n\tconst onRevealRef = React.useRef(onReveal);\n\tonRevealRef.current = onReveal;\n\n\tconst update = React.useCallback((next: Set<string>) => {\n\t\tsetRevealed(next);\n\t\tonRevealRef.current?.(Array.from(next));\n\t}, []);\n\n\tconst toggleBlank = React.useCallback(\n\t\t(id: string) => {\n\t\t\tconst next = new Set(revealed);\n\t\t\tif (next.has(id)) next.delete(id);\n\t\t\telse next.add(id);\n\t\t\tupdate(next);\n\t\t},\n\t\t[revealed, update],\n\t);\n\n\tconst allRevealed = total > 0 && revealed.size === total;\n\n\tconst toggleAll = React.useCallback(() => {\n\t\tif (allRevealed) {\n\t\t\tupdate(new Set());\n\t\t} else {\n\t\t\tconst next = new Set<string>();\n\t\t\tfor (const f of fragments) if (typeof f !== \"string\") next.add(f.id);\n\t\t\tupdate(next);\n\t\t}\n\t}, [allRevealed, fragments, update]);\n\n\treturn (\n\t\t<div\n\t\t\t{...rest}\n\t\t\tdata-hex-cloze\n\t\t\tdata-all-revealed={allRevealed}\n\t\t\tclassName={cn(\"text-base leading-relaxed\", className)}\n\t\t>\n\t\t\t<p data-hex-cloze-text>\n\t\t\t\t{fragments.map((f, i) => {\n\t\t\t\t\tif (typeof f === \"string\") return <React.Fragment key={`s-${i}`}>{f}</React.Fragment>;\n\t\t\t\t\tconst isRevealed = revealed.has(f.id);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={f.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tdata-hex-cloze-blank\n\t\t\t\t\t\t\tdata-blank-id={f.id}\n\t\t\t\t\t\t\tdata-revealed={isRevealed}\n\t\t\t\t\t\t\taria-pressed={isRevealed}\n\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\tisRevealed\n\t\t\t\t\t\t\t\t\t? `Blank ${f.blankIndex + 1} revealed: ${f.hidden}. Activate to hide.`\n\t\t\t\t\t\t\t\t\t: `Blank ${f.blankIndex + 1} of ${total}. Activate to reveal.`\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonClick={() => toggleBlank(f.id)}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"mx-0.5 inline-block rounded px-1.5 py-0 align-baseline transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n\t\t\t\t\t\t\t\tisRevealed\n\t\t\t\t\t\t\t\t\t? \"bg-primary/10 text-foreground underline decoration-primary decoration-dotted underline-offset-4\"\n\t\t\t\t\t\t\t\t\t: \"select-none bg-muted text-transparent\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{/* Always render the hidden text so the visual width matches\n\t\t\t\t\t\t\t once revealed; transparent text when hidden. */}\n\t\t\t\t\t\t\t{f.hidden}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</p>\n\t\t\t{revealMode === \"all\" && total > 0 ? (\n\t\t\t\t<div className=\"mt-3\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tdata-hex-cloze-toggle-all\n\t\t\t\t\t\taria-label={allRevealed ? \"Hide all blanks\" : \"Reveal all blanks\"}\n\t\t\t\t\t\tonClick={toggleAll}\n\t\t\t\t\t\tclassName=\"rounded-md border bg-background px-3 py-1 text-xs font-medium text-foreground transition-colors hover:bg-muted focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{allRevealed ? \"Hide all\" : \"Reveal all\"}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n\nexport { Cloze };\n"]}