@hex-core/components 1.8.1 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/dist/_tsup-dts-rollup.d.ts +855 -18
  2. package/dist/accordion.js.map +1 -1
  3. package/dist/alert-dialog.js.map +1 -1
  4. package/dist/alert.js.map +1 -1
  5. package/dist/arc.js.map +1 -1
  6. package/dist/attachment.js.map +1 -1
  7. package/dist/audio-player.js.map +1 -1
  8. package/dist/audio-waveform.js.map +1 -1
  9. package/dist/auth-forgot-password.d.ts +2 -0
  10. package/dist/auth-forgot-password.js +400 -0
  11. package/dist/auth-forgot-password.js.map +1 -0
  12. package/dist/auth-reset-password.d.ts +2 -0
  13. package/dist/auth-reset-password.js +323 -0
  14. package/dist/auth-reset-password.js.map +1 -0
  15. package/dist/auth-sign-in-split.d.ts +3 -0
  16. package/dist/auth-sign-in-split.js +443 -0
  17. package/dist/auth-sign-in-split.js.map +1 -0
  18. package/dist/auth-sign-up-card.d.ts +3 -0
  19. package/dist/auth-sign-up-card.js +590 -0
  20. package/dist/auth-sign-up-card.js.map +1 -0
  21. package/dist/auth-verify-email.d.ts +2 -0
  22. package/dist/auth-verify-email.js +339 -0
  23. package/dist/auth-verify-email.js.map +1 -0
  24. package/dist/auth-verify-otp.d.ts +2 -0
  25. package/dist/auth-verify-otp.js +349 -0
  26. package/dist/auth-verify-otp.js.map +1 -0
  27. package/dist/avatar.js.map +1 -1
  28. package/dist/badge.js.map +1 -1
  29. package/dist/branch.d.ts +2 -0
  30. package/dist/branch.js +136 -0
  31. package/dist/branch.js.map +1 -0
  32. package/dist/breadcrumb.js.map +1 -1
  33. package/dist/button.js.map +1 -1
  34. package/dist/calendar.js.map +1 -1
  35. package/dist/canvas.js.map +1 -1
  36. package/dist/card.js.map +1 -1
  37. package/dist/chain-of-thought.d.ts +3 -0
  38. package/dist/chain-of-thought.js +119 -0
  39. package/dist/chain-of-thought.js.map +1 -0
  40. package/dist/checkbox.js.map +1 -1
  41. package/dist/chord.js.map +1 -1
  42. package/dist/citation.js.map +1 -1
  43. package/dist/cloze.js.map +1 -1
  44. package/dist/cluster.js.map +1 -1
  45. package/dist/code-block-copy.js.map +1 -1
  46. package/dist/code-block.js.map +1 -1
  47. package/dist/color-picker.js.map +1 -1
  48. package/dist/combobox.js.map +1 -1
  49. package/dist/command.js.map +1 -1
  50. package/dist/compare-table.js.map +1 -1
  51. package/dist/composer.js.map +1 -1
  52. package/dist/container.js.map +1 -1
  53. package/dist/context-menu.js.map +1 -1
  54. package/dist/conversation.d.ts +3 -0
  55. package/dist/conversation.js +358 -0
  56. package/dist/conversation.js.map +1 -0
  57. package/dist/data-table.js.map +1 -1
  58. package/dist/date-picker.js.map +1 -1
  59. package/dist/deck.js.map +1 -1
  60. package/dist/dendrogram.js.map +1 -1
  61. package/dist/diagram.js.map +1 -1
  62. package/dist/dialog.js.map +1 -1
  63. package/dist/drawer.js.map +1 -1
  64. package/dist/dropdown-menu.js.map +1 -1
  65. package/dist/dropzone.js.map +1 -1
  66. package/dist/empty.js.map +1 -1
  67. package/dist/error-state.js.map +1 -1
  68. package/dist/file-tree.js.map +1 -1
  69. package/dist/flashcard.js.map +1 -1
  70. package/dist/flowchart.js.map +1 -1
  71. package/dist/form.js.map +1 -1
  72. package/dist/funnel.js.map +1 -1
  73. package/dist/gantt.js.map +1 -1
  74. package/dist/grid.js.map +1 -1
  75. package/dist/hover-card.js.map +1 -1
  76. package/dist/image-occlusion.js.map +1 -1
  77. package/dist/index.d.ts +40 -0
  78. package/dist/index.js +4839 -2813
  79. package/dist/index.js.map +1 -1
  80. package/dist/inline-citation.d.ts +2 -0
  81. package/dist/inline-citation.js +108 -0
  82. package/dist/inline-citation.js.map +1 -0
  83. package/dist/input-otp.js.map +1 -1
  84. package/dist/input.js.map +1 -1
  85. package/dist/label.js.map +1 -1
  86. package/dist/loading-indicator.js.map +1 -1
  87. package/dist/loading.js.map +1 -1
  88. package/dist/markdown.d.ts +1 -0
  89. package/dist/markdown.js +784 -4
  90. package/dist/markdown.js.map +1 -1
  91. package/dist/matrix.js.map +1 -1
  92. package/dist/menubar.js.map +1 -1
  93. package/dist/message-actions.js.map +1 -1
  94. package/dist/message-list.js.map +1 -1
  95. package/dist/message.js.map +1 -1
  96. package/dist/mind-map.js.map +1 -1
  97. package/dist/multi-combobox.js.map +1 -1
  98. package/dist/navigation-menu.js.map +1 -1
  99. package/dist/org-chart.js.map +1 -1
  100. package/dist/pagination.js.map +1 -1
  101. package/dist/plan.d.ts +3 -0
  102. package/dist/plan.js +183 -0
  103. package/dist/plan.js.map +1 -0
  104. package/dist/popover.js.map +1 -1
  105. package/dist/progress.js.map +1 -1
  106. package/dist/pyramid.js.map +1 -1
  107. package/dist/quiz.js.map +1 -1
  108. package/dist/radio-group.js.map +1 -1
  109. package/dist/reasoning.js.map +1 -1
  110. package/dist/resizable.js.map +1 -1
  111. package/dist/sankey.js.map +1 -1
  112. package/dist/schemas.d.ts +8 -0
  113. package/dist/schemas.js +774 -17
  114. package/dist/schemas.js.map +1 -1
  115. package/dist/scroll-area.js.map +1 -1
  116. package/dist/select.js.map +1 -1
  117. package/dist/separator.js.map +1 -1
  118. package/dist/sequence.js.map +1 -1
  119. package/dist/sheet.js.map +1 -1
  120. package/dist/shimmer.d.ts +2 -0
  121. package/dist/shimmer.js +39 -0
  122. package/dist/shimmer.js.map +1 -0
  123. package/dist/sidebar.js.map +1 -1
  124. package/dist/skeleton.js.map +1 -1
  125. package/dist/slider.js.map +1 -1
  126. package/dist/sources.d.ts +3 -0
  127. package/dist/sources.js +164 -0
  128. package/dist/sources.js.map +1 -0
  129. package/dist/spaced-repetition.js.map +1 -1
  130. package/dist/spacer.js.map +1 -1
  131. package/dist/speech-recognition.js.map +1 -1
  132. package/dist/stack.js.map +1 -1
  133. package/dist/stepper.js.map +1 -1
  134. package/dist/suggestion.js.map +1 -1
  135. package/dist/sunburst.js.map +1 -1
  136. package/dist/switch.js.map +1 -1
  137. package/dist/table.js.map +1 -1
  138. package/dist/tabs.js.map +1 -1
  139. package/dist/tag.js.map +1 -1
  140. package/dist/task.d.ts +3 -0
  141. package/dist/task.js +189 -0
  142. package/dist/task.js.map +1 -0
  143. package/dist/terminal.js +11 -0
  144. package/dist/terminal.js.map +1 -1
  145. package/dist/textarea.js.map +1 -1
  146. package/dist/time-axis.js.map +1 -1
  147. package/dist/time-picker.js.map +1 -1
  148. package/dist/timeline.js.map +1 -1
  149. package/dist/toggle-group.js.map +1 -1
  150. package/dist/toggle.js.map +1 -1
  151. package/dist/tool-call.js +5 -6
  152. package/dist/tool-call.js.map +1 -1
  153. package/dist/toolbar.js.map +1 -1
  154. package/dist/tooltip.js.map +1 -1
  155. package/dist/tree-map.js.map +1 -1
  156. package/dist/tree.js.map +1 -1
  157. package/dist/venn.js.map +1 -1
  158. package/package.json +9 -4
