@ai-matrx/design-system 0.86.356 → 0.86.357
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/CHANGELOG.md +5 -0
- package/dist/auth-gate-dialog.js +2 -2
- package/dist/carousel.js +7 -6
- package/dist/carousel.js.map +1 -1
- package/dist/{chunk-UWTODOMD.js → chunk-2BQAHLU3.js} +4 -4
- package/dist/chunk-5Z5GTXKL.js +79 -0
- package/dist/chunk-5Z5GTXKL.js.map +1 -0
- package/dist/{chunk-2PO3N42Q.js → chunk-ACZALXD6.js} +3 -3
- package/dist/{chunk-4WSXAP24.js → chunk-BB5LA7FQ.js} +3 -1
- package/dist/chunk-BB5LA7FQ.js.map +1 -0
- package/dist/{chunk-RLM4RSED.js → chunk-GUGBVQ4T.js} +6 -4
- package/dist/{chunk-RLM4RSED.js.map → chunk-GUGBVQ4T.js.map} +1 -1
- package/dist/{chunk-LJKF267O.js → chunk-HS6GMHKZ.js} +18 -76
- package/dist/chunk-HS6GMHKZ.js.map +1 -0
- package/dist/{chunk-ZMUPFGQO.js → chunk-TV2IDHPZ.js} +2 -2
- package/dist/{chunk-CFUXEGW2.js → chunk-XZGYKKCE.js} +2 -2
- package/dist/clipboard-fallback-dialog.js +2 -2
- package/dist/controls.cjs +15 -3
- package/dist/controls.cjs.map +1 -1
- package/dist/controls.js +5 -4
- package/dist/data-table/data-row-window.js +3 -3
- package/dist/data-table/drill-chart.cjs +15 -3
- package/dist/data-table/drill-chart.cjs.map +1 -1
- package/dist/data-table/drill-chart.js +2 -1
- package/dist/data-table/drill-chart.js.map +1 -1
- package/dist/data-table/index.cjs +15 -3
- package/dist/data-table/index.cjs.map +1 -1
- package/dist/data-table/index.js +8 -7
- package/dist/data-table/index.js.map +1 -1
- package/dist/desktop.cjs +26 -5
- package/dist/desktop.cjs.map +1 -1
- package/dist/desktop.js +15 -7
- package/dist/desktop.js.map +1 -1
- package/dist/email-input-dialog.cjs +15 -3
- package/dist/email-input-dialog.cjs.map +1 -1
- package/dist/email-input-dialog.js +4 -3
- package/dist/email-input-dialog.js.map +1 -1
- package/dist/error-sentence.cjs +130 -0
- package/dist/error-sentence.cjs.map +1 -0
- package/dist/error-sentence.d.cts +49 -0
- package/dist/error-sentence.d.ts +49 -0
- package/dist/error-sentence.js +22 -0
- package/dist/error-sentence.js.map +1 -0
- package/dist/index.cjs +16 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +17 -15
- package/dist/index.js.map +1 -1
- package/dist/item.js +2 -2
- package/dist/lite-table.cjs +15 -3
- package/dist/lite-table.cjs.map +1 -1
- package/dist/lite-table.js +3 -2
- package/dist/lite-table.js.map +1 -1
- package/dist/notice-stack.cjs +2 -0
- package/dist/notice-stack.cjs.map +1 -1
- package/dist/notice-stack.d.cts +11 -1
- package/dist/notice-stack.d.ts +11 -1
- package/dist/notice-stack.js +3 -1
- package/dist/record-list.cjs +15 -3
- package/dist/record-list.cjs.map +1 -1
- package/dist/record-list.js +3 -2
- package/dist/record-list.js.map +1 -1
- package/dist/sandbox-gate-dialog.js +2 -2
- package/dist/scope-mismatch-dialog.js +2 -2
- package/dist/swipe-deck.cjs +15 -3
- package/dist/swipe-deck.cjs.map +1 -1
- package/dist/swipe-deck.js +2 -1
- package/dist/swipe-deck.js.map +1 -1
- package/dist/text-input-dialog.cjs +15 -3
- package/dist/text-input-dialog.cjs.map +1 -1
- package/dist/text-input-dialog.js +4 -3
- package/dist/text-input-dialog.js.map +1 -1
- package/dist/value-prompts-dialog.js +2 -2
- package/dist/writing-field.js +2 -2
- package/package.json +12 -2
- package/dist/chunk-4WSXAP24.js.map +0 -1
- package/dist/chunk-LJKF267O.js.map +0 -1
- /package/dist/{chunk-UWTODOMD.js.map → chunk-2BQAHLU3.js.map} +0 -0
- /package/dist/{chunk-2PO3N42Q.js.map → chunk-ACZALXD6.js.map} +0 -0
- /package/dist/{chunk-ZMUPFGQO.js.map → chunk-TV2IDHPZ.js.map} +0 -0
- /package/dist/{chunk-CFUXEGW2.js.map → chunk-XZGYKKCE.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/data-table/DrillChart.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * THE DRILL CHART — `@ai-matrx/design-system/data-table/drill-chart` (lane DRILL-CHART,\n * DRILL-FINISH decision 5). ONE shared chart, fed by drill answers (`platform.drill_ask`):\n * stacked bars over time; the stack is the top N (`seriesLimit`, the host's knob\n * `drill.chart.top_n`, default 10) of the question's split Dimension ranked by the Measure over the\n * WHOLE window, everything else one Other series — every bar sums to its period's total and the\n * bars to the window total. No split = one series.\n *\n * What it asks is decided by the pure model in `drill.ts` (`drillChartQuestions` → round one,\n * `drillChartCellsQuestion` → round two, `drillChartData` → the bars); this file only draws.\n *\n * click a segment → drill: the value joins the trail, exactly as the answer table's drill\n * click a period → the window narrows to that period (`from..to`)\n * click Other → the period is broken out: the window narrows to it, where the answer table\n * lists every value one by one (said in the tooltip — never a dead click)\n * legend → buttons (keyboard reachable) that hide and show a series\n *\n * Its own entry, so `./data-table` never imports recharts — an OPTIONAL peer only a host that\n * draws this chart installs. Colors are the package's `--matrx-chart-*` tokens (light and dark).\n */\n\nimport { useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from \"recharts\";\n\nimport { formatCount } from \"@ai-matrx/kit/format\";\n\nimport { cn } from \"../cn\";\nimport { ErrorBox } from \"../error-box\";\nimport { Skeleton } from \"../skeleton\";\nimport {\n MATRX_DRILL_CHART_SERIES_LIMIT,\n dimensionRefLabel,\n drillChartData,\n drillChartDrill,\n drillChartNarrowToPeriod,\n drillChartQuestions,\n type MatrxDrillChartAnswers,\n type MatrxDrillChartData,\n type MatrxDrillChartPeriod,\n type MatrxDrillChartSeries,\n type MatrxDrillDimension,\n type MatrxDrillMeasure,\n type MatrxDrillQuestion,\n} from \"./drill\";\n\nexport {\n MATRX_DRILL_CHART_CEILING,\n MATRX_DRILL_CHART_OTHER,\n MATRX_DRILL_CHART_SERIES_LIMIT,\n drillChartCellsQuestion,\n drillChartData,\n drillChartDrill,\n drillChartNarrowToPeriod,\n drillChartQuestions,\n drillChartSeriesKey,\n type MatrxDrillChartAnswers,\n type MatrxDrillChartContext,\n type MatrxDrillChartData,\n type MatrxDrillChartPeriod,\n type MatrxDrillChartPlan,\n type MatrxDrillChartRequest,\n type MatrxDrillChartRequestKey,\n type MatrxDrillChartRow,\n type MatrxDrillChartSeries,\n} from \"./drill\";\n\nexport interface MatrxDrillChartProps {\n dimensions: readonly MatrxDrillDimension[];\n measures: readonly MatrxDrillMeasure[];\n /** The question the answer table answers; the chart asks its own questions from it. */\n question: MatrxDrillQuestion;\n onQuestionChange: (next: MatrxDrillQuestion) => void;\n /** The door's rows (with `kind`) per chart request key: `series`, `periods`, `cells`. */\n answers: MatrxDrillChartAnswers;\n /** Series before Other — the host feeds the knob `drill.chart.top_n`. Default 10. */\n seriesLimit?: number | undefined;\n /** The Measure stacked. Default: the question's first shown Measure. */\n measure?: string | null | undefined;\n /**\n * STACK THESE MEASURES instead (two or more that add up, e.g. input and output tokens): one series\n * each, no split; a segment click narrows to its period (lane DRILL-FLIP-FIXES L3).\n */\n stack?: readonly string[] | null | undefined;\n /** The time reference when the question does not group by time. */\n time?: string | null | undefined;\n /** The store's page ceiling, when the host knows it is not 1000. */\n ceiling?: number | undefined;\n /** Declared drill paths; a segment click follows them like the answer table. */\n paths?: readonly (readonly string[])[] | undefined;\n /** A read that failed, in words. */\n error?: string | null | undefined;\n emptyLabel?: string | undefined;\n /** Plot height in px (default 220). */\n height?: number | undefined;\n /** A fixed plot width in px; default fills its container. */\n width?: number | undefined;\n /** Words above the chart (a title, the freshness). */\n note?: ReactNode | undefined;\n className?: string | undefined;\n}\n\nconst NO_PATHS: readonly (readonly string[])[] = [];\nconst PLOT_MARGIN = { top: 4, right: 4, bottom: 0, left: 0 };\nconst Y_AXIS_WIDTH = 56;\n\nfunction colorOf(series: MatrxDrillChartSeries, index: number): string {\n if (series.color) return series.color;\n return series.other ? \"hsl(var(--matrx-chart-other))\" : `hsl(var(--matrx-chart-${(index % 10) + 1}))`;\n}\n\nfunction formatWith(measure: MatrxDrillMeasure | undefined, value: number | null | undefined): string {\n if (value === null || value === undefined) return \"not measured\";\n if (measure?.format) return measure.format(value);\n return value.toLocaleString(undefined, { maximumFractionDigits: 2 });\n}\n\n/** A short axis number: the Measure's own format when it has one, else 1.2k / 3.4M. */\n/**\n * A tick on the value axis: the measure's own words while they fit the axis (\"$12\", \"40 ms\"), else the\n * number in compact form (\"28M\") — the chart's title already names the unit (\"Cost (points) by day\").\n * A long formatted value (\"28,000,000 points\") was clipped to \",000,000 points\" (lane DRILL-ADOPT walk).\n */\nexport function drillChartAxisNumber(measure: MatrxDrillMeasure | undefined, value: number): string {\n // A fractional tick under a thousand keeps one decimal (0.5); everything else is kit's compact count.\n const compact =\n Math.abs(value) < 1000 && !Number.isInteger(value)\n ? String(Math.round(value * 10) / 10)\n : formatCount(value, { style: \"compact\" });\n if (!measure?.format) return compact;\n const said = measure.format(value);\n if (said.length <= 7) return said;\n // THE TICK SAYS THE NUMBER THE FORMAT SAID, NOT THE RAW VALUE. A Measure's format may convert its unit\n // (the usage explorer stores dollars and prints points at the points rate), so compacting the raw value\n // put \"450\" under \"Cost (points) by day\" for a 9,000,000-point day (localhost walk, 2026-09-30). The\n // number the format printed is compacted, keeping a leading currency sign (\"$1,234.56\" → \"$1.2k\").\n const printed = said.match(/^([^\\d-]*)(-?\\d[\\d,]*(?:\\.\\d+)?)/);\n if (!printed) return compact;\n const numeric = printed[2];\n if (!numeric) return compact;\n const n = Number(numeric.replace(/,/g, \"\"));\n if (!Number.isFinite(n)) return compact;\n const prefix = printed[1]?.trim() ?? \"\";\n const shown = Math.abs(n) < 1000 && !Number.isInteger(n) ? String(Math.round(n * 10) / 10) : formatCount(n, { style: \"compact\" });\n return prefix.length <= 1 ? `${prefix}${shown}` : shown;\n}\nconst axisNumber = drillChartAxisNumber;\n\nexport function MatrxDrillChart({\n dimensions,\n measures,\n question,\n onQuestionChange,\n answers,\n seriesLimit = MATRX_DRILL_CHART_SERIES_LIMIT,\n measure: measureKey,\n stack,\n time,\n ceiling,\n paths = NO_PATHS,\n error,\n emptyLabel = \"No value\",\n height = 220,\n width,\n note,\n className,\n}: MatrxDrillChartProps) {\n const plan = useMemo(\n () => drillChartQuestions(question, seriesLimit, { dimensions, measures, measure: measureKey, stack, time, ceiling }),\n [question, seriesLimit, dimensions, measures, measureKey, stack, time, ceiling],\n );\n const data = useMemo(() => drillChartData(plan, answers, dimensions, measures, emptyLabel), [plan, answers, dimensions, measures, emptyLabel]);\n const measure = measures.find((m) => m.key === plan.measure);\n const [hidden, setHidden] = useState<ReadonlySet<string>>(() => new Set());\n const [hover, setHover] = useState<string | null>(null);\n // A segment's click reaches the chart's own click too (it bubbles): the segment wins.\n const segmentClicked = useRef(false);\n const plotRef = useRef<HTMLDivElement | null>(null);\n\n const measureWords = plan.stack ? plan.stack.map((k) => measures.find((m) => m.key === k)?.label ?? k).join(\" and \") : measure?.label ?? plan.measure;\n const title = plan.time\n ? `${measureWords} by ${dimensionRefLabel(dimensions, plan.time).replace(/^.* by /, \"\")}${\n plan.split ? `, split by ${dimensionRefLabel(dimensions, plan.split)}` : \"\"\n }`\n : measureWords;\n\n const frame = (body: ReactNode) => (\n <section data-matrx-drill-chart aria-label={title} className={cn(\"flex min-w-0 flex-col gap-1.5 px-2 py-2\", className)}>\n {note ? <div data-matrx-drill-chart-note className=\"text-xs text-muted-foreground\">{note}</div> : null}\n {body}\n </section>\n );\n\n if (error) {\n return frame(<ErrorBox className=\"text-sm text-destructive-ink\" message={error} operation=\"Draw the chart\" />);\n }\n if (plan.refused) {\n return frame(\n <p data-matrx-drill-chart-refused className=\"text-xs text-muted-foreground\">\n {plan.refused}\n </p>,\n );\n }\n if (!data) {\n return frame(<Skeleton data-matrx-drill-chart-loading className=\"w-full\" style={{ height }} />);\n }\n if (data.periods.length === 0) {\n return frame(<p data-matrx-drill-chart-empty className=\"text-xs text-muted-foreground\">Nothing was counted in this window.</p>);\n }\n\n const toggle = (key: string) =>\n setHidden((was) => {\n const next = new Set(was);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n });\n const drawn = data.series.map((s, i) => ({ s, i, dataKey: `s${i}` })).filter(({ s }) => !hidden.has(s.key));\n const rows = data.periods.map((p) => {\n const row: Record<string, string | number | null> = { __key: p.key, __label: p.label };\n data.series.forEach((s, i) => {\n row[`s${i}`] = p.values[s.key] ?? null;\n });\n return row;\n });\n const splitLabel = data.split ? dimensionRefLabel(dimensions, data.split) : \"\";\n const onPeriod = (period: MatrxDrillChartPeriod | undefined) => {\n if (period) onQuestionChange(drillChartNarrowToPeriod(question, plan, period.value, dimensions));\n };\n const onSegment = (series: MatrxDrillChartSeries, period: MatrxDrillChartPeriod | undefined) => {\n segmentClicked.current = true;\n if (series.other || !data.split) {\n onPeriod(period);\n return;\n }\n onQuestionChange(drillChartDrill(question, plan, series.value, dimensions, paths));\n };\n const hintFor = (key: string | null): string | null => {\n const series = data.series.find((s) => s.key === key);\n if (!series) return \"Click a bar to narrow the window to its period.\";\n if (series.other) return `Other is everything past the top ${plan.seriesLimit}: click to break this period out, one by one, in the table.`;\n if (!data.split) return \"Click to narrow the window to this period.\";\n return `Click to drill into ${series.label}.`;\n };\n\n const plot = (\n <BarChart\n data={rows}\n margin={PLOT_MARGIN}\n barCategoryGap=\"12%\"\n onClick={(_state, event) => {\n if (segmentClicked.current) {\n segmentClicked.current = false;\n return;\n }\n // The period is read from WHERE the person clicked, never from the tooltip's last index:\n // a click that arrives before the chart has seen the pointer move would otherwise read a\n // stale index (walked: a quick click landed on the first day). Bands are equal-width over\n // the plot, which starts after the value axis and ends at the right margin.\n const box = (plotRef.current?.querySelector(\"svg.recharts-surface\") ?? plotRef.current)?.getBoundingClientRect();\n if (!box || data.periods.length === 0) return;\n const left = box.left + PLOT_MARGIN.left + Y_AXIS_WIDTH;\n const right = box.right - PLOT_MARGIN.right;\n const index = Math.floor(((event.clientX - left) / (right - left)) * data.periods.length);\n if (index >= 0 && index < data.periods.length) onPeriod(data.periods[index]);\n }}\n {...(width ? { width, height } : {})}\n >\n <CartesianGrid vertical={false} stroke=\"hsl(var(--border))\" strokeDasharray=\"0\" />\n <XAxis\n dataKey=\"__label\"\n tickLine={false}\n axisLine={{ stroke: \"hsl(var(--border))\" }}\n tick={{ fill: \"hsl(var(--muted-foreground))\", fontSize: 11 }}\n minTickGap={12}\n interval=\"preserveStartEnd\"\n />\n <YAxis\n tickLine={false}\n axisLine={false}\n width={Y_AXIS_WIDTH}\n tick={{ fill: \"hsl(var(--muted-foreground))\", fontSize: 11 }}\n tickFormatter={(v: number) => axisNumber(measure, v)}\n />\n <Tooltip\n cursor={{ fill: \"hsl(var(--muted))\", opacity: 0.6 }}\n isAnimationActive={false}\n content={({ active, label }) => {\n if (!active) return null;\n const period = data.periods.find((p) => p.label === label);\n if (!period) return null;\n return (\n <DrillChartTooltip\n period={period}\n data={data}\n hidden={hidden}\n measure={measure}\n splitLabel={splitLabel}\n hint={hintFor(hover)}\n />\n );\n }}\n />\n {drawn.map(({ s, i, dataKey }) => (\n <Bar\n key={s.key}\n dataKey={dataKey}\n name={s.label}\n stackId=\"drill\"\n fill={colorOf(s, i)}\n stroke=\"hsl(var(--background))\"\n strokeWidth={1}\n isAnimationActive={false}\n cursor=\"pointer\"\n onMouseEnter={() => setHover(s.key)}\n onMouseLeave={() => setHover(null)}\n onClick={(_item, index) => onSegment(s, data.periods[index])}\n />\n ))}\n </BarChart>\n );\n\n return frame(\n <>\n <div className=\"flex flex-wrap items-baseline justify-between gap-x-3 gap-y-0.5\">\n <h3 className=\"text-xs font-medium text-foreground\">{title}</h3>\n <span data-matrx-drill-chart-total className=\"text-xs text-muted-foreground\">\n Total {formatWith(measure, data.total)}\n </span>\n </div>\n <div ref={plotRef} data-matrx-drill-chart-plot className=\"w-full min-w-0\" style={{ height }}>\n {width ? plot : <ResponsiveContainer width=\"100%\" height=\"100%\">{plot}</ResponsiveContainer>}\n </div>\n {data.series.length > 1 || data.split ? (\n <ul data-matrx-drill-chart-legend aria-label=\"Series — press to hide or show\" className=\"flex flex-wrap gap-x-1 gap-y-0.5\">\n {data.series.map((s, i) => {\n const off = hidden.has(s.key);\n return (\n <li key={s.key} className=\"min-w-0\">\n <button\n type=\"button\"\n data-matrx-drill-chart-series={s.key}\n aria-pressed={!off}\n title={`${off ? \"Show\" : \"Hide\"} ${s.label} (${formatWith(measure, s.total)})`}\n onClick={() => toggle(s.key)}\n className={cn(\n \"inline-flex max-w-[16rem] items-center gap-1.5 rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring\",\n off && \"text-muted-foreground line-through\",\n )}\n >\n <span aria-hidden=\"true\" className=\"h-2.5 w-2.5 shrink-0 rounded-sm\" style={{ background: off ? \"transparent\" : colorOf(s, i), boxShadow: `inset 0 0 0 1.5px ${colorOf(s, i)}` }} />\n <span className=\"truncate\">{s.label}</span>\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">{formatWith(measure, s.total)}</span>\n </button>\n </li>\n );\n })}\n </ul>\n ) : null}\n {data.says.length > 0 ? (\n <p data-matrx-drill-chart-says className=\"text-xs text-muted-foreground\">\n {data.says.join(\" \")}\n </p>\n ) : null}\n </>,\n );\n}\n\n/** Every series' value in the period, each in the Measure's own format, and the period's total. */\nfunction DrillChartTooltip({\n period,\n data,\n hidden,\n measure,\n splitLabel,\n hint,\n}: {\n period: MatrxDrillChartPeriod;\n data: MatrxDrillChartData;\n hidden: ReadonlySet<string>;\n measure: MatrxDrillMeasure | undefined;\n splitLabel: string;\n hint: string | null;\n}) {\n return (\n <div\n data-matrx-drill-chart-tooltip\n className=\"min-w-[12rem] max-w-[18rem] rounded-md border border-border bg-popover px-2.5 py-2 text-xs text-popover-foreground shadow-md\"\n >\n <div className=\"mb-1 font-medium\">{period.label}</div>\n {data.split ? <div className=\"mb-1 text-muted-foreground\">{splitLabel}</div> : null}\n <ul className=\"flex flex-col gap-0.5\">\n {data.series.map((s, i) => (\n <li key={s.key} className={cn(\"flex items-center gap-1.5\", hidden.has(s.key) && \"opacity-50\")}>\n <span aria-hidden=\"true\" className=\"h-2 w-2 shrink-0 rounded-sm\" style={{ background: colorOf(s, i) }} />\n <span className=\"min-w-0 flex-1 truncate\">{s.label}</span>\n <span className=\"tabular-nums\">{formatWith(measure, period.values[s.key] ?? null)}</span>\n </li>\n ))}\n </ul>\n <div className=\"mt-1 flex justify-between border-t border-border pt-1 font-medium\">\n <span>Total</span>\n <span className=\"tabular-nums\">{formatWith(measure, period.total)}</span>\n </div>\n {hint ? <div className=\"mt-1 text-muted-foreground\">{hint}</div> : null}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/data-table/DrillChart.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * THE DRILL CHART — `@ai-matrx/design-system/data-table/drill-chart` (lane DRILL-CHART,\n * DRILL-FINISH decision 5). ONE shared chart, fed by drill answers (`platform.drill_ask`):\n * stacked bars over time; the stack is the top N (`seriesLimit`, the host's knob\n * `drill.chart.top_n`, default 10) of the question's split Dimension ranked by the Measure over the\n * WHOLE window, everything else one Other series — every bar sums to its period's total and the\n * bars to the window total. No split = one series.\n *\n * What it asks is decided by the pure model in `drill.ts` (`drillChartQuestions` → round one,\n * `drillChartCellsQuestion` → round two, `drillChartData` → the bars); this file only draws.\n *\n * click a segment → drill: the value joins the trail, exactly as the answer table's drill\n * click a period → the window narrows to that period (`from..to`)\n * click Other → the period is broken out: the window narrows to it, where the answer table\n * lists every value one by one (said in the tooltip — never a dead click)\n * legend → buttons (keyboard reachable) that hide and show a series\n *\n * Its own entry, so `./data-table` never imports recharts — an OPTIONAL peer only a host that\n * draws this chart installs. Colors are the package's `--matrx-chart-*` tokens (light and dark).\n */\n\nimport { useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from \"recharts\";\n\nimport { formatCount } from \"@ai-matrx/kit/format\";\n\nimport { cn } from \"../cn\";\nimport { ErrorBox } from \"../error-box\";\nimport { Skeleton } from \"../skeleton\";\nimport {\n MATRX_DRILL_CHART_SERIES_LIMIT,\n dimensionRefLabel,\n drillChartData,\n drillChartDrill,\n drillChartNarrowToPeriod,\n drillChartQuestions,\n type MatrxDrillChartAnswers,\n type MatrxDrillChartData,\n type MatrxDrillChartPeriod,\n type MatrxDrillChartSeries,\n type MatrxDrillDimension,\n type MatrxDrillMeasure,\n type MatrxDrillQuestion,\n} from \"./drill\";\n\nexport {\n MATRX_DRILL_CHART_CEILING,\n MATRX_DRILL_CHART_OTHER,\n MATRX_DRILL_CHART_SERIES_LIMIT,\n drillChartCellsQuestion,\n drillChartData,\n drillChartDrill,\n drillChartNarrowToPeriod,\n drillChartQuestions,\n drillChartSeriesKey,\n type MatrxDrillChartAnswers,\n type MatrxDrillChartContext,\n type MatrxDrillChartData,\n type MatrxDrillChartPeriod,\n type MatrxDrillChartPlan,\n type MatrxDrillChartRequest,\n type MatrxDrillChartRequestKey,\n type MatrxDrillChartRow,\n type MatrxDrillChartSeries,\n} from \"./drill\";\n\nexport interface MatrxDrillChartProps {\n dimensions: readonly MatrxDrillDimension[];\n measures: readonly MatrxDrillMeasure[];\n /** The question the answer table answers; the chart asks its own questions from it. */\n question: MatrxDrillQuestion;\n onQuestionChange: (next: MatrxDrillQuestion) => void;\n /** The door's rows (with `kind`) per chart request key: `series`, `periods`, `cells`. */\n answers: MatrxDrillChartAnswers;\n /** Series before Other — the host feeds the knob `drill.chart.top_n`. Default 10. */\n seriesLimit?: number | undefined;\n /** The Measure stacked. Default: the question's first shown Measure. */\n measure?: string | null | undefined;\n /**\n * STACK THESE MEASURES instead (two or more that add up, e.g. input and output tokens): one series\n * each, no split; a segment click narrows to its period (lane DRILL-FLIP-FIXES L3).\n */\n stack?: readonly string[] | null | undefined;\n /** The time reference when the question does not group by time. */\n time?: string | null | undefined;\n /** The store's page ceiling, when the host knows it is not 1000. */\n ceiling?: number | undefined;\n /** Declared drill paths; a segment click follows them like the answer table. */\n paths?: readonly (readonly string[])[] | undefined;\n /** A read that failed, in words. */\n error?: string | null | undefined;\n emptyLabel?: string | undefined;\n /** Plot height in px (default 220). */\n height?: number | undefined;\n /** A fixed plot width in px; default fills its container. */\n width?: number | undefined;\n /** Words above the chart (a title, the freshness). */\n note?: ReactNode | undefined;\n className?: string | undefined;\n}\n\nconst NO_PATHS: readonly (readonly string[])[] = [];\nconst PLOT_MARGIN = { top: 4, right: 4, bottom: 0, left: 0 };\nconst Y_AXIS_WIDTH = 56;\n\nfunction colorOf(series: MatrxDrillChartSeries, index: number): string {\n if (series.color) return series.color;\n return series.other ? \"hsl(var(--matrx-chart-other))\" : `hsl(var(--matrx-chart-${(index % 10) + 1}))`;\n}\n\nfunction formatWith(measure: MatrxDrillMeasure | undefined, value: number | null | undefined): string {\n if (value === null || value === undefined) return \"not measured\";\n if (measure?.format) return measure.format(value);\n return value.toLocaleString(undefined, { maximumFractionDigits: 2 });\n}\n\n/** A short axis number: the Measure's own format when it has one, else 1.2k / 3.4M. */\n/**\n * A tick on the value axis: the measure's own words while they fit the axis (\"$12\", \"40 ms\"), else the\n * number in compact form (\"28M\") — the chart's title already names the unit (\"Cost (points) by day\").\n * A long formatted value (\"28,000,000 points\") was clipped to \",000,000 points\" (lane DRILL-ADOPT walk).\n */\nexport function drillChartAxisNumber(measure: MatrxDrillMeasure | undefined, value: number): string {\n // A fractional tick under a thousand keeps one decimal (0.5); everything else is kit's compact count.\n const compact =\n Math.abs(value) < 1000 && !Number.isInteger(value)\n ? String(Math.round(value * 10) / 10)\n : formatCount(value, { style: \"compact\" });\n if (!measure?.format) return compact;\n const said = measure.format(value);\n if (said.length <= 7) return said;\n // THE TICK SAYS THE NUMBER THE FORMAT SAID, NOT THE RAW VALUE. A Measure's format may convert its unit\n // (the usage explorer stores dollars and prints points at the points rate), so compacting the raw value\n // put \"450\" under \"Cost (points) by day\" for a 9,000,000-point day (localhost walk, 2026-09-30). The\n // number the format printed is compacted, keeping a leading currency sign (\"$1,234.56\" → \"$1.2k\").\n const printed = said.match(/^([^\\d-]*)(-?\\d[\\d,]*(?:\\.\\d+)?)/);\n if (!printed) return compact;\n const numeric = printed[2];\n if (!numeric) return compact;\n const n = Number(numeric.replace(/,/g, \"\"));\n if (!Number.isFinite(n)) return compact;\n const prefix = printed[1]?.trim() ?? \"\";\n const shown = Math.abs(n) < 1000 && !Number.isInteger(n) ? String(Math.round(n * 10) / 10) : formatCount(n, { style: \"compact\" });\n return prefix.length <= 1 ? `${prefix}${shown}` : shown;\n}\nconst axisNumber = drillChartAxisNumber;\n\nexport function MatrxDrillChart({\n dimensions,\n measures,\n question,\n onQuestionChange,\n answers,\n seriesLimit = MATRX_DRILL_CHART_SERIES_LIMIT,\n measure: measureKey,\n stack,\n time,\n ceiling,\n paths = NO_PATHS,\n error,\n emptyLabel = \"No value\",\n height = 220,\n width,\n note,\n className,\n}: MatrxDrillChartProps) {\n const plan = useMemo(\n () => drillChartQuestions(question, seriesLimit, { dimensions, measures, measure: measureKey, stack, time, ceiling }),\n [question, seriesLimit, dimensions, measures, measureKey, stack, time, ceiling],\n );\n const data = useMemo(() => drillChartData(plan, answers, dimensions, measures, emptyLabel), [plan, answers, dimensions, measures, emptyLabel]);\n const measure = measures.find((m) => m.key === plan.measure);\n const [hidden, setHidden] = useState<ReadonlySet<string>>(() => new Set());\n const [hover, setHover] = useState<string | null>(null);\n // A segment's click reaches the chart's own click too (it bubbles): the segment wins.\n const segmentClicked = useRef(false);\n const plotRef = useRef<HTMLDivElement | null>(null);\n\n const measureWords = plan.stack ? plan.stack.map((k) => measures.find((m) => m.key === k)?.label ?? k).join(\" and \") : measure?.label ?? plan.measure;\n const title = plan.time\n ? `${measureWords} by ${dimensionRefLabel(dimensions, plan.time).replace(/^.* by /, \"\")}${\n plan.split ? `, split by ${dimensionRefLabel(dimensions, plan.split)}` : \"\"\n }`\n : measureWords;\n\n const frame = (body: ReactNode) => (\n <section data-matrx-drill-chart aria-label={title} className={cn(\"flex min-w-0 flex-col gap-1.5 px-2 py-2\", className)}>\n {note ? <div data-matrx-drill-chart-note className=\"text-xs text-muted-foreground\">{note}</div> : null}\n {body}\n </section>\n );\n\n if (error) {\n return frame(<ErrorBox className=\"text-sm text-destructive-ink\" message={error} operation=\"Draw the chart\" />);\n }\n if (plan.refused) {\n return frame(\n <p data-matrx-drill-chart-refused className=\"text-xs text-muted-foreground\">\n {plan.refused}\n </p>,\n );\n }\n if (!data) {\n return frame(<Skeleton data-matrx-drill-chart-loading className=\"w-full\" style={{ height }} />);\n }\n if (data.periods.length === 0) {\n return frame(<p data-matrx-drill-chart-empty className=\"text-xs text-muted-foreground\">Nothing was counted in this window.</p>);\n }\n\n const toggle = (key: string) =>\n setHidden((was) => {\n const next = new Set(was);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n });\n const drawn = data.series.map((s, i) => ({ s, i, dataKey: `s${i}` })).filter(({ s }) => !hidden.has(s.key));\n const rows = data.periods.map((p) => {\n const row: Record<string, string | number | null> = { __key: p.key, __label: p.label };\n data.series.forEach((s, i) => {\n row[`s${i}`] = p.values[s.key] ?? null;\n });\n return row;\n });\n const splitLabel = data.split ? dimensionRefLabel(dimensions, data.split) : \"\";\n const onPeriod = (period: MatrxDrillChartPeriod | undefined) => {\n if (period) onQuestionChange(drillChartNarrowToPeriod(question, plan, period.value, dimensions));\n };\n const onSegment = (series: MatrxDrillChartSeries, period: MatrxDrillChartPeriod | undefined) => {\n segmentClicked.current = true;\n if (series.other || !data.split) {\n onPeriod(period);\n return;\n }\n onQuestionChange(drillChartDrill(question, plan, series.value, dimensions, paths));\n };\n const hintFor = (key: string | null): string | null => {\n const series = data.series.find((s) => s.key === key);\n if (!series) return \"Click a bar to narrow the window to its period.\";\n if (series.other) return `Other is everything past the top ${plan.seriesLimit}: click to break this period out, one by one, in the table.`;\n if (!data.split) return \"Click to narrow the window to this period.\";\n return `Click to drill into ${series.label}.`;\n };\n\n const plot = (\n <BarChart\n data={rows}\n margin={PLOT_MARGIN}\n barCategoryGap=\"12%\"\n onClick={(_state, event) => {\n if (segmentClicked.current) {\n segmentClicked.current = false;\n return;\n }\n // The period is read from WHERE the person clicked, never from the tooltip's last index:\n // a click that arrives before the chart has seen the pointer move would otherwise read a\n // stale index (walked: a quick click landed on the first day). Bands are equal-width over\n // the plot, which starts after the value axis and ends at the right margin.\n const box = (plotRef.current?.querySelector(\"svg.recharts-surface\") ?? plotRef.current)?.getBoundingClientRect();\n if (!box || data.periods.length === 0) return;\n const left = box.left + PLOT_MARGIN.left + Y_AXIS_WIDTH;\n const right = box.right - PLOT_MARGIN.right;\n const index = Math.floor(((event.clientX - left) / (right - left)) * data.periods.length);\n if (index >= 0 && index < data.periods.length) onPeriod(data.periods[index]);\n }}\n {...(width ? { width, height } : {})}\n >\n <CartesianGrid vertical={false} stroke=\"hsl(var(--border))\" strokeDasharray=\"0\" />\n <XAxis\n dataKey=\"__label\"\n tickLine={false}\n axisLine={{ stroke: \"hsl(var(--border))\" }}\n tick={{ fill: \"hsl(var(--muted-foreground))\", fontSize: 11 }}\n minTickGap={12}\n interval=\"preserveStartEnd\"\n />\n <YAxis\n tickLine={false}\n axisLine={false}\n width={Y_AXIS_WIDTH}\n tick={{ fill: \"hsl(var(--muted-foreground))\", fontSize: 11 }}\n tickFormatter={(v: number) => axisNumber(measure, v)}\n />\n <Tooltip\n cursor={{ fill: \"hsl(var(--muted))\", opacity: 0.6 }}\n isAnimationActive={false}\n content={({ active, label }) => {\n if (!active) return null;\n const period = data.periods.find((p) => p.label === label);\n if (!period) return null;\n return (\n <DrillChartTooltip\n period={period}\n data={data}\n hidden={hidden}\n measure={measure}\n splitLabel={splitLabel}\n hint={hintFor(hover)}\n />\n );\n }}\n />\n {drawn.map(({ s, i, dataKey }) => (\n <Bar\n key={s.key}\n dataKey={dataKey}\n name={s.label}\n stackId=\"drill\"\n fill={colorOf(s, i)}\n stroke=\"hsl(var(--background))\"\n strokeWidth={1}\n isAnimationActive={false}\n cursor=\"pointer\"\n onMouseEnter={() => setHover(s.key)}\n onMouseLeave={() => setHover(null)}\n onClick={(_item, index) => onSegment(s, data.periods[index])}\n />\n ))}\n </BarChart>\n );\n\n return frame(\n <>\n <div className=\"flex flex-wrap items-baseline justify-between gap-x-3 gap-y-0.5\">\n <h3 className=\"text-xs font-medium text-foreground\">{title}</h3>\n <span data-matrx-drill-chart-total className=\"text-xs text-muted-foreground\">\n Total {formatWith(measure, data.total)}\n </span>\n </div>\n <div ref={plotRef} data-matrx-drill-chart-plot className=\"w-full min-w-0\" style={{ height }}>\n {width ? plot : <ResponsiveContainer width=\"100%\" height=\"100%\">{plot}</ResponsiveContainer>}\n </div>\n {data.series.length > 1 || data.split ? (\n <ul data-matrx-drill-chart-legend aria-label=\"Series — press to hide or show\" className=\"flex flex-wrap gap-x-1 gap-y-0.5\">\n {data.series.map((s, i) => {\n const off = hidden.has(s.key);\n return (\n <li key={s.key} className=\"min-w-0\">\n <button\n type=\"button\"\n data-matrx-drill-chart-series={s.key}\n aria-pressed={!off}\n title={`${off ? \"Show\" : \"Hide\"} ${s.label} (${formatWith(measure, s.total)})`}\n onClick={() => toggle(s.key)}\n className={cn(\n \"inline-flex max-w-[16rem] items-center gap-1.5 rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring\",\n off && \"text-muted-foreground line-through\",\n )}\n >\n <span aria-hidden=\"true\" className=\"h-2.5 w-2.5 shrink-0 rounded-sm\" style={{ background: off ? \"transparent\" : colorOf(s, i), boxShadow: `inset 0 0 0 1.5px ${colorOf(s, i)}` }} />\n <span className=\"truncate\">{s.label}</span>\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">{formatWith(measure, s.total)}</span>\n </button>\n </li>\n );\n })}\n </ul>\n ) : null}\n {data.says.length > 0 ? (\n <p data-matrx-drill-chart-says className=\"text-xs text-muted-foreground\">\n {data.says.join(\" \")}\n </p>\n ) : null}\n </>,\n );\n}\n\n/** Every series' value in the period, each in the Measure's own format, and the period's total. */\nfunction DrillChartTooltip({\n period,\n data,\n hidden,\n measure,\n splitLabel,\n hint,\n}: {\n period: MatrxDrillChartPeriod;\n data: MatrxDrillChartData;\n hidden: ReadonlySet<string>;\n measure: MatrxDrillMeasure | undefined;\n splitLabel: string;\n hint: string | null;\n}) {\n return (\n <div\n data-matrx-drill-chart-tooltip\n className=\"min-w-[12rem] max-w-[18rem] rounded-md border border-border bg-popover px-2.5 py-2 text-xs text-popover-foreground shadow-md\"\n >\n <div className=\"mb-1 font-medium\">{period.label}</div>\n {data.split ? <div className=\"mb-1 text-muted-foreground\">{splitLabel}</div> : null}\n <ul className=\"flex flex-col gap-0.5\">\n {data.series.map((s, i) => (\n <li key={s.key} className={cn(\"flex items-center gap-1.5\", hidden.has(s.key) && \"opacity-50\")}>\n <span aria-hidden=\"true\" className=\"h-2 w-2 shrink-0 rounded-sm\" style={{ background: colorOf(s, i) }} />\n <span className=\"min-w-0 flex-1 truncate\">{s.label}</span>\n <span className=\"tabular-nums\">{formatWith(measure, period.values[s.key] ?? null)}</span>\n </li>\n ))}\n </ul>\n <div className=\"mt-1 flex justify-between border-t border-border pt-1 font-medium\">\n <span>Total</span>\n <span className=\"tabular-nums\">{formatWith(measure, period.total)}</span>\n </div>\n {hint ? <div className=\"mt-1 text-muted-foreground\">{hint}</div> : null}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3905,6 +3905,16 @@ function errorSentenceOf(error) {
|
|
|
3905
3905
|
}
|
|
3906
3906
|
var TIMED_OUT_SENTENCE = "That took too long. Nothing was lost; try again.";
|
|
3907
3907
|
var FALLBACK_ERROR_SENTENCE = "Something went wrong. Try again.";
|
|
3908
|
+
var CARD_ERROR_LINE = {
|
|
3909
|
+
OFFLINE: "No connection",
|
|
3910
|
+
TIMEOUT: "Took too long. Nothing was lost.",
|
|
3911
|
+
UNAUTHORIZED: "Signed out. Sign in again.",
|
|
3912
|
+
FORBIDDEN: "Not allowed for this account",
|
|
3913
|
+
NOT_FOUND: "Not found. Refresh and retry.",
|
|
3914
|
+
RATE_LIMIT: "Too many requests. Wait a moment.",
|
|
3915
|
+
SERVER: "Server problem. Try again soon.",
|
|
3916
|
+
FALLBACK: "Something went wrong"
|
|
3917
|
+
};
|
|
3908
3918
|
function isTimedOutError(error, message, code) {
|
|
3909
3919
|
if (code === "57014" || code === "timed_out") return true;
|
|
3910
3920
|
if (error && typeof error === "object") {
|
|
@@ -3922,8 +3932,9 @@ var ANY_HOST_CODES = /* @__PURE__ */ new Set(["OFFLINE", "TIMEOUT", "UNAUTHORIZE
|
|
|
3922
3932
|
var MACHINE_PREFIX = /^\s*(?:\[[\w./-]+\]\s*|[a-z][\w]*(?:[._][\w]+)+:\s+)/;
|
|
3923
3933
|
var RAW_TEXT = /\b(?:Type|Reference|Syntax|Range|Internal|Eval|URI)Error\b|\bat\s+[\w$.<>]+\s*\(|\.(?:[cm]?[jt]sx?|py):\d+|(?:^|[\s(])(?:\/[\w.@-]+){2,}|\bundefined is not\b|\bcannot read propert(?:y|ies)\b|\bis not a function\b|\bunexpected token\b/i;
|
|
3924
3934
|
function peopleErrorSentence(error, message, options = {}) {
|
|
3925
|
-
|
|
3926
|
-
|
|
3935
|
+
const card = options.card === true;
|
|
3936
|
+
if (isTimedOutError(error, message, options.code)) return card ? CARD_ERROR_LINE.TIMEOUT : TIMED_OUT_SENTENCE;
|
|
3937
|
+
const fallback = options.fallback ?? (card ? CARD_ERROR_LINE.FALLBACK : FALLBACK_ERROR_SENTENCE);
|
|
3927
3938
|
const raw = message?.trim() || errorSentenceOf(error).trim();
|
|
3928
3939
|
if (!raw) return fallback;
|
|
3929
3940
|
let text = raw;
|
|
@@ -3931,7 +3942,8 @@ function peopleErrorSentence(error, message, options = {}) {
|
|
|
3931
3942
|
if (!text) return fallback;
|
|
3932
3943
|
if (offlineText(text) || RAW_TEXT.test(text) || text !== raw) {
|
|
3933
3944
|
const said = describeError(text, fallback);
|
|
3934
|
-
|
|
3945
|
+
if (!said.code || !ANY_HOST_CODES.has(said.code)) return fallback;
|
|
3946
|
+
return card ? CARD_ERROR_LINE[said.code] : said.cause;
|
|
3935
3947
|
}
|
|
3936
3948
|
return text;
|
|
3937
3949
|
}
|