@tetrascience-npm/tetrascience-react-ui 0.6.0 → 0.7.0-beta.103.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -0
- package/dist/components/ai/chain-of-thought.cjs +1 -1
- package/dist/components/ai/chain-of-thought.cjs.map +1 -1
- package/dist/components/ai/chain-of-thought.js +5 -5
- package/dist/components/ai/chain-of-thought.js.map +1 -1
- package/dist/components/ai/conversation.cjs +2 -2
- package/dist/components/ai/conversation.cjs.map +1 -1
- package/dist/components/ai/conversation.js +2 -2
- package/dist/components/ai/conversation.js.map +1 -1
- package/dist/components/ai/queue.cjs +1 -1
- package/dist/components/ai/queue.cjs.map +1 -1
- package/dist/components/ai/queue.js +9 -9
- package/dist/components/ai/queue.js.map +1 -1
- package/dist/components/charts/AreaGraph/AreaGraph.cjs +1 -1
- package/dist/components/charts/AreaGraph/AreaGraph.cjs.map +1 -1
- package/dist/components/charts/AreaGraph/AreaGraph.js +165 -103
- package/dist/components/charts/AreaGraph/AreaGraph.js.map +1 -1
- package/dist/components/charts/BarGraph/BarGraph.cjs +1 -1
- package/dist/components/charts/BarGraph/BarGraph.cjs.map +1 -1
- package/dist/components/charts/BarGraph/BarGraph.js +135 -90
- package/dist/components/charts/BarGraph/BarGraph.js.map +1 -1
- package/dist/components/charts/Boxplot/Boxplot.cjs +1 -1
- package/dist/components/charts/Boxplot/Boxplot.cjs.map +1 -1
- package/dist/components/charts/Boxplot/Boxplot.js +130 -92
- package/dist/components/charts/Boxplot/Boxplot.js.map +1 -1
- package/dist/components/charts/ChartTooltip/ChartTooltip.cjs +2 -0
- package/dist/components/charts/ChartTooltip/ChartTooltip.cjs.map +1 -0
- package/dist/components/charts/ChartTooltip/ChartTooltip.js +163 -0
- package/dist/components/charts/ChartTooltip/ChartTooltip.js.map +1 -0
- package/dist/components/charts/ChartTooltip/lines.cjs +2 -0
- package/dist/components/charts/ChartTooltip/lines.cjs.map +1 -0
- package/dist/components/charts/ChartTooltip/lines.js +29 -0
- package/dist/components/charts/ChartTooltip/lines.js.map +1 -0
- package/dist/components/charts/Chromatogram/Chromatogram.cjs +1 -1
- package/dist/components/charts/Chromatogram/Chromatogram.cjs.map +1 -1
- package/dist/components/charts/Chromatogram/Chromatogram.js +75 -61
- package/dist/components/charts/Chromatogram/Chromatogram.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.js +116 -108
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/annotations.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/annotations.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/annotations.js +32 -32
- package/dist/components/charts/ChromatogramChart/annotations.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.js +6 -6
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/constants.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/constants.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/constants.js +11 -5
- package/dist/components/charts/ChromatogramChart/constants.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/dataProcessing.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/dataProcessing.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/dataProcessing.js +38 -49
- package/dist/components/charts/ChromatogramChart/dataProcessing.js.map +1 -1
- package/dist/components/charts/DotPlot/DotPlot.cjs +1 -1
- package/dist/components/charts/DotPlot/DotPlot.cjs.map +1 -1
- package/dist/components/charts/DotPlot/DotPlot.js +112 -88
- package/dist/components/charts/DotPlot/DotPlot.js.map +1 -1
- package/dist/components/charts/Histogram/Histogram.cjs +1 -1
- package/dist/components/charts/Histogram/Histogram.cjs.map +1 -1
- package/dist/components/charts/Histogram/Histogram.js +132 -115
- package/dist/components/charts/Histogram/Histogram.js.map +1 -1
- package/dist/components/charts/LineGraph/LineGraph.cjs +1 -1
- package/dist/components/charts/LineGraph/LineGraph.cjs.map +1 -1
- package/dist/components/charts/LineGraph/LineGraph.js +151 -111
- package/dist/components/charts/LineGraph/LineGraph.js.map +1 -1
- package/dist/components/charts/PieChart/PieChart.cjs +1 -1
- package/dist/components/charts/PieChart/PieChart.cjs.map +1 -1
- package/dist/components/charts/PieChart/PieChart.js +81 -70
- package/dist/components/charts/PieChart/PieChart.js.map +1 -1
- package/dist/components/charts/PlateMap/PlateMap.cjs +1 -1
- package/dist/components/charts/PlateMap/PlateMap.cjs.map +1 -1
- package/dist/components/charts/PlateMap/PlateMap.js +271 -256
- package/dist/components/charts/PlateMap/PlateMap.js.map +1 -1
- package/dist/components/charts/PlateMap/constants.cjs +1 -1
- package/dist/components/charts/PlateMap/constants.cjs.map +1 -1
- package/dist/components/charts/PlateMap/constants.js +20 -29
- package/dist/components/charts/PlateMap/constants.js.map +1 -1
- package/dist/components/charts/ScatterGraph/ScatterGraph.cjs +1 -1
- package/dist/components/charts/ScatterGraph/ScatterGraph.cjs.map +1 -1
- package/dist/components/charts/ScatterGraph/ScatterGraph.js +154 -106
- package/dist/components/charts/ScatterGraph/ScatterGraph.js.map +1 -1
- package/dist/components/composed/DataAppShell/DataAppShell.cjs +1 -1
- package/dist/components/composed/DataAppShell/DataAppShell.cjs.map +1 -1
- package/dist/components/composed/DataAppShell/DataAppShell.js +118 -111
- package/dist/components/composed/DataAppShell/DataAppShell.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.js +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellLegend.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/WellLegend.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellLegend.js +8 -8
- package/dist/components/composed/PlateMapEditor/WellLegend.js.map +1 -1
- package/dist/components/composed/RichListItem/RichListItem.cjs +1 -1
- package/dist/components/composed/RichListItem/RichListItem.cjs.map +1 -1
- package/dist/components/composed/RichListItem/RichListItem.js +16 -16
- package/dist/components/composed/RichListItem/RichListItem.js.map +1 -1
- package/dist/components/ui/accordion.cjs +1 -1
- package/dist/components/ui/accordion.cjs.map +1 -1
- package/dist/components/ui/accordion.js +1 -1
- package/dist/components/ui/accordion.js.map +1 -1
- package/dist/components/ui/badge.cjs +1 -1
- package/dist/components/ui/badge.cjs.map +1 -1
- package/dist/components/ui/badge.js +8 -8
- package/dist/components/ui/badge.js.map +1 -1
- package/dist/components/ui/button.cjs +1 -1
- package/dist/components/ui/button.cjs.map +1 -1
- package/dist/components/ui/button.js +11 -11
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/checkbox.cjs +1 -1
- package/dist/components/ui/checkbox.cjs.map +1 -1
- package/dist/components/ui/checkbox.js +1 -1
- package/dist/components/ui/checkbox.js.map +1 -1
- package/dist/components/ui/combobox.cjs +1 -1
- package/dist/components/ui/combobox.cjs.map +1 -1
- package/dist/components/ui/combobox.js +12 -12
- package/dist/components/ui/combobox.js.map +1 -1
- package/dist/components/ui/input-group.cjs +1 -1
- package/dist/components/ui/input-group.cjs.map +1 -1
- package/dist/components/ui/input-group.js +19 -19
- package/dist/components/ui/input-group.js.map +1 -1
- package/dist/components/ui/item.cjs +1 -1
- package/dist/components/ui/item.cjs.map +1 -1
- package/dist/components/ui/item.js +1 -1
- package/dist/components/ui/item.js.map +1 -1
- package/dist/components/ui/menubar.cjs +1 -1
- package/dist/components/ui/menubar.cjs.map +1 -1
- package/dist/components/ui/menubar.js +1 -1
- package/dist/components/ui/menubar.js.map +1 -1
- package/dist/components/ui/navigation-menu.cjs +1 -1
- package/dist/components/ui/navigation-menu.cjs.map +1 -1
- package/dist/components/ui/navigation-menu.js +54 -54
- package/dist/components/ui/navigation-menu.js.map +1 -1
- package/dist/components/ui/radio-group.cjs +1 -1
- package/dist/components/ui/radio-group.cjs.map +1 -1
- package/dist/components/ui/radio-group.js +1 -1
- package/dist/components/ui/radio-group.js.map +1 -1
- package/dist/components/ui/resizable.cjs +1 -1
- package/dist/components/ui/resizable.cjs.map +1 -1
- package/dist/components/ui/resizable.js +27 -15
- package/dist/components/ui/resizable.js.map +1 -1
- package/dist/components/ui/select.cjs +1 -1
- package/dist/components/ui/select.cjs.map +1 -1
- package/dist/components/ui/select.js +1 -1
- package/dist/components/ui/select.js.map +1 -1
- package/dist/components/ui/slider.cjs +1 -1
- package/dist/components/ui/slider.cjs.map +1 -1
- package/dist/components/ui/slider.js +9 -9
- package/dist/components/ui/slider.js.map +1 -1
- package/dist/components/ui/table.cjs +1 -1
- package/dist/components/ui/table.cjs.map +1 -1
- package/dist/components/ui/table.js +13 -13
- package/dist/components/ui/table.js.map +1 -1
- package/dist/components/ui/tabs.cjs +1 -1
- package/dist/components/ui/tabs.cjs.map +1 -1
- package/dist/components/ui/tabs.js +7 -7
- package/dist/components/ui/tabs.js.map +1 -1
- package/dist/components/ui/toggle.cjs +1 -1
- package/dist/components/ui/toggle.cjs.map +1 -1
- package/dist/components/ui/toggle.js +12 -12
- package/dist/components/ui/toggle.js.map +1 -1
- package/dist/hooks/use-element-size.cjs +2 -0
- package/dist/hooks/use-element-size.cjs.map +1 -0
- package/dist/hooks/use-element-size.js +21 -0
- package/dist/hooks/use-element-size.js.map +1 -0
- package/dist/hooks/use-plotly-theme.cjs +1 -1
- package/dist/hooks/use-plotly-theme.cjs.map +1 -1
- package/dist/hooks/use-plotly-theme.js +4 -2
- package/dist/hooks/use-plotly-theme.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +254 -77
- package/dist/index.js +587 -581
- package/dist/index.js.map +1 -1
- package/dist/index.tailwind.css +1 -1
- package/dist/utils/colors.cjs +1 -1
- package/dist/utils/colors.cjs.map +1 -1
- package/dist/utils/colors.js +38 -93
- package/dist/utils/colors.js.map +1 -1
- package/package.json +18 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.js","sources":["../../../src/components/ai/queue.tsx"],"sourcesContent":["import { ChevronDownIcon, PaperclipIcon } from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport type { ComponentProps } from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface QueueMessagePart {\n type: string;\n text?: string;\n url?: string;\n filename?: string;\n mediaType?: string;\n}\n\nexport interface QueueMessage {\n id: string;\n parts: QueueMessagePart[];\n}\n\nexport interface QueueTodo {\n id: string;\n title: string;\n description?: string;\n status?: \"pending\" | \"completed\";\n}\n\n// ---------------------------------------------------------------------------\n// QueueItem\n// ---------------------------------------------------------------------------\n\nexport type QueueItemProps = ComponentProps<\"li\">;\n\nexport const QueueItem = ({ className, ...props }: QueueItemProps) => (\n <li\n className={cn(\n \"group flex flex-row items-center gap-2 rounded-md px-3 py-1 text-sm transition-colors hover:bg-muted\",\n className\n )}\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// QueueItemIndicator\n// ---------------------------------------------------------------------------\n\nexport type QueueItemStatus = \"pending\" | \"loading\" | \"done\" | \"error\";\n\nexport type QueueItemIndicatorProps = ComponentProps<\"span\"> & {\n /**\n * Visual state of the indicator dot.\n * - `pending` — unfilled muted ring\n * - `loading` — spinning ring (primary accent)\n * - `done` — filled muted dot (task complete)\n * - `error` — filled destructive dot\n */\n status?: QueueItemStatus;\n /** @deprecated Use `status=\"done\"` instead. */\n completed?: boolean;\n};\n\nconst INDICATOR_STATUS: Record<QueueItemStatus, string> = {\n pending: \"border border-muted-foreground/40\",\n loading:\n \"border-2 border-muted-foreground/20 border-t-primary animate-spin\",\n done: \"border border-muted-foreground/20 bg-muted-foreground/30\",\n error: \"border border-destructive/30 bg-destructive/70\",\n};\n\nexport const QueueItemIndicator = ({\n status,\n completed = false,\n className,\n ...props\n}: QueueItemIndicatorProps) => {\n const resolvedStatus: QueueItemStatus =\n status ?? (completed ? \"done\" : \"pending\");\n\n return (\n <span\n className={cn(\n \"inline-block size-2.5 shrink-0 rounded-full\",\n INDICATOR_STATUS[resolvedStatus],\n className\n )}\n {...props}\n />\n );\n};\n\n// ---------------------------------------------------------------------------\n// QueueItemContent\n// ---------------------------------------------------------------------------\n\nexport type QueueItemContentProps = ComponentProps<\"span\"> & {\n completed?: boolean;\n};\n\nexport const QueueItemContent = ({\n completed = false,\n className,\n ...props\n}: QueueItemContentProps) => (\n <span\n className={cn(\n \"min-w-0 flex-1 truncate\",\n completed\n ? \"text-muted-foreground/50 line-through\"\n : \"text-muted-foreground\",\n className\n )}\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// QueueItemDescription\n// For items with a description, wrap QueueItemContent + QueueItemDescription\n// in a <div className=\"flex flex-col gap-0.5 min-w-0 flex-1\">\n// ---------------------------------------------------------------------------\n\nexport type QueueItemDescriptionProps = ComponentProps<\"div\"> & {\n completed?: boolean;\n};\n\nexport const QueueItemDescription = ({\n completed = false,\n className,\n ...props\n}: QueueItemDescriptionProps) => (\n <div\n className={cn(\n \"text-xs\",\n completed\n ? \"text-muted-foreground/40 line-through\"\n : \"text-muted-foreground/70\",\n className\n )}\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// QueueItemActions / QueueItemAction\n// ---------------------------------------------------------------------------\n\nexport type QueueItemActionsProps = ComponentProps<\"div\">;\n\nexport const QueueItemActions = ({\n className,\n ...props\n}: QueueItemActionsProps) => (\n <div className={cn(\"ml-auto flex shrink-0 gap-1\", className)} {...props} />\n);\n\nexport type QueueItemActionProps = Omit<\n ComponentProps<typeof Button>,\n \"variant\" | \"size\"\n>;\n\nexport const QueueItemAction = ({\n className,\n ...props\n}: QueueItemActionProps) => (\n <Button\n className={cn(\n \"size-auto rounded p-1 text-muted-foreground opacity-0 transition-opacity hover:bg-muted-foreground/10 hover:text-foreground group-hover:opacity-100\",\n className\n )}\n size=\"icon\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// QueueItemAttachment / QueueItemImage / QueueItemFile\n// ---------------------------------------------------------------------------\n\nexport type QueueItemAttachmentProps = ComponentProps<\"div\">;\n\nexport const QueueItemAttachment = ({\n className,\n ...props\n}: QueueItemAttachmentProps) => (\n <div className={cn(\"flex flex-wrap gap-2\", className)} {...props} />\n);\n\nexport type QueueItemImageProps = ComponentProps<\"img\">;\n\nexport const QueueItemImage = ({\n className,\n ...props\n}: QueueItemImageProps) => (\n <img\n alt=\"\"\n className={cn(\"size-8 rounded border object-cover\", className)}\n height={32}\n width={32}\n {...props}\n />\n);\n\nexport type QueueItemFileProps = ComponentProps<\"span\">;\n\nexport const QueueItemFile = ({\n children,\n className,\n ...props\n}: QueueItemFileProps) => (\n <span\n className={cn(\n \"flex items-center gap-1 rounded border bg-muted px-2 py-1 text-xs\",\n className\n )}\n {...props}\n >\n <PaperclipIcon size={12} />\n <span className=\"max-w-[100px] truncate\">{children}</span>\n </span>\n);\n\n// ---------------------------------------------------------------------------\n// QueueList\n// ---------------------------------------------------------------------------\n\nexport type QueueListProps = ComponentProps<typeof ScrollArea>;\n\nexport const QueueList = ({\n children,\n className,\n ...props\n}: QueueListProps) => (\n <ScrollArea className={cn(\"-mb-1 mt-2\", className)} {...props}>\n <div className=\"max-h-40 pr-4\">\n <ul className=\"flex flex-col gap-0.5\">{children}</ul>\n </div>\n </ScrollArea>\n);\n\n// ---------------------------------------------------------------------------\n// QueueSection / QueueSectionTrigger / QueueSectionLabel / QueueSectionContent\n// ---------------------------------------------------------------------------\n\nexport type QueueSectionProps = ComponentProps<typeof Collapsible>;\n\nexport const QueueSection = ({\n className,\n defaultOpen = true,\n ...props\n}: QueueSectionProps) => (\n <Collapsible className={cn(className)} defaultOpen={defaultOpen} {...props} />\n);\n\nexport type QueueSectionTriggerProps = ComponentProps<\"button\">;\n\nexport const QueueSectionTrigger = ({\n children,\n className,\n ...props\n}: QueueSectionTriggerProps) => (\n <CollapsibleTrigger asChild>\n <button\n className={cn(\n \"group flex w-full items-center justify-between rounded-md bg-muted/40 px-3 py-2 text-left font-medium text-muted-foreground text-sm transition-colors hover:bg-muted\",\n className\n )}\n type=\"button\"\n {...props}\n >\n {children}\n </button>\n </CollapsibleTrigger>\n);\n\nexport type QueueSectionLabelProps = ComponentProps<\"span\"> & {\n count?: number;\n icon?: React.ReactNode;\n};\n\nexport const QueueSectionLabel = ({\n count,\n icon,\n className,\n children,\n ...props\n}: QueueSectionLabelProps) => (\n <span className={cn(\"flex items-center gap-2\", className)} {...props}>\n <ChevronDownIcon\n className=\"size-4 opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100 group-data-[state=open]:opacity-100 group-data-[state=closed]:-rotate-90\"\n data-slot=\"collapsible-chevron\"\n />\n {icon}\n <span>\n {count === undefined ? \"\" : `${count} `}\n {children}\n </span>\n </span>\n);\n\nexport type QueueSectionContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const QueueSectionContent = ({\n className,\n ...props\n}: QueueSectionContentProps) => (\n <CollapsibleContent className={cn(className)} {...props} />\n);\n\n// ---------------------------------------------------------------------------\n// Queue (root)\n// ---------------------------------------------------------------------------\n\nconst AUTO_HIDE_DELAY = 1000;\n\nexport type QueueProps = ComponentProps<\"div\"> & {\n isStreaming?: boolean;\n};\n\nexport const Queue = ({ className, isStreaming = false, children, style, id, ...props }: QueueProps) => {\n const [visible, setVisible] = useState(true);\n const hasEverStreamedRef = useRef(isStreaming);\n const [hasAutoHidden, setHasAutoHidden] = useState(false);\n\n useEffect(() => {\n if (isStreaming) hasEverStreamedRef.current = true;\n }, [isStreaming]);\n\n useEffect(() => {\n if (hasEverStreamedRef.current && !isStreaming && visible && !hasAutoHidden) {\n const timer = setTimeout(() => {\n setVisible(false);\n setHasAutoHidden(true);\n }, AUTO_HIDE_DELAY);\n return () => clearTimeout(timer);\n }\n }, [isStreaming, visible, hasAutoHidden]);\n\n // Spread data-* and aria-* attributes through; drop event handlers to avoid\n // onDrag type conflict between React and framer-motion.\n const passthroughProps = Object.fromEntries(\n Object.entries(props).filter(([k]) => k.startsWith(\"data-\") || k.startsWith(\"aria-\"))\n );\n\n return (\n <AnimatePresence>\n {visible && (\n <motion.div\n {...passthroughProps}\n className={cn(\n \"flex flex-col gap-2 rounded-xl border border-border bg-background px-2 pb-2 pt-2 shadow-xs\",\n className\n )}\n exit={{ opacity: 0, height: 0, marginTop: 0, marginBottom: 0, paddingTop: 0, paddingBottom: 0, overflow: \"hidden\" }}\n id={id}\n style={style}\n transition={{ duration: 0.35, ease: \"easeOut\" }}\n >\n {children}\n </motion.div>\n )}\n </AnimatePresence>\n );\n};\n"],"names":["QueueItem","className","props","jsx","cn","INDICATOR_STATUS","QueueItemIndicator","status","completed","QueueItemContent","QueueItemDescription","QueueItemActions","QueueItemAction","Button","QueueItemAttachment","QueueItemImage","QueueItemFile","children","jsxs","PaperclipIcon","QueueList","ScrollArea","QueueSection","defaultOpen","Collapsible","QueueSectionTrigger","CollapsibleTrigger","QueueSectionLabel","count","icon","ChevronDownIcon","QueueSectionContent","CollapsibleContent","AUTO_HIDE_DELAY","Queue","isStreaming","style","id","visible","setVisible","useState","hasEverStreamedRef","useRef","hasAutoHidden","setHasAutoHidden","useEffect","timer","passthroughProps","k","AnimatePresence","motion"],"mappings":";;;;;;;;AAyCO,MAAMA,IAAY,CAAC,EAAE,WAAAC,GAAW,GAAGC,QACxC,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC;AAAA,MACT;AAAA,MACAH;AAAA,IAAA;AAAA,IAED,GAAGC;AAAA,EAAA;AACN,GAsBIG,IAAoD;AAAA,EACxD,SAAS;AAAA,EACT,SACE;AAAA,EACF,MAAM;AAAA,EACN,OAAO;AACT,GAEaC,IAAqB,CAAC;AAAA,EACjC,QAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,WAAAP;AAAA,EACA,GAAGC;AACL,MAKI,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC;AAAA,MACT;AAAA,MACAC,EANJE,MAAWC,IAAY,SAAS,UAMG;AAAA,MAC/BP;AAAA,IAAA;AAAA,IAED,GAAGC;AAAA,EAAA;AAAA,GAaGO,IAAmB,CAAC;AAAA,EAC/B,WAAAD,IAAY;AAAA,EACZ,WAAAP;AAAA,EACA,GAAGC;AACL,MACE,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC;AAAA,MACT;AAAA,MACAI,IACI,0CACA;AAAA,MACJP;AAAA,IAAA;AAAA,IAED,GAAGC;AAAA,EAAA;AACN,GAaWQ,IAAuB,CAAC;AAAA,EACnC,WAAAF,IAAY;AAAA,EACZ,WAAAP;AAAA,EACA,GAAGC;AACL,MACE,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC;AAAA,MACT;AAAA,MACAI,IACI,0CACA;AAAA,MACJP;AAAA,IAAA;AAAA,IAED,GAAGC;AAAA,EAAA;AACN,GASWS,IAAmB,CAAC;AAAA,EAC/B,WAAAV;AAAA,EACA,GAAGC;AACL,MACE,gBAAAC,EAAC,SAAI,WAAWC,EAAG,+BAA+BH,CAAS,GAAI,GAAGC,EAAA,CAAO,GAQ9DU,IAAkB,CAAC;AAAA,EAC9B,WAAAX;AAAA,EACA,GAAGC;AACL,MACE,gBAAAC;AAAA,EAACU;AAAA,EAAA;AAAA,IACC,WAAWT;AAAA,MACT;AAAA,MACAH;AAAA,IAAA;AAAA,IAEF,MAAK;AAAA,IACL,MAAK;AAAA,IACL,SAAQ;AAAA,IACP,GAAGC;AAAA,EAAA;AACN,GASWY,IAAsB,CAAC;AAAA,EAClC,WAAAb;AAAA,EACA,GAAGC;AACL,MACE,gBAAAC,EAAC,SAAI,WAAWC,EAAG,wBAAwBH,CAAS,GAAI,GAAGC,EAAA,CAAO,GAKvDa,IAAiB,CAAC;AAAA,EAC7B,WAAAd;AAAA,EACA,GAAGC;AACL,MACE,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,KAAI;AAAA,IACJ,WAAWC,EAAG,sCAAsCH,CAAS;AAAA,IAC7D,QAAQ;AAAA,IACR,OAAO;AAAA,IACN,GAAGC;AAAA,EAAA;AACN,GAKWc,IAAgB,CAAC;AAAA,EAC5B,UAAAC;AAAA,EACA,WAAAhB;AAAA,EACA,GAAGC;AACL,MACE,gBAAAgB;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWd;AAAA,MACT;AAAA,MACAH;AAAA,IAAA;AAAA,IAED,GAAGC;AAAA,IAEJ,UAAA;AAAA,MAAA,gBAAAC,EAACgB,GAAA,EAAc,MAAM,GAAA,CAAI;AAAA,MACzB,gBAAAhB,EAAC,QAAA,EAAK,WAAU,0BAA0B,UAAAc,EAAA,CAAS;AAAA,IAAA;AAAA,EAAA;AACrD,GASWG,IAAY,CAAC;AAAA,EACxB,UAAAH;AAAA,EACA,WAAAhB;AAAA,EACA,GAAGC;AACL,wBACGmB,GAAA,EAAW,WAAWjB,EAAG,cAAcH,CAAS,GAAI,GAAGC,GACtD,4BAAC,OAAA,EAAI,WAAU,iBACb,UAAA,gBAAAC,EAAC,MAAA,EAAG,WAAU,yBAAyB,UAAAc,EAAA,CAAS,GAClD,EAAA,CACF,GASWK,IAAe,CAAC;AAAA,EAC3B,WAAArB;AAAA,EACA,aAAAsB,IAAc;AAAA,EACd,GAAGrB;AACL,MACE,gBAAAC,EAACqB,KAAY,WAAWpB,EAAGH,CAAS,GAAG,aAAAsB,GAA2B,GAAGrB,EAAA,CAAO,GAKjEuB,IAAsB,CAAC;AAAA,EAClC,UAAAR;AAAA,EACA,WAAAhB;AAAA,EACA,GAAGC;AACL,MACE,gBAAAC,EAACuB,GAAA,EAAmB,SAAO,IACzB,UAAA,gBAAAvB;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC;AAAA,MACT;AAAA,MACAH;AAAA,IAAA;AAAA,IAEF,MAAK;AAAA,IACJ,GAAGC;AAAA,IAEH,UAAAe;AAAA,EAAA;AACH,EAAA,CACF,GAQWU,IAAoB,CAAC;AAAA,EAChC,OAAAC;AAAA,EACA,MAAAC;AAAA,EACA,WAAA5B;AAAA,EACA,UAAAgB;AAAA,EACA,GAAGf;AACL,MACE,gBAAAgB,EAAC,UAAK,WAAWd,EAAG,2BAA2BH,CAAS,GAAI,GAAGC,GAC7D,UAAA;AAAA,EAAA,gBAAAC;AAAA,IAAC2B;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,aAAU;AAAA,IAAA;AAAA,EAAA;AAAA,EAEXD;AAAA,oBACA,QAAA,EACE,UAAA;AAAA,IAAAD,MAAU,SAAY,KAAK,GAAGA,CAAK;AAAA,IACnCX;AAAA,EAAA,EAAA,CACH;AAAA,EAAA,CACF,GAKWc,IAAsB,CAAC;AAAA,EAClC,WAAA9B;AAAA,EACA,GAAGC;AACL,wBACG8B,GAAA,EAAmB,WAAW5B,EAAGH,CAAS,GAAI,GAAGC,EAAA,CAAO,GAOrD+B,IAAkB,KAMXC,IAAQ,CAAC,EAAE,WAAAjC,GAAW,aAAAkC,IAAc,IAAO,UAAAlB,GAAU,OAAAmB,GAAO,IAAAC,GAAI,GAAGnC,QAAwB;AACtG,QAAM,CAACoC,GAASC,CAAU,IAAIC,EAAS,EAAI,GACrCC,IAAqBC,EAAOP,CAAW,GACvC,CAACQ,GAAeC,CAAgB,IAAIJ,EAAS,EAAK;AAExD,EAAAK,EAAU,MAAM;AACd,IAAIV,QAAgC,UAAU;AAAA,EAChD,GAAG,CAACA,CAAW,CAAC,GAEhBU,EAAU,MAAM;AACd,QAAIJ,EAAmB,WAAW,CAACN,KAAeG,KAAW,CAACK,GAAe;AAC3E,YAAMG,IAAQ,WAAW,MAAM;AAC7B,QAAAP,EAAW,EAAK,GAChBK,EAAiB,EAAI;AAAA,MACvB,GAAGX,CAAe;AAClB,aAAO,MAAM,aAAaa,CAAK;AAAA,IACjC;AAAA,EACF,GAAG,CAACX,GAAaG,GAASK,CAAa,CAAC;AAIxC,QAAMI,IAAmB,OAAO;AAAA,IAC9B,OAAO,QAAQ7C,CAAK,EAAE,OAAO,CAAC,CAAC8C,CAAC,MAAMA,EAAE,WAAW,OAAO,KAAKA,EAAE,WAAW,OAAO,CAAC;AAAA,EAAA;AAGtF,SACE,gBAAA7C,EAAC8C,KACE,UAAAX,KACC,gBAAAnC;AAAA,IAAC+C,EAAO;AAAA,IAAP;AAAA,MACE,GAAGH;AAAA,MACJ,WAAW3C;AAAA,QACT;AAAA,QACAH;AAAA,MAAA;AAAA,MAEF,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,cAAc,GAAG,YAAY,GAAG,eAAe,GAAG,UAAU,SAAA;AAAA,MACzG,IAAAoC;AAAA,MACA,OAAAD;AAAA,MACA,YAAY,EAAE,UAAU,MAAM,MAAM,UAAA;AAAA,MAEnC,UAAAnB;AAAA,IAAA;AAAA,EAAA,GAGP;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"queue.js","sources":["../../../src/components/ai/queue.tsx"],"sourcesContent":["import { ChevronDownIcon, PaperclipIcon } from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport type { ComponentProps } from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface QueueMessagePart {\n type: string;\n text?: string;\n url?: string;\n filename?: string;\n mediaType?: string;\n}\n\nexport interface QueueMessage {\n id: string;\n parts: QueueMessagePart[];\n}\n\nexport interface QueueTodo {\n id: string;\n title: string;\n description?: string;\n status?: \"pending\" | \"completed\";\n}\n\n// ---------------------------------------------------------------------------\n// QueueItem\n// ---------------------------------------------------------------------------\n\nexport type QueueItemProps = ComponentProps<\"li\">;\n\nexport const QueueItem = ({ className, ...props }: QueueItemProps) => (\n <li\n className={cn(\n \"group flex flex-row items-center gap-2 rounded-md px-3 py-1 text-sm transition-colors hover:bg-accent\",\n className\n )}\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// QueueItemIndicator\n// ---------------------------------------------------------------------------\n\nexport type QueueItemStatus = \"pending\" | \"loading\" | \"done\" | \"error\";\n\nexport type QueueItemIndicatorProps = ComponentProps<\"span\"> & {\n /**\n * Visual state of the indicator dot.\n * - `pending` — unfilled muted ring\n * - `loading` — spinning ring (primary accent)\n * - `done` — filled muted dot (task complete)\n * - `error` — filled destructive dot\n */\n status?: QueueItemStatus;\n /** @deprecated Use `status=\"done\"` instead. */\n completed?: boolean;\n};\n\nconst INDICATOR_STATUS: Record<QueueItemStatus, string> = {\n pending: \"border border-muted-foreground/40\",\n loading:\n \"border-2 border-muted-foreground/20 border-t-primary animate-spin\",\n done: \"border border-muted-foreground/20 bg-muted-foreground/30\",\n error: \"border border-destructive/30 bg-destructive/70\",\n};\n\nexport const QueueItemIndicator = ({\n status,\n completed = false,\n className,\n ...props\n}: QueueItemIndicatorProps) => {\n const resolvedStatus: QueueItemStatus =\n status ?? (completed ? \"done\" : \"pending\");\n\n return (\n <span\n className={cn(\n \"inline-block size-2.5 shrink-0 rounded-full\",\n INDICATOR_STATUS[resolvedStatus],\n className\n )}\n {...props}\n />\n );\n};\n\n// ---------------------------------------------------------------------------\n// QueueItemContent\n// ---------------------------------------------------------------------------\n\nexport type QueueItemContentProps = ComponentProps<\"span\"> & {\n completed?: boolean;\n};\n\nexport const QueueItemContent = ({\n completed = false,\n className,\n ...props\n}: QueueItemContentProps) => (\n <span\n className={cn(\n \"min-w-0 flex-1 truncate\",\n completed\n ? \"text-muted-foreground/50 line-through\"\n : \"text-muted-foreground\",\n className\n )}\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// QueueItemDescription\n// For items with a description, wrap QueueItemContent + QueueItemDescription\n// in a <div className=\"flex flex-col gap-0.5 min-w-0 flex-1\">\n// ---------------------------------------------------------------------------\n\nexport type QueueItemDescriptionProps = ComponentProps<\"div\"> & {\n completed?: boolean;\n};\n\nexport const QueueItemDescription = ({\n completed = false,\n className,\n ...props\n}: QueueItemDescriptionProps) => (\n <div\n className={cn(\n \"text-xs\",\n completed\n ? \"text-muted-foreground/40 line-through\"\n : \"text-muted-foreground/70\",\n className\n )}\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// QueueItemActions / QueueItemAction\n// ---------------------------------------------------------------------------\n\nexport type QueueItemActionsProps = ComponentProps<\"div\">;\n\nexport const QueueItemActions = ({\n className,\n ...props\n}: QueueItemActionsProps) => (\n <div className={cn(\"ml-auto flex shrink-0 gap-1\", className)} {...props} />\n);\n\nexport type QueueItemActionProps = Omit<\n ComponentProps<typeof Button>,\n \"variant\" | \"size\"\n>;\n\nexport const QueueItemAction = ({\n className,\n ...props\n}: QueueItemActionProps) => (\n <Button\n className={cn(\n \"size-auto rounded p-1 text-muted-foreground opacity-0 transition-opacity hover:bg-muted-foreground/10 hover:text-foreground group-hover:opacity-100\",\n className\n )}\n size=\"icon\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// QueueItemAttachment / QueueItemImage / QueueItemFile\n// ---------------------------------------------------------------------------\n\nexport type QueueItemAttachmentProps = ComponentProps<\"div\">;\n\nexport const QueueItemAttachment = ({\n className,\n ...props\n}: QueueItemAttachmentProps) => (\n <div className={cn(\"flex flex-wrap gap-2\", className)} {...props} />\n);\n\nexport type QueueItemImageProps = ComponentProps<\"img\">;\n\nexport const QueueItemImage = ({\n className,\n ...props\n}: QueueItemImageProps) => (\n <img\n alt=\"\"\n className={cn(\"size-8 rounded border object-cover\", className)}\n height={32}\n width={32}\n {...props}\n />\n);\n\nexport type QueueItemFileProps = ComponentProps<\"span\">;\n\nexport const QueueItemFile = ({\n children,\n className,\n ...props\n}: QueueItemFileProps) => (\n <span\n className={cn(\n \"flex items-center gap-1 rounded border bg-muted px-2 py-1 text-xs\",\n className\n )}\n {...props}\n >\n <PaperclipIcon size={12} />\n <span className=\"max-w-[100px] truncate\">{children}</span>\n </span>\n);\n\n// ---------------------------------------------------------------------------\n// QueueList\n// ---------------------------------------------------------------------------\n\nexport type QueueListProps = ComponentProps<typeof ScrollArea>;\n\nexport const QueueList = ({\n children,\n className,\n ...props\n}: QueueListProps) => (\n <ScrollArea className={cn(\"-mb-1 mt-2\", className)} {...props}>\n <div className=\"max-h-40 pr-4\">\n <ul className=\"flex flex-col gap-0.5\">{children}</ul>\n </div>\n </ScrollArea>\n);\n\n// ---------------------------------------------------------------------------\n// QueueSection / QueueSectionTrigger / QueueSectionLabel / QueueSectionContent\n// ---------------------------------------------------------------------------\n\nexport type QueueSectionProps = ComponentProps<typeof Collapsible>;\n\nexport const QueueSection = ({\n className,\n defaultOpen = true,\n ...props\n}: QueueSectionProps) => (\n <Collapsible className={cn(className)} defaultOpen={defaultOpen} {...props} />\n);\n\nexport type QueueSectionTriggerProps = ComponentProps<\"button\">;\n\nexport const QueueSectionTrigger = ({\n children,\n className,\n ...props\n}: QueueSectionTriggerProps) => (\n <CollapsibleTrigger asChild>\n <button\n className={cn(\n \"group flex w-full items-center justify-between rounded-md bg-muted/40 px-3 py-2 text-left font-medium text-muted-foreground text-sm transition-colors hover:bg-accent\",\n className\n )}\n type=\"button\"\n {...props}\n >\n {children}\n </button>\n </CollapsibleTrigger>\n);\n\nexport type QueueSectionLabelProps = ComponentProps<\"span\"> & {\n count?: number;\n icon?: React.ReactNode;\n};\n\nexport const QueueSectionLabel = ({\n count,\n icon,\n className,\n children,\n ...props\n}: QueueSectionLabelProps) => (\n <span className={cn(\"flex items-center gap-2\", className)} {...props}>\n <ChevronDownIcon\n className=\"size-4 opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100 group-data-[state=open]:opacity-100 group-data-[state=closed]:-rotate-90\"\n data-slot=\"collapsible-chevron\"\n />\n {icon}\n <span>\n {count === undefined ? \"\" : `${count} `}\n {children}\n </span>\n </span>\n);\n\nexport type QueueSectionContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const QueueSectionContent = ({\n className,\n ...props\n}: QueueSectionContentProps) => (\n <CollapsibleContent className={cn(className)} {...props} />\n);\n\n// ---------------------------------------------------------------------------\n// Queue (root)\n// ---------------------------------------------------------------------------\n\nconst AUTO_HIDE_DELAY = 1000;\n\nexport type QueueProps = ComponentProps<\"div\"> & {\n isStreaming?: boolean;\n};\n\nexport const Queue = ({ className, isStreaming = false, children, style, id, ...props }: QueueProps) => {\n const [visible, setVisible] = useState(true);\n const hasEverStreamedRef = useRef(isStreaming);\n const [hasAutoHidden, setHasAutoHidden] = useState(false);\n\n useEffect(() => {\n if (isStreaming) hasEverStreamedRef.current = true;\n }, [isStreaming]);\n\n useEffect(() => {\n if (hasEverStreamedRef.current && !isStreaming && visible && !hasAutoHidden) {\n const timer = setTimeout(() => {\n setVisible(false);\n setHasAutoHidden(true);\n }, AUTO_HIDE_DELAY);\n return () => clearTimeout(timer);\n }\n }, [isStreaming, visible, hasAutoHidden]);\n\n // Spread data-* and aria-* attributes through; drop event handlers to avoid\n // onDrag type conflict between React and framer-motion.\n const passthroughProps = Object.fromEntries(\n Object.entries(props).filter(([k]) => k.startsWith(\"data-\") || k.startsWith(\"aria-\"))\n );\n\n return (\n <AnimatePresence>\n {visible && (\n <motion.div\n {...passthroughProps}\n className={cn(\n \"flex flex-col gap-2 rounded-xl border border-border bg-background px-2 pb-2 pt-2 shadow-xs\",\n className\n )}\n exit={{ opacity: 0, height: 0, marginTop: 0, marginBottom: 0, paddingTop: 0, paddingBottom: 0, overflow: \"hidden\" }}\n id={id}\n style={style}\n transition={{ duration: 0.35, ease: \"easeOut\" }}\n >\n {children}\n </motion.div>\n )}\n </AnimatePresence>\n );\n};\n"],"names":["QueueItem","className","props","jsx","cn","INDICATOR_STATUS","QueueItemIndicator","status","completed","QueueItemContent","QueueItemDescription","QueueItemActions","QueueItemAction","Button","QueueItemAttachment","QueueItemImage","QueueItemFile","children","jsxs","PaperclipIcon","QueueList","ScrollArea","QueueSection","defaultOpen","Collapsible","QueueSectionTrigger","CollapsibleTrigger","QueueSectionLabel","count","icon","ChevronDownIcon","QueueSectionContent","CollapsibleContent","AUTO_HIDE_DELAY","Queue","isStreaming","style","id","visible","setVisible","useState","hasEverStreamedRef","useRef","hasAutoHidden","setHasAutoHidden","useEffect","timer","passthroughProps","k","AnimatePresence","motion"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("react/jsx-runtime"),L=require("plotly.js-dist"),n=require("react"),Z=require("../ChartTooltip/ChartTooltip.cjs"),$=require("../../../hooks/use-element-size.cjs"),ee=require("../../../hooks/use-plotly-theme.cjs"),te=require("../../../lib/utils.cjs"),W=require("../../../utils/colors.cjs"),oe=require("../ChartTooltip/lines.cjs"),re=80,ne=40,ie=({dataSeries:s,width:N,height:q,xRange:p,yRange:y,variant:w="normal",xTitle:v,yTitle:b,title:M,xTickText:x})=>{const m=n.useRef(null),r=ee.usePlotlyTheme(),[D,P]=$.useElementSize(),a=N??P.width,u=q??P.height,R=a>0&&u>0,F=N===void 0,J=q===void 0,k=n.useRef({width:a,height:u});k.current={width:a,height:u};const z=n.useRef(!1),E=n.useRef({width:0,height:0}),{bindTooltip:O,tooltipElement:K}=Z.useChartTooltip({getLines:t=>oe.chartTooltipLines(t.map(e=>typeof e.customdata=="number"?{...e,y:e.customdata}:e),{xLabel:v,yLabel:b})}),{xMin:X,xMax:T,yMin:V,yMax:Y}=n.useMemo(()=>{let t=Number.MAX_VALUE,e=Number.MIN_VALUE,i=Number.MAX_VALUE,o=Number.MIN_VALUE;s.forEach(h=>{h.x.forEach(f=>{t=Math.min(t,f),e=Math.max(e,f)}),h.y.forEach(f=>{i=Math.min(i,f),o=Math.max(o,f)})});const l=(e-t)*.1,c=(o-i)*.1;return{xMin:t-l,xMax:e+l,yMin:w==="stacked"?0:i-c,yMax:o+c}},[s,w]),d=n.useMemo(()=>p||[X,T],[p,X,T]),g=n.useMemo(()=>y||[V,Y],[y,V,Y]),j=n.useMemo(()=>{const t=d[1]-d[0];let e=Math.pow(10,Math.floor(Math.log10(t)));t/e>10&&(e=e*2),t/e<4&&(e=e/2);const i=[];let o=Math.ceil(d[0]/e)*e;for(;o<=d[1];)i.push(o),o+=e;return i},[d]),G=n.useMemo(()=>{const t=g[1]-g[0];let e=Math.pow(10,Math.floor(Math.log10(t)));t/e>10&&(e=e*2),t/e<4&&(e=e/2);const i=[];let o=Math.ceil(g[0]/e)*e;for(;o<=g[1];)i.push(o),o+=e;return i},[g]),I=n.useMemo(()=>[...new Set(s.flatMap(t=>t.x))].sort((t,e)=>t-e),[s]),C=!!x&&x.length===I.length,A=n.useMemo(()=>({tickcolor:r.tickColor,ticklen:12,tickwidth:1,ticks:"outside",tickfont:{size:16,color:r.textColor,family:"Inter, sans-serif",weight:400},linecolor:r.lineColor,linewidth:1,position:0,zeroline:!1}),[r]),_=n.useMemo(()=>M?{text:M,x:.5,y:.95,xanchor:"center",yanchor:"top",font:{size:32,weight:600,family:"Inter, sans-serif",color:r.textColor,lineheight:1.2,standoff:30}}:void 0,[M,r]);return n.useEffect(()=>{if(!m.current||!R)return;let t;if(w==="stacked"){const l=new Array(s[0]?.x.length||0).fill(0);t=s.map((c,h)=>{const f=c.y.map((Q,B)=>{const H=l[B]+Q;return l[B]=H,H}),U=W.seriesColor(h,c.color);return{x:c.x,y:f,customdata:c.y,type:"scatter",mode:"lines",name:c.name,hoverinfo:"none",fill:h===0?"tozeroy":"tonexty",fillcolor:U,line:{color:U,width:2}}})}else t=s.map((l,c)=>{const h=W.seriesColor(c,l.color);return{x:l.x,y:l.y,type:"scatter",mode:"lines",name:l.name,hoverinfo:"none",fill:l.fill||"tozeroy",fillcolor:h,line:{color:h,width:2}}});const e={width:k.current.width,height:k.current.height,..._?{title:_}:{},margin:{l:80,r:40,b:96,t:M?re:ne,pad:0},paper_bgcolor:r.paperBg,plot_bgcolor:r.plotBg,font:{family:"Inter, sans-serif"},dragmode:!1,xaxis:{title:{text:v,font:{size:16,color:r.textSecondary,family:"Inter, sans-serif",weight:400},standoff:15},gridcolor:r.gridColor,range:p,autorange:!p,tickmode:"array",tickvals:C?I:j,...C?{ticktext:x}:{},showgrid:!0,automargin:!0,...A},yaxis:{title:{text:b,font:{size:16,color:r.textSecondary,family:"Inter, sans-serif",weight:400},standoff:15},gridcolor:r.gridColor,range:y,autorange:!y,tickmode:"array",tickvals:G,showgrid:!0,automargin:!0,...A},legend:{x:.5,y:0,xanchor:"center",yanchor:"bottom",yref:"container",orientation:"h",font:{size:13,color:r.legendColor,family:"Inter, sans-serif",weight:500,lineheight:18}},showlegend:!0},i={responsive:!1,displayModeBar:!1,displaylogo:!1};L.newPlot(m.current,t,e,i),O(m.current);const o=m.current;return z.current=!0,E.current={...k.current},()=>{o&&(L.purge(o),z.current=!1)}},[s,R,p,y,d,g,w,v,b,M,_,A,j,G,I,C,x,r,O]),n.useEffect(()=>{const t=m.current;!t||!z.current||a<=0||u<=0||E.current.width===a&&E.current.height===u||(E.current={width:a,height:u},L.relayout(t,{width:a,height:u}).catch(()=>{}))},[a,u]),S.jsxs("div",{ref:D,className:te.cn("area-graph-container relative",F&&"w-full",J&&"h-full"),children:[S.jsx("div",{ref:m,style:{width:"100%",height:"100%"}}),K]})};exports.AreaGraph=ie;
|
|
2
2
|
//# sourceMappingURL=AreaGraph.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AreaGraph.cjs","sources":["../../../../src/components/charts/AreaGraph/AreaGraph.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\n\ninterface AreaDataSeries {\n x: number[];\n y: number[];\n name: string;\n color: string;\n fill?: \"tozeroy\" | \"tonexty\" | \"toself\";\n}\n\ntype AreaGraphVariant = \"normal\" | \"stacked\";\n\ninterface AreaGraphProps {\n dataSeries: AreaDataSeries[];\n width?: number;\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n variant?: AreaGraphVariant;\n xTitle?: string;\n yTitle?: string;\n title?: string;\n}\n\nconst AreaGraph: React.FC<AreaGraphProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n xRange,\n yRange,\n variant = \"normal\",\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n title = \"Area Graph\",\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n\n const { xMin, xMax, yMin, yMax } = useMemo(() => {\n let minX = Number.MAX_VALUE;\n let maxX = Number.MIN_VALUE;\n let minY = Number.MAX_VALUE;\n let maxY = Number.MIN_VALUE;\n\n dataSeries.forEach((series) => {\n series.x.forEach((x) => {\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n });\n series.y.forEach((y) => {\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n });\n });\n\n const xPadding = (maxX - minX) * 0.1;\n const yPadding = (maxY - minY) * 0.1;\n\n return {\n xMin: minX - xPadding,\n xMax: maxX + xPadding,\n yMin: variant === \"stacked\" ? 0 : minY - yPadding,\n yMax: maxY + yPadding,\n };\n }, [dataSeries, variant]);\n\n const effectiveXRange = useMemo(\n () => xRange || [xMin, xMax],\n [xRange, xMin, xMax],\n );\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const xTicks = useMemo(() => {\n const range = effectiveXRange[1] - effectiveXRange[0];\n let step = Math.pow(10, Math.floor(Math.log10(range)));\n\n if (range / step > 10) step = step * 2;\n if (range / step < 4) step = step / 2;\n\n const ticks = [];\n let current = Math.ceil(effectiveXRange[0] / step) * step;\n while (current <= effectiveXRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveXRange]);\n\n const yTicks = useMemo(() => {\n const range = effectiveYRange[1] - effectiveYRange[0];\n let step = Math.pow(10, Math.floor(Math.log10(range)));\n\n if (range / step > 10) step = step * 2;\n if (range / step < 4) step = step / 2;\n\n const ticks = [];\n let current = Math.ceil(effectiveYRange[0] / step) * step;\n while (current <= effectiveYRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveYRange]);\n\n const tickOptions = useMemo(\n () => ({\n tickcolor: theme.tickColor,\n ticklen: 12,\n tickwidth: 1,\n ticks: \"outside\" as const,\n tickfont: {\n size: 16,\n color: theme.textColor,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n linecolor: theme.lineColor,\n linewidth: 1,\n position: 0,\n zeroline: false,\n }),\n [theme],\n );\n\n const titleOptions = useMemo(\n () => ({\n text: title,\n x: 0.5,\n y: 0.95,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n font: {\n size: 32,\n weight: 600,\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n lineheight: 1.2,\n standoff: 30,\n },\n }),\n [title, theme],\n );\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n let data;\n\n if (variant === \"stacked\") {\n // For stacked mode, we need to calculate cumulative values\n const cumulativeY = new Array(dataSeries[0]?.x.length || 0).fill(0);\n\n data = dataSeries.map((series, index) => {\n // Calculate cumulative values for this series\n const stackedY = series.y.map((value, i) => {\n const result = cumulativeY[i] + value;\n cumulativeY[i] = result;\n return result;\n });\n\n return {\n x: series.x,\n y: stackedY,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: series.name,\n fill: index === 0 ? (\"tozeroy\" as const) : (\"tonexty\" as const),\n fillcolor: series.color,\n line: {\n color: series.color,\n width: 2,\n },\n };\n });\n } else {\n // Normal mode - each area fills independently from zero\n data = dataSeries.map((series) => ({\n x: series.x,\n y: series.y,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: series.name,\n fill: series.fill || (\"tozeroy\" as const),\n fillcolor: series.color,\n line: {\n color: series.color,\n width: 2,\n },\n }));\n }\n\n const layout = {\n width,\n height: height,\n title: titleOptions,\n margin: { l: 80, r: 40, b: 80, t: 80, pad: 0 },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: {\n family: \"Inter, sans-serif\",\n },\n dragmode: false as const,\n xaxis: {\n title: {\n text: xTitle,\n font: {\n size: 16,\n color: theme.textSecondary,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n standoff: 15,\n },\n gridcolor: theme.gridColor,\n range: xRange,\n autorange: !xRange,\n tickmode: \"array\" as const,\n tickvals: xTicks,\n showgrid: true,\n ...tickOptions,\n },\n yaxis: {\n title: {\n text: yTitle,\n font: {\n size: 16,\n color: theme.textSecondary,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n standoff: 15,\n },\n gridcolor: theme.gridColor,\n range: yRange,\n autorange: !yRange,\n tickmode: \"array\" as const,\n tickvals: yTicks,\n showgrid: true,\n ...tickOptions,\n },\n legend: {\n x: 0.5,\n y: -0.2,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n orientation: \"h\" as const,\n font: {\n size: 13,\n color: theme.legendColor,\n family: \"Inter, sans-serif\",\n weight: 500,\n lineheight: 18,\n },\n },\n showlegend: true,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, data, layout, config);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n // Cleanup function\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [dataSeries, width, height, xRange, yRange, effectiveXRange, effectiveYRange, variant, xTitle, yTitle, titleOptions, tickOptions, xTicks, yTicks, theme]);\n\n return (\n <div className=\"area-graph-container\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n </div>\n );\n};\n\nexport { AreaGraph };\nexport type { AreaDataSeries, AreaGraphVariant, AreaGraphProps };\n"],"names":["AreaGraph","dataSeries","width","height","xRange","yRange","variant","xTitle","yTitle","title","plotRef","useRef","theme","usePlotlyTheme","xMin","xMax","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveXRange","effectiveYRange","xTicks","range","step","ticks","current","yTicks","tickOptions","titleOptions","useEffect","data","cumulativeY","index","stackedY","value","i","result","layout","config","Plotly","plotElement","jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AreaGraph.cjs","sources":["../../../../src/components/charts/AreaGraph/AreaGraph.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { chartTooltipLines, useChartTooltip } from \"../ChartTooltip\";\n\nimport { useElementSize } from \"@/hooks/use-element-size\";\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { cn } from \"@/lib/utils\";\nimport { seriesColor } from \"@/utils/colors\";\n\ninterface AreaDataSeries {\n x: number[];\n y: number[];\n name: string;\n /** Optional color override (auto-assigned from CHART_COLORS if not provided) */\n color?: string;\n fill?: \"tozeroy\" | \"tonexty\" | \"toself\";\n}\n\ntype AreaGraphVariant = \"normal\" | \"stacked\";\n\n/** Top margin reserving room for the 32px title; reduced when no title is set */\nconst TITLE_MARGIN_TOP = 80;\nconst NO_TITLE_MARGIN_TOP = 40;\n\ninterface AreaGraphProps {\n dataSeries: AreaDataSeries[];\n /**\n * Fixed width in pixels. When omitted, the chart fills its container and\n * tracks the container's width via a `ResizeObserver`.\n */\n width?: number;\n /**\n * Fixed height in pixels. When omitted, the chart fills its container and\n * tracks the container's height via a `ResizeObserver`.\n */\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n variant?: AreaGraphVariant;\n xTitle?: string;\n yTitle?: string;\n title?: string;\n /**\n * Categorical labels for the x-axis ticks. When provided, the x data values\n * still drive area positioning but the displayed tick labels match these\n * strings in order (e.g. [\"Mon\", \"Tue\", …]). Should align 1:1 with the\n * unique, ordered x values across all series.\n */\n xTickText?: string[];\n}\n\nconst AreaGraph: React.FC<AreaGraphProps> = ({\n dataSeries,\n width,\n height,\n xRange,\n yRange,\n variant = \"normal\",\n xTitle,\n yTitle,\n title,\n xTickText,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n\n // When width/height are omitted the chart fills its container; otherwise the\n // explicit pixel size wins. The container is measured either way (cheap) but\n // only used as the resolved size for the omitted dimension(s).\n const [containerRef, measured] = useElementSize<HTMLDivElement>();\n const resolvedWidth = width ?? measured.width;\n const resolvedHeight = height ?? measured.height;\n const hasSize = resolvedWidth > 0 && resolvedHeight > 0;\n // Fill is per-dimension: omit width to fill the container width, omit height\n // to fill its height (so e.g. a fixed width with a container-driven height works).\n const fillWidth = width === undefined;\n const fillHeight = height === undefined;\n\n // Hold the latest resolved size in a ref so the newPlot effect can read it\n // without listing it as a dependency — size changes are handled by a\n // separate relayout effect rather than by tearing down and recreating the plot.\n const sizeRef = useRef({ width: resolvedWidth, height: resolvedHeight });\n sizeRef.current = { width: resolvedWidth, height: resolvedHeight };\n const plotInitedRef = useRef(false);\n // Size last applied to the plot, so the resize effect can skip a redundant\n // relayout right after newPlot already drew at that size.\n const appliedSizeRef = useRef({ width: 0, height: 0 });\n const { bindTooltip, tooltipElement } = useChartTooltip({\n // Stacked traces carry the original series values as customdata;\n // display those instead of the cumulative stack heights\n getLines: (points) =>\n chartTooltipLines(\n points.map((point) =>\n typeof point.customdata === \"number\"\n ? { ...point, y: point.customdata }\n : point,\n ),\n { xLabel: xTitle, yLabel: yTitle },\n ),\n });\n\n const { xMin, xMax, yMin, yMax } = useMemo(() => {\n let minX = Number.MAX_VALUE;\n let maxX = Number.MIN_VALUE;\n let minY = Number.MAX_VALUE;\n let maxY = Number.MIN_VALUE;\n\n dataSeries.forEach((series) => {\n series.x.forEach((x) => {\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n });\n series.y.forEach((y) => {\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n });\n });\n\n const xPadding = (maxX - minX) * 0.1;\n const yPadding = (maxY - minY) * 0.1;\n\n return {\n xMin: minX - xPadding,\n xMax: maxX + xPadding,\n yMin: variant === \"stacked\" ? 0 : minY - yPadding,\n yMax: maxY + yPadding,\n };\n }, [dataSeries, variant]);\n\n const effectiveXRange = useMemo(\n () => xRange || [xMin, xMax],\n [xRange, xMin, xMax],\n );\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const xTicks = useMemo(() => {\n const range = effectiveXRange[1] - effectiveXRange[0];\n let step = Math.pow(10, Math.floor(Math.log10(range)));\n\n if (range / step > 10) step = step * 2;\n if (range / step < 4) step = step / 2;\n\n const ticks = [];\n let current = Math.ceil(effectiveXRange[0] / step) * step;\n while (current <= effectiveXRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveXRange]);\n\n const yTicks = useMemo(() => {\n const range = effectiveYRange[1] - effectiveYRange[0];\n let step = Math.pow(10, Math.floor(Math.log10(range)));\n\n if (range / step > 10) step = step * 2;\n if (range / step < 4) step = step / 2;\n\n const ticks = [];\n let current = Math.ceil(effectiveYRange[0] / step) * step;\n while (current <= effectiveYRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveYRange]);\n\n // When categorical labels are supplied, ticks must sit on the actual data\n // x-positions rather than the computed nice-step values above. Sorted\n // ascending so labels map deterministically to x regardless of series order.\n const xDataValues = useMemo(\n () => [...new Set(dataSeries.flatMap((s) => s.x))].sort((a, b) => a - b),\n [dataSeries],\n );\n\n // Only apply categorical labels when they align 1:1 with the tick positions;\n // a mismatch would silently mis-label ticks, so fall back to numeric ticks.\n const useCategoricalX = !!xTickText && xTickText.length === xDataValues.length;\n\n const tickOptions = useMemo(\n () => ({\n tickcolor: theme.tickColor,\n ticklen: 12,\n tickwidth: 1,\n ticks: \"outside\" as const,\n tickfont: {\n size: 16,\n color: theme.textColor,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n linecolor: theme.lineColor,\n linewidth: 1,\n position: 0,\n zeroline: false,\n }),\n [theme],\n );\n\n const titleOptions = useMemo(\n () =>\n title\n ? {\n text: title,\n x: 0.5,\n y: 0.95,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n font: {\n size: 32,\n weight: 600,\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n lineheight: 1.2,\n standoff: 30,\n },\n }\n : undefined,\n [title, theme],\n );\n\n useEffect(() => {\n if (!plotRef.current || !hasSize) return;\n\n let data;\n\n if (variant === \"stacked\") {\n // For stacked mode, we need to calculate cumulative values\n const cumulativeY = new Array(dataSeries[0]?.x.length || 0).fill(0);\n\n data = dataSeries.map((series, index) => {\n // Calculate cumulative values for this series\n const stackedY = series.y.map((value, i) => {\n const result = cumulativeY[i] + value;\n cumulativeY[i] = result;\n return result;\n });\n\n const color = seriesColor(index, series.color);\n return {\n x: series.x,\n y: stackedY,\n // Tooltips report the series' own values, not the stacked sums\n customdata: series.y,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: series.name,\n hoverinfo: \"none\" as const,\n fill: index === 0 ? (\"tozeroy\" as const) : (\"tonexty\" as const),\n fillcolor: color,\n line: {\n color,\n width: 2,\n },\n };\n });\n } else {\n // Normal mode - each area fills independently from zero\n data = dataSeries.map((series, index) => {\n const color = seriesColor(index, series.color);\n return {\n x: series.x,\n y: series.y,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: series.name,\n hoverinfo: \"none\" as const,\n fill: series.fill || (\"tozeroy\" as const),\n fillcolor: color,\n line: {\n color,\n width: 2,\n },\n };\n });\n }\n\n const layout = {\n width: sizeRef.current.width,\n height: sizeRef.current.height,\n ...(titleOptions ? { title: titleOptions } : {}),\n margin: {\n l: 80,\n r: 40,\n // Reserve room for tick labels, the x-axis title, and the\n // container-anchored bottom legend stacked beneath them.\n b: 96,\n t: title ? TITLE_MARGIN_TOP : NO_TITLE_MARGIN_TOP,\n pad: 0,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: {\n family: \"Inter, sans-serif\",\n },\n dragmode: false as const,\n xaxis: {\n title: {\n text: xTitle,\n font: {\n size: 16,\n color: theme.textSecondary,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n standoff: 15,\n },\n gridcolor: theme.gridColor,\n range: xRange,\n autorange: !xRange,\n tickmode: \"array\" as const,\n tickvals: useCategoricalX ? xDataValues : xTicks,\n ...(useCategoricalX ? { ticktext: xTickText } : {}),\n showgrid: true,\n // Reserve space for tick labels + the axis title so the bottom legend\n // can't overlap them at small sizes (SW-2157).\n automargin: true,\n ...tickOptions,\n },\n yaxis: {\n title: {\n text: yTitle,\n font: {\n size: 16,\n color: theme.textSecondary,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n standoff: 15,\n },\n gridcolor: theme.gridColor,\n range: yRange,\n autorange: !yRange,\n tickmode: \"array\" as const,\n tickvals: yTicks,\n showgrid: true,\n automargin: true,\n ...tickOptions,\n },\n legend: {\n // Anchor to the bottom of the container (not the plot area) so the\n // legend always clears the x-axis tick labels + title — a paper-relative\n // fractional offset collapses into the ticks at small heights (SW-2157).\n x: 0.5,\n y: 0,\n xanchor: \"center\" as const,\n yanchor: \"bottom\" as const,\n yref: \"container\" as const,\n orientation: \"h\" as const,\n font: {\n size: 13,\n color: theme.legendColor,\n family: \"Inter, sans-serif\",\n weight: 500,\n lineheight: 18,\n },\n },\n showlegend: true,\n };\n\n const config = {\n // We drive sizing explicitly from the measured container, so Plotly's own\n // window-resize responsiveness is disabled (it can't see container resizes).\n responsive: false,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, data, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n plotInitedRef.current = true;\n appliedSizeRef.current = { ...sizeRef.current };\n\n // Cleanup function\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n plotInitedRef.current = false;\n }\n };\n }, [dataSeries, hasSize, xRange, yRange, effectiveXRange, effectiveYRange, variant, xTitle, yTitle, title, titleOptions, tickOptions, xTicks, yTicks, xDataValues, useCategoricalX, xTickText, theme, bindTooltip]);\n\n // Resize in place when the measured/overridden size changes — far cheaper\n // than recreating the plot (and it preserves tooltip/event bindings).\n useEffect(() => {\n const plotElement = plotRef.current;\n if (!plotElement || !plotInitedRef.current || resolvedWidth <= 0 || resolvedHeight <= 0) {\n return;\n }\n // newPlot already drew at the current size; skip the redundant relayout\n // (it would queue an automargin redraw that can reject if we unmount first).\n if (\n appliedSizeRef.current.width === resolvedWidth &&\n appliedSizeRef.current.height === resolvedHeight\n ) {\n return;\n }\n appliedSizeRef.current = { width: resolvedWidth, height: resolvedHeight };\n // Swallow rejections from a relayout that races an unmount/purge.\n void Plotly.relayout(plotElement, { width: resolvedWidth, height: resolvedHeight }).catch(\n () => {},\n );\n }, [resolvedWidth, resolvedHeight]);\n\n return (\n <div\n ref={containerRef}\n className={cn(\"area-graph-container relative\", fillWidth && \"w-full\", fillHeight && \"h-full\")}\n >\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n {tooltipElement}\n </div>\n );\n};\n\nexport { AreaGraph };\nexport type { AreaDataSeries, AreaGraphVariant, AreaGraphProps };\n"],"names":["TITLE_MARGIN_TOP","NO_TITLE_MARGIN_TOP","AreaGraph","dataSeries","width","height","xRange","yRange","variant","xTitle","yTitle","title","xTickText","plotRef","useRef","theme","usePlotlyTheme","containerRef","measured","useElementSize","resolvedWidth","resolvedHeight","hasSize","fillWidth","fillHeight","sizeRef","plotInitedRef","appliedSizeRef","bindTooltip","tooltipElement","useChartTooltip","points","chartTooltipLines","point","xMin","xMax","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveXRange","effectiveYRange","xTicks","range","step","ticks","current","yTicks","xDataValues","s","a","b","useCategoricalX","tickOptions","titleOptions","useEffect","data","cumulativeY","index","stackedY","value","i","result","color","seriesColor","layout","config","Plotly","plotElement","jsxs","cn","jsx"],"mappings":"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"}
|
|
@@ -1,59 +1,79 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import
|
|
3
|
-
import { useRef as
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import { jsxs as S, jsx as tt } from "react/jsx-runtime";
|
|
2
|
+
import N from "plotly.js-dist";
|
|
3
|
+
import { useRef as E, useMemo as f, useEffect as q } from "react";
|
|
4
|
+
import { useChartTooltip as ot } from "../ChartTooltip/ChartTooltip.js";
|
|
5
|
+
import { useElementSize as et } from "../../../hooks/use-element-size.js";
|
|
6
|
+
import { usePlotlyTheme as rt } from "../../../hooks/use-plotly-theme.js";
|
|
7
|
+
import { cn as nt } from "../../../lib/utils.js";
|
|
8
|
+
import { seriesColor as F } from "../../../utils/colors.js";
|
|
9
|
+
import { chartTooltipLines as it } from "../ChartTooltip/lines.js";
|
|
10
|
+
const lt = 80, ct = 40, yt = ({
|
|
11
|
+
dataSeries: c,
|
|
12
|
+
width: P,
|
|
13
|
+
height: X,
|
|
14
|
+
xRange: p,
|
|
15
|
+
yRange: y,
|
|
16
|
+
variant: M = "normal",
|
|
17
|
+
xTitle: I,
|
|
18
|
+
yTitle: b,
|
|
19
|
+
title: w,
|
|
20
|
+
xTickText: x
|
|
15
21
|
}) => {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
const u = E(null), r = rt(), [J, O] = et(), a = P ?? O.width, s = X ?? O.height, V = a > 0 && s > 0, K = P === void 0, Q = X === void 0, k = E({ width: a, height: s });
|
|
23
|
+
k.current = { width: a, height: s };
|
|
24
|
+
const z = E(!1), v = E({ width: 0, height: 0 }), { bindTooltip: Y, tooltipElement: Z } = ot({
|
|
25
|
+
// Stacked traces carry the original series values as customdata;
|
|
26
|
+
// display those instead of the cumulative stack heights
|
|
27
|
+
getLines: (o) => it(
|
|
28
|
+
o.map(
|
|
29
|
+
(t) => typeof t.customdata == "number" ? { ...t, y: t.customdata } : t
|
|
30
|
+
),
|
|
31
|
+
{ xLabel: I, yLabel: b }
|
|
32
|
+
)
|
|
33
|
+
}), { xMin: U, xMax: B, yMin: G, yMax: j } = f(() => {
|
|
34
|
+
let o = Number.MAX_VALUE, t = Number.MIN_VALUE, n = Number.MAX_VALUE, e = Number.MIN_VALUE;
|
|
35
|
+
c.forEach((h) => {
|
|
36
|
+
h.x.forEach((m) => {
|
|
37
|
+
o = Math.min(o, m), t = Math.max(t, m);
|
|
38
|
+
}), h.y.forEach((m) => {
|
|
39
|
+
n = Math.min(n, m), e = Math.max(e, m);
|
|
23
40
|
});
|
|
24
41
|
});
|
|
25
|
-
const
|
|
42
|
+
const i = (t - o) * 0.1, l = (e - n) * 0.1;
|
|
26
43
|
return {
|
|
27
|
-
xMin: o -
|
|
28
|
-
xMax: t +
|
|
29
|
-
yMin:
|
|
30
|
-
yMax: e +
|
|
44
|
+
xMin: o - i,
|
|
45
|
+
xMax: t + i,
|
|
46
|
+
yMin: M === "stacked" ? 0 : n - l,
|
|
47
|
+
yMax: e + l
|
|
31
48
|
};
|
|
32
|
-
}, [
|
|
33
|
-
() =>
|
|
34
|
-
[
|
|
35
|
-
),
|
|
36
|
-
() =>
|
|
37
|
-
[
|
|
38
|
-
),
|
|
39
|
-
const o =
|
|
49
|
+
}, [c, M]), d = f(
|
|
50
|
+
() => p || [U, B],
|
|
51
|
+
[p, U, B]
|
|
52
|
+
), g = f(
|
|
53
|
+
() => y || [G, j],
|
|
54
|
+
[y, G, j]
|
|
55
|
+
), H = f(() => {
|
|
56
|
+
const o = d[1] - d[0];
|
|
40
57
|
let t = Math.pow(10, Math.floor(Math.log10(o)));
|
|
41
58
|
o / t > 10 && (t = t * 2), o / t < 4 && (t = t / 2);
|
|
42
|
-
const
|
|
43
|
-
let e = Math.ceil(
|
|
44
|
-
for (; e <=
|
|
45
|
-
|
|
46
|
-
return
|
|
47
|
-
}, [
|
|
48
|
-
const o =
|
|
59
|
+
const n = [];
|
|
60
|
+
let e = Math.ceil(d[0] / t) * t;
|
|
61
|
+
for (; e <= d[1]; )
|
|
62
|
+
n.push(e), e += t;
|
|
63
|
+
return n;
|
|
64
|
+
}, [d]), R = f(() => {
|
|
65
|
+
const o = g[1] - g[0];
|
|
49
66
|
let t = Math.pow(10, Math.floor(Math.log10(o)));
|
|
50
67
|
o / t > 10 && (t = t * 2), o / t < 4 && (t = t / 2);
|
|
51
|
-
const
|
|
52
|
-
let e = Math.ceil(
|
|
53
|
-
for (; e <=
|
|
54
|
-
|
|
55
|
-
return
|
|
56
|
-
}, [
|
|
68
|
+
const n = [];
|
|
69
|
+
let e = Math.ceil(g[0] / t) * t;
|
|
70
|
+
for (; e <= g[1]; )
|
|
71
|
+
n.push(e), e += t;
|
|
72
|
+
return n;
|
|
73
|
+
}, [g]), _ = f(
|
|
74
|
+
() => [...new Set(c.flatMap((o) => o.x))].sort((o, t) => o - t),
|
|
75
|
+
[c]
|
|
76
|
+
), A = !!x && x.length === _.length, C = f(
|
|
57
77
|
() => ({
|
|
58
78
|
tickcolor: r.tickColor,
|
|
59
79
|
ticklen: 12,
|
|
@@ -71,9 +91,9 @@ const q = ({
|
|
|
71
91
|
zeroline: !1
|
|
72
92
|
}),
|
|
73
93
|
[r]
|
|
74
|
-
),
|
|
75
|
-
() =>
|
|
76
|
-
text:
|
|
94
|
+
), L = f(
|
|
95
|
+
() => w ? {
|
|
96
|
+
text: w,
|
|
77
97
|
x: 0.5,
|
|
78
98
|
y: 0.95,
|
|
79
99
|
xanchor: "center",
|
|
@@ -86,52 +106,67 @@ const q = ({
|
|
|
86
106
|
lineheight: 1.2,
|
|
87
107
|
standoff: 30
|
|
88
108
|
}
|
|
89
|
-
}
|
|
90
|
-
[
|
|
109
|
+
} : void 0,
|
|
110
|
+
[w, r]
|
|
91
111
|
);
|
|
92
|
-
return
|
|
93
|
-
if (!
|
|
112
|
+
return q(() => {
|
|
113
|
+
if (!u.current || !V) return;
|
|
94
114
|
let o;
|
|
95
|
-
if (
|
|
96
|
-
const
|
|
97
|
-
o =
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
return
|
|
101
|
-
});
|
|
115
|
+
if (M === "stacked") {
|
|
116
|
+
const i = new Array(c[0]?.x.length || 0).fill(0);
|
|
117
|
+
o = c.map((l, h) => {
|
|
118
|
+
const m = l.y.map(($, W) => {
|
|
119
|
+
const D = i[W] + $;
|
|
120
|
+
return i[W] = D, D;
|
|
121
|
+
}), T = F(h, l.color);
|
|
122
|
+
return {
|
|
123
|
+
x: l.x,
|
|
124
|
+
y: m,
|
|
125
|
+
// Tooltips report the series' own values, not the stacked sums
|
|
126
|
+
customdata: l.y,
|
|
127
|
+
type: "scatter",
|
|
128
|
+
mode: "lines",
|
|
129
|
+
name: l.name,
|
|
130
|
+
hoverinfo: "none",
|
|
131
|
+
fill: h === 0 ? "tozeroy" : "tonexty",
|
|
132
|
+
fillcolor: T,
|
|
133
|
+
line: {
|
|
134
|
+
color: T,
|
|
135
|
+
width: 2
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
} else
|
|
140
|
+
o = c.map((i, l) => {
|
|
141
|
+
const h = F(l, i.color);
|
|
102
142
|
return {
|
|
103
143
|
x: i.x,
|
|
104
|
-
y:
|
|
144
|
+
y: i.y,
|
|
105
145
|
type: "scatter",
|
|
106
146
|
mode: "lines",
|
|
107
147
|
name: i.name,
|
|
108
|
-
|
|
109
|
-
|
|
148
|
+
hoverinfo: "none",
|
|
149
|
+
fill: i.fill || "tozeroy",
|
|
150
|
+
fillcolor: h,
|
|
110
151
|
line: {
|
|
111
|
-
color:
|
|
152
|
+
color: h,
|
|
112
153
|
width: 2
|
|
113
154
|
}
|
|
114
155
|
};
|
|
115
156
|
});
|
|
116
|
-
} else
|
|
117
|
-
o = s.map((n) => ({
|
|
118
|
-
x: n.x,
|
|
119
|
-
y: n.y,
|
|
120
|
-
type: "scatter",
|
|
121
|
-
mode: "lines",
|
|
122
|
-
name: n.name,
|
|
123
|
-
fill: n.fill || "tozeroy",
|
|
124
|
-
fillcolor: n.color,
|
|
125
|
-
line: {
|
|
126
|
-
color: n.color,
|
|
127
|
-
width: 2
|
|
128
|
-
}
|
|
129
|
-
}));
|
|
130
157
|
const t = {
|
|
131
|
-
width:
|
|
132
|
-
height:
|
|
133
|
-
title:
|
|
134
|
-
margin: {
|
|
158
|
+
width: k.current.width,
|
|
159
|
+
height: k.current.height,
|
|
160
|
+
...L ? { title: L } : {},
|
|
161
|
+
margin: {
|
|
162
|
+
l: 80,
|
|
163
|
+
r: 40,
|
|
164
|
+
// Reserve room for tick labels, the x-axis title, and the
|
|
165
|
+
// container-anchored bottom legend stacked beneath them.
|
|
166
|
+
b: 96,
|
|
167
|
+
t: w ? lt : ct,
|
|
168
|
+
pad: 0
|
|
169
|
+
},
|
|
135
170
|
paper_bgcolor: r.paperBg,
|
|
136
171
|
plot_bgcolor: r.plotBg,
|
|
137
172
|
font: {
|
|
@@ -140,7 +175,7 @@ const q = ({
|
|
|
140
175
|
dragmode: !1,
|
|
141
176
|
xaxis: {
|
|
142
177
|
title: {
|
|
143
|
-
text:
|
|
178
|
+
text: I,
|
|
144
179
|
font: {
|
|
145
180
|
size: 16,
|
|
146
181
|
color: r.textSecondary,
|
|
@@ -150,16 +185,20 @@ const q = ({
|
|
|
150
185
|
standoff: 15
|
|
151
186
|
},
|
|
152
187
|
gridcolor: r.gridColor,
|
|
153
|
-
range:
|
|
154
|
-
autorange: !
|
|
188
|
+
range: p,
|
|
189
|
+
autorange: !p,
|
|
155
190
|
tickmode: "array",
|
|
156
|
-
tickvals:
|
|
191
|
+
tickvals: A ? _ : H,
|
|
192
|
+
...A ? { ticktext: x } : {},
|
|
157
193
|
showgrid: !0,
|
|
158
|
-
|
|
194
|
+
// Reserve space for tick labels + the axis title so the bottom legend
|
|
195
|
+
// can't overlap them at small sizes (SW-2157).
|
|
196
|
+
automargin: !0,
|
|
197
|
+
...C
|
|
159
198
|
},
|
|
160
199
|
yaxis: {
|
|
161
200
|
title: {
|
|
162
|
-
text:
|
|
201
|
+
text: b,
|
|
163
202
|
font: {
|
|
164
203
|
size: 16,
|
|
165
204
|
color: r.textSecondary,
|
|
@@ -169,18 +208,23 @@ const q = ({
|
|
|
169
208
|
standoff: 15
|
|
170
209
|
},
|
|
171
210
|
gridcolor: r.gridColor,
|
|
172
|
-
range:
|
|
173
|
-
autorange: !
|
|
211
|
+
range: y,
|
|
212
|
+
autorange: !y,
|
|
174
213
|
tickmode: "array",
|
|
175
|
-
tickvals:
|
|
214
|
+
tickvals: R,
|
|
176
215
|
showgrid: !0,
|
|
177
|
-
|
|
216
|
+
automargin: !0,
|
|
217
|
+
...C
|
|
178
218
|
},
|
|
179
219
|
legend: {
|
|
220
|
+
// Anchor to the bottom of the container (not the plot area) so the
|
|
221
|
+
// legend always clears the x-axis tick labels + title — a paper-relative
|
|
222
|
+
// fractional offset collapses into the ticks at small heights (SW-2157).
|
|
180
223
|
x: 0.5,
|
|
181
|
-
y:
|
|
224
|
+
y: 0,
|
|
182
225
|
xanchor: "center",
|
|
183
|
-
yanchor: "
|
|
226
|
+
yanchor: "bottom",
|
|
227
|
+
yref: "container",
|
|
184
228
|
orientation: "h",
|
|
185
229
|
font: {
|
|
186
230
|
size: 13,
|
|
@@ -191,19 +235,37 @@ const q = ({
|
|
|
191
235
|
}
|
|
192
236
|
},
|
|
193
237
|
showlegend: !0
|
|
194
|
-
},
|
|
195
|
-
|
|
238
|
+
}, n = {
|
|
239
|
+
// We drive sizing explicitly from the measured container, so Plotly's own
|
|
240
|
+
// window-resize responsiveness is disabled (it can't see container resizes).
|
|
241
|
+
responsive: !1,
|
|
196
242
|
displayModeBar: !1,
|
|
197
243
|
displaylogo: !1
|
|
198
244
|
};
|
|
199
|
-
|
|
200
|
-
const e =
|
|
201
|
-
return () => {
|
|
202
|
-
e &&
|
|
245
|
+
N.newPlot(u.current, o, t, n), Y(u.current);
|
|
246
|
+
const e = u.current;
|
|
247
|
+
return z.current = !0, v.current = { ...k.current }, () => {
|
|
248
|
+
e && (N.purge(e), z.current = !1);
|
|
203
249
|
};
|
|
204
|
-
}, [
|
|
250
|
+
}, [c, V, p, y, d, g, M, I, b, w, L, C, H, R, _, A, x, r, Y]), q(() => {
|
|
251
|
+
const o = u.current;
|
|
252
|
+
!o || !z.current || a <= 0 || s <= 0 || v.current.width === a && v.current.height === s || (v.current = { width: a, height: s }, N.relayout(o, { width: a, height: s }).catch(
|
|
253
|
+
() => {
|
|
254
|
+
}
|
|
255
|
+
));
|
|
256
|
+
}, [a, s]), /* @__PURE__ */ S(
|
|
257
|
+
"div",
|
|
258
|
+
{
|
|
259
|
+
ref: J,
|
|
260
|
+
className: nt("area-graph-container relative", K && "w-full", Q && "h-full"),
|
|
261
|
+
children: [
|
|
262
|
+
/* @__PURE__ */ tt("div", { ref: u, style: { width: "100%", height: "100%" } }),
|
|
263
|
+
Z
|
|
264
|
+
]
|
|
265
|
+
}
|
|
266
|
+
);
|
|
205
267
|
};
|
|
206
268
|
export {
|
|
207
|
-
|
|
269
|
+
yt as AreaGraph
|
|
208
270
|
};
|
|
209
271
|
//# sourceMappingURL=AreaGraph.js.map
|