package/dist/gantt.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/artifacts/gantt/gantt.tsx"],"names":[],"mappings":"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","file":"gantt.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 * Gantt chart — tasks as horizontal bars across a time axis, with\n * optional dependency arrows and progress fills. Pure SVG; no heavy\n * peer dependency.\n *\n * Distinct from TimeAxis (point events) and Sequence (actor messages):\n * Gantt encodes DURATION (start → end) per task and supports task-to-\n * task dependency arrows.\n *\n * @example\n * <Gantt\n * tasks={[\n * { id: \"design\", label: \"Design\", start: \"2025-01-01\", end: \"2025-01-15\", progress: 1 },\n * { id: \"build\", label: \"Build\", start: \"2025-01-10\", end: \"2025-02-20\", progress: 0.6, dependencies: [\"design\"] },\n * { id: \"ship\", label: \"Ship\", start: \"2025-02-15\", end: \"2025-02-28\", dependencies: [\"build\"] },\n * ]}\n * />\n */\nexport type GanttTask = {\n\tid: string;\n\tlabel: string;\n\tstart: Date | string | number;\n\tend: Date | string | number;\n\t/** Optional progress 0..1; renders as a filled portion of the bar. */\n\tprogress?: number;\n\t/** Optional list of task ids this task depends on; arrow drawn from each. */\n\tdependencies?: string[];\n};\n\nexport interface GanttProps extends Omit<React.SVGAttributes<SVGSVGElement>, \"children\"> {\n\t/** Tasks in display order (rows top-to-bottom). */\n\ttasks: GanttTask[];\n\t/** Pixel width of the rendered SVG. Default 800. */\n\twidth?: number;\n\t/** Pixel height of each task row. Default 32. */\n\trowHeight?: number;\n\t/** Pixel reserved on the left for task labels. Default 140. */\n\tlabelMargin?: number;\n\t/** Number of axis ticks to show. Default 6. */\n\ttickCount?: number;\n\t/** Fired when a task bar is clicked. */\n\tonTaskClick?: (task: GanttTask) => void;\n}\n\ninterface LaidOutTask {\n\ttask: GanttTask;\n\trowIndex: number;\n\tx: number;\n\ty: number;\n\tw: number;\n\th: number;\n\tprogressW: number;\n}\n\ninterface DepArrow {\n\tfrom: { x: number; y: number };\n\tto: { x: number; y: number };\n\tid: string;\n}\n\ninterface AxisTick {\n\tx: number;\n\tlabel: string;\n}\n\nconst HEADER_HEIGHT = 40;\nconst ROW_PADDING = 6;\n\nfunction Gantt({\n\ttasks,\n\twidth = 800,\n\trowHeight = 32,\n\tlabelMargin = 140,\n\ttickCount = 6,\n\tonTaskClick,\n\tclassName,\n\t...rest\n}: GanttProps) {\n\tconst laidOut = React.useMemo(\n\t\t() => layout(tasks, width, rowHeight, labelMargin, tickCount),\n\t\t[tasks, width, rowHeight, labelMargin, tickCount],\n\t);\n\n\tconst totalHeight = HEADER_HEIGHT + tasks.length * rowHeight + ROW_PADDING;\n\tconst desc = `Gantt with ${tasks.length} task${tasks.length === 1 ? \"\" : \"s\"}, range ${laidOut.startLabel} to ${laidOut.endLabel}`;\n\t// Per-instance arrowhead marker id keeps two <Gantt> on a page\n\t// from sharing a <defs> id.\n\tconst arrowId = React.useId().replace(/:/g, \"-\");\n\n\treturn (\n\t\t<svg\n\t\t\t{...rest}\n\t\t\tdata-hex-gantt\n\t\t\trole=\"img\"\n\t\t\twidth={width}\n\t\t\theight={totalHeight}\n\t\t\tviewBox={`0 0 ${width} ${totalHeight}`}\n\t\t\tclassName={cn(\"block\", className)}\n\t\t>\n\t\t\t<title>Gantt chart</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-gantt-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=\"5\"\n\t\t\t\t\tmarkerHeight=\"5\"\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(--muted-foreground))\" />\n\t\t\t\t</marker>\n\t\t\t</defs>\n\t\t\t{/* Axis header */}\n\t\t\t<g data-hex-gantt-axis>\n\t\t\t\t<line\n\t\t\t\t\tx1={labelMargin}\n\t\t\t\t\tx2={width - 16}\n\t\t\t\t\ty1={HEADER_HEIGHT - 8}\n\t\t\t\t\ty2={HEADER_HEIGHT - 8}\n\t\t\t\t\tstroke=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t/>\n\t\t\t\t{laidOut.ticks.map((t, i) => (\n\t\t\t\t\t<g key={`tick-${i}`} data-hex-gantt-tick>\n\t\t\t\t\t\t<line\n\t\t\t\t\t\t\tx1={t.x}\n\t\t\t\t\t\t\tx2={t.x}\n\t\t\t\t\t\t\ty1={HEADER_HEIGHT - 8}\n\t\t\t\t\t\t\ty2={totalHeight - 4}\n\t\t\t\t\t\t\tstroke=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\t\t\tstrokeOpacity={0.15}\n\t\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx={t.x}\n\t\t\t\t\t\t\ty={HEADER_HEIGHT - 14}\n\t\t\t\t\t\t\ttextAnchor=\"middle\"\n\t\t\t\t\t\t\tfontSize={10}\n\t\t\t\t\t\t\tfill=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t.label}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t</g>\n\t\t\t\t))}\n\t\t\t</g>\n\t\t\t{/* Row labels */}\n\t\t\t<g data-hex-gantt-labels>\n\t\t\t\t{laidOut.tasks.map((t) => (\n\t\t\t\t\t<text\n\t\t\t\t\t\tkey={`label-${t.task.id}`}\n\t\t\t\t\t\tx={labelMargin - 8}\n\t\t\t\t\t\ty={t.y + t.h / 2}\n\t\t\t\t\t\tdy=\"0.35em\"\n\t\t\t\t\t\ttextAnchor=\"end\"\n\t\t\t\t\t\tfontSize={11}\n\t\t\t\t\t\tfill=\"hsl(var(--foreground))\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{t.task.label}\n\t\t\t\t\t</text>\n\t\t\t\t))}\n\t\t\t</g>\n\t\t\t{/* Dependency arrows: elbow-and-jog routing — when the target\n\t\t\t task starts before (or near) the source's right edge, route\n\t\t\t out past the source first to avoid drawing through its bar. */}\n\t\t\t<g data-hex-gantt-deps fill=\"none\">\n\t\t\t\t{laidOut.deps.map((d) => {\n\t\t\t\t\tconst ELBOW = 8;\n\t\t\t\t\tconst needsJog = d.to.x < d.from.x + ELBOW;\n\t\t\t\t\tconst path = needsJog\n\t\t\t\t\t\t? `M${d.from.x},${d.from.y} L${d.from.x + ELBOW},${d.from.y} L${d.from.x + ELBOW},${d.to.y} L${d.to.x},${d.to.y}`\n\t\t\t\t\t\t: `M${d.from.x},${d.from.y} L${(d.from.x + d.to.x) / 2},${d.from.y} L${(d.from.x + d.to.x) / 2},${d.to.y} L${d.to.x},${d.to.y}`;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tkey={d.id}\n\t\t\t\t\t\t\tdata-hex-gantt-dep\n\t\t\t\t\t\t\td={path}\n\t\t\t\t\t\t\tstroke=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\t\t\tstrokeOpacity={0.55}\n\t\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t\t\tmarkerEnd={`url(#hex-gantt-arrow-${arrowId})`}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</g>\n\t\t\t{/* Task bars */}\n\t\t\t<g data-hex-gantt-tasks>\n\t\t\t\t{laidOut.tasks.map((t) => {\n\t\t\t\t\tconst interactive = Boolean(onTaskClick);\n\t\t\t\t\tconst handleActivate = () => onTaskClick?.(t.task);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<g\n\t\t\t\t\t\t\tkey={t.task.id}\n\t\t\t\t\t\t\tdata-hex-gantt-task\n\t\t\t\t\t\t\tdata-row={t.rowIndex}\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? `${t.task.label}, ${formatDate(toDate(t.task.start))} to ${formatDate(toDate(t.task.end))}${t.task.progress != null ? `, ${Math.round((t.task.progress ?? 0) * 100)}% complete` : \"\"}`\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<rect\n\t\t\t\t\t\t\t\tx={t.x}\n\t\t\t\t\t\t\t\ty={t.y}\n\t\t\t\t\t\t\t\twidth={Math.max(2, t.w)}\n\t\t\t\t\t\t\t\theight={t.h}\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(--primary))\"\n\t\t\t\t\t\t\t\tfillOpacity={0.25}\n\t\t\t\t\t\t\t\tstroke=\"hsl(var(--primary))\"\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{t.progressW > 0 ? (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\t\t\t\tx={t.x}\n\t\t\t\t\t\t\t\t\t\ty={t.y}\n\t\t\t\t\t\t\t\t\t\twidth={t.progressW}\n\t\t\t\t\t\t\t\t\t\theight={t.h}\n\t\t\t\t\t\t\t\t\t\trx={4}\n\t\t\t\t\t\t\t\t\t\try={4}\n\t\t\t\t\t\t\t\t\t\tfill=\"hsl(var(--primary))\"\n\t\t\t\t\t\t\t\t\t\tfillOpacity={0.7}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t{/* Hard right-edge line keeps the progress boundary visible for\n\t\t\t\t\t\t\t\t\t color-blind viewers and on low-contrast themes. Skipped at\n\t\t\t\t\t\t\t\t\t 100% progress where it overlaps the bar's own border. */}\n\t\t\t\t\t\t\t\t\t{t.progressW < t.w - 0.5 ? (\n\t\t\t\t\t\t\t\t\t\t<line\n\t\t\t\t\t\t\t\t\t\t\tx1={t.x + t.progressW}\n\t\t\t\t\t\t\t\t\t\t\tx2={t.x + t.progressW}\n\t\t\t\t\t\t\t\t\t\t\ty1={t.y}\n\t\t\t\t\t\t\t\t\t\t\ty2={t.y + t.h}\n\t\t\t\t\t\t\t\t\t\t\tstroke=\"hsl(var(--primary))\"\n\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t</>\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\ttasks: GanttTask[],\n\twidth: number,\n\trowHeight: number,\n\tlabelMargin: number,\n\ttickCount: number,\n): {\n\ttasks: LaidOutTask[];\n\tdeps: DepArrow[];\n\tticks: AxisTick[];\n\tstartLabel: string;\n\tendLabel: string;\n} {\n\tif (tasks.length === 0) {\n\t\treturn { tasks: [], deps: [], ticks: [], startLabel: \"—\", endLabel: \"—\" };\n\t}\n\n\tconst axisLeft = labelMargin;\n\tconst axisRight = width - 16;\n\tconst usable = axisRight - axisLeft;\n\n\t// Drop NaN-bearing endpoints so the axis range stays finite. Tasks with\n\t// either bound un-parseable get rendered with their own zero-width\n\t// fallback below; we still want them in the row layout, just clipped to\n\t// the axis edges.\n\tconst allTimes = tasks\n\t\t.flatMap((t) => [toDate(t.start).getTime(), toDate(t.end).getTime()])\n\t\t.filter((t) => Number.isFinite(t));\n\tif (allTimes.length === 0) {\n\t\treturn { tasks: [], deps: [], ticks: [], startLabel: \"—\", endLabel: \"—\" };\n\t}\n\tconst minTs = Math.min(...allTimes);\n\tconst maxTs = Math.max(...allTimes);\n\tconst span = Math.max(1, maxTs - minTs);\n\n\tconst tToX = (t: number) => axisLeft + ((t - minTs) / span) * usable;\n\n\tconst laidOutTasks: LaidOutTask[] = tasks.map((task, i) => {\n\t\tconst startTs = toDate(task.start).getTime();\n\t\tconst endTs = toDate(task.end).getTime();\n\t\tconst x = tToX(startTs);\n\t\tconst w = Math.max(0, tToX(endTs) - x);\n\t\tconst y = HEADER_HEIGHT + i * rowHeight + ROW_PADDING / 2;\n\t\tconst h = rowHeight - ROW_PADDING;\n\t\tconst progress = clamp01(task.progress ?? 0);\n\t\treturn {\n\t\t\ttask,\n\t\t\trowIndex: i,\n\t\t\tx,\n\t\t\ty,\n\t\t\tw,\n\t\t\th,\n\t\t\tprogressW: w * progress,\n\t\t};\n\t});\n\n\tconst byId = new Map(laidOutTasks.map((t) => [t.task.id, t]));\n\tconst deps: DepArrow[] = [];\n\tlaidOutTasks.forEach((t) => {\n\t\t(t.task.dependencies ?? []).forEach((depId, k) => {\n\t\t\tconst from = byId.get(depId);\n\t\t\tif (!from) return;\n\t\t\tdeps.push({\n\t\t\t\tfrom: { x: from.x + from.w, y: from.y + from.h / 2 },\n\t\t\t\tto: { x: t.x, y: t.y + t.h / 2 },\n\t\t\t\tid: `${depId}-${t.task.id}-${k}`,\n\t\t\t});\n\t\t});\n\t});\n\n\t// Generate ticks, then dedupe consecutive identical labels — at year-scale\n\t// or month-scale spans the formatter often emits the same string twice\n\t// (e.g. two ticks both inside January render as \"2025-01\"). Blanking the\n\t// duplicate keeps the gridline but drops the noisy repeated text.\n\tconst rawTicks: AxisTick[] = [];\n\tfor (let i = 0; i < tickCount; i++) {\n\t\tconst ts = minTs + (i / Math.max(1, tickCount - 1)) * span;\n\t\trawTicks.push({ x: tToX(ts), label: formatTick(new Date(ts), span) });\n\t}\n\tconst ticks: AxisTick[] = rawTicks.map((t, i) => ({\n\t\tx: t.x,\n\t\tlabel: i > 0 && rawTicks[i - 1]?.label === t.label ? \"\" : t.label,\n\t}));\n\n\treturn {\n\t\ttasks: laidOutTasks,\n\t\tdeps,\n\t\tticks,\n\t\tstartLabel: formatDate(new Date(minTs)),\n\t\tendLabel: formatDate(new Date(maxTs)),\n\t};\n}\n\nfunction toDate(v: Date | string | number): Date {\n\tif (v instanceof Date) return v;\n\tif (typeof v === \"number\") return new Date(v);\n\treturn new Date(v);\n}\n\nfunction clamp01(v: number): number {\n\treturn v < 0 ? 0 : v > 1 ? 1 : v;\n}\n\nfunction formatDate(d: Date): string {\n\tif (Number.isNaN(d.getTime())) return \"—\";\n\treturn d.toISOString().slice(0, 10);\n}\n\nfunction formatTick(d: Date, spanMs: number): string {\n\tif (Number.isNaN(d.getTime())) return \"—\";\n\tconst ONE_DAY = 24 * 60 * 60 * 1000;\n\t// Switch to MM-DD up to ~3 months — at 30 days the original threshold\n\t// produced \"2025-01\" / \"2025-01\" duplicates for ticks landing in the\n\t// same month. MM-DD scales to ~90 days before adjacent ticks merge.\n\tif (spanMs <= 90 * ONE_DAY) return d.toISOString().slice(5, 10); // MM-DD\n\tif (spanMs <= 730 * ONE_DAY) return d.toISOString().slice(0, 7); // YYYY-MM\n\treturn String(d.getUTCFullYear());\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 { Gantt };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/artifacts/gantt/gantt.tsx"],"names":[],"mappings":";;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;AC4DA,IAAM,aAAA,GAAgB,EAAA;AACtB,IAAM,WAAA,GAAc,CAAA;AAEpB,SAAS,KAAA,CAAM;AAAA,EACd,KAAA;AAAA,EACA,KAAA,GAAQ,GAAA;AAAA,EACR,SAAA,GAAY,EAAA;AAAA,EACZ,WAAA,GAAc,GAAA;AAAA,EACd,SAAA,GAAY,CAAA;AAAA,EACZ,WAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAG;AACJ,CAAA,EAAe;AACd,EAAA,MAAM,OAAA,GAAgB,KAAA,CAAA,OAAA;AAAA,IACrB,MAAM,MAAA,CAAO,KAAA,EAAO,KAAA,EAAO,SAAA,EAAW,aAAa,SAAS,CAAA;AAAA,IAC5D,CAAC,KAAA,EAAO,KAAA,EAAO,SAAA,EAAW,aAAa,SAAS;AAAA,GACjD;AAEA,EAAA,MAAM,WAAA,GAAc,aAAA,GAAgB,KAAA,CAAM,MAAA,GAAS,SAAA,GAAY,WAAA;AAC/D,EAAA,MAAM,IAAA,GAAO,CAAA,WAAA,EAAc,KAAA,CAAM,MAAM,QAAQ,KAAA,CAAM,MAAA,KAAW,CAAA,GAAI,EAAA,GAAK,GAAG,CAAA,QAAA,EAAW,OAAA,CAAQ,UAAU,CAAA,IAAA,EAAO,QAAQ,QAAQ,CAAA,CAAA;AAGhI,EAAA,MAAM,OAAA,GAAgB,KAAA,CAAA,KAAA,EAAM,CAAE,OAAA,CAAQ,MAAM,GAAG,CAAA;AAE/C,EAAA,uBACC,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAG,IAAA;AAAA,MACJ,gBAAA,EAAc,IAAA;AAAA,MACd,IAAA,EAAK,KAAA;AAAA,MACL,KAAA;AAAA,MACA,MAAA,EAAQ,WAAA;AAAA,MACR,OAAA,EAAS,CAAA,IAAA,EAAO,KAAK,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA;AAAA,MACpC,SAAA,EAAW,EAAA,CAAG,OAAA,EAAS,SAAS,CAAA;AAAA,MAEhC,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,WAAM,QAAA,EAAA,aAAA,EAAW,CAAA;AAAA,wBAClB,GAAA,CAAC,UAAM,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,4BACX,MAAA,EAAA,EACA,QAAA,kBAAA,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACA,EAAA,EAAI,mBAAmB,OAAO,CAAA,CAAA;AAAA,YAC9B,OAAA,EAAQ,WAAA;AAAA,YACR,IAAA,EAAK,IAAA;AAAA,YACL,IAAA,EAAK,GAAA;AAAA,YACL,WAAA,EAAY,GAAA;AAAA,YACZ,YAAA,EAAa,GAAA;AAAA,YACb,MAAA,EAAO,oBAAA;AAAA,YAEP,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,uBAAA,EAAwB,MAAK,8BAAA,EAA+B;AAAA;AAAA,SACrE,EACD,CAAA;AAAA,wBAEA,IAAA,CAAC,GAAA,EAAA,EAAE,qBAAA,EAAmB,IAAA,EACrB,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACA,EAAA,EAAI,WAAA;AAAA,cACJ,IAAI,KAAA,GAAQ,EAAA;AAAA,cACZ,IAAI,aAAA,GAAgB,CAAA;AAAA,cACpB,IAAI,aAAA,GAAgB,CAAA;AAAA,cACpB,MAAA,EAAO,8BAAA;AAAA,cACP,WAAA,EAAa;AAAA;AAAA,WACd;AAAA,UACC,OAAA,CAAQ,MAAM,GAAA,CAAI,CAAC,GAAG,CAAA,qBACtB,IAAA,CAAC,GAAA,EAAA,EAAoB,qBAAA,EAAmB,IAAA,EACvC,QAAA,EAAA;AAAA,4BAAA,GAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACA,IAAI,CAAA,CAAE,CAAA;AAAA,gBACN,IAAI,CAAA,CAAE,CAAA;AAAA,gBACN,IAAI,aAAA,GAAgB,CAAA;AAAA,gBACpB,IAAI,WAAA,GAAc,CAAA;AAAA,gBAClB,MAAA,EAAO,8BAAA;AAAA,gBACP,aAAA,EAAe,IAAA;AAAA,gBACf,WAAA,EAAa;AAAA;AAAA,aACd;AAAA,4BACA,GAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACA,GAAG,CAAA,CAAE,CAAA;AAAA,gBACL,GAAG,aAAA,GAAgB,EAAA;AAAA,gBACnB,UAAA,EAAW,QAAA;AAAA,gBACX,QAAA,EAAU,EAAA;AAAA,gBACV,IAAA,EAAK,8BAAA;AAAA,gBAEJ,QAAA,EAAA,CAAA,CAAE;AAAA;AAAA;AACJ,WAAA,EAAA,EAlBO,CAAA,KAAA,EAAQ,CAAC,CAAA,CAmBjB,CACA;AAAA,SAAA,EACF,CAAA;AAAA,wBAEA,GAAA,CAAC,OAAE,uBAAA,EAAqB,IAAA,EACtB,kBAAQ,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,qBACnB,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YAEA,GAAG,WAAA,GAAc,CAAA;AAAA,YACjB,CAAA,EAAG,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAA,GAAI,CAAA;AAAA,YACf,EAAA,EAAG,QAAA;AAAA,YACH,UAAA,EAAW,KAAA;AAAA,YACX,QAAA,EAAU,EAAA;AAAA,YACV,IAAA,EAAK,wBAAA;AAAA,YAEJ,YAAE,IAAA,CAAK;AAAA,WAAA;AAAA,UARH,CAAA,MAAA,EAAS,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AAAA,SAUxB,CAAA,EACF,CAAA;AAAA,wBAIA,GAAA,CAAC,GAAA,EAAA,EAAE,qBAAA,EAAmB,IAAA,EAAC,IAAA,EAAK,QAC1B,QAAA,EAAA,OAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM;AACxB,UAAA,MAAM,KAAA,GAAQ,CAAA;AACd,UAAA,MAAM,WAAW,CAAA,CAAE,EAAA,CAAG,CAAA,GAAI,CAAA,CAAE,KAAK,CAAA,GAAI,KAAA;AACrC,UAAA,MAAM,OAAO,QAAA,GACV,CAAA,CAAA,EAAI,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,CAAA,EAAI,CAAA,CAAE,IAAA,CAAK,CAAC,KAAK,CAAA,CAAE,IAAA,CAAK,CAAA,GAAI,KAAK,IAAI,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAA,EAAK,EAAE,IAAA,CAAK,CAAA,GAAI,KAAK,CAAA,CAAA,EAAI,EAAE,EAAA,CAAG,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,GAAG,CAAC,CAAA,CAAA,EAAI,CAAA,CAAE,EAAA,CAAG,CAAC,CAAA,CAAA,GAC7G,CAAA,CAAA,EAAI,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,CAAA,EAAI,CAAA,CAAE,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,IAAA,CAAK,CAAA,GAAI,CAAA,CAAE,GAAG,CAAA,IAAK,CAAC,CAAA,CAAA,EAAI,CAAA,CAAE,KAAK,CAAC,CAAA,EAAA,EAAA,CAAM,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,CAAE,EAAA,CAAG,CAAA,IAAK,CAAC,IAAI,CAAA,CAAE,EAAA,CAAG,CAAC,CAAA,EAAA,EAAK,EAAE,EAAA,CAAG,CAAC,CAAA,CAAA,EAAI,CAAA,CAAE,GAAG,CAAC,CAAA,CAAA;AAC9H,UAAA,uBACC,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cAEA,oBAAA,EAAkB,IAAA;AAAA,cAClB,CAAA,EAAG,IAAA;AAAA,cACH,MAAA,EAAO,8BAAA;AAAA,cACP,aAAA,EAAe,IAAA;AAAA,cACf,WAAA,EAAa,CAAA;AAAA,cACb,SAAA,EAAW,wBAAwB,OAAO,CAAA,CAAA;AAAA,aAAA;AAAA,YANrC,CAAA,CAAE;AAAA,WAOR;AAAA,QAEF,CAAC,CAAA,EACF,CAAA;AAAA,wBAEA,GAAA,CAAC,OAAE,sBAAA,EAAoB,IAAA,EACrB,kBAAQ,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM;AACzB,UAAA,MAAM,WAAA,GAAc,QAAQ,WAAW,CAAA;AACvC,UAAA,MAAM,cAAA,GAAiB,MAAM,WAAA,GAAc,CAAA,CAAE,IAAI,CAAA;AACjD,UAAA,uBACC,IAAA;AAAA,YAAC,GAAA;AAAA,YAAA;AAAA,cAEA,qBAAA,EAAmB,IAAA;AAAA,cACnB,YAAU,CAAA,CAAE,QAAA;AAAA,cACZ,IAAA,EAAM,cAAc,QAAA,GAAW,MAAA;AAAA,cAC/B,QAAA,EAAU,cAAc,CAAA,GAAI,MAAA;AAAA,cAC5B,cACC,WAAA,GACG,CAAA,EAAG,CAAA,CAAE,IAAA,CAAK,KAAK,CAAA,EAAA,EAAK,UAAA,CAAW,MAAA,CAAO,CAAA,CAAE,KAAK,KAAK,CAAC,CAAC,CAAA,IAAA,EAAO,UAAA,CAAW,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAC,CAAA,EAAG,CAAA,CAAE,IAAA,CAAK,QAAA,IAAY,OAAO,CAAA,EAAA,EAAK,IAAA,CAAK,KAAA,CAAA,CAAO,CAAA,CAAE,KAAK,QAAA,IAAY,CAAA,IAAK,GAAG,CAAC,CAAA,UAAA,CAAA,GAAe,EAAE,CAAA,CAAA,GACpL,MAAA;AAAA,cAEJ,KAAA,EAAO,WAAA,GAAc,EAAE,MAAA,EAAQ,WAAU,GAAI,MAAA;AAAA,cAC7C,OAAA,EAAS,cAAc,cAAA,GAAiB,MAAA;AAAA,cACxC,WAAW,WAAA,GAAc,CAAC,MAAM,aAAA,CAAc,CAAA,EAAG,cAAc,CAAA,GAAI,MAAA;AAAA,cAEnE,QAAA,EAAA;AAAA,gCAAA,GAAA;AAAA,kBAAC,MAAA;AAAA,kBAAA;AAAA,oBACA,GAAG,CAAA,CAAE,CAAA;AAAA,oBACL,GAAG,CAAA,CAAE,CAAA;AAAA,oBACL,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,EAAE,CAAC,CAAA;AAAA,oBACtB,QAAQ,CAAA,CAAE,CAAA;AAAA,oBACV,EAAA,EAAI,CAAA;AAAA,oBACJ,EAAA,EAAI,CAAA;AAAA,oBACJ,IAAA,EAAK,qBAAA;AAAA,oBACL,WAAA,EAAa,IAAA;AAAA,oBACb,MAAA,EAAO,qBAAA;AAAA,oBACP,WAAA,EAAa;AAAA;AAAA,iBACd;AAAA,gBACC,CAAA,CAAE,SAAA,GAAY,CAAA,mBACd,IAAA,CAAA,QAAA,EAAA,EACC,QAAA,EAAA;AAAA,kCAAA,GAAA;AAAA,oBAAC,MAAA;AAAA,oBAAA;AAAA,sBACA,GAAG,CAAA,CAAE,CAAA;AAAA,sBACL,GAAG,CAAA,CAAE,CAAA;AAAA,sBACL,OAAO,CAAA,CAAE,SAAA;AAAA,sBACT,QAAQ,CAAA,CAAE,CAAA;AAAA,sBACV,EAAA,EAAI,CAAA;AAAA,sBACJ,EAAA,EAAI,CAAA;AAAA,sBACJ,IAAA,EAAK,qBAAA;AAAA,sBACL,WAAA,EAAa;AAAA;AAAA,mBACd;AAAA,kBAIC,CAAA,CAAE,SAAA,GAAY,CAAA,CAAE,CAAA,GAAI,GAAA,mBACpB,GAAA;AAAA,oBAAC,MAAA;AAAA,oBAAA;AAAA,sBACA,EAAA,EAAI,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,SAAA;AAAA,sBACZ,EAAA,EAAI,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,SAAA;AAAA,sBACZ,IAAI,CAAA,CAAE,CAAA;AAAA,sBACN,EAAA,EAAI,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAA;AAAA,sBACZ,MAAA,EAAO,qBAAA;AAAA,sBACP,WAAA,EAAa;AAAA;AAAA,mBACd,GACG;AAAA,iBAAA,EACL,CAAA,GACG;AAAA;AAAA,aAAA;AAAA,YApDC,EAAE,IAAA,CAAK;AAAA,WAqDb;AAAA,QAEF,CAAC,CAAA,EACF;AAAA;AAAA;AAAA,GACD;AAEF;AAEA,SAAS,MAAA,CACR,KAAA,EACA,KAAA,EACA,SAAA,EACA,aACA,SAAA,EAOC;AACD,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACvB,IAAA,OAAO,EAAE,KAAA,EAAO,EAAC,EAAG,IAAA,EAAM,EAAC,EAAG,KAAA,EAAO,EAAC,EAAG,UAAA,EAAY,QAAA,EAAK,UAAU,QAAA,EAAI;AAAA,EACzE;AAEA,EAAA,MAAM,QAAA,GAAW,WAAA;AACjB,EAAA,MAAM,YAAY,KAAA,GAAQ,EAAA;AAC1B,EAAA,MAAM,SAAS,SAAA,GAAY,QAAA;AAM3B,EAAA,MAAM,QAAA,GAAW,KAAA,CACf,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAC,MAAA,CAAO,CAAA,CAAE,KAAK,CAAA,CAAE,OAAA,EAAQ,EAAG,MAAA,CAAO,EAAE,GAAG,CAAA,CAAE,OAAA,EAAS,CAAC,CAAA,CACnE,MAAA,CAAO,CAAC,CAAA,KAAM,MAAA,CAAO,QAAA,CAAS,CAAC,CAAC,CAAA;AAClC,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,OAAO,EAAE,KAAA,EAAO,EAAC,EAAG,IAAA,EAAM,EAAC,EAAG,KAAA,EAAO,EAAC,EAAG,UAAA,EAAY,QAAA,EAAK,UAAU,QAAA,EAAI;AAAA,EACzE;AACA,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAG,QAAQ,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAG,QAAQ,CAAA;AAClC,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,KAAK,CAAA;AAEtC,EAAA,MAAM,OAAO,CAAC,CAAA,KAAc,QAAA,GAAA,CAAa,CAAA,GAAI,SAAS,IAAA,GAAQ,MAAA;AAE9D,EAAA,MAAM,YAAA,GAA8B,KAAA,CAAM,GAAA,CAAI,CAAC,MAAM,CAAA,KAAM;AAC1D,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,KAAK,EAAE,OAAA,EAAQ;AAC3C,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,GAAG,EAAE,OAAA,EAAQ;AACvC,IAAA,MAAM,CAAA,GAAI,KAAK,OAAO,CAAA;AACtB,IAAA,MAAM,IAAI,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,KAAK,IAAI,CAAC,CAAA;AACrC,IAAA,MAAM,CAAA,GAAI,aAAA,GAAgB,CAAA,GAAI,SAAA,GAAY,WAAA,GAAc,CAAA;AACxD,IAAA,MAAM,IAAI,SAAA,GAAY,WAAA;AACtB,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,IAAA,CAAK,QAAA,IAAY,CAAC,CAAA;AAC3C,IAAA,OAAO;AAAA,MACN,IAAA;AAAA,MACA,QAAA,EAAU,CAAA;AAAA,MACV,CAAA;AAAA,MACA,CAAA;AAAA,MACA,CAAA;AAAA,MACA,CAAA;AAAA,MACA,WAAW,CAAA,GAAI;AAAA,KAChB;AAAA,EACD,CAAC,CAAA;AAED,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,IAAA,CAAK,EAAA,EAAI,CAAC,CAAC,CAAC,CAAA;AAC5D,EAAA,MAAM,OAAmB,EAAC;AAC1B,EAAA,YAAA,CAAa,OAAA,CAAQ,CAAC,CAAA,KAAM;AAC3B,IAAA,CAAC,CAAA,CAAE,KAAK,YAAA,IAAgB,IAAI,OAAA,CAAQ,CAAC,OAAO,CAAA,KAAM;AACjD,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AAC3B,MAAA,IAAI,CAAC,IAAA,EAAM;AACX,MAAA,IAAA,CAAK,IAAA,CAAK;AAAA,QACT,IAAA,EAAM,EAAE,CAAA,EAAG,IAAA,CAAK,CAAA,GAAI,IAAA,CAAK,CAAA,EAAG,CAAA,EAAG,IAAA,CAAK,CAAA,GAAI,IAAA,CAAK,CAAA,GAAI,CAAA,EAAE;AAAA,QACnD,EAAA,EAAI,EAAE,CAAA,EAAG,CAAA,CAAE,CAAA,EAAG,GAAG,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAA,GAAI,CAAA,EAAE;AAAA,QAC/B,EAAA,EAAI,GAAG,KAAK,CAAA,CAAA,EAAI,EAAE,IAAA,CAAK,EAAE,IAAI,CAAC,CAAA;AAAA,OAC9B,CAAA;AAAA,IACF,CAAC,CAAA;AAAA,EACF,CAAC,CAAA;AAMD,EAAA,MAAM,WAAuB,EAAC;AAC9B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,EAAW,CAAA,EAAA,EAAK;AACnC,IAAA,MAAM,EAAA,GAAK,QAAS,CAAA,GAAI,IAAA,CAAK,IAAI,CAAA,EAAG,SAAA,GAAY,CAAC,CAAA,GAAK,IAAA;AACtD,IAAA,QAAA,CAAS,IAAA,CAAK,EAAE,CAAA,EAAG,IAAA,CAAK,EAAE,CAAA,EAAG,KAAA,EAAO,UAAA,CAAW,IAAI,IAAA,CAAK,EAAE,CAAA,EAAG,IAAI,GAAG,CAAA;AAAA,EACrE;AACA,EAAA,MAAM,KAAA,GAAoB,QAAA,CAAS,GAAA,CAAI,CAAC,GAAG,CAAA,MAAO;AAAA,IACjD,GAAG,CAAA,CAAE,CAAA;AAAA,IACL,KAAA,EAAO,CAAA,GAAI,CAAA,IAAK,QAAA,CAAS,CAAA,GAAI,CAAC,CAAA,EAAG,KAAA,KAAU,CAAA,CAAE,KAAA,GAAQ,EAAA,GAAK,CAAA,CAAE;AAAA,GAC7D,CAAE,CAAA;AAEF,EAAA,OAAO;AAAA,IACN,KAAA,EAAO,YAAA;AAAA,IACP,IAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAA,EAAY,UAAA,CAAW,IAAI,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,IACtC,QAAA,EAAU,UAAA,CAAW,IAAI,IAAA,CAAK,KAAK,CAAC;AAAA,GACrC;AACD;AAEA,SAAS,OAAO,CAAA,EAAiC;AAChD,EAAA,IAAI,CAAA,YAAa,MAAM,OAAO,CAAA;AAC9B,EAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,IAAI,KAAK,CAAC,CAAA;AAC5C,EAAA,OAAO,IAAI,KAAK,CAAC,CAAA;AAClB;AAEA,SAAS,QAAQ,CAAA,EAAmB;AACnC,EAAA,OAAO,CAAA,GAAI,CAAA,GAAI,CAAA,GAAI,CAAA,GAAI,IAAI,CAAA,GAAI,CAAA;AAChC;AAEA,SAAS,WAAW,CAAA,EAAiB;AACpC,EAAA,IAAI,OAAO,KAAA,CAAM,CAAA,CAAE,OAAA,EAAS,GAAG,OAAO,QAAA;AACtC,EAAA,OAAO,CAAA,CAAE,WAAA,EAAY,CAAE,KAAA,CAAM,GAAG,EAAE,CAAA;AACnC;AAEA,SAAS,UAAA,CAAW,GAAS,MAAA,EAAwB;AACpD,EAAA,IAAI,OAAO,KAAA,CAAM,CAAA,CAAE,OAAA,EAAS,GAAG,OAAO,QAAA;AACtC,EAAA,MAAM,OAAA,GAAU,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAI/B,EAAA,IAAI,MAAA,IAAU,KAAK,OAAA,EAAS,OAAO,EAAE,WAAA,EAAY,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC9D,EAAA,IAAI,MAAA,IAAU,MAAM,OAAA,EAAS,OAAO,EAAE,WAAA,EAAY,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AAC9D,EAAA,OAAO,MAAA,CAAO,CAAA,CAAE,cAAA,EAAgB,CAAA;AACjC;AAEA,SAAS,aAAA,CAAc,GAAwB,EAAA,EAAsB;AACpE,EAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,OAAA,IAAW,CAAA,CAAE,QAAQ,GAAA,EAAK;AACvC,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,EAAA,EAAG;AAAA,EACJ;AACD","file":"gantt.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 * Gantt chart — tasks as horizontal bars across a time axis, with\n * optional dependency arrows and progress fills. Pure SVG; no heavy\n * peer dependency.\n *\n * Distinct from TimeAxis (point events) and Sequence (actor messages):\n * Gantt encodes DURATION (start → end) per task and supports task-to-\n * task dependency arrows.\n *\n * @example\n * <Gantt\n * tasks={[\n * { id: \"design\", label: \"Design\", start: \"2025-01-01\", end: \"2025-01-15\", progress: 1 },\n * { id: \"build\", label: \"Build\", start: \"2025-01-10\", end: \"2025-02-20\", progress: 0.6, dependencies: [\"design\"] },\n * { id: \"ship\", label: \"Ship\", start: \"2025-02-15\", end: \"2025-02-28\", dependencies: [\"build\"] },\n * ]}\n * />\n */\nexport type GanttTask = {\n\tid: string;\n\tlabel: string;\n\tstart: Date | string | number;\n\tend: Date | string | number;\n\t/** Optional progress 0..1; renders as a filled portion of the bar. */\n\tprogress?: number;\n\t/** Optional list of task ids this task depends on; arrow drawn from each. */\n\tdependencies?: string[];\n};\n\nexport interface GanttProps extends Omit<React.SVGAttributes<SVGSVGElement>, \"children\"> {\n\t/** Tasks in display order (rows top-to-bottom). */\n\ttasks: GanttTask[];\n\t/** Pixel width of the rendered SVG. Default 800. */\n\twidth?: number;\n\t/** Pixel height of each task row. Default 32. */\n\trowHeight?: number;\n\t/** Pixel reserved on the left for task labels. Default 140. */\n\tlabelMargin?: number;\n\t/** Number of axis ticks to show. Default 6. */\n\ttickCount?: number;\n\t/** Fired when a task bar is clicked. */\n\tonTaskClick?: (task: GanttTask) => void;\n}\n\ninterface LaidOutTask {\n\ttask: GanttTask;\n\trowIndex: number;\n\tx: number;\n\ty: number;\n\tw: number;\n\th: number;\n\tprogressW: number;\n}\n\ninterface DepArrow {\n\tfrom: { x: number; y: number };\n\tto: { x: number; y: number };\n\tid: string;\n}\n\ninterface AxisTick {\n\tx: number;\n\tlabel: string;\n}\n\nconst HEADER_HEIGHT = 40;\nconst ROW_PADDING = 6;\n\nfunction Gantt({\n\ttasks,\n\twidth = 800,\n\trowHeight = 32,\n\tlabelMargin = 140,\n\ttickCount = 6,\n\tonTaskClick,\n\tclassName,\n\t...rest\n}: GanttProps) {\n\tconst laidOut = React.useMemo(\n\t\t() => layout(tasks, width, rowHeight, labelMargin, tickCount),\n\t\t[tasks, width, rowHeight, labelMargin, tickCount],\n\t);\n\n\tconst totalHeight = HEADER_HEIGHT + tasks.length * rowHeight + ROW_PADDING;\n\tconst desc = `Gantt with ${tasks.length} task${tasks.length === 1 ? \"\" : \"s\"}, range ${laidOut.startLabel} to ${laidOut.endLabel}`;\n\t// Per-instance arrowhead marker id keeps two <Gantt> on a page\n\t// from sharing a <defs> id.\n\tconst arrowId = React.useId().replace(/:/g, \"-\");\n\n\treturn (\n\t\t<svg\n\t\t\t{...rest}\n\t\t\tdata-hex-gantt\n\t\t\trole=\"img\"\n\t\t\twidth={width}\n\t\t\theight={totalHeight}\n\t\t\tviewBox={`0 0 ${width} ${totalHeight}`}\n\t\t\tclassName={cn(\"block\", className)}\n\t\t>\n\t\t\t<title>Gantt chart</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-gantt-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=\"5\"\n\t\t\t\t\tmarkerHeight=\"5\"\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(--muted-foreground))\" />\n\t\t\t\t</marker>\n\t\t\t</defs>\n\t\t\t{/* Axis header */}\n\t\t\t<g data-hex-gantt-axis>\n\t\t\t\t<line\n\t\t\t\t\tx1={labelMargin}\n\t\t\t\t\tx2={width - 16}\n\t\t\t\t\ty1={HEADER_HEIGHT - 8}\n\t\t\t\t\ty2={HEADER_HEIGHT - 8}\n\t\t\t\t\tstroke=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t/>\n\t\t\t\t{laidOut.ticks.map((t, i) => (\n\t\t\t\t\t<g key={`tick-${i}`} data-hex-gantt-tick>\n\t\t\t\t\t\t<line\n\t\t\t\t\t\t\tx1={t.x}\n\t\t\t\t\t\t\tx2={t.x}\n\t\t\t\t\t\t\ty1={HEADER_HEIGHT - 8}\n\t\t\t\t\t\t\ty2={totalHeight - 4}\n\t\t\t\t\t\t\tstroke=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\t\t\tstrokeOpacity={0.15}\n\t\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx={t.x}\n\t\t\t\t\t\t\ty={HEADER_HEIGHT - 14}\n\t\t\t\t\t\t\ttextAnchor=\"middle\"\n\t\t\t\t\t\t\tfontSize={10}\n\t\t\t\t\t\t\tfill=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t.label}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t</g>\n\t\t\t\t))}\n\t\t\t</g>\n\t\t\t{/* Row labels */}\n\t\t\t<g data-hex-gantt-labels>\n\t\t\t\t{laidOut.tasks.map((t) => (\n\t\t\t\t\t<text\n\t\t\t\t\t\tkey={`label-${t.task.id}`}\n\t\t\t\t\t\tx={labelMargin - 8}\n\t\t\t\t\t\ty={t.y + t.h / 2}\n\t\t\t\t\t\tdy=\"0.35em\"\n\t\t\t\t\t\ttextAnchor=\"end\"\n\t\t\t\t\t\tfontSize={11}\n\t\t\t\t\t\tfill=\"hsl(var(--foreground))\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{t.task.label}\n\t\t\t\t\t</text>\n\t\t\t\t))}\n\t\t\t</g>\n\t\t\t{/* Dependency arrows: elbow-and-jog routing — when the target\n\t\t\t task starts before (or near) the source's right edge, route\n\t\t\t out past the source first to avoid drawing through its bar. */}\n\t\t\t<g data-hex-gantt-deps fill=\"none\">\n\t\t\t\t{laidOut.deps.map((d) => {\n\t\t\t\t\tconst ELBOW = 8;\n\t\t\t\t\tconst needsJog = d.to.x < d.from.x + ELBOW;\n\t\t\t\t\tconst path = needsJog\n\t\t\t\t\t\t? `M${d.from.x},${d.from.y} L${d.from.x + ELBOW},${d.from.y} L${d.from.x + ELBOW},${d.to.y} L${d.to.x},${d.to.y}`\n\t\t\t\t\t\t: `M${d.from.x},${d.from.y} L${(d.from.x + d.to.x) / 2},${d.from.y} L${(d.from.x + d.to.x) / 2},${d.to.y} L${d.to.x},${d.to.y}`;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tkey={d.id}\n\t\t\t\t\t\t\tdata-hex-gantt-dep\n\t\t\t\t\t\t\td={path}\n\t\t\t\t\t\t\tstroke=\"hsl(var(--muted-foreground))\"\n\t\t\t\t\t\t\tstrokeOpacity={0.55}\n\t\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t\t\tmarkerEnd={`url(#hex-gantt-arrow-${arrowId})`}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</g>\n\t\t\t{/* Task bars */}\n\t\t\t<g data-hex-gantt-tasks>\n\t\t\t\t{laidOut.tasks.map((t) => {\n\t\t\t\t\tconst interactive = Boolean(onTaskClick);\n\t\t\t\t\tconst handleActivate = () => onTaskClick?.(t.task);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<g\n\t\t\t\t\t\t\tkey={t.task.id}\n\t\t\t\t\t\t\tdata-hex-gantt-task\n\t\t\t\t\t\t\tdata-row={t.rowIndex}\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? `${t.task.label}, ${formatDate(toDate(t.task.start))} to ${formatDate(toDate(t.task.end))}${t.task.progress != null ? `, ${Math.round((t.task.progress ?? 0) * 100)}% complete` : \"\"}`\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<rect\n\t\t\t\t\t\t\t\tx={t.x}\n\t\t\t\t\t\t\t\ty={t.y}\n\t\t\t\t\t\t\t\twidth={Math.max(2, t.w)}\n\t\t\t\t\t\t\t\theight={t.h}\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(--primary))\"\n\t\t\t\t\t\t\t\tfillOpacity={0.25}\n\t\t\t\t\t\t\t\tstroke=\"hsl(var(--primary))\"\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{t.progressW > 0 ? (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\t\t\t\tx={t.x}\n\t\t\t\t\t\t\t\t\t\ty={t.y}\n\t\t\t\t\t\t\t\t\t\twidth={t.progressW}\n\t\t\t\t\t\t\t\t\t\theight={t.h}\n\t\t\t\t\t\t\t\t\t\trx={4}\n\t\t\t\t\t\t\t\t\t\try={4}\n\t\t\t\t\t\t\t\t\t\tfill=\"hsl(var(--primary))\"\n\t\t\t\t\t\t\t\t\t\tfillOpacity={0.7}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t{/* Hard right-edge line keeps the progress boundary visible for\n\t\t\t\t\t\t\t\t\t color-blind viewers and on low-contrast themes. Skipped at\n\t\t\t\t\t\t\t\t\t 100% progress where it overlaps the bar's own border. */}\n\t\t\t\t\t\t\t\t\t{t.progressW < t.w - 0.5 ? (\n\t\t\t\t\t\t\t\t\t\t<line\n\t\t\t\t\t\t\t\t\t\t\tx1={t.x + t.progressW}\n\t\t\t\t\t\t\t\t\t\t\tx2={t.x + t.progressW}\n\t\t\t\t\t\t\t\t\t\t\ty1={t.y}\n\t\t\t\t\t\t\t\t\t\t\ty2={t.y + t.h}\n\t\t\t\t\t\t\t\t\t\t\tstroke=\"hsl(var(--primary))\"\n\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t</>\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\ttasks: GanttTask[],\n\twidth: number,\n\trowHeight: number,\n\tlabelMargin: number,\n\ttickCount: number,\n): {\n\ttasks: LaidOutTask[];\n\tdeps: DepArrow[];\n\tticks: AxisTick[];\n\tstartLabel: string;\n\tendLabel: string;\n} {\n\tif (tasks.length === 0) {\n\t\treturn { tasks: [], deps: [], ticks: [], startLabel: \"—\", endLabel: \"—\" };\n\t}\n\n\tconst axisLeft = labelMargin;\n\tconst axisRight = width - 16;\n\tconst usable = axisRight - axisLeft;\n\n\t// Drop NaN-bearing endpoints so the axis range stays finite. Tasks with\n\t// either bound un-parseable get rendered with their own zero-width\n\t// fallback below; we still want them in the row layout, just clipped to\n\t// the axis edges.\n\tconst allTimes = tasks\n\t\t.flatMap((t) => [toDate(t.start).getTime(), toDate(t.end).getTime()])\n\t\t.filter((t) => Number.isFinite(t));\n\tif (allTimes.length === 0) {\n\t\treturn { tasks: [], deps: [], ticks: [], startLabel: \"—\", endLabel: \"—\" };\n\t}\n\tconst minTs = Math.min(...allTimes);\n\tconst maxTs = Math.max(...allTimes);\n\tconst span = Math.max(1, maxTs - minTs);\n\n\tconst tToX = (t: number) => axisLeft + ((t - minTs) / span) * usable;\n\n\tconst laidOutTasks: LaidOutTask[] = tasks.map((task, i) => {\n\t\tconst startTs = toDate(task.start).getTime();\n\t\tconst endTs = toDate(task.end).getTime();\n\t\tconst x = tToX(startTs);\n\t\tconst w = Math.max(0, tToX(endTs) - x);\n\t\tconst y = HEADER_HEIGHT + i * rowHeight + ROW_PADDING / 2;\n\t\tconst h = rowHeight - ROW_PADDING;\n\t\tconst progress = clamp01(task.progress ?? 0);\n\t\treturn {\n\t\t\ttask,\n\t\t\trowIndex: i,\n\t\t\tx,\n\t\t\ty,\n\t\t\tw,\n\t\t\th,\n\t\t\tprogressW: w * progress,\n\t\t};\n\t});\n\n\tconst byId = new Map(laidOutTasks.map((t) => [t.task.id, t]));\n\tconst deps: DepArrow[] = [];\n\tlaidOutTasks.forEach((t) => {\n\t\t(t.task.dependencies ?? []).forEach((depId, k) => {\n\t\t\tconst from = byId.get(depId);\n\t\t\tif (!from) return;\n\t\t\tdeps.push({\n\t\t\t\tfrom: { x: from.x + from.w, y: from.y + from.h / 2 },\n\t\t\t\tto: { x: t.x, y: t.y + t.h / 2 },\n\t\t\t\tid: `${depId}-${t.task.id}-${k}`,\n\t\t\t});\n\t\t});\n\t});\n\n\t// Generate ticks, then dedupe consecutive identical labels — at year-scale\n\t// or month-scale spans the formatter often emits the same string twice\n\t// (e.g. two ticks both inside January render as \"2025-01\"). Blanking the\n\t// duplicate keeps the gridline but drops the noisy repeated text.\n\tconst rawTicks: AxisTick[] = [];\n\tfor (let i = 0; i < tickCount; i++) {\n\t\tconst ts = minTs + (i / Math.max(1, tickCount - 1)) * span;\n\t\trawTicks.push({ x: tToX(ts), label: formatTick(new Date(ts), span) });\n\t}\n\tconst ticks: AxisTick[] = rawTicks.map((t, i) => ({\n\t\tx: t.x,\n\t\tlabel: i > 0 && rawTicks[i - 1]?.label === t.label ? \"\" : t.label,\n\t}));\n\n\treturn {\n\t\ttasks: laidOutTasks,\n\t\tdeps,\n\t\tticks,\n\t\tstartLabel: formatDate(new Date(minTs)),\n\t\tendLabel: formatDate(new Date(maxTs)),\n\t};\n}\n\nfunction toDate(v: Date | string | number): Date {\n\tif (v instanceof Date) return v;\n\tif (typeof v === \"number\") return new Date(v);\n\treturn new Date(v);\n}\n\nfunction clamp01(v: number): number {\n\treturn v < 0 ? 0 : v > 1 ? 1 : v;\n}\n\nfunction formatDate(d: Date): string {\n\tif (Number.isNaN(d.getTime())) return \"—\";\n\treturn d.toISOString().slice(0, 10);\n}\n\nfunction formatTick(d: Date, spanMs: number): string {\n\tif (Number.isNaN(d.getTime())) return \"—\";\n\tconst ONE_DAY = 24 * 60 * 60 * 1000;\n\t// Switch to MM-DD up to ~3 months — at 30 days the original threshold\n\t// produced \"2025-01\" / \"2025-01\" duplicates for ticks landing in the\n\t// same month. MM-DD scales to ~90 days before adjacent ticks merge.\n\tif (spanMs <= 90 * ONE_DAY) return d.toISOString().slice(5, 10); // MM-DD\n\tif (spanMs <= 730 * ONE_DAY) return d.toISOString().slice(0, 7); // YYYY-MM\n\treturn String(d.getUTCFullYear());\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 { Gantt };\n"]}
package/dist/grid.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/_shared/layout-variants.ts","../src/primitives/grid/grid.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;;;ACCO,IAAM,WAAA,GAAc;AAAA,EAC1B,EAAA,EAAI,6BAAA;AAAA,EACJ,EAAA,EAAI,4BAAA;AAAA,EACJ,EAAA,EAAI,0BAAA;AAAA,EACJ,EAAA,EAAI,4BAAA;AAAA,EACJ,EAAA,EAAI;AACL,CAAA;AAWO,IAAM,iBAAA,GAAoB;AAAA,EAChC,KAAA,EAAO,aAAA;AAAA,EACP,MAAA,EAAQ,cAAA;AAAA,EACR,GAAA,EAAK,WAAA;AAAA,EACL,OAAA,EAAS;AACV,CAAA;ACpBA,IAAM,YAAA,GAAe,IAAI,MAAA,EAAQ;AAAA,EAChC,QAAA,EAAU;AAAA,IACT,IAAA,EAAM;AAAA,MACL,CAAA,EAAG,aAAA;AAAA,MACH,CAAA,EAAG,aAAA;AAAA,MACH,CAAA,EAAG,aAAA;AAAA,MACH,CAAA,EAAG,aAAA;AAAA,MACH,CAAA,EAAG,aAAA;AAAA,MACH,UAAA,EAAY;AAAA,KACb;AAAA,IACA,GAAA,EAAK,WAAA;AAAA,IACL,KAAA,EAAO;AAAA,GACR;AAAA,EACA,eAAA,EAAiB;AAAA,IAChB,IAAA,EAAM,CAAA;AAAA,IACN,GAAA,EAAK,IAAA;AAAA,IACL,KAAA,EAAO;AAAA;AAET,CAAC;AAkCD,SAAS,IAAA,CAAK,EAAE,SAAA,EAAW,IAAA,EAAM,GAAA,EAAK,KAAA,EAAO,WAAA,GAAc,OAAA,EAAS,KAAA,EAAO,GAAG,KAAA,EAAM,EAAc;AAGjG,EAAA,MAAM,WAAA,GACL,IAAA,KAAS,UAAA,GACN,EAAE,mBAAA,EAAqB,2BAA2B,WAAW,CAAA,OAAA,CAAA,EAAW,GAAG,KAAA,EAAM,GACjF,KAAA;AACJ,EAAA,uBACC,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,SAAA,EAAW,GAAG,YAAA,CAAa,EAAE,MAAM,GAAA,EAAK,KAAA,EAAO,CAAA,EAAG,SAAS,CAAA;AAAA,MAC3D,KAAA,EAAO,WAAA;AAAA,MACN,GAAG;AAAA;AAAA,GACL;AAEF","file":"grid.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","/**\n * Single source of truth for layout-primitive CVA variant maps.\n *\n * Stack, Cluster, Grid all share `gap` and `justify` value sets; align values\n * differ slightly (`stretch` for column-like flows, `baseline` for row flows).\n * Centralizing the maps here keeps token names and Tailwind classes in one\n * file — when the gap scale changes (renamed token, new step, etc.), all\n * three components update together.\n */\n\n/** Gap scale bound to `--gap-*` tokens. Used by Stack, Cluster, Grid. */\nexport const gapVariants = {\n\txs: \"gap-[var(--gap-xs,0.25rem)]\",\n\tsm: \"gap-[var(--gap-sm,0.5rem)]\",\n\tmd: \"gap-[var(--gap-md,1rem)]\",\n\tlg: \"gap-[var(--gap-lg,1.5rem)]\",\n\txl: \"gap-[var(--gap-xl,2rem)]\",\n} as const;\n\n/** `justify-content` values shared by Stack and Cluster. */\nexport const justifyVariants = {\n\tstart: \"justify-start\",\n\tcenter: \"justify-center\",\n\tend: \"justify-end\",\n\tbetween: \"justify-between\",\n} as const;\n\n/** Cross-axis `align-items` values for vertical/grid flows (column-like). */\nexport const flexAlignVariants = {\n\tstart: \"items-start\",\n\tcenter: \"items-center\",\n\tend: \"items-end\",\n\tstretch: \"items-stretch\",\n} as const;\n\n/** Cross-axis `align-items` values for horizontal flows. Includes `baseline`. */\nexport const clusterAlignVariants = {\n\tstart: \"items-start\",\n\tcenter: \"items-center\",\n\tend: \"items-end\",\n\tstretch: \"items-stretch\",\n\tbaseline: \"items-baseline\",\n} as const;\n","import { type VariantProps, cva } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\nimport { flexAlignVariants, gapVariants } from \"../_shared/layout-variants.js\";\n\n/**\n * CVA variants for Grid — CSS grid with column-count presets and shared `gap`.\n * `cols` accepts 1/2/3/4/6 fixed columns or `\"auto-fit\"` for responsive auto-sizing\n * (in which case the consumer should pass `minColWidth` for the min track size).\n *\n * `cols` keys are TypeScript numeric literals (`cols={3}`) at the type level;\n * the schema's `enumValues` serializes them as strings for JSON-shape parity.\n */\nconst gridVariants = cva(\"grid\", {\n\tvariants: {\n\t\tcols: {\n\t\t\t1: \"grid-cols-1\",\n\t\t\t2: \"grid-cols-2\",\n\t\t\t3: \"grid-cols-3\",\n\t\t\t4: \"grid-cols-4\",\n\t\t\t6: \"grid-cols-6\",\n\t\t\t\"auto-fit\": \"\",\n\t\t},\n\t\tgap: gapVariants,\n\t\talign: flexAlignVariants,\n\t},\n\tdefaultVariants: {\n\t\tcols: 3,\n\t\tgap: \"md\",\n\t\talign: \"stretch\",\n\t},\n});\n\n/** Props for the Grid component. */\nexport interface GridProps\n\textends React.HTMLAttributes<HTMLDivElement>,\n\t\tVariantProps<typeof gridVariants> {\n\t/**\n\t * Minimum column width for `cols=\"auto-fit\"`. Tracks repeat to fill the container,\n\t * never shrinking below this value. Ignored when `cols` is a fixed integer.\n\t * @default \"16rem\"\n\t */\n\tminColWidth?: string;\n}\n\n/**\n * CSS grid with column-count presets and consistent gap. Use for card grids,\n * dashboards, image galleries, and any layout where children should align to\n * shared row/column tracks.\n *\n * Pass `cols=\"auto-fit\"` and `minColWidth` for responsive grids that fit as\n * many columns as the viewport allows without media queries.\n *\n * @param props - Grid props including `cols`, `gap`, `align`, and `minColWidth`.\n * @returns A CSS grid container.\n * @example\n * ```tsx\n * <Grid cols={3} gap=\"md\">\n * {items.map((i) => <Card key={i.id}>{i.title}</Card>)}\n * </Grid>\n * <Grid cols=\"auto-fit\" minColWidth=\"20rem\" gap=\"lg\">\n * {responsiveItems.map(...)}\n * </Grid>\n * ```\n */\nfunction Grid({ className, cols, gap, align, minColWidth = \"16rem\", style, ...props }: GridProps) {\n\t// Consumer's inline `style` is spread last so a passed `gridTemplateColumns`\n\t// overrides our auto-fit default. That's the right precedence: explicit wins.\n\tconst inlineStyle =\n\t\tcols === \"auto-fit\"\n\t\t\t? { gridTemplateColumns: `repeat(auto-fit, minmax(${minColWidth}, 1fr))`, ...style }\n\t\t\t: style;\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(gridVariants({ cols, gap, align }), className)}\n\t\t\tstyle={inlineStyle}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport { Grid, gridVariants };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/primitives/_shared/layout-variants.ts","../src/primitives/grid/grid.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;;;ACCO,IAAM,WAAA,GAAc;AAAA,EAC1B,EAAA,EAAI,6BAAA;AAAA,EACJ,EAAA,EAAI,4BAAA;AAAA,EACJ,EAAA,EAAI,0BAAA;AAAA,EACJ,EAAA,EAAI,4BAAA;AAAA,EACJ,EAAA,EAAI;AACL,CAAA;AAWO,IAAM,iBAAA,GAAoB;AAAA,EAChC,KAAA,EAAO,aAAA;AAAA,EACP,MAAA,EAAQ,cAAA;AAAA,EACR,GAAA,EAAK,WAAA;AAAA,EACL,OAAA,EAAS;AACV,CAAA;ACpBA,IAAM,YAAA,GAAe,IAAI,MAAA,EAAQ;AAAA,EAChC,QAAA,EAAU;AAAA,IACT,IAAA,EAAM;AAAA,MACL,CAAA,EAAG,aAAA;AAAA,MACH,CAAA,EAAG,aAAA;AAAA,MACH,CAAA,EAAG,aAAA;AAAA,MACH,CAAA,EAAG,aAAA;AAAA,MACH,CAAA,EAAG,aAAA;AAAA,MACH,UAAA,EAAY;AAAA,KACb;AAAA,IACA,GAAA,EAAK,WAAA;AAAA,IACL,KAAA,EAAO;AAAA,GACR;AAAA,EACA,eAAA,EAAiB;AAAA,IAChB,IAAA,EAAM,CAAA;AAAA,IACN,GAAA,EAAK,IAAA;AAAA,IACL,KAAA,EAAO;AAAA;AAET,CAAC;AAkCD,SAAS,IAAA,CAAK,EAAE,SAAA,EAAW,IAAA,EAAM,GAAA,EAAK,KAAA,EAAO,WAAA,GAAc,OAAA,EAAS,KAAA,EAAO,GAAG,KAAA,EAAM,EAAc;AAGjG,EAAA,MAAM,WAAA,GACL,IAAA,KAAS,UAAA,GACN,EAAE,mBAAA,EAAqB,2BAA2B,WAAW,CAAA,OAAA,CAAA,EAAW,GAAG,KAAA,EAAM,GACjF,KAAA;AACJ,EAAA,uBACC,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,SAAA,EAAW,GAAG,YAAA,CAAa,EAAE,MAAM,GAAA,EAAK,KAAA,EAAO,CAAA,EAAG,SAAS,CAAA;AAAA,MAC3D,KAAA,EAAO,WAAA;AAAA,MACN,GAAG;AAAA;AAAA,GACL;AAEF","file":"grid.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","/**\n * Single source of truth for layout-primitive CVA variant maps.\n *\n * Stack, Cluster, Grid all share `gap` and `justify` value sets; align values\n * differ slightly (`stretch` for column-like flows, `baseline` for row flows).\n * Centralizing the maps here keeps token names and Tailwind classes in one\n * file — when the gap scale changes (renamed token, new step, etc.), all\n * three components update together.\n */\n\n/** Gap scale bound to `--gap-*` tokens. Used by Stack, Cluster, Grid. */\nexport const gapVariants = {\n\txs: \"gap-[var(--gap-xs,0.25rem)]\",\n\tsm: \"gap-[var(--gap-sm,0.5rem)]\",\n\tmd: \"gap-[var(--gap-md,1rem)]\",\n\tlg: \"gap-[var(--gap-lg,1.5rem)]\",\n\txl: \"gap-[var(--gap-xl,2rem)]\",\n} as const;\n\n/** `justify-content` values shared by Stack and Cluster. */\nexport const justifyVariants = {\n\tstart: \"justify-start\",\n\tcenter: \"justify-center\",\n\tend: \"justify-end\",\n\tbetween: \"justify-between\",\n} as const;\n\n/** Cross-axis `align-items` values for vertical/grid flows (column-like). */\nexport const flexAlignVariants = {\n\tstart: \"items-start\",\n\tcenter: \"items-center\",\n\tend: \"items-end\",\n\tstretch: \"items-stretch\",\n} as const;\n\n/** Cross-axis `align-items` values for horizontal flows. Includes `baseline`. */\nexport const clusterAlignVariants = {\n\tstart: \"items-start\",\n\tcenter: \"items-center\",\n\tend: \"items-end\",\n\tstretch: \"items-stretch\",\n\tbaseline: \"items-baseline\",\n} as const;\n","import { type VariantProps, cva } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\nimport { flexAlignVariants, gapVariants } from \"../_shared/layout-variants.js\";\n\n/**\n * CVA variants for Grid — CSS grid with column-count presets and shared `gap`.\n * `cols` accepts 1/2/3/4/6 fixed columns or `\"auto-fit\"` for responsive auto-sizing\n * (in which case the consumer should pass `minColWidth` for the min track size).\n *\n * `cols` keys are TypeScript numeric literals (`cols={3}`) at the type level;\n * the schema's `enumValues` serializes them as strings for JSON-shape parity.\n */\nconst gridVariants = cva(\"grid\", {\n\tvariants: {\n\t\tcols: {\n\t\t\t1: \"grid-cols-1\",\n\t\t\t2: \"grid-cols-2\",\n\t\t\t3: \"grid-cols-3\",\n\t\t\t4: \"grid-cols-4\",\n\t\t\t6: \"grid-cols-6\",\n\t\t\t\"auto-fit\": \"\",\n\t\t},\n\t\tgap: gapVariants,\n\t\talign: flexAlignVariants,\n\t},\n\tdefaultVariants: {\n\t\tcols: 3,\n\t\tgap: \"md\",\n\t\talign: \"stretch\",\n\t},\n});\n\n/** Props for the Grid component. */\nexport interface GridProps\n\textends React.HTMLAttributes<HTMLDivElement>,\n\t\tVariantProps<typeof gridVariants> {\n\t/**\n\t * Minimum column width for `cols=\"auto-fit\"`. Tracks repeat to fill the container,\n\t * never shrinking below this value. Ignored when `cols` is a fixed integer.\n\t * @default \"16rem\"\n\t */\n\tminColWidth?: string;\n}\n\n/**\n * CSS grid with column-count presets and consistent gap. Use for card grids,\n * dashboards, image galleries, and any layout where children should align to\n * shared row/column tracks.\n *\n * Pass `cols=\"auto-fit\"` and `minColWidth` for responsive grids that fit as\n * many columns as the viewport allows without media queries.\n *\n * @param props - Grid props including `cols`, `gap`, `align`, and `minColWidth`.\n * @returns A CSS grid container.\n * @example\n * ```tsx\n * <Grid cols={3} gap=\"md\">\n * {items.map((i) => <Card key={i.id}>{i.title}</Card>)}\n * </Grid>\n * <Grid cols=\"auto-fit\" minColWidth=\"20rem\" gap=\"lg\">\n * {responsiveItems.map(...)}\n * </Grid>\n * ```\n */\nfunction Grid({ className, cols, gap, align, minColWidth = \"16rem\", style, ...props }: GridProps) {\n\t// Consumer's inline `style` is spread last so a passed `gridTemplateColumns`\n\t// overrides our auto-fit default. That's the right precedence: explicit wins.\n\tconst inlineStyle =\n\t\tcols === \"auto-fit\"\n\t\t\t? { gridTemplateColumns: `repeat(auto-fit, minmax(${minColWidth}, 1fr))`, ...style }\n\t\t\t: style;\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(gridVariants({ cols, gap, align }), className)}\n\t\t\tstyle={inlineStyle}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport { Grid, gridVariants };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/components/hover-card/hover-card.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACHA,IAAM,SAAA,GAA+B,kBAAA,CAAA;AAGrC,IAAM,gBAAA,GAAsC,kBAAA,CAAA;AAG5C,IAAM,gBAAA,GAAyB,KAAA,CAAA,UAAA,CAG7B,CAAC,EAAE,WAAW,KAAA,GAAQ,QAAA,EAAU,UAAA,GAAa,CAAA,EAAG,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC7D,GAAA,CAAoB,2BAAnB,EACA,QAAA,kBAAA,GAAA;AAAA,EAAoB,kBAAA,CAAA,OAAA;AAAA,EAAnB;AAAA,IACA,GAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,wIAAA;AAAA,MACA,8DAAA;AAAA,MACA,4DAAA;AAAA,MACA,8DAAA;AAAA,MACA,6JAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG;AAAA;AACL,CAAA,EACD,CACA;AACD,gBAAA,CAAiB,WAAA,GAAc,kBAAA","file":"hover-card.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as HoverCardPrimitive from \"@radix-ui/react-hover-card\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/** Root container for a hover-card. */\nconst HoverCard = HoverCardPrimitive.Root;\n\n/** The element that reveals the card on hover/focus. */\nconst HoverCardTrigger = HoverCardPrimitive.Trigger;\n\n/** The floating hover-card content panel. Richer than a tooltip. */\nconst HoverCardContent = React.forwardRef<\n\tReact.ComponentRef<typeof HoverCardPrimitive.Content>,\n\tReact.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n\t<HoverCardPrimitive.Portal>\n\t\t<HoverCardPrimitive.Content\n\t\t\tref={ref}\n\t\t\talign={align}\n\t\t\tsideOffset={sideOffset}\n\t\t\tclassName={cn(\n\t\t\t\t\"z-50 w-64 rounded-md border border-foreground/[0.08] bg-popover p-[var(--space-4,1rem)] text-popover-foreground shadow-md outline-none\",\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\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t</HoverCardPrimitive.Portal>\n));\nHoverCardContent.displayName = \"HoverCardContent\";\n\nexport { HoverCard, HoverCardTrigger, HoverCardContent };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/hover-card/hover-card.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACHA,IAAM,SAAA,GAA+B,kBAAA,CAAA;AAGrC,IAAM,gBAAA,GAAsC,kBAAA,CAAA;AAG5C,IAAM,gBAAA,GAAyB,KAAA,CAAA,UAAA,CAG7B,CAAC,EAAE,WAAW,KAAA,GAAQ,QAAA,EAAU,UAAA,GAAa,CAAA,EAAG,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC7D,GAAA,CAAoB,2BAAnB,EACA,QAAA,kBAAA,GAAA;AAAA,EAAoB,kBAAA,CAAA,OAAA;AAAA,EAAnB;AAAA,IACA,GAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,wIAAA;AAAA,MACA,8DAAA;AAAA,MACA,4DAAA;AAAA,MACA,8DAAA;AAAA,MACA,6JAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG;AAAA;AACL,CAAA,EACD,CACA;AACD,gBAAA,CAAiB,WAAA,GAAc,kBAAA","file":"hover-card.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n\nconst SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"mailto:\"] as const;\n\n/**\n * Allowlist a URL for use as an `<a href>` against untrusted input.\n *\n * Returns the raw string when it's `http(s):` / `mailto:` / a relative\n * URL (no scheme); returns `undefined` otherwise. Defends against\n * `javascript:` / `data:` / `vbscript:` injection from streamed model\n * output or third-party JSON payloads that flow into citation chips.\n *\n * Inside a Markdown render path, `rehype-sanitize` already strips\n * `javascript:` from inline-link hrefs — but it does NOT introspect\n * JSON nested inside attribute values (e.g. `<sources data='[…]'/>`),\n * so the components that consume that data must guard themselves.\n *\n * @param raw - The candidate URL, or `undefined` when none was supplied.\n * @returns The URL when safe to render, otherwise `undefined`.\n */\nexport function safeUrl(raw: string | undefined): string | undefined {\n\tif (raw === undefined || raw === \"\") return undefined;\n\t// Relative URLs have no scheme — `new URL(relative)` throws without a base,\n\t// so a thrown URL means either malformed input OR a relative path. Treat\n\t// \"throws + does not contain a colon\" as a relative path (safe).\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(raw);\n\t} catch {\n\t\treturn raw.includes(\":\") ? undefined : raw;\n\t}\n\treturn SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : undefined;\n}\n","\"use client\";\n\nimport * as HoverCardPrimitive from \"@radix-ui/react-hover-card\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n/** Root container for a hover-card. */\nconst HoverCard = HoverCardPrimitive.Root;\n\n/** The element that reveals the card on hover/focus. */\nconst HoverCardTrigger = HoverCardPrimitive.Trigger;\n\n/** The floating hover-card content panel. Richer than a tooltip. */\nconst HoverCardContent = React.forwardRef<\n\tReact.ComponentRef<typeof HoverCardPrimitive.Content>,\n\tReact.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n\t<HoverCardPrimitive.Portal>\n\t\t<HoverCardPrimitive.Content\n\t\t\tref={ref}\n\t\t\talign={align}\n\t\t\tsideOffset={sideOffset}\n\t\t\tclassName={cn(\n\t\t\t\t\"z-50 w-64 rounded-md border border-foreground/[0.08] bg-popover p-[var(--space-4,1rem)] text-popover-foreground shadow-md outline-none\",\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\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t</HoverCardPrimitive.Portal>\n));\nHoverCardContent.displayName = \"HoverCardContent\";\n\nexport { HoverCard, HoverCardTrigger, HoverCardContent };\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/artifacts/image-occlusion/image-occlusion.tsx"],"names":[],"mappings":"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","file":"image-occlusion.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 * Image occlusion — image with rectangular regions hidden behind opaque\n * overlays. Click / Enter / Space on a region reveals what's underneath.\n * Coordinates are 0–1 fractions of the rendered image so the layout\n * stays correct at any size. Pure HTML; no heavy peer.\n *\n * Common for anatomy diagrams, geographic maps, code snippets — any\n * visual where labels or sub-regions are the recall target.\n *\n * @example\n * <ImageOcclusion\n * src=\"/anatomy/heart.png\"\n * alt=\"Cross-section of a human heart\"\n * regions={[\n * { id: \"lv\", x: 0.42, y: 0.55, width: 0.18, height: 0.22, label: \"Left ventricle\" },\n * { id: \"ra\", x: 0.58, y: 0.20, width: 0.16, height: 0.18, label: \"Right atrium\" },\n * ]}\n * />\n */\nexport type OcclusionRegion = {\n\tid: string;\n\t/** All coords are 0–1 fractions of the rendered image. */\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n\tlabel?: string;\n};\n\nexport interface ImageOcclusionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"children\"> {\n\t/** Image source URL. */\n\tsrc: string;\n\t/** Alt text for the underlying image. */\n\talt: string;\n\t/** Rectangular regions to hide on top of the image. */\n\tregions: OcclusionRegion[];\n\t/** Fired with the region id when a region is revealed (not when hidden again). */\n\tonRegionReveal?: (id: string) => void;\n}\n\nfunction ImageOcclusion({\n\tsrc,\n\talt,\n\tregions,\n\tonRegionReveal,\n\tclassName,\n\t...rest\n}: ImageOcclusionProps) {\n\tconst [revealed, setRevealed] = React.useState<Set<string>>(() => new Set());\n\tconst onRevealRef = React.useRef(onRegionReveal);\n\tonRevealRef.current = onRegionReveal;\n\n\t// Surface mistakes early in dev when fractional coords escape [0, 1].\n\tconst warnedRef = React.useRef(false);\n\tconst nodeEnv = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV;\n\tif (nodeEnv !== \"production\" && !warnedRef.current) {\n\t\tconst offender = regions.find(\n\t\t\t(r) => r.x < 0 || r.y < 0 || r.x + r.width > 1.0001 || r.y + r.height > 1.0001,\n\t\t);\n\t\tif (offender) {\n\t\t\twarnedRef.current = true;\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(\n\t\t\t\t`[hex-core/ImageOcclusion] Region \"${offender.id}\" coords escape [0, 1]. Pass fractions, not pixels — e.g. x: 0.42 (not 168).`,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst toggle = React.useCallback((id: string) => {\n\t\tsetRevealed((prev) => {\n\t\t\tconst next = new Set(prev);\n\t\t\tif (next.has(id)) {\n\t\t\t\tnext.delete(id);\n\t\t\t} else {\n\t\t\t\tnext.add(id);\n\t\t\t\tonRevealRef.current?.(id);\n\t\t\t}\n\t\t\treturn next;\n\t\t});\n\t}, []);\n\n\treturn (\n\t\t<div\n\t\t\t{...rest}\n\t\t\tdata-hex-image-occlusion\n\t\t\tclassName={cn(\"relative inline-block\", className)}\n\t\t>\n\t\t\t<img\n\t\t\t\tsrc={src}\n\t\t\t\talt={alt}\n\t\t\t\tdata-hex-image-occlusion-img\n\t\t\t\tclassName=\"block h-auto w-full select-none\"\n\t\t\t\tdraggable={false}\n\t\t\t/>\n\t\t\t<div\n\t\t\t\tdata-hex-image-occlusion-overlay\n\t\t\t\tclassName=\"pointer-events-none absolute inset-0\"\n\t\t\t>\n\t\t\t\t{regions.map((r, i) => {\n\t\t\t\t\tconst isRevealed = revealed.has(r.id);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={r.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tdata-hex-image-occlusion-region\n\t\t\t\t\t\t\tdata-region-id={r.id}\n\t\t\t\t\t\t\tdata-revealed={isRevealed}\n\t\t\t\t\t\t\taria-pressed={isRevealed}\n\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\tr.label\n\t\t\t\t\t\t\t\t\t? isRevealed\n\t\t\t\t\t\t\t\t\t\t? `Region ${i + 1} revealed: ${r.label}. Activate to hide.`\n\t\t\t\t\t\t\t\t\t\t: `Region ${i + 1} of ${regions.length}, hidden. Activate to reveal: ${r.label}.`\n\t\t\t\t\t\t\t\t\t: isRevealed\n\t\t\t\t\t\t\t\t\t\t? `Region ${i + 1} revealed. Activate to hide.`\n\t\t\t\t\t\t\t\t\t\t: `Region ${i + 1} of ${regions.length}, hidden. Activate to reveal.`\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonClick={() => toggle(r.id)}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"pointer-events-auto absolute rounded-sm border-2 border-primary/60 transition-opacity focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n\t\t\t\t\t\t\t\tisRevealed\n\t\t\t\t\t\t\t\t\t? \"bg-transparent opacity-30 hover:opacity-60\"\n\t\t\t\t\t\t\t\t\t: \"bg-primary opacity-95 hover:bg-primary/90\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tleft: `${r.x * 100}%`,\n\t\t\t\t\t\t\t\ttop: `${r.y * 100}%`,\n\t\t\t\t\t\t\t\twidth: `${r.width * 100}%`,\n\t\t\t\t\t\t\t\theight: `${r.height * 100}%`,\n\t\t\t\t\t\t\t\t// Explicit z-index = array index makes stacking deterministic:\n\t\t\t\t\t\t\t\t// later array entries always render (and click-catch) on top.\n\t\t\t\t\t\t\t\tzIndex: i,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport { ImageOcclusion };\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/artifacts/image-occlusion/image-occlusion.tsx"],"names":[],"mappings":"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","file":"image-occlusion.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 * Image occlusion — image with rectangular regions hidden behind opaque\n * overlays. Click / Enter / Space on a region reveals what's underneath.\n * Coordinates are 0–1 fractions of the rendered image so the layout\n * stays correct at any size. Pure HTML; no heavy peer.\n *\n * Common for anatomy diagrams, geographic maps, code snippets — any\n * visual where labels or sub-regions are the recall target.\n *\n * @example\n * <ImageOcclusion\n * src=\"/anatomy/heart.png\"\n * alt=\"Cross-section of a human heart\"\n * regions={[\n * { id: \"lv\", x: 0.42, y: 0.55, width: 0.18, height: 0.22, label: \"Left ventricle\" },\n * { id: \"ra\", x: 0.58, y: 0.20, width: 0.16, height: 0.18, label: \"Right atrium\" },\n * ]}\n * />\n */\nexport type OcclusionRegion = {\n\tid: string;\n\t/** All coords are 0–1 fractions of the rendered image. */\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n\tlabel?: string;\n};\n\nexport interface ImageOcclusionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"children\"> {\n\t/** Image source URL. */\n\tsrc: string;\n\t/** Alt text for the underlying image. */\n\talt: string;\n\t/** Rectangular regions to hide on top of the image. */\n\tregions: OcclusionRegion[];\n\t/** Fired with the region id when a region is revealed (not when hidden again). */\n\tonRegionReveal?: (id: string) => void;\n}\n\nfunction ImageOcclusion({\n\tsrc,\n\talt,\n\tregions,\n\tonRegionReveal,\n\tclassName,\n\t...rest\n}: ImageOcclusionProps) {\n\tconst [revealed, setRevealed] = React.useState<Set<string>>(() => new Set());\n\tconst onRevealRef = React.useRef(onRegionReveal);\n\tonRevealRef.current = onRegionReveal;\n\n\t// Surface mistakes early in dev when fractional coords escape [0, 1].\n\tconst warnedRef = React.useRef(false);\n\tconst nodeEnv = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV;\n\tif (nodeEnv !== \"production\" && !warnedRef.current) {\n\t\tconst offender = regions.find(\n\t\t\t(r) => r.x < 0 || r.y < 0 || r.x + r.width > 1.0001 || r.y + r.height > 1.0001,\n\t\t);\n\t\tif (offender) {\n\t\t\twarnedRef.current = true;\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(\n\t\t\t\t`[hex-core/ImageOcclusion] Region \"${offender.id}\" coords escape [0, 1]. Pass fractions, not pixels — e.g. x: 0.42 (not 168).`,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst toggle = React.useCallback((id: string) => {\n\t\tsetRevealed((prev) => {\n\t\t\tconst next = new Set(prev);\n\t\t\tif (next.has(id)) {\n\t\t\t\tnext.delete(id);\n\t\t\t} else {\n\t\t\t\tnext.add(id);\n\t\t\t\tonRevealRef.current?.(id);\n\t\t\t}\n\t\t\treturn next;\n\t\t});\n\t}, []);\n\n\treturn (\n\t\t<div\n\t\t\t{...rest}\n\t\t\tdata-hex-image-occlusion\n\t\t\tclassName={cn(\"relative inline-block\", className)}\n\t\t>\n\t\t\t<img\n\t\t\t\tsrc={src}\n\t\t\t\talt={alt}\n\t\t\t\tdata-hex-image-occlusion-img\n\t\t\t\tclassName=\"block h-auto w-full select-none\"\n\t\t\t\tdraggable={false}\n\t\t\t/>\n\t\t\t<div\n\t\t\t\tdata-hex-image-occlusion-overlay\n\t\t\t\tclassName=\"pointer-events-none absolute inset-0\"\n\t\t\t>\n\t\t\t\t{regions.map((r, i) => {\n\t\t\t\t\tconst isRevealed = revealed.has(r.id);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={r.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tdata-hex-image-occlusion-region\n\t\t\t\t\t\t\tdata-region-id={r.id}\n\t\t\t\t\t\t\tdata-revealed={isRevealed}\n\t\t\t\t\t\t\taria-pressed={isRevealed}\n\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\tr.label\n\t\t\t\t\t\t\t\t\t? isRevealed\n\t\t\t\t\t\t\t\t\t\t? `Region ${i + 1} revealed: ${r.label}. Activate to hide.`\n\t\t\t\t\t\t\t\t\t\t: `Region ${i + 1} of ${regions.length}, hidden. Activate to reveal: ${r.label}.`\n\t\t\t\t\t\t\t\t\t: isRevealed\n\t\t\t\t\t\t\t\t\t\t? `Region ${i + 1} revealed. Activate to hide.`\n\t\t\t\t\t\t\t\t\t\t: `Region ${i + 1} of ${regions.length}, hidden. Activate to reveal.`\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonClick={() => toggle(r.id)}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"pointer-events-auto absolute rounded-sm border-2 border-primary/60 transition-opacity focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n\t\t\t\t\t\t\t\tisRevealed\n\t\t\t\t\t\t\t\t\t? \"bg-transparent opacity-30 hover:opacity-60\"\n\t\t\t\t\t\t\t\t\t: \"bg-primary opacity-95 hover:bg-primary/90\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tleft: `${r.x * 100}%`,\n\t\t\t\t\t\t\t\ttop: `${r.y * 100}%`,\n\t\t\t\t\t\t\t\twidth: `${r.width * 100}%`,\n\t\t\t\t\t\t\t\theight: `${r.height * 100}%`,\n\t\t\t\t\t\t\t\t// Explicit z-index = array index makes stacking deterministic:\n\t\t\t\t\t\t\t\t// later array entries always render (and click-catch) on top.\n\t\t\t\t\t\t\t\tzIndex: i,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport { ImageOcclusion };\n"]}
package/dist/index.d.ts CHANGED
@@ -334,6 +334,27 @@ export { Attachment } from './_tsup-dts-rollup.js';
334
334
  export { attachmentVariants } from './_tsup-dts-rollup.js';
