@hex-core/components 1.9.0 → 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 (146) hide show
  1. package/dist/_tsup-dts-rollup.d.ts +575 -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.js.map +1 -1
  10. package/dist/auth-reset-password.js.map +1 -1
  11. package/dist/auth-sign-in-split.js.map +1 -1
  12. package/dist/auth-sign-up-card.js.map +1 -1
  13. package/dist/auth-verify-email.js.map +1 -1
  14. package/dist/auth-verify-otp.js.map +1 -1
  15. package/dist/avatar.js.map +1 -1
  16. package/dist/badge.js.map +1 -1
  17. package/dist/branch.d.ts +2 -0
  18. package/dist/branch.js +136 -0
  19. package/dist/branch.js.map +1 -0
  20. package/dist/breadcrumb.js.map +1 -1
  21. package/dist/button.js.map +1 -1
  22. package/dist/calendar.js.map +1 -1
  23. package/dist/canvas.js.map +1 -1
  24. package/dist/card.js.map +1 -1
  25. package/dist/chain-of-thought.d.ts +3 -0
  26. package/dist/chain-of-thought.js +119 -0
  27. package/dist/chain-of-thought.js.map +1 -0
  28. package/dist/checkbox.js.map +1 -1
  29. package/dist/chord.js.map +1 -1
  30. package/dist/citation.js.map +1 -1
  31. package/dist/cloze.js.map +1 -1
  32. package/dist/cluster.js.map +1 -1
  33. package/dist/code-block-copy.js.map +1 -1
  34. package/dist/code-block.js.map +1 -1
  35. package/dist/color-picker.js.map +1 -1
  36. package/dist/combobox.js.map +1 -1
  37. package/dist/command.js.map +1 -1
  38. package/dist/compare-table.js.map +1 -1
  39. package/dist/composer.js.map +1 -1
  40. package/dist/container.js.map +1 -1
  41. package/dist/context-menu.js.map +1 -1
  42. package/dist/conversation.d.ts +3 -0
  43. package/dist/conversation.js +358 -0
  44. package/dist/conversation.js.map +1 -0
  45. package/dist/data-table.js.map +1 -1
  46. package/dist/date-picker.js.map +1 -1
  47. package/dist/deck.js.map +1 -1
  48. package/dist/dendrogram.js.map +1 -1
  49. package/dist/diagram.js.map +1 -1
  50. package/dist/dialog.js.map +1 -1
  51. package/dist/drawer.js.map +1 -1
  52. package/dist/dropdown-menu.js.map +1 -1
  53. package/dist/dropzone.js.map +1 -1
  54. package/dist/empty.js.map +1 -1
  55. package/dist/error-state.js.map +1 -1
  56. package/dist/file-tree.js.map +1 -1
  57. package/dist/flashcard.js.map +1 -1
  58. package/dist/flowchart.js.map +1 -1
  59. package/dist/form.js.map +1 -1
  60. package/dist/funnel.js.map +1 -1
  61. package/dist/gantt.js.map +1 -1
  62. package/dist/grid.js.map +1 -1
  63. package/dist/hover-card.js.map +1 -1
  64. package/dist/image-occlusion.js.map +1 -1
  65. package/dist/index.d.ts +21 -0
  66. package/dist/index.js +1011 -13
  67. package/dist/index.js.map +1 -1
  68. package/dist/inline-citation.d.ts +2 -0
  69. package/dist/inline-citation.js +108 -0
  70. package/dist/inline-citation.js.map +1 -0
  71. package/dist/input-otp.js.map +1 -1
  72. package/dist/input.js.map +1 -1
  73. package/dist/label.js.map +1 -1
  74. package/dist/loading-indicator.js.map +1 -1
  75. package/dist/loading.js.map +1 -1
  76. package/dist/markdown.d.ts +1 -0
  77. package/dist/markdown.js +784 -4
  78. package/dist/markdown.js.map +1 -1
  79. package/dist/matrix.js.map +1 -1
  80. package/dist/menubar.js.map +1 -1
  81. package/dist/message-actions.js.map +1 -1
  82. package/dist/message-list.js.map +1 -1
  83. package/dist/message.js.map +1 -1
  84. package/dist/mind-map.js.map +1 -1
  85. package/dist/multi-combobox.js.map +1 -1
  86. package/dist/navigation-menu.js.map +1 -1
  87. package/dist/org-chart.js.map +1 -1
  88. package/dist/pagination.js.map +1 -1
  89. package/dist/plan.d.ts +3 -0
  90. package/dist/plan.js +183 -0
  91. package/dist/plan.js.map +1 -0
  92. package/dist/popover.js.map +1 -1
  93. package/dist/progress.js.map +1 -1
  94. package/dist/pyramid.js.map +1 -1
  95. package/dist/quiz.js.map +1 -1
  96. package/dist/radio-group.js.map +1 -1
  97. package/dist/reasoning.js.map +1 -1
  98. package/dist/resizable.js.map +1 -1
  99. package/dist/sankey.js.map +1 -1
  100. package/dist/schemas.d.ts +8 -0
  101. package/dist/schemas.js +774 -17
  102. package/dist/schemas.js.map +1 -1
  103. package/dist/scroll-area.js.map +1 -1
  104. package/dist/select.js.map +1 -1
  105. package/dist/separator.js.map +1 -1
  106. package/dist/sequence.js.map +1 -1
  107. package/dist/sheet.js.map +1 -1
  108. package/dist/shimmer.d.ts +2 -0
  109. package/dist/shimmer.js +39 -0
  110. package/dist/shimmer.js.map +1 -0
  111. package/dist/sidebar.js.map +1 -1
  112. package/dist/skeleton.js.map +1 -1
  113. package/dist/slider.js.map +1 -1
  114. package/dist/sources.d.ts +3 -0
  115. package/dist/sources.js +164 -0
  116. package/dist/sources.js.map +1 -0
  117. package/dist/spaced-repetition.js.map +1 -1
  118. package/dist/spacer.js.map +1 -1
  119. package/dist/speech-recognition.js.map +1 -1
  120. package/dist/stack.js.map +1 -1
  121. package/dist/stepper.js.map +1 -1
  122. package/dist/suggestion.js.map +1 -1
  123. package/dist/sunburst.js.map +1 -1
  124. package/dist/switch.js.map +1 -1
  125. package/dist/table.js.map +1 -1
  126. package/dist/tabs.js.map +1 -1
  127. package/dist/tag.js.map +1 -1
  128. package/dist/task.d.ts +3 -0
  129. package/dist/task.js +189 -0
  130. package/dist/task.js.map +1 -0
  131. package/dist/terminal.js +11 -0
  132. package/dist/terminal.js.map +1 -1
  133. package/dist/textarea.js.map +1 -1
  134. package/dist/time-axis.js.map +1 -1
  135. package/dist/time-picker.js.map +1 -1
  136. package/dist/timeline.js.map +1 -1
  137. package/dist/toggle-group.js.map +1 -1
  138. package/dist/toggle.js.map +1 -1
  139. package/dist/tool-call.js +5 -6
  140. package/dist/tool-call.js.map +1 -1
  141. package/dist/toolbar.js.map +1 -1
  142. package/dist/tooltip.js.map +1 -1
  143. package/dist/tree-map.js.map +1 -1
  144. package/dist/tree.js.map +1 -1
  145. package/dist/venn.js.map +1 -1
  146. package/package.json +8 -3
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/scroll-area/scroll-area.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACQA,IAAM,UAAA,GAAmB,KAAA,CAAA,UAAA,CAGvB,CAAC,EAAE,SAAA,EAAW,QAAA,EAAU,gBAAA,GAAmB,CAAA,EAAG,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC3D,IAAA;AAAA,EAAqB,mBAAA,CAAA,IAAA;AAAA,EAApB;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,0BAAA,EAA4B,SAAS,CAAA;AAAA,IAClD,GAAG,KAAA;AAAA,IAEJ,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAqB,mBAAA,CAAA,QAAA;AAAA,QAApB;AAAA,UACA,QAAA,EAAU,gBAAA;AAAA,UACV,SAAA,EAAW,EAAA;AAAA,YACV,iCAAA;AAAA,YACA,oBAAoB,CAAA,IACnB;AAAA,WACF;AAAA,UAEC;AAAA;AAAA,OACF;AAAA,sBAGA,GAAA,CAAC,SAAA,EAAA,EAAU,WAAA,EAAY,UAAA,EAAW,CAAA;AAAA,sBAClC,GAAA,CAAC,SAAA,EAAA,EAAU,WAAA,EAAY,YAAA,EAAa,CAAA;AAAA,sBACpC,GAAA,CAAqB,4BAApB,EAA2B;AAAA;AAAA;AAC7B,CACA;AACD,UAAA,CAAW,WAAA,GAAc,YAAA;AAGzB,IAAM,SAAA,GAAkB,KAAA,CAAA,UAAA,CAGtB,CAAC,EAAE,SAAA,EAAW,cAAc,UAAA,EAAY,GAAG,KAAA,EAAM,EAAG,GAAA,qBACrD,GAAA;AAAA,EAAqB,mBAAA,CAAA,mBAAA;AAAA,EAApB;AAAA,IACA,GAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,6FAAA;AAAA,MACA,gBAAgB,UAAA,IACf,oDAAA;AAAA,MACD,gBAAgB,YAAA,IACf,sDAAA;AAAA,MACD;AAAA,KACD;AAAA,IACC,GAAG,KAAA;AAAA,IAEJ,QAAA,kBAAA,GAAA,CAAqB,mBAAA,CAAA,eAAA,EAApB,EAAoC,SAAA,EAAU,mDAAA,EAAoD;AAAA;AACpG,CACA;AACD,SAAA,CAAU,WAAA,GAAc,WAAA","file":"scroll-area.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 ScrollAreaPrimitive from \"@radix-ui/react-scroll-area\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\ninterface ScrollAreaProps\n\textends React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root> {\n\t/**\n\t * tabIndex applied to the scroll viewport so keyboard users can scroll\n\t * without a pointer. Defaults to `0` (focusable) — pass `-1` to skip the\n\t * viewport in the tab order when ScrollArea wraps purely decorative or\n\t * already-keyboard-reachable content.\n\t */\n\tviewportTabIndex?: number;\n}\n\n/** A scrollable area with custom-styled scrollbars. Content must be explicitly sized. */\nconst ScrollArea = React.forwardRef<\n\tReact.ComponentRef<typeof ScrollAreaPrimitive.Root>,\n\tScrollAreaProps\n>(({ className, children, viewportTabIndex = 0, ...props }, ref) => (\n\t<ScrollAreaPrimitive.Root\n\t\tref={ref}\n\t\tclassName={cn(\"relative overflow-hidden\", className)}\n\t\t{...props}\n\t>\n\t\t<ScrollAreaPrimitive.Viewport\n\t\t\ttabIndex={viewportTabIndex}\n\t\t\tclassName={cn(\n\t\t\t\t\"h-full w-full rounded-[inherit]\",\n\t\t\t\tviewportTabIndex >= 0 &&\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)}\n\t\t>\n\t\t\t{children}\n\t\t</ScrollAreaPrimitive.Viewport>\n\t\t{/* Both orientations mount unconditionally; Radix paints each only when content\n\t\t overflows on that axis, so there's no cost for single-axis content. */}\n\t\t<ScrollBar orientation=\"vertical\" />\n\t\t<ScrollBar orientation=\"horizontal\" />\n\t\t<ScrollAreaPrimitive.Corner />\n\t</ScrollAreaPrimitive.Root>\n));\nScrollArea.displayName = \"ScrollArea\";\n\n/** Styled scrollbar track + thumb. Rendered inside ScrollArea automatically. */\nconst ScrollBar = React.forwardRef<\n\tReact.ComponentRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,\n\tReact.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>\n>(({ className, orientation = \"vertical\", ...props }, ref) => (\n\t<ScrollAreaPrimitive.ScrollAreaScrollbar\n\t\tref={ref}\n\t\torientation={orientation}\n\t\tclassName={cn(\n\t\t\t\"flex touch-none select-none transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\torientation === \"vertical\" &&\n\t\t\t\t\"h-full w-2.5 border-l border-l-transparent p-[1px]\",\n\t\t\torientation === \"horizontal\" &&\n\t\t\t\t\"h-2.5 flex-col border-t border-t-transparent p-[1px]\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t<ScrollAreaPrimitive.ScrollAreaThumb className=\"relative flex-1 rounded-full bg-foreground/[0.18]\" />\n\t</ScrollAreaPrimitive.ScrollAreaScrollbar>\n));\nScrollBar.displayName = \"ScrollBar\";\n\nexport { ScrollArea, ScrollBar };\nexport type { ScrollAreaProps };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/scroll-area/scroll-area.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACQA,IAAM,UAAA,GAAmB,KAAA,CAAA,UAAA,CAGvB,CAAC,EAAE,SAAA,EAAW,QAAA,EAAU,gBAAA,GAAmB,CAAA,EAAG,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC3D,IAAA;AAAA,EAAqB,mBAAA,CAAA,IAAA;AAAA,EAApB;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,0BAAA,EAA4B,SAAS,CAAA;AAAA,IAClD,GAAG,KAAA;AAAA,IAEJ,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAqB,mBAAA,CAAA,QAAA;AAAA,QAApB;AAAA,UACA,QAAA,EAAU,gBAAA;AAAA,UACV,SAAA,EAAW,EAAA;AAAA,YACV,iCAAA;AAAA,YACA,oBAAoB,CAAA,IACnB;AAAA,WACF;AAAA,UAEC;AAAA;AAAA,OACF;AAAA,sBAGA,GAAA,CAAC,SAAA,EAAA,EAAU,WAAA,EAAY,UAAA,EAAW,CAAA;AAAA,sBAClC,GAAA,CAAC,SAAA,EAAA,EAAU,WAAA,EAAY,YAAA,EAAa,CAAA;AAAA,sBACpC,GAAA,CAAqB,4BAApB,EAA2B;AAAA;AAAA;AAC7B,CACA;AACD,UAAA,CAAW,WAAA,GAAc,YAAA;AAGzB,IAAM,SAAA,GAAkB,KAAA,CAAA,UAAA,CAGtB,CAAC,EAAE,SAAA,EAAW,cAAc,UAAA,EAAY,GAAG,KAAA,EAAM,EAAG,GAAA,qBACrD,GAAA;AAAA,EAAqB,mBAAA,CAAA,mBAAA;AAAA,EAApB;AAAA,IACA,GAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,6FAAA;AAAA,MACA,gBAAgB,UAAA,IACf,oDAAA;AAAA,MACD,gBAAgB,YAAA,IACf,sDAAA;AAAA,MACD;AAAA,KACD;AAAA,IACC,GAAG,KAAA;AAAA,IAEJ,QAAA,kBAAA,GAAA,CAAqB,mBAAA,CAAA,eAAA,EAApB,EAAoC,SAAA,EAAU,mDAAA,EAAoD;AAAA;AACpG,CACA;AACD,SAAA,CAAU,WAAA,GAAc,WAAA","file":"scroll-area.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 ScrollAreaPrimitive from \"@radix-ui/react-scroll-area\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\ninterface ScrollAreaProps\n\textends React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root> {\n\t/**\n\t * tabIndex applied to the scroll viewport so keyboard users can scroll\n\t * without a pointer. Defaults to `0` (focusable) — pass `-1` to skip the\n\t * viewport in the tab order when ScrollArea wraps purely decorative or\n\t * already-keyboard-reachable content.\n\t */\n\tviewportTabIndex?: number;\n}\n\n/** A scrollable area with custom-styled scrollbars. Content must be explicitly sized. */\nconst ScrollArea = React.forwardRef<\n\tReact.ComponentRef<typeof ScrollAreaPrimitive.Root>,\n\tScrollAreaProps\n>(({ className, children, viewportTabIndex = 0, ...props }, ref) => (\n\t<ScrollAreaPrimitive.Root\n\t\tref={ref}\n\t\tclassName={cn(\"relative overflow-hidden\", className)}\n\t\t{...props}\n\t>\n\t\t<ScrollAreaPrimitive.Viewport\n\t\t\ttabIndex={viewportTabIndex}\n\t\t\tclassName={cn(\n\t\t\t\t\"h-full w-full rounded-[inherit]\",\n\t\t\t\tviewportTabIndex >= 0 &&\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)}\n\t\t>\n\t\t\t{children}\n\t\t</ScrollAreaPrimitive.Viewport>\n\t\t{/* Both orientations mount unconditionally; Radix paints each only when content\n\t\t overflows on that axis, so there's no cost for single-axis content. */}\n\t\t<ScrollBar orientation=\"vertical\" />\n\t\t<ScrollBar orientation=\"horizontal\" />\n\t\t<ScrollAreaPrimitive.Corner />\n\t</ScrollAreaPrimitive.Root>\n));\nScrollArea.displayName = \"ScrollArea\";\n\n/** Styled scrollbar track + thumb. Rendered inside ScrollArea automatically. */\nconst ScrollBar = React.forwardRef<\n\tReact.ComponentRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,\n\tReact.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>\n>(({ className, orientation = \"vertical\", ...props }, ref) => (\n\t<ScrollAreaPrimitive.ScrollAreaScrollbar\n\t\tref={ref}\n\t\torientation={orientation}\n\t\tclassName={cn(\n\t\t\t\"flex touch-none select-none transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\torientation === \"vertical\" &&\n\t\t\t\t\"h-full w-2.5 border-l border-l-transparent p-[1px]\",\n\t\t\torientation === \"horizontal\" &&\n\t\t\t\t\"h-2.5 flex-col border-t border-t-transparent p-[1px]\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t<ScrollAreaPrimitive.ScrollAreaThumb className=\"relative flex-1 rounded-full bg-foreground/[0.18]\" />\n\t</ScrollAreaPrimitive.ScrollAreaScrollbar>\n));\nScrollBar.displayName = \"ScrollBar\";\n\nexport { ScrollArea, ScrollBar };\nexport type { ScrollAreaProps };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/select/select.tsx"],"names":[],"mappings":"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","file":"select.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 SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/** Root container controlling the select's state. */\nconst Select = SelectPrimitive.Root;\n\n/** Groups a set of related SelectItem elements. */\nconst SelectGroup = SelectPrimitive.Group;\n\n/** Renders the selected value (or placeholder) inside the trigger. */\nconst SelectValue = SelectPrimitive.Value;\n\n/** The button users click to open the dropdown. */\nconst SelectTrigger = React.forwardRef<\n\tReact.ComponentRef<typeof SelectPrimitive.Trigger>,\n\tReact.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n\t<SelectPrimitive.Trigger\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"flex h-[var(--control-height-md,2.5rem)] w-full items-center justify-between rounded-md border border-input bg-background px-[var(--space-3,0.75rem)] py-[var(--space-2,0.5rem)] text-sm\",\n\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out shadow-sm inset-ring-1 inset-ring-foreground/[0.06]\",\n\t\t\t\"placeholder:text-muted-foreground\",\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\"focus-visible:shadow-md focus-visible:border-ring/50\",\n\t\t\t\"hover:border-ring/30 hover:shadow-md\",\n\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\"[&>span]:line-clamp-1\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t{children}\n\t\t<SelectPrimitive.Icon asChild>\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 opacity-50\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<path d=\"m7 15 5 5 5-5\" />\n\t\t\t\t<path d=\"m7 9 5-5 5 5\" />\n\t\t\t</svg>\n\t\t</SelectPrimitive.Icon>\n\t</SelectPrimitive.Trigger>\n));\nSelectTrigger.displayName = \"SelectTrigger\";\n\n/** The dropdown panel containing selectable options. */\nconst SelectContent = React.forwardRef<\n\tReact.ComponentRef<typeof SelectPrimitive.Content>,\n\tReact.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = \"popper\", ...props }, ref) => (\n\t<SelectPrimitive.Portal>\n\t\t<SelectPrimitive.Content\n\t\t\tref={ref}\n\t\t\tposition={position}\n\t\t\tclassName={cn(\n\t\t\t\t\"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border border-foreground/[0.08] bg-popover text-popover-foreground shadow-md\",\n\t\t\t\t\"data-[state=open]:animate-in data-[state=closed]:animate-out\",\n\t\t\t\t\"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n\t\t\t\t\"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n\t\t\t\t\"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n\t\t\t\tposition === \"popper\" &&\n\t\t\t\t\t\"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<SelectPrimitive.Viewport\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"p-[var(--space-1,0.25rem)]\",\n\t\t\t\t\tposition === \"popper\" &&\n\t\t\t\t\t\t\"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</SelectPrimitive.Viewport>\n\t\t</SelectPrimitive.Content>\n\t</SelectPrimitive.Portal>\n));\nSelectContent.displayName = \"SelectContent\";\n\n/** A non-interactive label within a SelectGroup. */\nconst SelectLabel = React.forwardRef<\n\tReact.ComponentRef<typeof SelectPrimitive.Label>,\n\tReact.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n\t<SelectPrimitive.Label\n\t\tref={ref}\n\t\tclassName={cn(\"py-1.5 pl-[var(--space-8,2rem)] pr-[var(--space-2,0.5rem)] text-sm font-semibold\", className)}\n\t\t{...props}\n\t/>\n));\nSelectLabel.displayName = \"SelectLabel\";\n\n/** A selectable option. */\nconst SelectItem = React.forwardRef<\n\tReact.ComponentRef<typeof SelectPrimitive.Item>,\n\tReact.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n\t<SelectPrimitive.Item\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-[var(--space-8,2rem)] pr-[var(--space-2,0.5rem)] text-sm outline-none\",\n\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\"focus:bg-accent focus:text-accent-foreground\",\n\t\t\t\"data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t<span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n\t\t\t<SelectPrimitive.ItemIndicator>\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=\"3\"\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\tclassName=\"h-3.5 w-3.5\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t\t\t</svg>\n\t\t\t</SelectPrimitive.ItemIndicator>\n\t\t</span>\n\t\t<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n\t</SelectPrimitive.Item>\n));\nSelectItem.displayName = \"SelectItem\";\n\n/** Horizontal divider between groups inside SelectContent. */\nconst SelectSeparator = React.forwardRef<\n\tReact.ComponentRef<typeof SelectPrimitive.Separator>,\n\tReact.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n\t<SelectPrimitive.Separator\n\t\tref={ref}\n\t\tclassName={cn(\"-mx-[var(--space-1,0.25rem)] my-[var(--space-1,0.25rem)] h-px bg-foreground/[0.12]\", className)}\n\t\t{...props}\n\t/>\n));\nSelectSeparator.displayName = \"SelectSeparator\";\n\nexport {\n\tSelect,\n\tSelectGroup,\n\tSelectValue,\n\tSelectTrigger,\n\tSelectContent,\n\tSelectLabel,\n\tSelectItem,\n\tSelectSeparator,\n};\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/select/select.tsx"],"names":[],"mappings":"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","file":"select.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 SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/** Root container controlling the select's state. */\nconst Select = SelectPrimitive.Root;\n\n/** Groups a set of related SelectItem elements. */\nconst SelectGroup = SelectPrimitive.Group;\n\n/** Renders the selected value (or placeholder) inside the trigger. */\nconst SelectValue = SelectPrimitive.Value;\n\n/** The button users click to open the dropdown. */\nconst SelectTrigger = React.forwardRef<\n\tReact.ComponentRef<typeof SelectPrimitive.Trigger>,\n\tReact.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n\t<SelectPrimitive.Trigger\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"flex h-[var(--control-height-md,2.5rem)] w-full items-center justify-between rounded-md border border-input bg-background px-[var(--space-3,0.75rem)] py-[var(--space-2,0.5rem)] text-sm\",\n\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out shadow-sm inset-ring-1 inset-ring-foreground/[0.06]\",\n\t\t\t\"placeholder:text-muted-foreground\",\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\"focus-visible:shadow-md focus-visible:border-ring/50\",\n\t\t\t\"hover:border-ring/30 hover:shadow-md\",\n\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\"[&>span]:line-clamp-1\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t{children}\n\t\t<SelectPrimitive.Icon asChild>\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 opacity-50\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<path d=\"m7 15 5 5 5-5\" />\n\t\t\t\t<path d=\"m7 9 5-5 5 5\" />\n\t\t\t</svg>\n\t\t</SelectPrimitive.Icon>\n\t</SelectPrimitive.Trigger>\n));\nSelectTrigger.displayName = \"SelectTrigger\";\n\n/** The dropdown panel containing selectable options. */\nconst SelectContent = React.forwardRef<\n\tReact.ComponentRef<typeof SelectPrimitive.Content>,\n\tReact.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = \"popper\", ...props }, ref) => (\n\t<SelectPrimitive.Portal>\n\t\t<SelectPrimitive.Content\n\t\t\tref={ref}\n\t\t\tposition={position}\n\t\t\tclassName={cn(\n\t\t\t\t\"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border border-foreground/[0.08] bg-popover text-popover-foreground shadow-md\",\n\t\t\t\t\"data-[state=open]:animate-in data-[state=closed]:animate-out\",\n\t\t\t\t\"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n\t\t\t\t\"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n\t\t\t\t\"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n\t\t\t\tposition === \"popper\" &&\n\t\t\t\t\t\"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<SelectPrimitive.Viewport\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"p-[var(--space-1,0.25rem)]\",\n\t\t\t\t\tposition === \"popper\" &&\n\t\t\t\t\t\t\"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</SelectPrimitive.Viewport>\n\t\t</SelectPrimitive.Content>\n\t</SelectPrimitive.Portal>\n));\nSelectContent.displayName = \"SelectContent\";\n\n/** A non-interactive label within a SelectGroup. */\nconst SelectLabel = React.forwardRef<\n\tReact.ComponentRef<typeof SelectPrimitive.Label>,\n\tReact.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n\t<SelectPrimitive.Label\n\t\tref={ref}\n\t\tclassName={cn(\"py-1.5 pl-[var(--space-8,2rem)] pr-[var(--space-2,0.5rem)] text-sm font-semibold\", className)}\n\t\t{...props}\n\t/>\n));\nSelectLabel.displayName = \"SelectLabel\";\n\n/** A selectable option. */\nconst SelectItem = React.forwardRef<\n\tReact.ComponentRef<typeof SelectPrimitive.Item>,\n\tReact.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n\t<SelectPrimitive.Item\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-[var(--space-8,2rem)] pr-[var(--space-2,0.5rem)] text-sm outline-none\",\n\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\"focus:bg-accent focus:text-accent-foreground\",\n\t\t\t\"data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t<span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n\t\t\t<SelectPrimitive.ItemIndicator>\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=\"3\"\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\tclassName=\"h-3.5 w-3.5\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t\t\t</svg>\n\t\t\t</SelectPrimitive.ItemIndicator>\n\t\t</span>\n\t\t<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n\t</SelectPrimitive.Item>\n));\nSelectItem.displayName = \"SelectItem\";\n\n/** Horizontal divider between groups inside SelectContent. */\nconst SelectSeparator = React.forwardRef<\n\tReact.ComponentRef<typeof SelectPrimitive.Separator>,\n\tReact.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n\t<SelectPrimitive.Separator\n\t\tref={ref}\n\t\tclassName={cn(\"-mx-[var(--space-1,0.25rem)] my-[var(--space-1,0.25rem)] h-px bg-foreground/[0.12]\", className)}\n\t\t{...props}\n\t/>\n));\nSelectSeparator.displayName = \"SelectSeparator\";\n\nexport {\n\tSelect,\n\tSelectGroup,\n\tSelectValue,\n\tSelectTrigger,\n\tSelectContent,\n\tSelectLabel,\n\tSelectItem,\n\tSelectSeparator,\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/separator/separator.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACEA,IAAM,SAAA,GAAkB,KAAA,CAAA,UAAA,CAGtB,CAAC,EAAE,SAAA,EAAW,WAAA,GAAc,YAAA,EAAc,UAAA,GAAa,IAAA,EAAM,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC1E,GAAA;AAAA,EAAoB,kBAAA,CAAA,IAAA;AAAA,EAAnB;AAAA,IACA,GAAA;AAAA,IACA,UAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,+BAAA;AAAA,MACA,WAAA,KAAgB,eAAe,gBAAA,GAAmB,gBAAA;AAAA,MAClD;AAAA,KACD;AAAA,IACC,GAAG;AAAA;AACL,CACA;AACD,SAAA,CAAU,WAAA,GAAc,WAAA","file":"separator.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 SeparatorPrimitive from \"@radix-ui/react-separator\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * A visual divider between content sections.\n * Built on Radix UI Separator for proper accessibility semantics.\n */\nexport type SeparatorProps = React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>;\n\nconst Separator = React.forwardRef<\n\tReact.ComponentRef<typeof SeparatorPrimitive.Root>,\n\tSeparatorProps\n>(({ className, orientation = \"horizontal\", decorative = true, ...props }, ref) => (\n\t<SeparatorPrimitive.Root\n\t\tref={ref}\n\t\tdecorative={decorative}\n\t\torientation={orientation}\n\t\tclassName={cn(\n\t\t\t\"shrink-0 bg-foreground/[0.12]\",\n\t\t\torientation === \"horizontal\" ? \"h-[1px] w-full\" : \"h-full w-[1px]\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nSeparator.displayName = \"Separator\";\n\nexport { Separator };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/separator/separator.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACEA,IAAM,SAAA,GAAkB,KAAA,CAAA,UAAA,CAGtB,CAAC,EAAE,SAAA,EAAW,WAAA,GAAc,YAAA,EAAc,UAAA,GAAa,IAAA,EAAM,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC1E,GAAA;AAAA,EAAoB,kBAAA,CAAA,IAAA;AAAA,EAAnB;AAAA,IACA,GAAA;AAAA,IACA,UAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,+BAAA;AAAA,MACA,WAAA,KAAgB,eAAe,gBAAA,GAAmB,gBAAA;AAAA,MAClD;AAAA,KACD;AAAA,IACC,GAAG;AAAA;AACL,CACA;AACD,SAAA,CAAU,WAAA,GAAc,WAAA","file":"separator.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 SeparatorPrimitive from \"@radix-ui/react-separator\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * A visual divider between content sections.\n * Built on Radix UI Separator for proper accessibility semantics.\n */\nexport type SeparatorProps = React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>;\n\nconst Separator = React.forwardRef<\n\tReact.ComponentRef<typeof SeparatorPrimitive.Root>,\n\tSeparatorProps\n>(({ className, orientation = \"horizontal\", decorative = true, ...props }, ref) => (\n\t<SeparatorPrimitive.Root\n\t\tref={ref}\n\t\tdecorative={decorative}\n\t\torientation={orientation}\n\t\tclassName={cn(\n\t\t\t\"shrink-0 bg-foreground/[0.12]\",\n\t\t\torientation === \"horizontal\" ? \"h-[1px] w-full\" : \"h-full w-[1px]\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nSeparator.displayName = \"Separator\";\n\nexport { Separator };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/artifacts/sequence/sequence.tsx"],"names":[],"mappings":"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","file":"sequence.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 * UML-style sequence diagram. Actors render as columns with vertical\n * lifelines; messages render as horizontal arrows between actors,\n * stacked top-to-bottom in declaration order. Pure SVG; no heavy peer\n * dependency.\n *\n * Distinct from Flowchart (DAG of steps) and TimeAxis (events on a\n * time axis): Sequence encodes WHO talks to WHO and IN WHAT ORDER.\n *\n * @example\n * <Sequence\n * actors={[\n * { id: \"user\", label: \"User\" },\n * { id: \"api\", label: \"API\" },\n * { id: \"db\", label: \"DB\" },\n * ]}\n * messages={[\n * { from: \"user\", to: \"api\", label: \"POST /signup\" },\n * { from: \"api\", to: \"db\", label: \"INSERT user\" },\n * { from: \"db\", to: \"api\", label: \"ok\", type: \"return\" },\n * { from: \"api\", to: \"user\", label: \"201 Created\", type: \"return\" },\n * ]}\n * />\n */\nexport type SequenceActor = {\n\tid: string;\n\tlabel: string;\n};\n\nexport type SequenceMessage = {\n\tfrom: string;\n\tto: string;\n\tlabel?: string;\n\t/** \"sync\" (default) draws a solid arrow; \"async\" draws a thinner half-head; \"return\" is dashed. */\n\ttype?: \"sync\" | \"async\" | \"return\";\n};\n\nexport interface SequenceProps extends Omit<React.SVGAttributes<SVGSVGElement>, \"children\"> {\n\t/** Actors in display order (columns left-to-right). */\n\tactors: SequenceActor[];\n\t/** Messages in chronological order (top-to-bottom). */\n\tmessages: SequenceMessage[];\n\t/** Pixel width of the rendered SVG. Default 720. */\n\twidth?: number;\n\t/** Pixel height of each actor header. Default 40. */\n\theaderHeight?: number;\n\t/** Pixel vertical gap between consecutive messages. Default 36. */\n\tmessageGap?: number;\n\t/** Fired when an actor header is clicked. */\n\tonActorClick?: (actor: SequenceActor) => void;\n\t/** Fired when a message arrow is clicked. */\n\tonMessageClick?: (message: SequenceMessage) => void;\n}\n\ninterface ActorPos {\n\tactor: SequenceActor;\n\tx: number;\n\tdepth: number;\n}\n\ninterface LaidOutMessage {\n\tmessage: SequenceMessage;\n\tfrom: ActorPos;\n\tto: ActorPos;\n\ty: number;\n\tdepth: number;\n\tisSelfCall: boolean;\n}\n\nconst HEADER_PADDING = 16;\nconst MESSAGE_TOP_PADDING = 24;\n\nfunction Sequence({\n\tactors,\n\tmessages,\n\twidth = 720,\n\theaderHeight = 40,\n\tmessageGap = 36,\n\tonActorClick,\n\tonMessageClick,\n\tclassName,\n\t...rest\n}: SequenceProps) {\n\tconst laidOut = React.useMemo(\n\t\t() => layout(actors, messages, width, headerHeight, messageGap),\n\t\t[actors, messages, width, headerHeight, messageGap],\n\t);\n\n\tconst desc = `Sequence diagram with ${actors.length} actor${actors.length === 1 ? \"\" : \"s\"} and ${messages.length} message${messages.length === 1 ? \"\" : \"s\"}`;\n\t// Per-instance to avoid <defs> id collision when two <Sequence> mount on\n\t// the same page; React.useId() is unique per component instance.\n\tconst arrowId = React.useId().replace(/:/g, \"-\");\n\t// Loopback height scales with messageGap so the self-call doesn't\n\t// overflow into the next message at small messageGap values.\n\tconst SELF_CALL_DROP = Math.min(14, Math.max(6, messageGap * 0.4));\n\tconst SELF_CALL_OUT = 28;\n\n\treturn (\n\t\t<svg\n\t\t\t{...rest}\n\t\t\tdata-hex-sequence\n\t\t\trole=\"img\"\n\t\t\twidth={width}\n\t\t\theight={laidOut.totalHeight}\n\t\t\tviewBox={`0 0 ${width} ${laidOut.totalHeight}`}\n\t\t\tclassName={cn(\"block\", className)}\n\t\t>\n\t\t\t<title>Sequence diagram</title>\n\t\t\t<desc>{desc}</desc>\n\t\t\t<defs>\n\t\t\t\t<marker\n\t\t\t\t\tid={`hex-sequence-arrow-${arrowId}`}\n\t\t\t\t\tviewBox=\"0 0 10 10\"\n\t\t\t\t\trefX=\"10\"\n\t\t\t\t\trefY=\"5\"\n\t\t\t\t\tmarkerWidth=\"6\"\n\t\t\t\t\tmarkerHeight=\"6\"\n\t\t\t\t\torient=\"auto-start-reverse\"\n\t\t\t\t>\n\t\t\t\t\t<path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"hsl(var(--foreground))\" />\n\t\t\t\t</marker>\n\t\t\t</defs>\n\t\t\t{/* Lifelines */}\n\t\t\t<g data-hex-sequence-lifelines>\n\t\t\t\t{laidOut.actors.map((a) => (\n\t\t\t\t\t<line\n\t\t\t\t\t\tkey={`lifeline-${a.actor.id}`}\n\t\t\t\t\t\tdata-hex-sequence-lifeline\n\t\t\t\t\t\tx1={a.x}\n\t\t\t\t\t\tx2={a.x}\n\t\t\t\t\t\ty1={headerHeight}\n\t\t\t\t\t\ty2={laidOut.totalHeight - 8}\n\t\t\t\t\t\tstroke=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\t\tstrokeOpacity={0.7}\n\t\t\t\t\t\tstrokeDasharray=\"3 4\"\n\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</g>\n\t\t\t{/* Actor headers */}\n\t\t\t<g data-hex-sequence-actors>\n\t\t\t\t{laidOut.actors.map((a) => {\n\t\t\t\t\tconst interactive = Boolean(onActorClick);\n\t\t\t\t\tconst handleActivate = () => onActorClick?.(a.actor);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<g\n\t\t\t\t\t\t\tkey={a.actor.id}\n\t\t\t\t\t\t\tdata-hex-sequence-actor\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.actor.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<rect\n\t\t\t\t\t\t\t\tx={a.x - 64}\n\t\t\t\t\t\t\t\ty={4}\n\t\t\t\t\t\t\t\twidth={128}\n\t\t\t\t\t\t\t\theight={headerHeight - 8}\n\t\t\t\t\t\t\t\trx={4}\n\t\t\t\t\t\t\t\try={4}\n\t\t\t\t\t\t\t\tfill=\"hsl(var(--card))\"\n\t\t\t\t\t\t\t\tstroke=\"hsl(var(--border))\"\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.x}\n\t\t\t\t\t\t\t\ty={headerHeight / 2}\n\t\t\t\t\t\t\t\tdy=\"0.35em\"\n\t\t\t\t\t\t\t\ttextAnchor=\"middle\"\n\t\t\t\t\t\t\t\tfontSize={12}\n\t\t\t\t\t\t\t\tfontWeight={600}\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.actor.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\t{/* Messages */}\n\t\t\t<g data-hex-sequence-messages>\n\t\t\t\t{laidOut.messages.map((m, i) => {\n\t\t\t\t\tconst interactive = Boolean(onMessageClick);\n\t\t\t\t\tconst handleActivate = () => onMessageClick?.(m.message);\n\t\t\t\t\tconst stroke = \"hsl(var(--foreground))\";\n\t\t\t\t\tconst dashed = m.message.type === \"return\" ? \"4 3\" : undefined;\n\t\t\t\t\tconst strokeWidth = m.message.type === \"async\" ? 1 : 1.25;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<g\n\t\t\t\t\t\t\tkey={`${m.message.from}-${m.message.to}-${i}`}\n\t\t\t\t\t\t\tdata-hex-sequence-message\n\t\t\t\t\t\t\tdata-depth={m.depth}\n\t\t\t\t\t\t\tdata-type={m.message.type ?? \"sync\"}\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? `Message ${i + 1}: from ${m.from.actor.label} to ${m.to.actor.label}${m.message.label ? `, \"${m.message.label}\"` : \"\"}`\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={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{m.isSelfCall ? (\n\t\t\t\t\t\t\t\t// Loopback: out + down + back. Drop scales with messageGap.\n\t\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\t\td={`M${m.from.x},${m.y} L${m.from.x + SELF_CALL_OUT},${m.y} L${m.from.x + SELF_CALL_OUT},${m.y + SELF_CALL_DROP} L${m.from.x + 4},${m.y + SELF_CALL_DROP}`}\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke={stroke}\n\t\t\t\t\t\t\t\t\tstrokeWidth={strokeWidth}\n\t\t\t\t\t\t\t\t\tstrokeDasharray={dashed}\n\t\t\t\t\t\t\t\t\tmarkerEnd={`url(#hex-sequence-arrow-${arrowId})`}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<line\n\t\t\t\t\t\t\t\t\tx1={m.from.x}\n\t\t\t\t\t\t\t\t\tx2={m.to.x}\n\t\t\t\t\t\t\t\t\ty1={m.y}\n\t\t\t\t\t\t\t\t\ty2={m.y}\n\t\t\t\t\t\t\t\t\tstroke={stroke}\n\t\t\t\t\t\t\t\t\tstrokeWidth={strokeWidth}\n\t\t\t\t\t\t\t\t\tstrokeDasharray={dashed}\n\t\t\t\t\t\t\t\t\tmarkerEnd={`url(#hex-sequence-arrow-${arrowId})`}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{m.message.label ? (\n\t\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\t\t// Self-calls anchor the label right of the loopback's apex\n\t\t\t\t\t\t\t\t\t// (start-anchored, just past the outbound segment) so it\n\t\t\t\t\t\t\t\t\t// doesn't sit above the actor's own lifeline. Non-self\n\t\t\t\t\t\t\t\t\t// messages center the label between the two actors.\n\t\t\t\t\t\t\t\t\tx={m.isSelfCall ? m.from.x + SELF_CALL_OUT + 4 : (m.from.x + m.to.x) / 2}\n\t\t\t\t\t\t\t\t\ty={m.y - 4}\n\t\t\t\t\t\t\t\t\ttextAnchor={m.isSelfCall ? \"start\" : \"middle\"}\n\t\t\t\t\t\t\t\t\tfontSize={11}\n\t\t\t\t\t\t\t\t\tfill=\"hsl(var(--foreground))\"\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tpaintOrder: \"stroke\",\n\t\t\t\t\t\t\t\t\t\tpointerEvents: \"none\",\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tstroke=\"hsl(var(--background))\"\n\t\t\t\t\t\t\t\t\tstrokeWidth={3}\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{m.message.label}\n\t\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t\t) : null}\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\tactors: SequenceActor[],\n\tmessages: SequenceMessage[],\n\twidth: number,\n\theaderHeight: number,\n\tmessageGap: number,\n): {\n\tactors: ActorPos[];\n\tmessages: LaidOutMessage[];\n\ttotalHeight: number;\n} {\n\tif (actors.length === 0) {\n\t\treturn { actors: [], messages: [], totalHeight: headerHeight + 16 };\n\t}\n\n\tconst usableWidth = width - HEADER_PADDING * 2;\n\tconst colStep = actors.length > 1 ? usableWidth / (actors.length - 1) : 0;\n\tconst actorPositions: ActorPos[] = actors.map((a, i) => ({\n\t\tactor: a,\n\t\tx: HEADER_PADDING + colStep * i,\n\t\tdepth: i,\n\t}));\n\tconst byId = new Map(actorPositions.map((a) => [a.actor.id, a]));\n\n\tconst laidOutMessages: LaidOutMessage[] = messages\n\t\t.map((message, i) => {\n\t\t\tconst from = byId.get(message.from);\n\t\t\tconst to = byId.get(message.to);\n\t\t\tif (!from || !to) return null;\n\t\t\treturn {\n\t\t\t\tmessage,\n\t\t\t\tfrom,\n\t\t\t\tto,\n\t\t\t\ty: headerHeight + MESSAGE_TOP_PADDING + i * messageGap,\n\t\t\t\tdepth: i,\n\t\t\t\tisSelfCall: message.from === message.to,\n\t\t\t};\n\t\t})\n\t\t.filter((m): m is LaidOutMessage => m !== null);\n\n\tconst totalHeight =\n\t\theaderHeight +\n\t\tMESSAGE_TOP_PADDING +\n\t\tMath.max(0, laidOutMessages.length - 1) * messageGap +\n\t\t32;\n\n\treturn { actors: actorPositions, messages: laidOutMessages, totalHeight };\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 { Sequence };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/artifacts/sequence/sequence.tsx"],"names":[],"mappings":"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","file":"sequence.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 * UML-style sequence diagram. Actors render as columns with vertical\n * lifelines; messages render as horizontal arrows between actors,\n * stacked top-to-bottom in declaration order. Pure SVG; no heavy peer\n * dependency.\n *\n * Distinct from Flowchart (DAG of steps) and TimeAxis (events on a\n * time axis): Sequence encodes WHO talks to WHO and IN WHAT ORDER.\n *\n * @example\n * <Sequence\n * actors={[\n * { id: \"user\", label: \"User\" },\n * { id: \"api\", label: \"API\" },\n * { id: \"db\", label: \"DB\" },\n * ]}\n * messages={[\n * { from: \"user\", to: \"api\", label: \"POST /signup\" },\n * { from: \"api\", to: \"db\", label: \"INSERT user\" },\n * { from: \"db\", to: \"api\", label: \"ok\", type: \"return\" },\n * { from: \"api\", to: \"user\", label: \"201 Created\", type: \"return\" },\n * ]}\n * />\n */\nexport type SequenceActor = {\n\tid: string;\n\tlabel: string;\n};\n\nexport type SequenceMessage = {\n\tfrom: string;\n\tto: string;\n\tlabel?: string;\n\t/** \"sync\" (default) draws a solid arrow; \"async\" draws a thinner half-head; \"return\" is dashed. */\n\ttype?: \"sync\" | \"async\" | \"return\";\n};\n\nexport interface SequenceProps extends Omit<React.SVGAttributes<SVGSVGElement>, \"children\"> {\n\t/** Actors in display order (columns left-to-right). */\n\tactors: SequenceActor[];\n\t/** Messages in chronological order (top-to-bottom). */\n\tmessages: SequenceMessage[];\n\t/** Pixel width of the rendered SVG. Default 720. */\n\twidth?: number;\n\t/** Pixel height of each actor header. Default 40. */\n\theaderHeight?: number;\n\t/** Pixel vertical gap between consecutive messages. Default 36. */\n\tmessageGap?: number;\n\t/** Fired when an actor header is clicked. */\n\tonActorClick?: (actor: SequenceActor) => void;\n\t/** Fired when a message arrow is clicked. */\n\tonMessageClick?: (message: SequenceMessage) => void;\n}\n\ninterface ActorPos {\n\tactor: SequenceActor;\n\tx: number;\n\tdepth: number;\n}\n\ninterface LaidOutMessage {\n\tmessage: SequenceMessage;\n\tfrom: ActorPos;\n\tto: ActorPos;\n\ty: number;\n\tdepth: number;\n\tisSelfCall: boolean;\n}\n\nconst HEADER_PADDING = 16;\nconst MESSAGE_TOP_PADDING = 24;\n\nfunction Sequence({\n\tactors,\n\tmessages,\n\twidth = 720,\n\theaderHeight = 40,\n\tmessageGap = 36,\n\tonActorClick,\n\tonMessageClick,\n\tclassName,\n\t...rest\n}: SequenceProps) {\n\tconst laidOut = React.useMemo(\n\t\t() => layout(actors, messages, width, headerHeight, messageGap),\n\t\t[actors, messages, width, headerHeight, messageGap],\n\t);\n\n\tconst desc = `Sequence diagram with ${actors.length} actor${actors.length === 1 ? \"\" : \"s\"} and ${messages.length} message${messages.length === 1 ? \"\" : \"s\"}`;\n\t// Per-instance to avoid <defs> id collision when two <Sequence> mount on\n\t// the same page; React.useId() is unique per component instance.\n\tconst arrowId = React.useId().replace(/:/g, \"-\");\n\t// Loopback height scales with messageGap so the self-call doesn't\n\t// overflow into the next message at small messageGap values.\n\tconst SELF_CALL_DROP = Math.min(14, Math.max(6, messageGap * 0.4));\n\tconst SELF_CALL_OUT = 28;\n\n\treturn (\n\t\t<svg\n\t\t\t{...rest}\n\t\t\tdata-hex-sequence\n\t\t\trole=\"img\"\n\t\t\twidth={width}\n\t\t\theight={laidOut.totalHeight}\n\t\t\tviewBox={`0 0 ${width} ${laidOut.totalHeight}`}\n\t\t\tclassName={cn(\"block\", className)}\n\t\t>\n\t\t\t<title>Sequence diagram</title>\n\t\t\t<desc>{desc}</desc>\n\t\t\t<defs>\n\t\t\t\t<marker\n\t\t\t\t\tid={`hex-sequence-arrow-${arrowId}`}\n\t\t\t\t\tviewBox=\"0 0 10 10\"\n\t\t\t\t\trefX=\"10\"\n\t\t\t\t\trefY=\"5\"\n\t\t\t\t\tmarkerWidth=\"6\"\n\t\t\t\t\tmarkerHeight=\"6\"\n\t\t\t\t\torient=\"auto-start-reverse\"\n\t\t\t\t>\n\t\t\t\t\t<path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"hsl(var(--foreground))\" />\n\t\t\t\t</marker>\n\t\t\t</defs>\n\t\t\t{/* Lifelines */}\n\t\t\t<g data-hex-sequence-lifelines>\n\t\t\t\t{laidOut.actors.map((a) => (\n\t\t\t\t\t<line\n\t\t\t\t\t\tkey={`lifeline-${a.actor.id}`}\n\t\t\t\t\t\tdata-hex-sequence-lifeline\n\t\t\t\t\t\tx1={a.x}\n\t\t\t\t\t\tx2={a.x}\n\t\t\t\t\t\ty1={headerHeight}\n\t\t\t\t\t\ty2={laidOut.totalHeight - 8}\n\t\t\t\t\t\tstroke=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\t\tstrokeOpacity={0.7}\n\t\t\t\t\t\tstrokeDasharray=\"3 4\"\n\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</g>\n\t\t\t{/* Actor headers */}\n\t\t\t<g data-hex-sequence-actors>\n\t\t\t\t{laidOut.actors.map((a) => {\n\t\t\t\t\tconst interactive = Boolean(onActorClick);\n\t\t\t\t\tconst handleActivate = () => onActorClick?.(a.actor);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<g\n\t\t\t\t\t\t\tkey={a.actor.id}\n\t\t\t\t\t\t\tdata-hex-sequence-actor\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.actor.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<rect\n\t\t\t\t\t\t\t\tx={a.x - 64}\n\t\t\t\t\t\t\t\ty={4}\n\t\t\t\t\t\t\t\twidth={128}\n\t\t\t\t\t\t\t\theight={headerHeight - 8}\n\t\t\t\t\t\t\t\trx={4}\n\t\t\t\t\t\t\t\try={4}\n\t\t\t\t\t\t\t\tfill=\"hsl(var(--card))\"\n\t\t\t\t\t\t\t\tstroke=\"hsl(var(--border))\"\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.x}\n\t\t\t\t\t\t\t\ty={headerHeight / 2}\n\t\t\t\t\t\t\t\tdy=\"0.35em\"\n\t\t\t\t\t\t\t\ttextAnchor=\"middle\"\n\t\t\t\t\t\t\t\tfontSize={12}\n\t\t\t\t\t\t\t\tfontWeight={600}\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.actor.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\t{/* Messages */}\n\t\t\t<g data-hex-sequence-messages>\n\t\t\t\t{laidOut.messages.map((m, i) => {\n\t\t\t\t\tconst interactive = Boolean(onMessageClick);\n\t\t\t\t\tconst handleActivate = () => onMessageClick?.(m.message);\n\t\t\t\t\tconst stroke = \"hsl(var(--foreground))\";\n\t\t\t\t\tconst dashed = m.message.type === \"return\" ? \"4 3\" : undefined;\n\t\t\t\t\tconst strokeWidth = m.message.type === \"async\" ? 1 : 1.25;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<g\n\t\t\t\t\t\t\tkey={`${m.message.from}-${m.message.to}-${i}`}\n\t\t\t\t\t\t\tdata-hex-sequence-message\n\t\t\t\t\t\t\tdata-depth={m.depth}\n\t\t\t\t\t\t\tdata-type={m.message.type ?? \"sync\"}\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? `Message ${i + 1}: from ${m.from.actor.label} to ${m.to.actor.label}${m.message.label ? `, \"${m.message.label}\"` : \"\"}`\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={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{m.isSelfCall ? (\n\t\t\t\t\t\t\t\t// Loopback: out + down + back. Drop scales with messageGap.\n\t\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\t\td={`M${m.from.x},${m.y} L${m.from.x + SELF_CALL_OUT},${m.y} L${m.from.x + SELF_CALL_OUT},${m.y + SELF_CALL_DROP} L${m.from.x + 4},${m.y + SELF_CALL_DROP}`}\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke={stroke}\n\t\t\t\t\t\t\t\t\tstrokeWidth={strokeWidth}\n\t\t\t\t\t\t\t\t\tstrokeDasharray={dashed}\n\t\t\t\t\t\t\t\t\tmarkerEnd={`url(#hex-sequence-arrow-${arrowId})`}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<line\n\t\t\t\t\t\t\t\t\tx1={m.from.x}\n\t\t\t\t\t\t\t\t\tx2={m.to.x}\n\t\t\t\t\t\t\t\t\ty1={m.y}\n\t\t\t\t\t\t\t\t\ty2={m.y}\n\t\t\t\t\t\t\t\t\tstroke={stroke}\n\t\t\t\t\t\t\t\t\tstrokeWidth={strokeWidth}\n\t\t\t\t\t\t\t\t\tstrokeDasharray={dashed}\n\t\t\t\t\t\t\t\t\tmarkerEnd={`url(#hex-sequence-arrow-${arrowId})`}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{m.message.label ? (\n\t\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\t\t// Self-calls anchor the label right of the loopback's apex\n\t\t\t\t\t\t\t\t\t// (start-anchored, just past the outbound segment) so it\n\t\t\t\t\t\t\t\t\t// doesn't sit above the actor's own lifeline. Non-self\n\t\t\t\t\t\t\t\t\t// messages center the label between the two actors.\n\t\t\t\t\t\t\t\t\tx={m.isSelfCall ? m.from.x + SELF_CALL_OUT + 4 : (m.from.x + m.to.x) / 2}\n\t\t\t\t\t\t\t\t\ty={m.y - 4}\n\t\t\t\t\t\t\t\t\ttextAnchor={m.isSelfCall ? \"start\" : \"middle\"}\n\t\t\t\t\t\t\t\t\tfontSize={11}\n\t\t\t\t\t\t\t\t\tfill=\"hsl(var(--foreground))\"\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tpaintOrder: \"stroke\",\n\t\t\t\t\t\t\t\t\t\tpointerEvents: \"none\",\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tstroke=\"hsl(var(--background))\"\n\t\t\t\t\t\t\t\t\tstrokeWidth={3}\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{m.message.label}\n\t\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t\t) : null}\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\tactors: SequenceActor[],\n\tmessages: SequenceMessage[],\n\twidth: number,\n\theaderHeight: number,\n\tmessageGap: number,\n): {\n\tactors: ActorPos[];\n\tmessages: LaidOutMessage[];\n\ttotalHeight: number;\n} {\n\tif (actors.length === 0) {\n\t\treturn { actors: [], messages: [], totalHeight: headerHeight + 16 };\n\t}\n\n\tconst usableWidth = width - HEADER_PADDING * 2;\n\tconst colStep = actors.length > 1 ? usableWidth / (actors.length - 1) : 0;\n\tconst actorPositions: ActorPos[] = actors.map((a, i) => ({\n\t\tactor: a,\n\t\tx: HEADER_PADDING + colStep * i,\n\t\tdepth: i,\n\t}));\n\tconst byId = new Map(actorPositions.map((a) => [a.actor.id, a]));\n\n\tconst laidOutMessages: LaidOutMessage[] = messages\n\t\t.map((message, i) => {\n\t\t\tconst from = byId.get(message.from);\n\t\t\tconst to = byId.get(message.to);\n\t\t\tif (!from || !to) return null;\n\t\t\treturn {\n\t\t\t\tmessage,\n\t\t\t\tfrom,\n\t\t\t\tto,\n\t\t\t\ty: headerHeight + MESSAGE_TOP_PADDING + i * messageGap,\n\t\t\t\tdepth: i,\n\t\t\t\tisSelfCall: message.from === message.to,\n\t\t\t};\n\t\t})\n\t\t.filter((m): m is LaidOutMessage => m !== null);\n\n\tconst totalHeight =\n\t\theaderHeight +\n\t\tMESSAGE_TOP_PADDING +\n\t\tMath.max(0, laidOutMessages.length - 1) * messageGap +\n\t\t32;\n\n\treturn { actors: actorPositions, messages: laidOutMessages, totalHeight };\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 { Sequence };\n"]}
package/dist/sheet.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/components/sheet/sheet.tsx"],"names":[],"mappings":"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","file":"sheet.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 SheetPrimitive from \"@radix-ui/react-dialog\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/** Root container controlling open state of a side sheet. */\nconst Sheet = SheetPrimitive.Root;\n\n/** The element (usually a button) that opens the sheet. */\nconst SheetTrigger = SheetPrimitive.Trigger;\n\n/** Closes the sheet when rendered inside SheetContent. */\nconst SheetClose = SheetPrimitive.Close;\n\n/** Portals the sheet overlay and content into the body. */\nconst SheetPortal = SheetPrimitive.Portal;\n\n/** Dimmed backdrop rendered behind the sheet content. */\nconst SheetOverlay = React.forwardRef<\n\tReact.ComponentRef<typeof SheetPrimitive.Overlay>,\n\tReact.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Overlay\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm\",\n\t\t\t\"data-[state=open]:animate-in data-[state=closed]:animate-out\",\n\t\t\t\"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nSheetOverlay.displayName = \"SheetOverlay\";\n\nconst sheetVariants = cva(\n\tcn(\n\t\t\"fixed z-50 gap-[var(--gap-md,1rem)] bg-background p-[var(--space-6,1.5rem)] shadow-lg\",\n\t\t\"border-foreground/[0.08]\",\n\t\t\"transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out\",\n\t\t\"data-[state=closed]:duration-[var(--duration-slow,300ms)] data-[state=open]:duration-500\",\n\t),\n\t{\n\t\tvariants: {\n\t\t\tside: {\n\t\t\t\ttop: \"inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top\",\n\t\t\t\tbottom:\n\t\t\t\t\t\"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom\",\n\t\t\t\tleft: \"inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm\",\n\t\t\t\tright:\n\t\t\t\t\t\"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tside: \"right\",\n\t\t},\n\t},\n);\n\ninterface SheetContentProps\n\textends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,\n\t\tVariantProps<typeof sheetVariants> {}\n\n/** The sheet content panel that slides in from a side of the viewport. */\nconst SheetContent = React.forwardRef<\n\tReact.ComponentRef<typeof SheetPrimitive.Content>,\n\tSheetContentProps\n>(({ side = \"right\", className, children, ...props }, ref) => (\n\t<SheetPortal>\n\t\t<SheetOverlay />\n\t\t<SheetPrimitive.Content\n\t\t\tref={ref}\n\t\t\tclassName={cn(sheetVariants({ side }), className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t<SheetPrimitive.Close\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background\",\n\t\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out hover:opacity-100\",\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\t\"disabled:pointer-events-none\",\n\t\t\t\t)}\n\t\t\t>\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\tclassName=\"h-4 w-4\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<path d=\"M18 6 6 18\" />\n\t\t\t\t\t<path d=\"m6 6 12 12\" />\n\t\t\t\t</svg>\n\t\t\t\t<span className=\"sr-only\">Close</span>\n\t\t\t</SheetPrimitive.Close>\n\t\t</SheetPrimitive.Content>\n\t</SheetPortal>\n));\nSheetContent.displayName = \"SheetContent\";\n\n/**\n * Header container inside SheetContent; stacks title and description.\n * @returns A div with vertical rhythm.\n */\nfunction SheetHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\"flex flex-col space-y-2 text-center sm:text-left\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n/**\n * Footer container inside SheetContent; aligns action buttons.\n * @returns A div that stacks buttons on mobile and right-aligns on desktop.\n */\nfunction SheetFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n/** Accessible sheet title; Radix wires it to aria-labelledby automatically. */\nconst SheetTitle = React.forwardRef<\n\tReact.ComponentRef<typeof SheetPrimitive.Title>,\n\tReact.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Title\n\t\tref={ref}\n\t\tclassName={cn(\"text-lg font-semibold text-foreground\", className)}\n\t\t{...props}\n\t/>\n));\nSheetTitle.displayName = \"SheetTitle\";\n\n/** Accessible sheet description; Radix wires it to aria-describedby automatically. */\nconst SheetDescription = React.forwardRef<\n\tReact.ComponentRef<typeof SheetPrimitive.Description>,\n\tReact.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Description\n\t\tref={ref}\n\t\tclassName={cn(\"text-sm text-muted-foreground\", className)}\n\t\t{...props}\n\t/>\n));\nSheetDescription.displayName = \"SheetDescription\";\n\nexport {\n\tSheet,\n\tSheetPortal,\n\tSheetOverlay,\n\tSheetTrigger,\n\tSheetClose,\n\tSheetContent,\n\tSheetHeader,\n\tSheetFooter,\n\tSheetTitle,\n\tSheetDescription,\n};\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/sheet/sheet.tsx"],"names":[],"mappings":"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","file":"sheet.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 SheetPrimitive from \"@radix-ui/react-dialog\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/** Root container controlling open state of a side sheet. */\nconst Sheet = SheetPrimitive.Root;\n\n/** The element (usually a button) that opens the sheet. */\nconst SheetTrigger = SheetPrimitive.Trigger;\n\n/** Closes the sheet when rendered inside SheetContent. */\nconst SheetClose = SheetPrimitive.Close;\n\n/** Portals the sheet overlay and content into the body. */\nconst SheetPortal = SheetPrimitive.Portal;\n\n/** Dimmed backdrop rendered behind the sheet content. */\nconst SheetOverlay = React.forwardRef<\n\tReact.ComponentRef<typeof SheetPrimitive.Overlay>,\n\tReact.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Overlay\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm\",\n\t\t\t\"data-[state=open]:animate-in data-[state=closed]:animate-out\",\n\t\t\t\"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nSheetOverlay.displayName = \"SheetOverlay\";\n\nconst sheetVariants = cva(\n\tcn(\n\t\t\"fixed z-50 gap-[var(--gap-md,1rem)] bg-background p-[var(--space-6,1.5rem)] shadow-lg\",\n\t\t\"border-foreground/[0.08]\",\n\t\t\"transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out\",\n\t\t\"data-[state=closed]:duration-[var(--duration-slow,300ms)] data-[state=open]:duration-500\",\n\t),\n\t{\n\t\tvariants: {\n\t\t\tside: {\n\t\t\t\ttop: \"inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top\",\n\t\t\t\tbottom:\n\t\t\t\t\t\"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom\",\n\t\t\t\tleft: \"inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm\",\n\t\t\t\tright:\n\t\t\t\t\t\"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tside: \"right\",\n\t\t},\n\t},\n);\n\ninterface SheetContentProps\n\textends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,\n\t\tVariantProps<typeof sheetVariants> {}\n\n/** The sheet content panel that slides in from a side of the viewport. */\nconst SheetContent = React.forwardRef<\n\tReact.ComponentRef<typeof SheetPrimitive.Content>,\n\tSheetContentProps\n>(({ side = \"right\", className, children, ...props }, ref) => (\n\t<SheetPortal>\n\t\t<SheetOverlay />\n\t\t<SheetPrimitive.Content\n\t\t\tref={ref}\n\t\t\tclassName={cn(sheetVariants({ side }), className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t<SheetPrimitive.Close\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background\",\n\t\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out hover:opacity-100\",\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\t\"disabled:pointer-events-none\",\n\t\t\t\t)}\n\t\t\t>\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\tclassName=\"h-4 w-4\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<path d=\"M18 6 6 18\" />\n\t\t\t\t\t<path d=\"m6 6 12 12\" />\n\t\t\t\t</svg>\n\t\t\t\t<span className=\"sr-only\">Close</span>\n\t\t\t</SheetPrimitive.Close>\n\t\t</SheetPrimitive.Content>\n\t</SheetPortal>\n));\nSheetContent.displayName = \"SheetContent\";\n\n/**\n * Header container inside SheetContent; stacks title and description.\n * @returns A div with vertical rhythm.\n */\nfunction SheetHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\"flex flex-col space-y-2 text-center sm:text-left\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n/**\n * Footer container inside SheetContent; aligns action buttons.\n * @returns A div that stacks buttons on mobile and right-aligns on desktop.\n */\nfunction SheetFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n/** Accessible sheet title; Radix wires it to aria-labelledby automatically. */\nconst SheetTitle = React.forwardRef<\n\tReact.ComponentRef<typeof SheetPrimitive.Title>,\n\tReact.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Title\n\t\tref={ref}\n\t\tclassName={cn(\"text-lg font-semibold text-foreground\", className)}\n\t\t{...props}\n\t/>\n));\nSheetTitle.displayName = \"SheetTitle\";\n\n/** Accessible sheet description; Radix wires it to aria-describedby automatically. */\nconst SheetDescription = React.forwardRef<\n\tReact.ComponentRef<typeof SheetPrimitive.Description>,\n\tReact.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Description\n\t\tref={ref}\n\t\tclassName={cn(\"text-sm text-muted-foreground\", className)}\n\t\t{...props}\n\t/>\n));\nSheetDescription.displayName = \"SheetDescription\";\n\nexport {\n\tSheet,\n\tSheetPortal,\n\tSheetOverlay,\n\tSheetTrigger,\n\tSheetClose,\n\tSheetContent,\n\tSheetHeader,\n\tSheetFooter,\n\tSheetTitle,\n\tSheetDescription,\n};\n"]}
@@ -0,0 +1,2 @@
1
+ export { ShimmerProps_alias_1 as ShimmerProps } from './_tsup-dts-rollup.js';
2
+ export { Shimmer_alias_1 as Shimmer } from './_tsup-dts-rollup.js';
@@ -0,0 +1,39 @@
1
+ "use client";
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ function cn(...inputs) {
7
+ return twMerge(clsx(inputs));
8
+ }
9
+ function Shimmer({
10
+ width = "100%",
11
+ height = "1.5rem",
12
+ durationMs = 1500,
13
+ label = "Loading\u2026",
14
+ className
15
+ }) {
16
+ return /* @__PURE__ */ jsx(
17
+ "div",
18
+ {
19
+ role: "status",
20
+ "aria-label": label,
21
+ "aria-live": "polite",
22
+ className: cn(
23
+ // `motion-safe:` gates the pulse on `prefers-reduced-motion: no-preference` —
24
+ // users with reduce-motion get a static bar.
25
+ "motion-safe:animate-pulse rounded-md border border-foreground/[0.06] bg-muted",
26
+ className
27
+ ),
28
+ style: {
29
+ width,
30
+ height,
31
+ animationDuration: `${durationMs}ms`
32
+ }
33
+ }
34
+ );
35
+ }
36
+
37
+ export { Shimmer };
38
+ //# sourceMappingURL=shimmer.js.map
39
+ //# sourceMappingURL=shimmer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/ai/shimmer/shimmer.tsx"],"names":[],"mappings":";;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACkCA,SAAS,OAAA,CAAQ;AAAA,EAChB,KAAA,GAAQ,MAAA;AAAA,EACR,MAAA,GAAS,QAAA;AAAA,EACT,UAAA,GAAa,IAAA;AAAA,EACb,KAAA,GAAQ,eAAA;AAAA,EACR;AACD,CAAA,EAAiB;AAChB,EAAA,uBACC,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,IAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAY,KAAA;AAAA,MACZ,WAAA,EAAU,QAAA;AAAA,MACV,SAAA,EAAW,EAAA;AAAA;AAAA;AAAA,QAGV,+EAAA;AAAA,QACA;AAAA,OACD;AAAA,MACA,KAAA,EAAO;AAAA,QACN,KAAA;AAAA,QACA,MAAA;AAAA,QACA,iBAAA,EAAmB,GAAG,UAAU,CAAA,EAAA;AAAA;AACjC;AAAA,GACD;AAEF","file":"shimmer.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 * Single-line streaming placeholder. Used during the dead-time between\n * a user submitting a prompt and the first stream token arriving — a\n * gradient sweep across a flat bar that signals \"the model is thinking\n * but hasn't started speaking yet.\"\n *\n * Wider than `<Loading>` (which is a multi-row skeleton) and narrower\n * than `<Skeleton>` (which is a sized placeholder block); use Shimmer\n * for the conversation pane, Loading for whole-screen states, Skeleton\n * for arbitrary placeholder shapes.\n *\n * @example\n * {isStreaming && <Shimmer width=\"80%\" />}\n */\nexport interface ShimmerProps {\n\t/** CSS width — accepts any width value (e.g. `\"60%\"`, `\"24rem\"`). Defaults to full width. */\n\twidth?: string;\n\t/** Override the default 1.5rem height for taller streaming bars. */\n\theight?: string;\n\t/** Sweep duration in ms. Defaults to 1500. */\n\tdurationMs?: number;\n\t/** Accessible label announced to screen readers. */\n\tlabel?: string;\n\tclassName?: string;\n}\n\n/**\n * Render a streaming placeholder bar.\n *\n * Uses Tailwind's `animate-pulse` for the loading effect — same\n * approach as `<Skeleton>` so consumers don't need extra global CSS or\n * keyframes. The `durationMs` prop scales the pulse cycle via a CSS\n * variable so the animation stays in pulse's vertical-opacity family\n * rather than introducing a custom sweep keyframe (which would\n * conflict with React 19's stricter style-tag handling).\n *\n * @param props - Optional sizing + duration + label overrides.\n * @returns A pulsing placeholder bar.\n */\nfunction Shimmer({\n\twidth = \"100%\",\n\theight = \"1.5rem\",\n\tdurationMs = 1500,\n\tlabel = \"Loading…\",\n\tclassName,\n}: ShimmerProps) {\n\treturn (\n\t\t<div\n\t\t\trole=\"status\"\n\t\t\taria-label={label}\n\t\t\taria-live=\"polite\"\n\t\t\tclassName={cn(\n\t\t\t\t// `motion-safe:` gates the pulse on `prefers-reduced-motion: no-preference` —\n\t\t\t\t// users with reduce-motion get a static bar.\n\t\t\t\t\"motion-safe:animate-pulse rounded-md border border-foreground/[0.06] bg-muted\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tstyle={{\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\tanimationDuration: `${durationMs}ms`,\n\t\t\t}}\n\t\t/>\n\t);\n}\n\nexport { Shimmer };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/components/sidebar/sidebar.tsx"],"names":[],"mappings":"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","file":"sidebar.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 { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\ninterface SidebarContextValue {\n\t/** Current open/collapsed state. */\n\topen: boolean;\n\t/** Toggle or set open state. */\n\tsetOpen: (open: boolean) => void;\n}\n\nconst SidebarContext = React.createContext<SidebarContextValue | null>(null);\n\n/**\n * Reads sidebar state from context. Throws if used outside SidebarProvider.\n * @returns `{ open, setOpen }` bound to the nearest SidebarProvider.\n */\nfunction useSidebar(): SidebarContextValue {\n\tconst ctx = React.useContext(SidebarContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useSidebar must be used inside <SidebarProvider>\");\n\t}\n\treturn ctx;\n}\n\ninterface SidebarProviderProps {\n\t/** Controlled open state. */\n\topen?: boolean;\n\t/** Uncontrolled initial open state (defaults to true). */\n\tdefaultOpen?: boolean;\n\t/** Callback fired when open state changes. */\n\tonOpenChange?: (open: boolean) => void;\n\t/** Children — typically a Sidebar + app content sibling. */\n\tchildren: React.ReactNode;\n\t/** Extra class names on the provider wrapper. */\n\tclassName?: string;\n}\n\n/**\n * Hosts sidebar state. Wrap your app shell (Sidebar + main content) in this.\n * @returns A flex container with a SidebarContext provider.\n */\nfunction SidebarProvider({\n\topen: openProp,\n\tdefaultOpen = true,\n\tonOpenChange,\n\tchildren,\n\tclassName,\n}: SidebarProviderProps) {\n\tconst [internalOpen, setInternalOpen] = React.useState(defaultOpen);\n\tconst isControlled = openProp !== undefined;\n\tconst open = isControlled ? openProp : internalOpen;\n\n\tconst setOpen = React.useCallback(\n\t\t(next: boolean) => {\n\t\t\tif (!isControlled) {\n\t\t\t\tsetInternalOpen(next);\n\t\t\t}\n\t\t\tonOpenChange?.(next);\n\t\t},\n\t\t[isControlled, onOpenChange],\n\t);\n\n\tconst value = React.useMemo(() => ({ open, setOpen }), [open, setOpen]);\n\n\treturn (\n\t\t<SidebarContext.Provider value={value}>\n\t\t\t<div\n\t\t\t\tdata-state={open ? \"open\" : \"closed\"}\n\t\t\t\tclassName={cn(\"flex min-h-screen w-full\", className)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</SidebarContext.Provider>\n\t);\n}\nSidebarProvider.displayName = \"SidebarProvider\";\n\nconst sidebarVariants = cva(\n\tcn(\n\t\t\"flex h-full shrink-0 flex-col border-foreground/[0.08] border-r bg-background text-foreground\",\n\t\t\"transition-[width] duration-[var(--duration-normal,200ms)] ease-out\",\n\t),\n\t{\n\t\tvariants: {\n\t\t\tside: {\n\t\t\t\tleft: \"border-r\",\n\t\t\t\tright: \"order-last border-l border-r-0\",\n\t\t\t},\n\t\t\tstate: {\n\t\t\t\topen: \"w-64\",\n\t\t\t\tclosed: \"w-0 overflow-hidden border-r-0\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tside: \"left\",\n\t\t\tstate: \"open\",\n\t\t},\n\t},\n);\n\ninterface SidebarProps\n\textends React.HTMLAttributes<HTMLElement>,\n\t\tPick<VariantProps<typeof sidebarVariants>, \"side\"> {}\n\n/**\n * App-shell sidebar. Reads open state from SidebarProvider and animates width.\n * @returns An aside element that expands/collapses.\n */\nconst Sidebar = React.forwardRef<HTMLElement, SidebarProps>(\n\t({ className, side = \"left\", children, ...props }, ref) => {\n\t\tconst { open } = useSidebar();\n\t\treturn (\n\t\t\t<aside\n\t\t\t\tref={ref}\n\t\t\t\tdata-state={open ? \"open\" : \"closed\"}\n\t\t\t\taria-hidden={!open || undefined}\n\t\t\t\tinert={!open}\n\t\t\t\tclassName={cn(sidebarVariants({ side, state: open ? \"open\" : \"closed\" }), className)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</aside>\n\t\t);\n\t},\n);\nSidebar.displayName = \"Sidebar\";\n\ninterface SidebarTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n\t/** Render as the child element (Button, etc.) using Radix Slot. */\n\tasChild?: boolean;\n}\n\n/**\n * Toggles the sidebar open/closed. Renders a button by default; use asChild to style.\n * @returns A button that flips SidebarProvider state.\n */\nconst SidebarTrigger = React.forwardRef<HTMLButtonElement, SidebarTriggerProps>(\n\t({ asChild, className, onClick, \"aria-label\": ariaLabel, ...props }, ref) => {\n\t\tconst { open, setOpen } = useSidebar();\n\t\tconst Comp = asChild ? Slot : \"button\";\n\t\t// When asChild, prefer the consumer's aria-label (or visible text) — don't force ours.\n\t\tconst resolvedAriaLabel =\n\t\t\tariaLabel ?? (asChild ? undefined : open ? \"Collapse sidebar\" : \"Expand sidebar\");\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\ttype={asChild ? undefined : \"button\"}\n\t\t\t\taria-label={resolvedAriaLabel}\n\t\t\t\taria-expanded={open}\n\t\t\t\tonClick={(event: React.MouseEvent<HTMLElement>) => {\n\t\t\t\t\tonClick?.(event as React.MouseEvent<HTMLButtonElement>);\n\t\t\t\t\tif (!event.defaultPrevented) {\n\t\t\t\t\t\tsetOpen(!open);\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\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 text-muted-foreground\",\n\t\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out hover:bg-accent hover:text-accent-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\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{asChild ? null : (\n\t\t\t\t\t<>\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=\"h-4 w-4\"\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<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" />\n\t\t\t\t\t\t\t<line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t<span className=\"sr-only\">Toggle sidebar</span>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</Comp>\n\t\t);\n\t},\n);\nSidebarTrigger.displayName = \"SidebarTrigger\";\n\n/** Header container at the top of the sidebar. */\nconst SidebarHeader = 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 gap-[var(--gap-sm,0.5rem)] border-b border-b-foreground/[0.08] p-[var(--space-4,1rem)]\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nSidebarHeader.displayName = \"SidebarHeader\";\n\n/** Scrollable main area of the sidebar. */\nconst SidebarContent = 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-1 overflow-auto p-[var(--space-2,0.5rem)]\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nSidebarContent.displayName = \"SidebarContent\";\n\n/** Footer container at the bottom of the sidebar. */\nconst SidebarFooter = 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(\"mt-auto border-t border-t-foreground/[0.08] p-[var(--space-4,1rem)]\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nSidebarFooter.displayName = \"SidebarFooter\";\n\ninterface SidebarItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n\t/** Render as the child element (next/link, etc.) via Slot. */\n\tasChild?: boolean;\n\t/** Mark as the current/selected item. */\n\tactive?: boolean;\n}\n\n/**\n * Single selectable row inside SidebarContent. Compose icon + label in children.\n * @returns An accessible button (or Slot) styled as a sidebar row.\n */\nconst SidebarItem = React.forwardRef<HTMLButtonElement, SidebarItemProps>(\n\t({ asChild, active, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"button\";\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\ttype={asChild ? undefined : \"button\"}\n\t\t\t\taria-current={active ? \"page\" : undefined}\n\t\t\t\tdata-active={active ? \"\" : undefined}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"inline-flex w-full items-center gap-[var(--gap-sm,0.5rem)] rounded-md px-[var(--space-3,0.75rem)] py-[var(--space-2,0.5rem)] text-sm font-medium\",\n\t\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\t\"hover:bg-accent hover:text-accent-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\t\"data-[active]:bg-accent data-[active]:text-accent-foreground\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nSidebarItem.displayName = \"SidebarItem\";\n\nexport {\n\tSidebarProvider,\n\tSidebar,\n\tSidebarTrigger,\n\tSidebarHeader,\n\tSidebarContent,\n\tSidebarFooter,\n\tSidebarItem,\n\tuseSidebar,\n};\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/sidebar/sidebar.tsx"],"names":[],"mappings":"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","file":"sidebar.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 { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\ninterface SidebarContextValue {\n\t/** Current open/collapsed state. */\n\topen: boolean;\n\t/** Toggle or set open state. */\n\tsetOpen: (open: boolean) => void;\n}\n\nconst SidebarContext = React.createContext<SidebarContextValue | null>(null);\n\n/**\n * Reads sidebar state from context. Throws if used outside SidebarProvider.\n * @returns `{ open, setOpen }` bound to the nearest SidebarProvider.\n */\nfunction useSidebar(): SidebarContextValue {\n\tconst ctx = React.useContext(SidebarContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useSidebar must be used inside <SidebarProvider>\");\n\t}\n\treturn ctx;\n}\n\ninterface SidebarProviderProps {\n\t/** Controlled open state. */\n\topen?: boolean;\n\t/** Uncontrolled initial open state (defaults to true). */\n\tdefaultOpen?: boolean;\n\t/** Callback fired when open state changes. */\n\tonOpenChange?: (open: boolean) => void;\n\t/** Children — typically a Sidebar + app content sibling. */\n\tchildren: React.ReactNode;\n\t/** Extra class names on the provider wrapper. */\n\tclassName?: string;\n}\n\n/**\n * Hosts sidebar state. Wrap your app shell (Sidebar + main content) in this.\n * @returns A flex container with a SidebarContext provider.\n */\nfunction SidebarProvider({\n\topen: openProp,\n\tdefaultOpen = true,\n\tonOpenChange,\n\tchildren,\n\tclassName,\n}: SidebarProviderProps) {\n\tconst [internalOpen, setInternalOpen] = React.useState(defaultOpen);\n\tconst isControlled = openProp !== undefined;\n\tconst open = isControlled ? openProp : internalOpen;\n\n\tconst setOpen = React.useCallback(\n\t\t(next: boolean) => {\n\t\t\tif (!isControlled) {\n\t\t\t\tsetInternalOpen(next);\n\t\t\t}\n\t\t\tonOpenChange?.(next);\n\t\t},\n\t\t[isControlled, onOpenChange],\n\t);\n\n\tconst value = React.useMemo(() => ({ open, setOpen }), [open, setOpen]);\n\n\treturn (\n\t\t<SidebarContext.Provider value={value}>\n\t\t\t<div\n\t\t\t\tdata-state={open ? \"open\" : \"closed\"}\n\t\t\t\tclassName={cn(\"flex min-h-screen w-full\", className)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</SidebarContext.Provider>\n\t);\n}\nSidebarProvider.displayName = \"SidebarProvider\";\n\nconst sidebarVariants = cva(\n\tcn(\n\t\t\"flex h-full shrink-0 flex-col border-foreground/[0.08] border-r bg-background text-foreground\",\n\t\t\"transition-[width] duration-[var(--duration-normal,200ms)] ease-out\",\n\t),\n\t{\n\t\tvariants: {\n\t\t\tside: {\n\t\t\t\tleft: \"border-r\",\n\t\t\t\tright: \"order-last border-l border-r-0\",\n\t\t\t},\n\t\t\tstate: {\n\t\t\t\topen: \"w-64\",\n\t\t\t\tclosed: \"w-0 overflow-hidden border-r-0\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tside: \"left\",\n\t\t\tstate: \"open\",\n\t\t},\n\t},\n);\n\ninterface SidebarProps\n\textends React.HTMLAttributes<HTMLElement>,\n\t\tPick<VariantProps<typeof sidebarVariants>, \"side\"> {}\n\n/**\n * App-shell sidebar. Reads open state from SidebarProvider and animates width.\n * @returns An aside element that expands/collapses.\n */\nconst Sidebar = React.forwardRef<HTMLElement, SidebarProps>(\n\t({ className, side = \"left\", children, ...props }, ref) => {\n\t\tconst { open } = useSidebar();\n\t\treturn (\n\t\t\t<aside\n\t\t\t\tref={ref}\n\t\t\t\tdata-state={open ? \"open\" : \"closed\"}\n\t\t\t\taria-hidden={!open || undefined}\n\t\t\t\tinert={!open}\n\t\t\t\tclassName={cn(sidebarVariants({ side, state: open ? \"open\" : \"closed\" }), className)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</aside>\n\t\t);\n\t},\n);\nSidebar.displayName = \"Sidebar\";\n\ninterface SidebarTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n\t/** Render as the child element (Button, etc.) using Radix Slot. */\n\tasChild?: boolean;\n}\n\n/**\n * Toggles the sidebar open/closed. Renders a button by default; use asChild to style.\n * @returns A button that flips SidebarProvider state.\n */\nconst SidebarTrigger = React.forwardRef<HTMLButtonElement, SidebarTriggerProps>(\n\t({ asChild, className, onClick, \"aria-label\": ariaLabel, ...props }, ref) => {\n\t\tconst { open, setOpen } = useSidebar();\n\t\tconst Comp = asChild ? Slot : \"button\";\n\t\t// When asChild, prefer the consumer's aria-label (or visible text) — don't force ours.\n\t\tconst resolvedAriaLabel =\n\t\t\tariaLabel ?? (asChild ? undefined : open ? \"Collapse sidebar\" : \"Expand sidebar\");\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\ttype={asChild ? undefined : \"button\"}\n\t\t\t\taria-label={resolvedAriaLabel}\n\t\t\t\taria-expanded={open}\n\t\t\t\tonClick={(event: React.MouseEvent<HTMLElement>) => {\n\t\t\t\t\tonClick?.(event as React.MouseEvent<HTMLButtonElement>);\n\t\t\t\t\tif (!event.defaultPrevented) {\n\t\t\t\t\t\tsetOpen(!open);\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\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 text-muted-foreground\",\n\t\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out hover:bg-accent hover:text-accent-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\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{asChild ? null : (\n\t\t\t\t\t<>\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=\"h-4 w-4\"\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<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" />\n\t\t\t\t\t\t\t<line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t<span className=\"sr-only\">Toggle sidebar</span>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</Comp>\n\t\t);\n\t},\n);\nSidebarTrigger.displayName = \"SidebarTrigger\";\n\n/** Header container at the top of the sidebar. */\nconst SidebarHeader = 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 gap-[var(--gap-sm,0.5rem)] border-b border-b-foreground/[0.08] p-[var(--space-4,1rem)]\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nSidebarHeader.displayName = \"SidebarHeader\";\n\n/** Scrollable main area of the sidebar. */\nconst SidebarContent = 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-1 overflow-auto p-[var(--space-2,0.5rem)]\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nSidebarContent.displayName = \"SidebarContent\";\n\n/** Footer container at the bottom of the sidebar. */\nconst SidebarFooter = 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(\"mt-auto border-t border-t-foreground/[0.08] p-[var(--space-4,1rem)]\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nSidebarFooter.displayName = \"SidebarFooter\";\n\ninterface SidebarItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n\t/** Render as the child element (next/link, etc.) via Slot. */\n\tasChild?: boolean;\n\t/** Mark as the current/selected item. */\n\tactive?: boolean;\n}\n\n/**\n * Single selectable row inside SidebarContent. Compose icon + label in children.\n * @returns An accessible button (or Slot) styled as a sidebar row.\n */\nconst SidebarItem = React.forwardRef<HTMLButtonElement, SidebarItemProps>(\n\t({ asChild, active, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"button\";\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\ttype={asChild ? undefined : \"button\"}\n\t\t\t\taria-current={active ? \"page\" : undefined}\n\t\t\t\tdata-active={active ? \"\" : undefined}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"inline-flex w-full items-center gap-[var(--gap-sm,0.5rem)] rounded-md px-[var(--space-3,0.75rem)] py-[var(--space-2,0.5rem)] text-sm font-medium\",\n\t\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\t\"hover:bg-accent hover:text-accent-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\t\"data-[active]:bg-accent data-[active]:text-accent-foreground\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nSidebarItem.displayName = \"SidebarItem\";\n\nexport {\n\tSidebarProvider,\n\tSidebar,\n\tSidebarTrigger,\n\tSidebarHeader,\n\tSidebarContent,\n\tSidebarFooter,\n\tSidebarItem,\n\tuseSidebar,\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/skeleton/skeleton.tsx"],"names":[],"mappings":";;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACFA,SAAS,QAAA,CAAS,EAAE,SAAA,EAAW,GAAG,OAAM,EAAyC;AAChF,EAAA,uBACC,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,mEAAA,EAAqE,SAAS,CAAA;AAAA,MAC3F,GAAG;AAAA;AAAA,GACL;AAEF","file":"skeleton.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 * A placeholder shimmer element shown while content is loading.\n * Pair with explicit width/height via className.\n * @returns A div with pulsing muted background\n */\nfunction Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\"animate-pulse rounded-md border border-foreground/[0.06] bg-muted\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport { Skeleton };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/skeleton/skeleton.tsx"],"names":[],"mappings":";;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACFA,SAAS,QAAA,CAAS,EAAE,SAAA,EAAW,GAAG,OAAM,EAAyC;AAChF,EAAA,uBACC,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,mEAAA,EAAqE,SAAS,CAAA;AAAA,MAC3F,GAAG;AAAA;AAAA,GACL;AAEF","file":"skeleton.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 * A placeholder shimmer element shown while content is loading.\n * Pair with explicit width/height via className.\n * @returns A div with pulsing muted background\n */\nfunction Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\"animate-pulse rounded-md border border-foreground/[0.06] bg-muted\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport { Skeleton };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/slider/slider.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACiBA,IAAM,MAAA,GAAe,iBAGnB,CAAC,EAAE,WAAW,WAAA,EAAa,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAChD,EAAA,MAAM,SAAS,KAAA,CAAM,KAAA,IAAS,KAAA,CAAM,YAAA,IAAgB,CAAC,CAAC,CAAA;AACtD,EAAA,MAAM,SAAA,GAAY,MAAM,YAAY,CAAA;AACpC,EAAA,MAAM,cAAA,GAAiB,MAAM,iBAAiB,CAAA;AAE9C,EAAA,IACC,OAAO,OAAA,KAAY,WAAA,IACnB,OAAA,CAAQ,GAAA,EAAK,QAAA,KAAa,YAAA,IAC1B,WAAA,IACA,WAAA,CAAY,MAAA,KAAW,MAAA,CAAO,MAAA,EAC7B;AACD,IAAA,OAAA,CAAQ,IAAA;AAAA,MACP,CAAA,4BAAA,EAA+B,WAAA,CAAY,MAAM,CAAA,+BAAA,EAAkC,OAAO,MAAM,CAAA,uEAAA;AAAA,KAEjG;AAAA,EACD;AAEA,EAAA,uBACC,IAAA;AAAA,IAAiB,eAAA,CAAA,IAAA;AAAA,IAAhB;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,0DAAA,EAA4D,SAAS,CAAA;AAAA,MAClF,GAAG,KAAA;AAAA,MAEJ,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAiB,eAAA,CAAA,KAAA,EAAhB,EAAsB,SAAA,EAAU,oGAAA,EAChC,8BAAiB,eAAA,CAAA,KAAA,EAAhB,EAAsB,SAAA,EAAU,4BAAA,EAA6B,CAAA,EAC/D,CAAA;AAAA,QACC,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM;AACrB,UAAA,MAAM,QAAA,GAAW,cAAc,CAAC,CAAA;AAChC,UAAA,MAAM,QAAA,GACL,MAAA,CAAO,MAAA,KAAW,CAAA,GACf,YACA,SAAA,GACC,CAAA,EAAG,SAAS,CAAA,EAAA,EAAK,CAAA,GAAI,CAAC,CAAA,IAAA,EAAO,MAAA,CAAO,MAAM,CAAA,CAAA,CAAA,GAC1C,MAAA;AACL,UAAA,uBACC,GAAA;AAAA,YAAiB,eAAA,CAAA,KAAA;AAAA,YAAhB;AAAA,cAGA,cAAY,QAAA,IAAY,QAAA;AAAA,cACxB,iBAAA,EACC,QAAA,IAAY,QAAA,GAAW,MAAA,GAAY,cAAA;AAAA,cAEpC,SAAA,EAAW,EAAA;AAAA,gBACV,kEAAA;AAAA,gBACA,2EAAA;AAAA,gBACA,iCAAA;AAAA,gBACA,qGAAA;AAAA,gBACA;AAAA;AACD,aAAA;AAAA,YAXK;AAAA,WAYN;AAAA,QAEF,CAAC;AAAA;AAAA;AAAA,GACF;AAEF,CAAC;AACD,MAAA,CAAO,WAAA,GAAc,QAAA","file":"slider.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 SliderPrimitive from \"@radix-ui/react-slider\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n// Local ambient — components run in browsers where bundlers (Next, Vite, tsup)\n// replace `process.env.NODE_ENV` at build time. Avoids pulling @types/node into\n// the components package just for one dev-mode warning.\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined;\n\ninterface SliderProps\n\textends React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> {\n\t/**\n\t * Per-thumb accessible labels. When the slider has multiple thumbs, pass\n\t * one entry per thumb (e.g. [\"Minimum\", \"Maximum\"]). For a single-thumb\n\t * slider, the Root's `aria-label` / `aria-labelledby` is mirrored onto\n\t * the thumb automatically — pass `thumbLabels` only when those defaults\n\t * are insufficient.\n\t */\n\tthumbLabels?: string[];\n}\n\n/**\n * A range input with one or more draggable thumbs.\n * Built on Radix UI Slider with keyboard controls (arrows, Home, End, PageUp/Down).\n */\nconst Slider = React.forwardRef<\n\tReact.ComponentRef<typeof SliderPrimitive.Root>,\n\tSliderProps\n>(({ className, thumbLabels, ...props }, ref) => {\n\tconst values = props.value ?? props.defaultValue ?? [0];\n\tconst rootLabel = props[\"aria-label\"];\n\tconst rootLabelledBy = props[\"aria-labelledby\"];\n\n\tif (\n\t\ttypeof process !== \"undefined\" &&\n\t\tprocess.env?.NODE_ENV !== \"production\" &&\n\t\tthumbLabels &&\n\t\tthumbLabels.length !== values.length\n\t) {\n\t\tconsole.warn(\n\t\t\t`Slider: thumbLabels.length (${thumbLabels.length}) does not match value.length (${values.length}). ` +\n\t\t\t\t`Missing labels fall back to indexed names; extra labels are ignored.`,\n\t\t);\n\t}\n\n\treturn (\n\t\t<SliderPrimitive.Root\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"relative flex w-full touch-none select-none items-center\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<SliderPrimitive.Track className=\"relative h-2 w-full grow overflow-hidden rounded-full border border-foreground/[0.08] bg-secondary\">\n\t\t\t\t<SliderPrimitive.Range className=\"absolute h-full bg-primary\" />\n\t\t\t</SliderPrimitive.Track>\n\t\t\t{values.map((_, i) => {\n\t\t\t\tconst explicit = thumbLabels?.[i];\n\t\t\t\tconst fallback =\n\t\t\t\t\tvalues.length === 1\n\t\t\t\t\t\t? rootLabel\n\t\t\t\t\t\t: rootLabel\n\t\t\t\t\t\t\t? `${rootLabel} (${i + 1} of ${values.length})`\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\treturn (\n\t\t\t\t\t<SliderPrimitive.Thumb\n\t\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: Radix renders one thumb per value by index\n\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\taria-label={explicit ?? fallback}\n\t\t\t\t\t\taria-labelledby={\n\t\t\t\t\t\t\texplicit || fallback ? undefined : rootLabelledBy\n\t\t\t\t\t\t}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"block h-5 w-5 rounded-full border-2 border-primary bg-background\",\n\t\t\t\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out shadow-md\",\n\t\t\t\t\t\t\t\"hover:shadow-lg hover:scale-110\",\n\t\t\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\t\t\t\"disabled:pointer-events-none disabled:opacity-50\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t})}\n\t\t</SliderPrimitive.Root>\n\t);\n});\nSlider.displayName = \"Slider\";\n\nexport type { SliderProps };\n\nexport { Slider };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/slider/slider.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACiBA,IAAM,MAAA,GAAe,iBAGnB,CAAC,EAAE,WAAW,WAAA,EAAa,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAChD,EAAA,MAAM,SAAS,KAAA,CAAM,KAAA,IAAS,KAAA,CAAM,YAAA,IAAgB,CAAC,CAAC,CAAA;AACtD,EAAA,MAAM,SAAA,GAAY,MAAM,YAAY,CAAA;AACpC,EAAA,MAAM,cAAA,GAAiB,MAAM,iBAAiB,CAAA;AAE9C,EAAA,IACC,OAAO,OAAA,KAAY,WAAA,IACnB,OAAA,CAAQ,GAAA,EAAK,QAAA,KAAa,YAAA,IAC1B,WAAA,IACA,WAAA,CAAY,MAAA,KAAW,MAAA,CAAO,MAAA,EAC7B;AACD,IAAA,OAAA,CAAQ,IAAA;AAAA,MACP,CAAA,4BAAA,EAA+B,WAAA,CAAY,MAAM,CAAA,+BAAA,EAAkC,OAAO,MAAM,CAAA,uEAAA;AAAA,KAEjG;AAAA,EACD;AAEA,EAAA,uBACC,IAAA;AAAA,IAAiB,eAAA,CAAA,IAAA;AAAA,IAAhB;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,0DAAA,EAA4D,SAAS,CAAA;AAAA,MAClF,GAAG,KAAA;AAAA,MAEJ,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAiB,eAAA,CAAA,KAAA,EAAhB,EAAsB,SAAA,EAAU,oGAAA,EAChC,8BAAiB,eAAA,CAAA,KAAA,EAAhB,EAAsB,SAAA,EAAU,4BAAA,EAA6B,CAAA,EAC/D,CAAA;AAAA,QACC,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM;AACrB,UAAA,MAAM,QAAA,GAAW,cAAc,CAAC,CAAA;AAChC,UAAA,MAAM,QAAA,GACL,MAAA,CAAO,MAAA,KAAW,CAAA,GACf,YACA,SAAA,GACC,CAAA,EAAG,SAAS,CAAA,EAAA,EAAK,CAAA,GAAI,CAAC,CAAA,IAAA,EAAO,MAAA,CAAO,MAAM,CAAA,CAAA,CAAA,GAC1C,MAAA;AACL,UAAA,uBACC,GAAA;AAAA,YAAiB,eAAA,CAAA,KAAA;AAAA,YAAhB;AAAA,cAGA,cAAY,QAAA,IAAY,QAAA;AAAA,cACxB,iBAAA,EACC,QAAA,IAAY,QAAA,GAAW,MAAA,GAAY,cAAA;AAAA,cAEpC,SAAA,EAAW,EAAA;AAAA,gBACV,kEAAA;AAAA,gBACA,2EAAA;AAAA,gBACA,iCAAA;AAAA,gBACA,qGAAA;AAAA,gBACA;AAAA;AACD,aAAA;AAAA,YAXK;AAAA,WAYN;AAAA,QAEF,CAAC;AAAA;AAAA;AAAA,GACF;AAEF,CAAC;AACD,MAAA,CAAO,WAAA,GAAc,QAAA","file":"slider.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 SliderPrimitive from \"@radix-ui/react-slider\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n// Local ambient — components run in browsers where bundlers (Next, Vite, tsup)\n// replace `process.env.NODE_ENV` at build time. Avoids pulling @types/node into\n// the components package just for one dev-mode warning.\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined;\n\ninterface SliderProps\n\textends React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> {\n\t/**\n\t * Per-thumb accessible labels. When the slider has multiple thumbs, pass\n\t * one entry per thumb (e.g. [\"Minimum\", \"Maximum\"]). For a single-thumb\n\t * slider, the Root's `aria-label` / `aria-labelledby` is mirrored onto\n\t * the thumb automatically — pass `thumbLabels` only when those defaults\n\t * are insufficient.\n\t */\n\tthumbLabels?: string[];\n}\n\n/**\n * A range input with one or more draggable thumbs.\n * Built on Radix UI Slider with keyboard controls (arrows, Home, End, PageUp/Down).\n */\nconst Slider = React.forwardRef<\n\tReact.ComponentRef<typeof SliderPrimitive.Root>,\n\tSliderProps\n>(({ className, thumbLabels, ...props }, ref) => {\n\tconst values = props.value ?? props.defaultValue ?? [0];\n\tconst rootLabel = props[\"aria-label\"];\n\tconst rootLabelledBy = props[\"aria-labelledby\"];\n\n\tif (\n\t\ttypeof process !== \"undefined\" &&\n\t\tprocess.env?.NODE_ENV !== \"production\" &&\n\t\tthumbLabels &&\n\t\tthumbLabels.length !== values.length\n\t) {\n\t\tconsole.warn(\n\t\t\t`Slider: thumbLabels.length (${thumbLabels.length}) does not match value.length (${values.length}). ` +\n\t\t\t\t`Missing labels fall back to indexed names; extra labels are ignored.`,\n\t\t);\n\t}\n\n\treturn (\n\t\t<SliderPrimitive.Root\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"relative flex w-full touch-none select-none items-center\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<SliderPrimitive.Track className=\"relative h-2 w-full grow overflow-hidden rounded-full border border-foreground/[0.08] bg-secondary\">\n\t\t\t\t<SliderPrimitive.Range className=\"absolute h-full bg-primary\" />\n\t\t\t</SliderPrimitive.Track>\n\t\t\t{values.map((_, i) => {\n\t\t\t\tconst explicit = thumbLabels?.[i];\n\t\t\t\tconst fallback =\n\t\t\t\t\tvalues.length === 1\n\t\t\t\t\t\t? rootLabel\n\t\t\t\t\t\t: rootLabel\n\t\t\t\t\t\t\t? `${rootLabel} (${i + 1} of ${values.length})`\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\treturn (\n\t\t\t\t\t<SliderPrimitive.Thumb\n\t\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: Radix renders one thumb per value by index\n\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\taria-label={explicit ?? fallback}\n\t\t\t\t\t\taria-labelledby={\n\t\t\t\t\t\t\texplicit || fallback ? undefined : rootLabelledBy\n\t\t\t\t\t\t}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"block h-5 w-5 rounded-full border-2 border-primary bg-background\",\n\t\t\t\t\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out shadow-md\",\n\t\t\t\t\t\t\t\"hover:shadow-lg hover:scale-110\",\n\t\t\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\t\t\t\"disabled:pointer-events-none disabled:opacity-50\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t})}\n\t\t</SliderPrimitive.Root>\n\t);\n});\nSlider.displayName = \"Slider\";\n\nexport type { SliderProps };\n\nexport { Slider };\n"]}
@@ -0,0 +1,3 @@
1
+ export { SourcesProps_alias_1 as SourcesProps } from './_tsup-dts-rollup.js';
2
+ export { SourceRef_alias_1 as SourceRef } from './_tsup-dts-rollup.js';
3
+ export { Sources_alias_1 as Sources } from './_tsup-dts-rollup.js';