335
335
  export { AttachmentFile } from './_tsup-dts-rollup.js';
336
336
  export { AttachmentProps } from './_tsup-dts-rollup.js';
337
+ export { Sources } from './_tsup-dts-rollup.js';
338
+ export { SourcesProps } from './_tsup-dts-rollup.js';
339
+ export { SourceRef } from './_tsup-dts-rollup.js';
340
+ export { InlineCitation } from './_tsup-dts-rollup.js';
341
+ export { InlineCitationProps } from './_tsup-dts-rollup.js';
342
+ export { Task } from './_tsup-dts-rollup.js';
343
+ export { TaskProps } from './_tsup-dts-rollup.js';
344
+ export { TaskStep } from './_tsup-dts-rollup.js';
345
+ export { Shimmer } from './_tsup-dts-rollup.js';
346
+ export { ShimmerProps } from './_tsup-dts-rollup.js';
347
+ export { Branch } from './_tsup-dts-rollup.js';
348
+ export { BranchProps } from './_tsup-dts-rollup.js';
349
+ export { Plan } from './_tsup-dts-rollup.js';
350
+ export { PlanProps } from './_tsup-dts-rollup.js';
351
+ export { PlanStep } from './_tsup-dts-rollup.js';
352
+ export { Conversation } from './_tsup-dts-rollup.js';
353
+ export { ConversationProps } from './_tsup-dts-rollup.js';
354
+ export { ConversationMessage } from './_tsup-dts-rollup.js';
355
+ export { ChainOfThought } from './_tsup-dts-rollup.js';
356
+ export { ChainOfThoughtProps } from './_tsup-dts-rollup.js';
357
+ export { ChainOfThoughtStep } from './_tsup-dts-rollup.js';
337
358
  export { MindMap } from './_tsup-dts-rollup.js';
338
359
  export { MindMapNode } from './_tsup-dts-rollup.js';
339
360
  export { MindMapProps } from './_tsup-dts-rollup.js';
@@ -408,4 +429,23 @@ export { DeckProps } from './_tsup-dts-rollup.js';
408
429
  export { SpacedRepetition } from './_tsup-dts-rollup.js';
409
430
  export { SpacedRepetitionProps } from './_tsup-dts-rollup.js';
410
431
  export { SrsRating } from './_tsup-dts-rollup.js';
432
+ export { AuthAdapter } from './_tsup-dts-rollup.js';
433
+ export { AuthAdapterResult } from './_tsup-dts-rollup.js';
434
+ export { AuthForgotPasswordProps } from './_tsup-dts-rollup.js';
435
+ export { AuthOtpIntent } from './_tsup-dts-rollup.js';
436
+ export { AuthResetPasswordProps } from './_tsup-dts-rollup.js';
437
+ export { AuthSignInSocialProvider } from './_tsup-dts-rollup.js';
438
+ export { AuthSignInSplitProps } from './_tsup-dts-rollup.js';
439
+ export { AuthSignUpCardProps } from './_tsup-dts-rollup.js';
440
+ export { AuthSignUpCardSocialProvider } from './_tsup-dts-rollup.js';
441
+ export { AuthSocialProvider } from './_tsup-dts-rollup.js';
442
+ export { AuthVerifyEmailProps } from './_tsup-dts-rollup.js';
443
+ export { AuthVerifyOtpProps } from './_tsup-dts-rollup.js';
444
+ export { AuthForgotPassword } from './_tsup-dts-rollup.js';
445
+ export { AuthResetPassword } from './_tsup-dts-rollup.js';
446
+ export { AuthSignInSplit } from './_tsup-dts-rollup.js';
447
+ export { AuthSignUpCard } from './_tsup-dts-rollup.js';
448
+ export { AuthVerifyEmail } from './_tsup-dts-rollup.js';
449
+ export { AuthVerifyOtp } from './_tsup-dts-rollup.js';
450
+ export { mockAuthAdapter } from './_tsup-dts-rollup.js';
411
451
  export { cn } from './_tsup-dts-rollup.js';