@pixerate/editor 0.51.0 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/agent/index.cjs +23 -23
  2. package/dist/agent/index.js +4 -4
  3. package/dist/chart/index.cjs +475 -124
  4. package/dist/chart/index.cjs.map +1 -1
  5. package/dist/chart/index.d.cts +174 -25
  6. package/dist/chart/index.d.ts +174 -25
  7. package/dist/chart/index.js +375 -24
  8. package/dist/chart/index.js.map +1 -1
  9. package/dist/{chunk-GJBIVWB2.js → chunk-3S72F46R.js} +387 -9
  10. package/dist/chunk-3S72F46R.js.map +1 -0
  11. package/dist/{chunk-5TWIN7ZJ.js → chunk-47WWV3LI.js} +34 -4
  12. package/dist/chunk-47WWV3LI.js.map +1 -0
  13. package/dist/{chunk-OV7UAKIY.js → chunk-633QC34G.js} +172 -1
  14. package/dist/chunk-633QC34G.js.map +1 -0
  15. package/dist/{chunk-MR2764X2.js → chunk-AGGUNWT6.js} +2 -322
  16. package/dist/chunk-AGGUNWT6.js.map +1 -0
  17. package/dist/{chunk-T6XU4B54.js → chunk-BQQZ6MOI.js} +7 -7
  18. package/dist/{chunk-LNKZPIQD.cjs → chunk-C3JHII3M.cjs} +67 -67
  19. package/dist/{chunk-LNKZPIQD.cjs.map → chunk-C3JHII3M.cjs.map} +1 -1
  20. package/dist/{chunk-JOX6MJW4.cjs → chunk-CKRNELPO.cjs} +176 -5
  21. package/dist/chunk-CKRNELPO.cjs.map +1 -0
  22. package/dist/{chunk-TGBCBQFV.cjs → chunk-DK6QBGCS.cjs} +45 -15
  23. package/dist/chunk-DK6QBGCS.cjs.map +1 -0
  24. package/dist/{chunk-GTZXF4BI.cjs → chunk-NK3WL5TJ.cjs} +298 -133
  25. package/dist/chunk-NK3WL5TJ.cjs.map +1 -0
  26. package/dist/{chunk-3JNRQVTS.cjs → chunk-NN3JGUSX.cjs} +402 -24
  27. package/dist/chunk-NN3JGUSX.cjs.map +1 -0
  28. package/dist/{chunk-3CC7OPUQ.cjs → chunk-O6FO6VI3.cjs} +3 -323
  29. package/dist/chunk-O6FO6VI3.cjs.map +1 -0
  30. package/dist/{chunk-DQPBQXKG.js → chunk-OIKYP7XC.js} +8 -8
  31. package/dist/{chunk-FEMIVHN3.cjs → chunk-P43HUQRX.cjs} +16 -16
  32. package/dist/{chunk-FEMIVHN3.cjs.map → chunk-P43HUQRX.cjs.map} +1 -1
  33. package/dist/{chunk-QFTVLEVN.js → chunk-RIXTW3C4.js} +3 -3
  34. package/dist/{chunk-WBOAXDKD.js → chunk-VODBAO32.js} +222 -57
  35. package/dist/chunk-VODBAO32.js.map +1 -0
  36. package/dist/{chunk-2Q46FKZK.cjs → chunk-YZZMX6V7.cjs} +25 -25
  37. package/dist/{chunk-2Q46FKZK.cjs.map → chunk-YZZMX6V7.cjs.map} +1 -1
  38. package/dist/{controller-DS3drIvy.d.cts → controller-CX0QfSv0.d.cts} +53 -2
  39. package/dist/{controller-BdKzaxs2.d.ts → controller-DscWQbjO.d.ts} +53 -2
  40. package/dist/export/index.cjs +5 -5
  41. package/dist/export/index.js +4 -4
  42. package/dist/extensions/index.cjs +7 -7
  43. package/dist/extensions/index.d.cts +2 -2
  44. package/dist/extensions/index.d.ts +2 -2
  45. package/dist/extensions/index.js +6 -6
  46. package/dist/{index-Dt9lzydb.d.ts → index-CALDD35B.d.ts} +1 -1
  47. package/dist/{index-DOy9HzfC.d.cts → index-DIWB6xMf.d.cts} +1 -1
  48. package/dist/index.cjs +15 -14
  49. package/dist/index.cjs.map +1 -1
  50. package/dist/index.d.cts +6 -113
  51. package/dist/index.d.ts +6 -113
  52. package/dist/index.js +13 -12
  53. package/dist/index.js.map +1 -1
  54. package/dist/zip-4nG0YAH7.d.cts +110 -0
  55. package/dist/zip-4nG0YAH7.d.ts +110 -0
  56. package/package.json +1 -1
  57. package/dist/chunk-3CC7OPUQ.cjs.map +0 -1
  58. package/dist/chunk-3JNRQVTS.cjs.map +0 -1
  59. package/dist/chunk-5TWIN7ZJ.js.map +0 -1
  60. package/dist/chunk-GJBIVWB2.js.map +0 -1
  61. package/dist/chunk-GTZXF4BI.cjs.map +0 -1
  62. package/dist/chunk-JOX6MJW4.cjs.map +0 -1
  63. package/dist/chunk-MR2764X2.js.map +0 -1
  64. package/dist/chunk-OV7UAKIY.js.map +0 -1
  65. package/dist/chunk-TGBCBQFV.cjs.map +0 -1
  66. package/dist/chunk-WBOAXDKD.js.map +0 -1
  67. /package/dist/{chunk-T6XU4B54.js.map → chunk-BQQZ6MOI.js.map} +0 -0
  68. /package/dist/{chunk-DQPBQXKG.js.map → chunk-OIKYP7XC.js.map} +0 -0
  69. /package/dist/{chunk-QFTVLEVN.js.map → chunk-RIXTW3C4.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/chunk-JOX6MJW4.cjs","../src/chart/color.ts","../src/chart/spec.ts"],"names":["text"],"mappings":"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C8B,EAAA;AACgC,EAAA;AACX,EAAA;AACgE,EAAA;AACjF,EAAA;AACI,EAAA;AACA,EAAA;AACxB,IAAA;AACiF,IAAA;AAC9F,EAAA;AAC8B,EAAA;AACO,EAAA;AACyE,IAAA;AAC5E,IAAA;AACY,MAAA;AACnB,MAAA;AACqE,QAAA;AACvF,QAAA;AACR,MAAA;AACO,MAAA;AACP,IAAA;AACgD,IAAA;AAClD,EAAA;AAC8B,EAAA;AACA,IAAA;AACe,MAAA;AACuC,MAAA;AACjE,MAAA;AACjB,IAAA;AACkC,IAAA;AACpC,EAAA;AACoC,EAAA;AACrC;AAG0J;AAClJ,EAAA;AAC0D,IAAA;AACkC,IAAA;AACnG,EAAA;AACD;AAG4D;AACC,EAAA;AAC+C,EAAA;AACpG,EAAA;AACR;AF6BkH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/editor/editor/packages/core/dist/chunk-JOX6MJW4.cjs","sourcesContent":[null,"// Portions ported from gridcraft-main/crates/chart/src/resolve.rs (palette tint cycle) and\n// crates/chart/src/render.rs (`on`: label colour from the fill), and designcraft-main/crates/color/src/cms/mod.rs\n// (`simulate_cvd`, Machado–Oliveira–Fernandes 2009 matrices) (MIT OR Apache-2.0, © ArtCraft Team and contributors).\n// See THIRD_PARTY_NOTICES.md.\n\n/** An sRGB colour with channels from 0 to 1. */\nexport type ChartRgb = [number, number, number];\n\nconst NAMED: Record<string, string> = {\n\tblack: '#000000',\n\twhite: '#ffffff',\n\tred: '#ff0000',\n\tgreen: '#008000',\n\tblue: '#0000ff',\n\tyellow: '#ffff00',\n\torange: '#ffa500',\n\tpurple: '#800080',\n\tgray: '#808080',\n\tgrey: '#808080',\n\tteal: '#008080',\n\tnavy: '#000080',\n\tmaroon: '#800000',\n\tolive: '#808000',\n\tsilver: '#c0c0c0',\n\tlime: '#00ff00',\n\taqua: '#00ffff',\n\tcyan: '#00ffff',\n\tfuchsia: '#ff00ff',\n\tmagenta: '#ff00ff',\n\tpink: '#ffc0cb',\n\tbrown: '#a52a2a'\n};\n\n/**\n * Reads `#rgb`, `#rrggbb`, `#rrggbbaa`, `rgb()` / `rgba()` and a few colour names. Returns\n * `null` for anything else (CSS variables, `hsl()`, …), so callers can leave such colours alone.\n */\nexport function parseChartColor(color: string): ChartRgb | null {\n\tconst text = color.trim().toLowerCase();\n\tconst hex = NAMED[text] ?? text;\n\tlet m = /^#([0-9a-f]{3})$/.exec(hex);\n\tif (m) return [...m[1]].map((c) => parseInt(c + c, 16) / 255) as ChartRgb;\n\tm = /^#([0-9a-f]{6})([0-9a-f]{2})?$/.exec(hex);\n\tif (m) return [0, 2, 4].map((i) => parseInt(m![1].slice(i, i + 2), 16) / 255) as ChartRgb;\n\tm = /^rgba?\\(\\s*([\\d.]+)%?[\\s,]+([\\d.]+)%?[\\s,]+([\\d.]+)%?(?:[\\s,/]+[\\d.]+%?)?\\s*\\)$/.exec(text);\n\tif (m) {\n\t\tconst pct = text.includes('%');\n\t\treturn [m[1], m[2], m[3]].map((v) => Math.max(0, Math.min(1, Number(v) / (pct ? 100 : 255)))) as ChartRgb;\n\t}\n\treturn null;\n}\n\nexport function chartRgbToHex(rgb: ChartRgb): string {\n\treturn `#${rgb.map((c) => Math.round(Math.max(0, Math.min(1, c)) * 255).toString(16).padStart(2, '0')).join('')}`;\n}\n\n/**\n * A lighter (`amount` > 0, towards white) or darker (`amount` < 0, towards black) shade of\n * `color`. Colours it cannot read (CSS variables) come back unchanged.\n */\nexport function shadeChartColor(color: string, amount: number): string {\n\tconst rgb = parseChartColor(color);\n\tif (!rgb || !amount) return color;\n\tconst t = Math.max(-1, Math.min(1, amount));\n\treturn chartRgbToHex(rgb.map((c) => (t > 0 ? c + (1 - c) * t : c * (1 + t))) as ChartRgb);\n}\n\n/** Shades used once a palette is used up: the same hues, lighter then darker (GridCraft's cycle). */\nexport const CHART_PALETTE_SHADES: readonly number[] = [0, 0.4, -0.25, 0.6, -0.5, 0.2];\n\n/** The palette colour for the `index`-th item: the palette in order, then lighter and darker rounds of it. */\nexport function cyclePaletteColor(palette: readonly string[], index: number): string {\n\tconst base = palette[index % palette.length];\n\tconst round = Math.floor(index / palette.length) % CHART_PALETTE_SHADES.length;\n\treturn shadeChartColor(base, CHART_PALETTE_SHADES[round]);\n}\n\nconst toLinear = (c: number) => (c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));\nconst fromLinear = (c: number) => (c <= 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055);\n\n/** WCAG relative luminance (0 black – 1 white). */\nexport function chartLuminance(rgb: ChartRgb): number {\n\tconst [r, g, b] = rgb.map(toLinear);\n\treturn 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\n/** WCAG contrast ratio (1–21) between two colours, or `null` when either cannot be read. */\nexport function chartContrastRatio(a: string, b: string): number | null {\n\tconst ra = parseChartColor(a);\n\tconst rb = parseChartColor(b);\n\tif (!ra || !rb) return null;\n\tconst la = chartLuminance(ra);\n\tconst lb = chartLuminance(rb);\n\treturn (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);\n}\n\n/**\n * Dark or white text, whichever reads better on `fill`; `fallback` when the fill cannot be\n * read (a CSS variable).\n */\nexport function chartTextOn(fill: string, fallback: string, dark = '#0f172a', light = '#ffffff'): string {\n\tconst rgb = parseChartColor(fill);\n\tif (!rgb) return fallback;\n\tconst darkRatio = chartContrastRatio(fill, dark)!;\n\tconst lightRatio = chartContrastRatio(fill, light)!;\n\treturn darkRatio >= lightRatio ? dark : light;\n}\n\n/** OKLab (Ottosson) from sRGB. */\nexport function chartRgbToOklab(rgb: ChartRgb): [number, number, number] {\n\tconst [r, g, b] = rgb.map(toLinear);\n\tconst l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);\n\tconst m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);\n\tconst s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);\n\treturn [\n\t\t0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n\t\t1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n\t\t0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s\n\t];\n}\n\n/** Perceptual distance between two colours (Euclidean in OKLab; ≈0.02 is just noticeable). */\nexport function chartColorDistance(a: ChartRgb, b: ChartRgb): number {\n\tconst p = chartRgbToOklab(a);\n\tconst q = chartRgbToOklab(b);\n\treturn Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);\n}\n\nexport type ChartVision = 'normal' | 'protanopia' | 'deuteranopia' | 'tritanopia';\n\n// Machado, Oliveira & Fernandes (2009), severity 1.0, applied in linear RGB.\nconst CVD: Record<Exclude<ChartVision, 'normal'>, number[][]> = {\n\tprotanopia: [\n\t\t[0.152286, 1.052583, -0.204868],\n\t\t[0.114503, 0.786281, 0.099216],\n\t\t[-0.003882, -0.048116, 1.051998]\n\t],\n\tdeuteranopia: [\n\t\t[0.367322, 0.860646, -0.227968],\n\t\t[0.280085, 0.672501, 0.047413],\n\t\t[-0.01182, 0.04294, 0.968881]\n\t],\n\ttritanopia: [\n\t\t[1.255528, -0.076749, -0.178779],\n\t\t[-0.078411, 0.930809, 0.147602],\n\t\t[0.004733, 0.691367, 0.3039]\n\t]\n};\n\n/** How a colour looks with a colour-vision deficiency (Machado et al. 2009, full severity). */\nexport function simulateChartVision(rgb: ChartRgb, vision: ChartVision): ChartRgb {\n\tif (vision === 'normal') return rgb;\n\tconst lin = rgb.map(toLinear);\n\tconst m = CVD[vision];\n\treturn m.map((row) => fromLinear(Math.max(0, Math.min(1, row[0] * lin[0] + row[1] * lin[1] + row[2] * lin[2])))) as ChartRgb;\n}\n\nexport interface ChartColorPair {\n\ta: number;\n\tb: number;\n\tcolors: [string, string];\n\tdistance: number;\n}\n\nexport interface ChartColorCheck {\n\t/** No problems found. */\n\tok: boolean;\n\t/** Per vision: the closest pair of colours and their OKLab distance. */\n\tclosest: Partial<Record<ChartVision, ChartColorPair>>;\n\t/** Contrast ratio of each colour against the surface (null when unreadable). */\n\tcontrast: (number | null)[];\n\t/** Problems, as sentences. */\n\tissues: string[];\n\t/** Colours that could not be read (CSS variables, `hsl()`); they are skipped. */\n\tskipped: string[];\n}\n\nexport interface ChartColorCheckOptions {\n\t/** The page colour behind the marks (default white). */\n\tsurface?: string;\n\t/** Smallest OKLab distance two series may have (default 0.08). */\n\tminDistance?: number;\n\t/** Smallest contrast ratio against the surface (default 1.5; WCAG asks 3 for graphics). */\n\tminContrast?: number;\n\t/** Visions to check (default all four). */\n\tvisions?: readonly ChartVision[];\n}\n\n/**\n * Checks that series colours can be told apart, with normal vision and the three\n * colour-vision deficiencies, and stand out from the surface. Returns the closest pair per\n * vision and problems as sentences.\n */\nexport function checkChartColors(colors: readonly string[], options: ChartColorCheckOptions = {}): ChartColorCheck {\n\tconst surface = options.surface ?? '#ffffff';\n\tconst minDistance = options.minDistance ?? 0.08;\n\tconst minContrast = options.minContrast ?? 1.5;\n\tconst visions = options.visions ?? (['normal', 'protanopia', 'deuteranopia', 'tritanopia'] as const);\n\tconst parsed = colors.map(parseChartColor);\n\tconst skipped = colors.filter((_, i) => !parsed[i]);\n\tconst issues: string[] = [];\n\tconst closest: ChartColorCheck['closest'] = {};\n\tfor (const vision of visions) {\n\t\tconst seen = parsed.map((c) => (c ? simulateChartVision(c, vision) : null));\n\t\tlet best: ChartColorPair | undefined;\n\t\tfor (let a = 0; a < seen.length; a++) {\n\t\t\tfor (let b = a + 1; b < seen.length; b++) {\n\t\t\t\tif (!seen[a] || !seen[b]) continue;\n\t\t\t\tconst distance = chartColorDistance(seen[a]!, seen[b]!);\n\t\t\t\tif (!best || distance < best.distance) best = { a, b, colors: [colors[a], colors[b]], distance: Math.round(distance * 1000) / 1000 };\n\t\t\t}\n\t\t}\n\t\tif (best) {\n\t\t\tclosest[vision] = best;\n\t\t\tif (best.distance < minDistance) {\n\t\t\t\tconst who = vision === 'normal' ? '' : ` with ${vision}`;\n\t\t\t\tissues.push(`Colours ${best.a + 1} (${best.colors[0]}) and ${best.b + 1} (${best.colors[1]}) are hard to tell apart${who} (distance ${best.distance}, want at least ${minDistance}).`);\n\t\t\t}\n\t\t}\n\t}\n\tconst contrast = colors.map((c) => {\n\t\tconst ratio = chartContrastRatio(c, surface);\n\t\treturn ratio === null ? null : Math.round(ratio * 100) / 100;\n\t});\n\tcontrast.forEach((ratio, i) => {\n\t\tif (ratio !== null && ratio < minContrast) issues.push(`Colour ${i + 1} (${colors[i]}) barely stands out from the background ${surface} (contrast ${ratio}:1, want at least ${minContrast}:1).`);\n\t});\n\treturn { ok: issues.length === 0, closest, contrast, issues, skipped };\n}\n","import { cyclePaletteColor } from './color.js';\nimport type {\n\tChartAxis,\n\tChartCurve,\n\tChartIssue,\n\tChartLabelPosition,\n\tChartLegend,\n\tChartLegendPosition,\n\tChartMarker,\n\tChartNumberFormat,\n\tChartOrientation,\n\tChartSeries,\n\tChartSeriesType,\n\tChartSpec,\n\tChartStacking,\n\tChartTheme,\n\tChartTrendline,\n\tChartTrendlineType,\n\tChartType,\n\tChartValue\n} from './types.js';\n\nexport const CHART_TYPES: readonly ChartType[] = ['bar', 'line', 'area', 'scatter', 'bubble', 'pie', 'donut', 'radar', 'waterfall', 'histogram', 'box', 'funnel', 'treemap'];\nexport const CHART_MARKERS: readonly ChartMarker[] = ['circle', 'square', 'diamond', 'triangle', 'cross', 'none'];\nexport const CHART_TRENDLINE_TYPES: readonly ChartTrendlineType[] = ['linear', 'exponential', 'logarithmic', 'power', 'polynomial', 'moving-average'];\nexport const CHART_LABEL_POSITIONS: readonly ChartLabelPosition[] = ['auto', 'inside', 'outside', 'center'];\nexport const CHART_AXIS_KINDS: readonly NonNullable<ChartAxis['kind']>[] = ['category', 'date'];\nexport const CHART_SERIES_TYPES: readonly ChartSeriesType[] = ['bar', 'line', 'area', 'scatter'];\nexport const CHART_STACKINGS: readonly ChartStacking[] = ['none', 'stacked', 'percent'];\nexport const CHART_CURVES: readonly ChartCurve[] = ['linear', 'smooth', 'step'];\nexport const CHART_ORIENTATIONS: readonly ChartOrientation[] = ['vertical', 'horizontal'];\nexport const CHART_LEGEND_POSITIONS: readonly ChartLegendPosition[] = ['top', 'bottom', 'left', 'right'];\nexport const CHART_NUMBER_STYLES: readonly NonNullable<ChartNumberFormat['style']>[] = ['number', 'percent', 'currency', 'compact'];\n\n/** Labels for pickers, shared by the React and Svelte components. */\nexport const CHART_TYPE_LABELS: Readonly<Record<ChartType, string>> = {\n\tbar: 'Bar',\n\tline: 'Line',\n\tarea: 'Area',\n\tscatter: 'Scatter',\n\tbubble: 'Bubble',\n\tpie: 'Pie',\n\tdonut: 'Donut',\n\tradar: 'Radar',\n\twaterfall: 'Waterfall',\n\thistogram: 'Histogram',\n\tbox: 'Box plot',\n\tfunnel: 'Funnel',\n\ttreemap: 'Treemap'\n};\n\n/** How a chart type is laid out. */\nexport type ChartFamily = 'cartesian' | 'xy' | 'pie' | 'radar' | 'waterfall' | 'histogram' | 'box' | 'funnel' | 'treemap';\n\n/** A colour-blind-friendly categorical palette (Okabe–Ito order, tuned for light and dark backgrounds). */\nexport const DEFAULT_CHART_PALETTE: readonly string[] = ['#4269d0', '#efb118', '#ff725c', '#6cc5b0', '#3ca951', '#ff8ab7', '#a463f2', '#97bbf5', '#9c6b4e', '#9498a0'];\n\nexport const DEFAULT_CHART_THEME: ChartTheme = {\n\tbackground: '#ffffff',\n\tsurface: '#ffffff',\n\ttext: '#0f172a',\n\tmutedText: '#64748b',\n\tgrid: '#e2e8f0',\n\taxis: '#94a3b8',\n\tselection: '#2563eb',\n\tpositive: '#3ca951',\n\tnegative: '#e5484d',\n\tfontFamily: 'system-ui, -apple-system, \"Segoe UI\", sans-serif',\n\tfontSize: 11,\n\ttitleSize: 15\n};\n\n/**\n * A theme that reads the page's `--background`, `--foreground`, `--muted-foreground`,\n * `--border` and `--primary` colour variables (full colours, as the other components'\n * inline styles use them), with light fallbacks. The React and Svelte canvases use it.\n */\nexport const CSS_VARIABLE_CHART_THEME: ChartTheme = {\n\t...DEFAULT_CHART_THEME,\n\tbackground: 'transparent',\n\tsurface: 'var(--background, #ffffff)',\n\ttext: 'var(--foreground, #0f172a)',\n\tmutedText: 'var(--muted-foreground, #64748b)',\n\tgrid: 'var(--border, #e2e8f0)',\n\taxis: 'var(--muted-foreground, #94a3b8)',\n\tselection: 'var(--primary, #2563eb)',\n\tfontFamily: 'inherit'\n};\n\n/** Bar, line, area and scatter: categories (or numeric x) against values, series may mix. */\nexport function isCartesianChart(type: ChartType): boolean {\n\treturn type === 'bar' || type === 'line' || type === 'area' || type === 'scatter';\n}\n\n/** Whether the chart plots series against a numeric x axis (bubble charts, and scatter charts with x values). */\nexport function isXyChart(spec: Pick<ChartSpec, 'type' | 'series'>): boolean {\n\tif (spec.type === 'bubble') return true;\n\treturn spec.type === 'scatter' && spec.series.some((s) => !s.hidden && Array.isArray(s.x) && s.x.some((v) => v !== null));\n}\n\n/** How a chart is laid out (see `ChartType`). */\nexport function chartFamily(spec: Pick<ChartSpec, 'type' | 'series'>): ChartFamily {\n\tif (isXyChart(spec)) return 'xy';\n\tswitch (spec.type) {\n\t\tcase 'pie':\n\t\tcase 'donut':\n\t\t\treturn 'pie';\n\t\tcase 'radar':\n\t\tcase 'waterfall':\n\t\tcase 'histogram':\n\t\tcase 'box':\n\t\tcase 'funnel':\n\t\tcase 'treemap':\n\t\t\treturn spec.type;\n\t\tcase 'bubble':\n\t\t\treturn 'xy';\n\t\tdefault:\n\t\t\treturn 'cartesian';\n\t}\n}\n\n/** Chart types whose legend lists categories (one colour per category) rather than series. */\nexport function chartColorsByCategory(type: ChartType): boolean {\n\treturn type === 'pie' || type === 'donut' || type === 'funnel' || type === 'treemap';\n}\n\nexport function defaultChartAxis(value: boolean): ChartAxis {\n\treturn { show: true, title: '', min: null, max: null, step: null, gridlines: value, format: {} };\n}\n\n/** A complete spec with every default filled in. */\nexport function createChartSpec(partial: Partial<ChartSpec> = {}): ChartSpec {\n\treturn normalizeChartSpec(partial).spec;\n}\n\n/** The colour a series is drawn with. */\nexport function chartSeriesColor(spec: Pick<ChartSpec, 'palette' | 'series'>, seriesIndex: number): string {\n\tconst series = spec.series[seriesIndex];\n\tif (series?.color) return series.color;\n\treturn cyclePaletteColor(spec.palette.length ? spec.palette : DEFAULT_CHART_PALETTE, seriesIndex);\n}\n\n/** The colour a pie slice is drawn with (by category). */\nexport function chartSliceColor(spec: Pick<ChartSpec, 'palette'>, index: number): string {\n\treturn cyclePaletteColor(spec.palette.length ? spec.palette : DEFAULT_CHART_PALETTE, index);\n}\n\n/** The colour of one bar or point: its override, else the series colour. */\nexport function chartPointColor(spec: Pick<ChartSpec, 'palette' | 'series'>, seriesIndex: number, index: number): string {\n\treturn spec.series[seriesIndex]?.pointColors?.[index] || chartSeriesColor(spec, seriesIndex);\n}\n\n/** How a series is drawn in a cartesian chart. */\nexport function chartSeriesType(spec: Pick<ChartSpec, 'type'>, series: ChartSeries): ChartSeriesType {\n\tif (series.type) return series.type;\n\tif (spec.type === 'bubble') return 'scatter';\n\treturn isCartesianChart(spec.type) ? (spec.type as ChartSeriesType) : 'bar';\n}\n\n/** An id not used by any series (`series-1`, `series-2`, …). */\nexport function uniqueChartSeriesId(series: readonly Pick<ChartSeries, 'id'>[], base = 'series'): string {\n\tconst used = new Set(series.map((s) => s.id));\n\tfor (let i = series.length + 1; ; i++) {\n\t\tconst id = `${base}-${i}`;\n\t\tif (!used.has(id)) return id;\n\t}\n}\n\n/**\n * Reads a number the way people type it in a data grid: `1,234.5`, `12%` (→ 0.12),\n * `$40`, `(3)` (→ -3). Blank → `null`. Returns `undefined` when it is not a number.\n */\nexport function parseChartValue(input: unknown): ChartValue | undefined {\n\tif (input === null || input === undefined) return null;\n\tif (typeof input === 'number') return Number.isFinite(input) ? input : undefined;\n\tif (typeof input !== 'string') return undefined;\n\tlet text = input.trim();\n\tif (!text || text === '-' || text === '—') return null;\n\tlet negative = false;\n\tif (/^\\(.*\\)$/.test(text)) {\n\t\tnegative = true;\n\t\ttext = text.slice(1, -1).trim();\n\t}\n\tconst percent = text.endsWith('%');\n\tif (percent) text = text.slice(0, -1).trim();\n\ttext = text.replace(/^[$€£¥]/, '').replace(/,/g, '').replace(/\\s+/g, '');\n\tif (!/^[-+]?(\\d+\\.?\\d*|\\.\\d+)(e[-+]?\\d+)?$/i.test(text)) return undefined;\n\tlet value = Number(text);\n\tif (percent) value /= 100;\n\tif (negative) value = -value;\n\treturn Number.isFinite(value) ? value : undefined;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null && !Array.isArray(value);\n\nfunction pick<T extends string>(value: unknown, options: readonly T[], fallback: T, path: string, issues: ChartIssue[]): T {\n\tif (value === undefined) return fallback;\n\tif (typeof value === 'string' && (options as readonly string[]).includes(value)) return value as T;\n\tissues.push({ path, message: `${path} must be one of ${options.map((o) => `\"${o}\"`).join(', ')}; got ${JSON.stringify(value)}.` });\n\treturn fallback;\n}\n\nfunction text(value: unknown, fallback: string, path: string, issues: ChartIssue[]): string {\n\tif (value === undefined || value === null) return fallback;\n\tif (typeof value === 'string') return value;\n\tif (typeof value === 'number' || typeof value === 'boolean') return String(value);\n\tissues.push({ path, message: `${path} must be text.` });\n\treturn fallback;\n}\n\nfunction flag(value: unknown, fallback: boolean, path: string, issues: ChartIssue[]): boolean {\n\tif (value === undefined) return fallback;\n\tif (typeof value === 'boolean') return value;\n\tissues.push({ path, message: `${path} must be true or false.` });\n\treturn fallback;\n}\n\nfunction bound(value: unknown, path: string, issues: ChartIssue[]): number | null {\n\tif (value === undefined || value === null || value === '') return null;\n\tconst n = typeof value === 'string' ? Number(value) : value;\n\tif (typeof n === 'number' && Number.isFinite(n)) return n;\n\tissues.push({ path, message: `${path} must be a number or null.` });\n\treturn null;\n}\n\nfunction normalizeFormat(value: unknown, path: string, issues: ChartIssue[]): ChartNumberFormat {\n\tif (value === undefined || value === null) return {};\n\tif (!isRecord(value)) {\n\t\tissues.push({ path, message: `${path} must be an object.` });\n\t\treturn {};\n\t}\n\tconst out: ChartNumberFormat = {};\n\tif (value.style !== undefined) out.style = pick(value.style, CHART_NUMBER_STYLES, 'number', `${path}.style`, issues);\n\tif (value.decimals !== undefined) {\n\t\tconst d = Number(value.decimals);\n\t\tif (Number.isInteger(d) && d >= 0 && d <= 10) out.decimals = d;\n\t\telse issues.push({ path: `${path}.decimals`, message: `${path}.decimals must be a whole number from 0 to 10.` });\n\t}\n\tfor (const key of ['currency', 'prefix', 'suffix', 'code'] as const) {\n\t\tif (value[key] !== undefined) out[key] = text(value[key], '', `${path}.${key}`, issues);\n\t}\n\treturn out;\n}\n\nexport function normalizeChartAxis(value: unknown, fallback: ChartAxis, path: string, issues: ChartIssue[] = []): ChartAxis {\n\tif (value === undefined) return { ...fallback, format: { ...fallback.format } };\n\tif (!isRecord(value)) {\n\t\tissues.push({ path, message: `${path} must be an object.` });\n\t\treturn { ...fallback, format: { ...fallback.format } };\n\t}\n\tlet min = 'min' in value ? bound(value.min, `${path}.min`, issues) : fallback.min;\n\tlet max = 'max' in value ? bound(value.max, `${path}.max`, issues) : fallback.max;\n\tif (min !== null && max !== null && min >= max) {\n\t\tissues.push({ path: `${path}.max`, message: `${path}.max (${max}) must be greater than ${path}.min (${min}).` });\n\t\tmin = fallback.min;\n\t\tmax = fallback.max;\n\t}\n\tlet step = 'step' in value ? bound(value.step, `${path}.step`, issues) : fallback.step;\n\tif (step !== null && !(step > 0)) {\n\t\tissues.push({ path: `${path}.step`, message: `${path}.step must be greater than 0 (or null for automatic).` });\n\t\tstep = fallback.step;\n\t}\n\tconst axis: ChartAxis = {\n\t\tshow: flag(value.show, fallback.show, `${path}.show`, issues),\n\t\ttitle: text(value.title, fallback.title, `${path}.title`, issues),\n\t\tmin,\n\t\tmax,\n\t\tstep,\n\t\tgridlines: flag(value.gridlines, fallback.gridlines, `${path}.gridlines`, issues),\n\t\tformat: 'format' in value ? normalizeFormat(value.format, `${path}.format`, issues) : { ...fallback.format }\n\t};\n\tconst kind = 'kind' in value ? (value.kind === null ? undefined : pick(value.kind, CHART_AXIS_KINDS, 'category', `${path}.kind`, issues)) : fallback.kind;\n\tif (kind && kind !== 'category') axis.kind = kind;\n\treturn axis;\n}\n\nfunction normalizeLegend(value: unknown, issues: ChartIssue[]): ChartLegend {\n\tconst fallback: ChartLegend = { show: true, position: 'bottom' };\n\tif (value === undefined) return fallback;\n\tif (!isRecord(value)) {\n\t\tissues.push({ path: 'legend', message: 'legend must be an object.' });\n\t\treturn fallback;\n\t}\n\treturn {\n\t\tshow: flag(value.show, fallback.show, 'legend.show', issues),\n\t\tposition: pick(value.position, CHART_LEGEND_POSITIONS, fallback.position, 'legend.position', issues)\n\t};\n}\n\n/** Values as numbers or nulls; bad entries become null and are reported. */\nexport function normalizeChartValues(value: unknown, length: number | undefined, path: string, issues: ChartIssue[] = []): ChartValue[] {\n\tif (value === undefined) return length ? Array(length).fill(null) : [];\n\tif (!Array.isArray(value)) {\n\t\tissues.push({ path, message: `${path} must be an array of numbers.` });\n\t\treturn length ? Array(length).fill(null) : [];\n\t}\n\tconst out = value.map((v, i) => {\n\t\tconst parsed = parseChartValue(v);\n\t\tif (parsed === undefined) {\n\t\t\tissues.push({ path: `${path}[${i}]`, message: `${path}[${i}] is not a number: ${JSON.stringify(v)}.` });\n\t\t\treturn null;\n\t\t}\n\t\treturn parsed;\n\t});\n\tif (length === undefined) return out;\n\tif (out.length > length) return out.slice(0, length);\n\twhile (out.length < length) out.push(null);\n\treturn out;\n}\n\nfunction normalizeSeries(value: unknown, length: number, used: Set<string>, index: number, issues: ChartIssue[]): ChartSeries | null {\n\tconst path = `series[${index}]`;\n\tif (!isRecord(value)) {\n\t\tissues.push({ path, message: `${path} must be an object with a name and values.` });\n\t\treturn null;\n\t}\n\tlet id = typeof value.id === 'string' && value.id.trim() ? value.id.trim() : '';\n\tif (!id || used.has(id)) {\n\t\tif (id) issues.push({ path: `${path}.id`, message: `Series id \"${id}\" is used twice; the second was renamed.` });\n\t\tfor (let n = index + 1; ; n++) {\n\t\t\tid = `series-${n}`;\n\t\t\tif (!used.has(id)) break;\n\t\t}\n\t}\n\tused.add(id);\n\tconst series: ChartSeries = {\n\t\tid,\n\t\tname: text(value.name, `Series ${index + 1}`, `${path}.name`, issues),\n\t\tvalues: normalizeChartValues(value.values, length, `${path}.values`, issues)\n\t};\n\tif (typeof value.color === 'string' && value.color.trim()) series.color = value.color.trim();\n\tif (value.type !== undefined && value.type !== null) series.type = pick(value.type, CHART_SERIES_TYPES, 'bar', `${path}.type`, issues);\n\tif (value.hidden === true) series.hidden = true;\n\tif (value.axis !== undefined && value.axis !== null && pick(value.axis, ['primary', 'secondary'] as const, 'primary', `${path}.axis`, issues) === 'secondary') series.axis = 'secondary';\n\tfor (const key of ['x', 'sizes'] as const) {\n\t\tif (value[key] === undefined || value[key] === null) continue;\n\t\tconst list = normalizeChartValues(value[key], length, `${path}.${key}`, issues);\n\t\tif (list.some((v) => v !== null)) series[key] = list;\n\t}\n\tif (key(value, 'sizes') && series.sizes?.some((v) => v !== null && v < 0)) {\n\t\tissues.push({ path: `${path}.sizes`, message: `${path}.sizes must not be negative.` });\n\t\tseries.sizes = series.sizes.map((v) => (v !== null && v < 0 ? null : v));\n\t}\n\tif (value.pointColors !== undefined && value.pointColors !== null) {\n\t\tif (!Array.isArray(value.pointColors)) issues.push({ path: `${path}.pointColors`, message: `${path}.pointColors must be an array of colours or nulls.` });\n\t\telse {\n\t\t\tconst colors = Array.from({ length }, (_, i) => {\n\t\t\t\tconst c = (value.pointColors as unknown[])[i];\n\t\t\t\treturn typeof c === 'string' && c.trim() ? c.trim() : null;\n\t\t\t});\n\t\t\tif (colors.some((c) => c !== null)) series.pointColors = colors;\n\t\t}\n\t}\n\tif (value.marker !== undefined && value.marker !== null) series.marker = pick(value.marker, CHART_MARKERS, 'circle', `${path}.marker`, issues);\n\tif (value.curve !== undefined && value.curve !== null) series.curve = pick(value.curve, CHART_CURVES, 'linear', `${path}.curve`, issues);\n\tif (value.dataLabels !== undefined && value.dataLabels !== null) series.dataLabels = flag(value.dataLabels, false, `${path}.dataLabels`, issues);\n\tif (value.format !== undefined && value.format !== null) {\n\t\tconst format = normalizeFormat(value.format, `${path}.format`, issues);\n\t\tif (Object.keys(format).length) series.format = format;\n\t}\n\tif (value.trendlines !== undefined && value.trendlines !== null) {\n\t\tif (!Array.isArray(value.trendlines)) issues.push({ path: `${path}.trendlines`, message: `${path}.trendlines must be an array.` });\n\t\telse {\n\t\t\tconst lines = value.trendlines.map((t, i) => normalizeChartTrendline(t, `${path}.trendlines[${i}]`, issues)).filter((t): t is ChartTrendline => t !== null);\n\t\t\tif (lines.length) series.trendlines = lines;\n\t\t}\n\t}\n\treturn series;\n}\n\nconst key = (value: Record<string, unknown>, name: string) => value[name] !== undefined && value[name] !== null;\n\n/** Checks one trendline; `null` (reported) when it is unusable. */\nexport function normalizeChartTrendline(value: unknown, path: string, issues: ChartIssue[] = []): ChartTrendline | null {\n\tif (!isRecord(value)) {\n\t\tissues.push({ path, message: `${path} must be an object with a type.` });\n\t\treturn null;\n\t}\n\tconst type = pick(value.type, CHART_TRENDLINE_TYPES, 'linear', `${path}.type`, issues);\n\tconst line: ChartTrendline = { type };\n\tconst whole = (name: 'order' | 'period', min: number, max: number) => {\n\t\tif (!key(value, name)) return;\n\t\tconst n = Number(value[name]);\n\t\tif (Number.isInteger(n) && n >= min && n <= max) line[name] = n;\n\t\telse issues.push({ path: `${path}.${name}`, message: `${path}.${name} must be a whole number from ${min} to ${max}.` });\n\t};\n\tif (type === 'polynomial') whole('order', 2, 6);\n\tif (type === 'moving-average') whole('period', 2, 1000);\n\tfor (const name of ['forward', 'backward'] as const) {\n\t\tif (!key(value, name)) continue;\n\t\tconst n = Number(value[name]);\n\t\tif (Number.isFinite(n) && n >= 0) {\n\t\t\tif (n > 0) line[name] = n;\n\t\t} else issues.push({ path: `${path}.${name}`, message: `${path}.${name} must be a number of x units, 0 or more.` });\n\t}\n\tif (key(value, 'intercept')) {\n\t\tconst n = Number(value.intercept);\n\t\tif (!Number.isFinite(n)) issues.push({ path: `${path}.intercept`, message: `${path}.intercept must be a number or null.` });\n\t\telse if (type === 'linear' || type === 'polynomial' || type === 'exponential') {\n\t\t\tif (type === 'exponential' && n <= 0) issues.push({ path: `${path}.intercept`, message: `${path}.intercept must be greater than 0 for an exponential trendline.` });\n\t\t\telse line.intercept = n;\n\t\t} else issues.push({ path: `${path}.intercept`, message: `A ${type} trendline cannot have a fixed intercept; use linear, polynomial or exponential.` });\n\t}\n\tfor (const name of ['showEquation', 'showR2'] as const) if (key(value, name) && flag(value[name], false, `${path}.${name}`, issues)) line[name] = true;\n\tfor (const name of ['name', 'color'] as const) {\n\t\tif (!key(value, name)) continue;\n\t\tconst t = text(value[name], '', `${path}.${name}`, issues).trim();\n\t\tif (t) line[name] = t;\n\t}\n\treturn line;\n}\n\n/**\n * Turns any input (a partial spec, saved JSON, an agent's arguments) into a complete,\n * valid `ChartSpec`. Every value is checked; problems are reported as sentences in\n * `issues` and replaced by defaults, so the result is always drawable. Series values are\n * padded or trimmed to the number of categories.\n */\nexport function normalizeChartSpec(input: unknown): { spec: ChartSpec; issues: ChartIssue[] } {\n\tconst issues: ChartIssue[] = [];\n\tconst value = isRecord(input) ? input : {};\n\tif (input !== undefined && !isRecord(input)) issues.push({ path: '', message: 'A chart must be an object.' });\n\tconst type = pick(value.type, CHART_TYPES, 'bar', 'type', issues);\n\tconst rawSeries = Array.isArray(value.series) ? value.series : [];\n\tif (value.series !== undefined && !Array.isArray(value.series)) issues.push({ path: 'series', message: 'series must be an array.' });\n\n\tlet categories: string[];\n\tif (Array.isArray(value.categories)) categories = value.categories.map((c, i) => text(c, '', `categories[${i}]`, issues));\n\telse {\n\t\tif (value.categories !== undefined) issues.push({ path: 'categories', message: 'categories must be an array of labels.' });\n\t\tconst longest = rawSeries.reduce<number>((n, s) => Math.max(n, isRecord(s) && Array.isArray(s.values) ? s.values.length : 0), 0);\n\t\tcategories = Array.from({ length: longest }, (_, i) => `${i + 1}`);\n\t}\n\n\tconst used = new Set<string>();\n\tconst series = rawSeries.map((s, i) => normalizeSeries(s, categories.length, used, i, issues)).filter((s): s is ChartSeries => s !== null);\n\n\tlet palette = [...DEFAULT_CHART_PALETTE];\n\tif (Array.isArray(value.palette)) {\n\t\tconst colors = value.palette.filter((c): c is string => typeof c === 'string' && c.trim() !== '');\n\t\tif (colors.length) palette = colors;\n\t\telse issues.push({ path: 'palette', message: 'palette must list at least one colour.' });\n\t} else if (value.palette !== undefined) issues.push({ path: 'palette', message: 'palette must be an array of colours.' });\n\n\tconst fraction = (name: string, fallback: number, min: number, max: number) => {\n\t\tif (value[name] === undefined) return fallback;\n\t\tconst r = Number(value[name]);\n\t\tif (value[name] !== null && Number.isFinite(r) && r >= min && r <= max) return r;\n\t\tissues.push({ path: name, message: `${name} must be a number from ${min} to ${max}.` });\n\t\treturn fallback;\n\t};\n\tconst innerRadius = fraction('innerRadius', 0.55, 0, 0.9);\n\tconst gapWidth = fraction('gapWidth', 0.28, 0, 0.9);\n\tconst overlap = fraction('overlap', -0.12, -1, 1);\n\tlet bins: number | null = null;\n\tif (value.bins !== undefined && value.bins !== null) {\n\t\tconst b = Number(value.bins);\n\t\tif (Number.isInteger(b) && b >= 1 && b <= 500) bins = b;\n\t\telse issues.push({ path: 'bins', message: 'bins must be a whole number from 1 to 500, or null for automatic.' });\n\t}\n\n\tconst spec: ChartSpec = {\n\t\tversion: 1,\n\t\ttype,\n\t\ttitle: text(value.title, '', 'title', issues),\n\t\tsubtitle: text(value.subtitle, '', 'subtitle', issues),\n\t\tcategories,\n\t\tseries,\n\t\txAxis: normalizeChartAxis(value.xAxis, defaultChartAxis(false), 'xAxis', issues),\n\t\tyAxis: normalizeChartAxis(value.yAxis, defaultChartAxis(true), 'yAxis', issues),\n\t\tyAxis2: normalizeChartAxis(value.yAxis2, defaultChartAxis(false), 'yAxis2', issues),\n\t\tlegend: normalizeLegend(value.legend, issues),\n\t\tstacking: pick(value.stacking, CHART_STACKINGS, 'none', 'stacking', issues),\n\t\torientation: pick(value.orientation, CHART_ORIENTATIONS, 'vertical', 'orientation', issues),\n\t\tcurve: pick(value.curve, CHART_CURVES, 'linear', 'curve', issues),\n\t\tpoints: flag(value.points, true, 'points', issues),\n\t\tdataLabels: flag(value.dataLabels, false, 'dataLabels', issues),\n\t\tlabelPosition: pick(value.labelPosition, CHART_LABEL_POSITIONS, 'auto', 'labelPosition', issues),\n\t\tpalette,\n\t\tinnerRadius,\n\t\tgapWidth,\n\t\toverlap,\n\t\tbins,\n\t\tshowTotal: flag(value.showTotal, true, 'showTotal', issues)\n\t};\n\treturn { spec, issues };\n}\n\n/** A deep copy (specs are plain JSON). */\nexport function cloneChartSpec(spec: ChartSpec): ChartSpec {\n\treturn {\n\t\t...spec,\n\t\tcategories: [...spec.categories],\n\t\tseries: spec.series.map(cloneChartSeries),\n\t\txAxis: { ...spec.xAxis, format: { ...spec.xAxis.format } },\n\t\tyAxis: { ...spec.yAxis, format: { ...spec.yAxis.format } },\n\t\tyAxis2: { ...spec.yAxis2, format: { ...spec.yAxis2.format } },\n\t\tlegend: { ...spec.legend },\n\t\tpalette: [...spec.palette]\n\t};\n}\n\nexport function cloneChartSeries(series: ChartSeries): ChartSeries {\n\tconst copy: ChartSeries = { ...series, values: [...series.values] };\n\tif (series.x) copy.x = [...series.x];\n\tif (series.sizes) copy.sizes = [...series.sizes];\n\tif (series.pointColors) copy.pointColors = [...series.pointColors];\n\tif (series.format) copy.format = { ...series.format };\n\tif (series.trendlines) copy.trendlines = series.trendlines.map((t) => ({ ...t }));\n\treturn copy;\n}\n\nexport interface ChartTableOptions {\n\t/**\n\t * `columns` (default): the first column holds categories and each other column is a\n\t * series. `rows`: the first row holds categories and each other row is a series.\n\t */\n\tseriesIn?: 'columns' | 'rows';\n\t/**\n\t * The first row (or column for `rows`) holds series names (default `true`). `auto`: only\n\t * when one of its value cells is not a number.\n\t */\n\theader?: boolean | 'auto';\n\t/**\n\t * Read the first column as numeric x values (scatter and bubble charts): every series gets\n\t * them as `x`, and the categories are their labels.\n\t */\n\txFromFirstColumn?: boolean;\n}\n\nexport interface ChartTableData {\n\tcategories: string[];\n\tseries: ChartSeries[];\n\tissues: ChartIssue[];\n}\n\n/**\n * Reads a grid of cells (from CSV, a spreadsheet range or the clipboard) as categories and\n * series. Cells that are not numbers become gaps and are reported.\n */\nexport function chartDataFromTable(rows: ReadonlyArray<ReadonlyArray<unknown>>, options: ChartTableOptions = {}): ChartTableData {\n\tlet grid = rows.map((r) => [...r]).filter((r) => r.some((c) => c !== null && c !== undefined && String(c).trim() !== ''));\n\tif (options.seriesIn === 'rows') {\n\t\tconst width = Math.max(0, ...grid.map((r) => r.length));\n\t\tgrid = Array.from({ length: width }, (_, c) => grid.map((r) => r[c]));\n\t}\n\tconst issues: ChartIssue[] = [];\n\tif (!grid.length) return { categories: [], series: [], issues };\n\tconst width = Math.max(...grid.map((r) => r.length));\n\tconst header = options.header === 'auto' ? grid[0].slice(1).some((c) => c !== null && c !== undefined && String(c).trim() !== '' && parseChartValue(c) === undefined) : (options.header ?? true);\n\tconst names = header ? grid[0] : [];\n\tconst body = header ? grid.slice(1) : grid;\n\tconst categories = body.map((r, i) => {\n\t\tconst c = r[0];\n\t\treturn c === null || c === undefined || String(c).trim() === '' ? `${i + 1}` : String(c).trim();\n\t});\n\tconst series: ChartSeries[] = [];\n\tfor (let col = 1; col < width; col++) {\n\t\tconst name = names[col] !== undefined && String(names[col]).trim() ? String(names[col]).trim() : `Series ${col}`;\n\t\tconst values = body.map((r, i) => {\n\t\t\tconst parsed = parseChartValue(r[col] ?? null);\n\t\t\tif (parsed === undefined) {\n\t\t\t\tissues.push({ path: `${name}[${i}]`, message: `\"${String(r[col])}\" in ${name} (${categories[i]}) is not a number; it was left blank.` });\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn parsed;\n\t\t});\n\t\tseries.push({ id: `series-${col}`, name, values });\n\t}\n\tif (options.xFromFirstColumn) {\n\t\tconst x = body.map((r, i) => {\n\t\t\tconst parsed = parseChartValue(r[0] ?? null);\n\t\t\tif (parsed === undefined) issues.push({ path: `x[${i}]`, message: `\"${String(r[0])}\" in the first column is not a number; that point has no x.` });\n\t\t\treturn parsed ?? null;\n\t\t});\n\t\tfor (const s of series) s.x = [...x];\n\t}\n\treturn { categories, series, issues };\n}\n\n/** The chart's data as a grid: a header row of series names, then one row per category. */\nexport function chartDataToTable(spec: Pick<ChartSpec, 'categories' | 'series'>, options: { categoryHeader?: string } = {}): (string | number | null)[][] {\n\treturn [\n\t\t[options.categoryHeader ?? '', ...spec.series.map((s) => s.name)],\n\t\t...spec.categories.map((category, i) => [category, ...spec.series.map((s) => s.values[i] ?? null)])\n\t];\n}\n\n/** A colour input value (`#rrggbb`) for a CSS colour: `#abc` expands, non-hex colours show as black. */\nexport function chartColorInputValue(color: string): string {\n\tif (/^#[0-9a-f]{6}$/i.test(color)) return color.toLowerCase();\n\tif (/^#[0-9a-f]{3}$/i.test(color)) return `#${[...color.slice(1)].map((c) => c + c).join('')}`.toLowerCase();\n\treturn '#000000';\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/extensions/paragraph-styles/registry.ts","../src/import/zip.ts"],"sourcesContent":["// Portions ported from wordcraft/crates/doc/src/styles.rs and wordcraft/crates/doc/src/resolve.rs (MIT OR Apache-2.0, © ArtCraft Team and contributors). See THIRD_PARTY_NOTICES.md.\n\n/** Paragraph styles format whole blocks; character styles format runs of text. */\nexport type StyleKind = \"paragraph\" | \"character\";\n\n/** Character formatting of a style (CSS values). */\nexport interface CharacterFormat {\n fontFamily?: string;\n /** CSS length, e.g. `\"1.5em\"` or `\"18px\"`. */\n fontSize?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strike?: boolean;\n color?: string;\n backgroundColor?: string;\n letterSpacing?: string;\n textTransform?: \"none\" | \"uppercase\" | \"lowercase\" | \"capitalize\";\n smallCaps?: boolean;\n}\n\n/** Paragraph formatting of a style (CSS values). */\nexport interface ParagraphFormat {\n textAlign?: \"left\" | \"center\" | \"right\" | \"justify\";\n lineHeight?: string;\n spaceBefore?: string;\n spaceAfter?: string;\n indentLeft?: string;\n indentRight?: string;\n indentFirstLine?: string;\n /** CSS border shorthand, e.g. `\"3px solid currentColor\"`. */\n borderLeft?: string;\n paddingLeft?: string;\n backgroundColor?: string;\n}\n\n/** The block node a paragraph style uses (`heading` with `level` for Heading N). */\nexport interface StyleBlock {\n type: string;\n attrs?: Record<string, any>;\n}\n\nexport interface StyleDefinition {\n /** Stable id (`Heading1`): letters, digits, `_` and `-`, starting with a letter. */\n id: string;\n /** Display name (`Heading 1`). */\n name: string;\n kind: StyleKind;\n /** Style this one inherits from; what it sets wins over its base. */\n basedOn?: string | null;\n /** Style of the paragraph after this one when Enter is pressed at its end (paragraph styles). */\n next?: string | null;\n /** Linked style: a paragraph style's character style, or a character style's paragraph style. */\n linked?: string | null;\n paragraph?: ParagraphFormat;\n character?: CharacterFormat;\n /** Block node of a paragraph style. Inherited along `basedOn`; `paragraph` by default. */\n block?: StyleBlock | null;\n /** Gallery order (lower first). */\n priority?: number;\n /** Shown in the styles gallery. */\n quick?: boolean;\n hidden?: boolean;\n /** Built in (cannot be removed). */\n builtin?: boolean;\n}\n\n/** A style with its `basedOn` chain and the defaults merged. */\nexport interface ResolvedStyle {\n id: string;\n paragraph: ParagraphFormat;\n character: CharacterFormat;\n block: StyleBlock;\n /** Id of the style after Enter at the end of a paragraph. */\n next: string;\n}\n\nexport interface StyleDefaults {\n paragraph?: ParagraphFormat;\n character?: CharacterFormat;\n}\n\nexport interface StyleRegistryOptions {\n /** Styles added to (or replacing) the built-in ones. */\n styles?: readonly StyleDefinition[];\n /** Include the built-in styles. Default `true`. */\n builtins?: boolean;\n /** Document defaults, applied below every style. */\n defaults?: StyleDefaults;\n}\n\nexport interface StyleRegistrySnapshot {\n styles: readonly StyleDefinition[];\n defaults: StyleDefaults;\n /** Increases on every change. */\n version: number;\n}\n\n/** Serializable registry content (`registry.toJSON()`). */\nexport interface StyleRegistryJSON {\n styles: StyleDefinition[];\n defaults: StyleDefaults;\n}\n\nexport interface StyleCSSOptions {\n /** Selector the rules are scoped to. Default `.ProseMirror`. */\n scope?: string;\n /**\n * Element selector of blocks that use a style without naming it\n * (`data-style` absent), e.g. `h2` for Heading 2. Return `null` for none.\n */\n tagFor?: (block: StyleBlock) => string | null;\n}\n\n/** Longest `basedOn` chain followed (cycle and depth guard). */\nconst MAX_CHAIN = 32;\nconst STYLE_ID = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;\n/** CSS values that could escape a declaration or load resources are dropped. */\nconst UNSAFE_CSS = /[;{}<>\\\\]|\\/\\*|url\\s*\\(|expression\\s*\\(|@import|javascript:/i;\n\nexport const NORMAL_STYLE_ID = \"Normal\";\n\nconst PREVIEW_PROPERTIES = new Set([\n \"font-family\",\n \"font-weight\",\n \"font-style\",\n \"color\",\n \"text-decoration-line\",\n \"text-transform\",\n \"letter-spacing\",\n \"font-variant-caps\",\n]);\n\n/** Whether `id` is a valid style id. */\nexport function isValidStyleId(id: unknown): id is string {\n return typeof id === \"string\" && STYLE_ID.test(id);\n}\n\nconst MUTED = \"var(--pixerate-style-muted, #6b7280)\";\nconst HEADING_SIZES = [\"2em\", \"1.5em\", \"1.25em\", \"1.1em\", \"1em\", \"0.9em\"];\n\nfunction builtinStyles(): StyleDefinition[] {\n const styles: StyleDefinition[] = [\n {\n id: NORMAL_STYLE_ID,\n name: \"Normal\",\n kind: \"paragraph\",\n block: { type: \"paragraph\" },\n priority: 0,\n quick: true,\n builtin: true,\n },\n {\n id: \"Title\",\n name: \"Title\",\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n next: NORMAL_STYLE_ID,\n linked: \"TitleChar\",\n paragraph: { spaceAfter: \"0.25em\", lineHeight: \"1.15\" },\n character: { fontSize: \"2.5em\", bold: true, letterSpacing: \"-0.01em\" },\n priority: 10,\n quick: true,\n builtin: true,\n },\n {\n id: \"Subtitle\",\n name: \"Subtitle\",\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n next: NORMAL_STYLE_ID,\n linked: \"SubtitleChar\",\n paragraph: { spaceAfter: \"0.75em\" },\n character: { fontSize: \"1.25em\", color: MUTED },\n priority: 11,\n quick: true,\n builtin: true,\n },\n ];\n HEADING_SIZES.forEach((fontSize, i) => {\n const level = i + 1;\n styles.push({\n id: `Heading${level}`,\n name: `Heading ${level}`,\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n next: NORMAL_STYLE_ID,\n linked: `Heading${level}Char`,\n block: { type: \"heading\", attrs: { level } },\n paragraph: { spaceBefore: level <= 2 ? \"1em\" : \"0.75em\", spaceAfter: \"0.25em\" },\n character: { fontSize, bold: true },\n priority: 11 + level,\n quick: level <= 3,\n builtin: true,\n });\n });\n styles.push(\n {\n id: \"Quote\",\n name: \"Quote\",\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n next: NORMAL_STYLE_ID,\n linked: \"QuoteChar\",\n paragraph: { indentLeft: \"1em\", paddingLeft: \"0.75em\", borderLeft: \"3px solid currentColor\" },\n character: { italic: true, color: MUTED },\n priority: 29,\n quick: true,\n builtin: true,\n },\n {\n id: \"Code\",\n name: \"Code\",\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n next: NORMAL_STYLE_ID,\n block: { type: \"codeBlock\" },\n character: {\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Consolas, monospace\",\n fontSize: \"0.9em\",\n },\n priority: 30,\n quick: true,\n builtin: true,\n },\n {\n id: \"ListParagraph\",\n name: \"List Paragraph\",\n kind: \"paragraph\",\n basedOn: NORMAL_STYLE_ID,\n paragraph: { indentLeft: \"2em\" },\n priority: 34,\n quick: true,\n builtin: true,\n },\n );\n // Linked character styles: their formatting is the paragraph style's.\n const linked = [\"Title\", \"Subtitle\", \"Quote\", ...HEADING_SIZES.map((_, i) => `Heading${i + 1}`)];\n linked.forEach((paragraphId) => {\n const name = styles.find((s) => s.id === paragraphId)!.name;\n styles.push({\n id: `${paragraphId}Char`,\n name: `${name} Char`,\n kind: \"character\",\n linked: paragraphId,\n priority: 99,\n hidden: true,\n builtin: true,\n });\n });\n styles.push(\n {\n id: \"Emphasis\",\n name: \"Emphasis\",\n kind: \"character\",\n character: { italic: true },\n priority: 20,\n quick: true,\n builtin: true,\n },\n {\n id: \"Strong\",\n name: \"Strong\",\n kind: \"character\",\n character: { bold: true },\n priority: 22,\n quick: true,\n builtin: true,\n },\n );\n return styles;\n}\n\n/** The built-in styles: Normal, Title, Subtitle, Heading 1–6, Quote, Code, List Paragraph and character styles. */\nexport const DEFAULT_STYLES: readonly StyleDefinition[] = Object.freeze(builtinStyles());\n\nconst clone = <T>(value: T): T => (value === undefined ? value : JSON.parse(JSON.stringify(value)));\n\n/** Copies only defined values of `patch` over `base`. */\nfunction overlay<T extends object>(base: T, patch: T | undefined | null): T {\n if (!patch) return base;\n const out: Record<string, unknown> = { ...(base as Record<string, unknown>) };\n Object.entries(patch).forEach(([key, value]) => {\n if (value !== undefined && value !== null) out[key] = value;\n });\n return out as T;\n}\n\nfunction sameBlock(a: StyleBlock, type: string, attrs: Record<string, any>): boolean {\n if (a.type !== type) return false;\n return Object.entries(a.attrs ?? {}).every(([key, value]) => attrs[key] === value);\n}\n\n/**\n * Style definitions with `basedOn` inheritance, next-style and linked\n * character/paragraph styles, resolved in cascade order: document defaults →\n * style chain (base first) → direct formatting. Chains are cycle-safe.\n *\n * `subscribe` calls the listener immediately and on every change (Svelte\n * store contract); `getSnapshot` is stable between changes.\n */\nexport class StyleRegistry {\n private styles = new Map<string, StyleDefinition>();\n private defaults: StyleDefaults;\n private version = 0;\n private snapshot: StyleRegistrySnapshot | null = null;\n private listeners = new Set<(snapshot: StyleRegistrySnapshot) => void>();\n\n constructor(options: StyleRegistryOptions = {}) {\n this.defaults = clone(options.defaults ?? {});\n if (options.builtins !== false) DEFAULT_STYLES.forEach((style) => this.styles.set(style.id, clone(style)));\n (options.styles ?? []).forEach((style) => this.put(style));\n }\n\n // -- Reading --------------------------------------------------------------\n\n get(id: string | null | undefined): StyleDefinition | undefined {\n return id ? this.styles.get(id) : undefined;\n }\n\n /** Finds a style by id or display name (case-insensitive). */\n find(nameOrId: string): StyleDefinition | undefined {\n const direct = this.styles.get(nameOrId);\n if (direct) return direct;\n const lower = nameOrId.toLowerCase();\n return this.list().find((style) => style.name.toLowerCase() === lower);\n }\n\n /** All styles (optionally of one kind) in gallery order. */\n list(kind?: StyleKind): StyleDefinition[] {\n return Array.from(this.styles.values())\n .filter((style) => !kind || style.kind === kind)\n .sort((a, b) => (a.priority ?? 99) - (b.priority ?? 99) || a.name.localeCompare(b.name));\n }\n\n /** Styles shown in the gallery (`quick`, not hidden), paragraph styles by default. */\n gallery(kind: StyleKind = \"paragraph\"): StyleDefinition[] {\n return this.list(kind).filter((style) => style.quick && !style.hidden);\n }\n\n /** The `basedOn` chain from the root style down to `id` (cycle-safe, bounded). */\n chain(id: string): StyleDefinition[] {\n const out: StyleDefinition[] = [];\n let current = this.styles.get(id);\n while (current && out.length < MAX_CHAIN && !out.includes(current)) {\n out.push(current);\n current = current.basedOn ? this.styles.get(current.basedOn) : undefined;\n }\n return out.reverse();\n }\n\n /**\n * Resolves a paragraph style: defaults, then each style of the chain (base\n * first). Unknown ids resolve to the defaults in a `paragraph` block.\n */\n resolve(id: string): ResolvedStyle {\n let paragraph = overlay<ParagraphFormat>({}, this.defaults.paragraph);\n let character = overlay<CharacterFormat>({}, this.defaults.character);\n let block: StyleBlock = { type: \"paragraph\" };\n this.chain(id).forEach((style) => {\n if (style.kind !== \"paragraph\") return;\n paragraph = overlay(paragraph, style.paragraph);\n character = overlay(character, style.character);\n if (style.block) block = clone(style.block);\n });\n return { id, paragraph, character, block, next: this.nextStyleId(id) };\n }\n\n /** Character formatting a paragraph style's chain sets (without defaults). */\n private paragraphCharacter(id: string): CharacterFormat {\n let character: CharacterFormat = {};\n this.chain(id).forEach((style) => {\n if (style.kind === \"paragraph\") character = overlay(character, style.character);\n });\n return character;\n }\n\n /**\n * Character formatting of a character style's chain. A style linked to a\n * paragraph style takes that style's character formatting first.\n */\n resolveCharacterStyle(id: string): CharacterFormat {\n let character: CharacterFormat = {};\n this.chain(id).forEach((style) => {\n if (style.kind === \"character\" && style.linked && this.get(style.linked)?.kind === \"paragraph\") {\n character = overlay(character, this.paragraphCharacter(style.linked));\n }\n character = overlay(character, style.character);\n });\n return character;\n }\n\n /**\n * Character formatting of text: defaults → paragraph style chain →\n * character style chain → direct formatting.\n */\n resolveText(input: {\n paragraphStyle?: string | null;\n characterStyle?: string | null;\n direct?: CharacterFormat;\n }): CharacterFormat {\n let character = this.resolve(input.paragraphStyle || NORMAL_STYLE_ID).character;\n if (input.characterStyle) character = overlay(character, this.resolveCharacterStyle(input.characterStyle));\n return overlay(character, input.direct);\n }\n\n /** The style after Enter at the end of a paragraph of `id` (itself when unset or unknown). */\n nextStyleId(id: string): string {\n const next = this.styles.get(id)?.next;\n return next && this.styles.get(next)?.kind === \"paragraph\" ? next : id;\n }\n\n /** The linked character style of a paragraph style, if any. */\n linkedCharacterStyle(id: string): StyleDefinition | undefined {\n const style = this.styles.get(id);\n const linked = style?.linked ? this.styles.get(style.linked) : undefined;\n return style?.kind === \"paragraph\" && linked?.kind === \"character\" ? linked : undefined;\n }\n\n /**\n * The style a block uses when it names none: Normal for paragraphs,\n * Heading N for headings of level N, Code for code blocks (the built-in\n * style whose own `block` matches).\n */\n defaultStyleFor(type: string, attrs: Record<string, any> = {}): string | null {\n if (type === \"paragraph\" && this.styles.get(NORMAL_STYLE_ID)) return NORMAL_STYLE_ID;\n const candidates = this.list(\"paragraph\").filter(\n (style) => style.block && sameBlock(style.block, type, attrs),\n );\n return (candidates.find((s) => s.builtin) ?? candidates[0])?.id ?? null;\n }\n\n /** The style of a block: its `styleId` when known, otherwise the block's default style. */\n styleOfBlock(type: string, attrs: Record<string, any> = {}): string | null {\n const id = attrs.styleId;\n if (id && this.styles.get(id)?.kind === \"paragraph\") return id;\n return this.defaultStyleFor(type, attrs);\n }\n\n getSnapshot = (): StyleRegistrySnapshot => {\n if (!this.snapshot) {\n this.snapshot = Object.freeze({\n styles: Object.freeze(this.list()),\n defaults: this.defaults,\n version: this.version,\n });\n }\n return this.snapshot;\n };\n\n subscribe = (listener: (snapshot: StyleRegistrySnapshot) => void): (() => void) => {\n this.listeners.add(listener);\n listener(this.getSnapshot());\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n toJSON(): StyleRegistryJSON {\n return { styles: clone(Array.from(this.styles.values())), defaults: clone(this.defaults) };\n }\n\n // -- Writing --------------------------------------------------------------\n\n /** Adds or replaces a style. Throws on an invalid id. */\n upsert(style: StyleDefinition): StyleDefinition {\n const stored = this.put(style);\n this.changed();\n return stored;\n }\n\n /** Merges `patch` into a style (formats are merged key by key). Returns `undefined` for unknown ids. */\n update(id: string, patch: Partial<Omit<StyleDefinition, \"id\">>): StyleDefinition | undefined {\n const current = this.styles.get(id);\n if (!current) return undefined;\n const next: StyleDefinition = {\n ...current,\n ...patch,\n id,\n paragraph: patch.paragraph ? { ...current.paragraph, ...patch.paragraph } : current.paragraph,\n character: patch.character ? { ...current.character, ...patch.character } : current.character,\n };\n return this.upsert(next);\n }\n\n /**\n * Removes a style and returns it. Built-in styles cannot be removed. Styles\n * based on it are rebased onto its own base, and `next`/`linked`\n * references to it are dropped.\n */\n remove(id: string): StyleDefinition | undefined {\n const gone = this.styles.get(id);\n if (!gone || gone.builtin) return undefined;\n this.styles.delete(id);\n this.styles.forEach((style, key) => {\n let changed = style;\n if (style.basedOn === id) {\n changed = { ...changed, basedOn: gone.basedOn && gone.basedOn !== key ? gone.basedOn : null };\n }\n if (style.next === id) changed = { ...changed, next: null };\n if (style.linked === id) changed = { ...changed, linked: null };\n if (changed !== style) this.styles.set(key, changed);\n });\n this.changed();\n return gone;\n }\n\n /** Replaces the document defaults. */\n setDefaults(defaults: StyleDefaults): void {\n this.defaults = clone(defaults);\n this.changed();\n }\n\n /** An unused id derived from a display name (`My Style` → `MyStyle`, then `MyStyle1`, …). */\n newId(name: string): string {\n let base = name.replace(/[^A-Za-z0-9_-]+/g, \"\").replace(/^[^A-Za-z]+/, \"\").slice(0, 56);\n if (!base) base = \"Style\";\n if (!this.styles.has(base)) return base;\n for (let i = 1; i < 100000; i++) {\n const id = `${base}${i}`;\n if (!this.styles.has(id)) return id;\n }\n return `${base}${Date.now()}`;\n }\n\n // -- CSS --------------------------------------------------------------------\n\n /** CSS declarations (`property: value`) of a resolved paragraph or character style. */\n cssDeclarations(id: string): Record<string, string> {\n const style = this.styles.get(id);\n if (style?.kind === \"character\") return characterCSS(this.resolveCharacterStyle(id));\n const resolved = this.resolve(id);\n return { ...paragraphCSS(resolved.paragraph), ...characterCSS(resolved.character) };\n }\n\n /**\n * Declarations for previewing a style in a menu or gallery: font family,\n * weight, style, color, decoration, case and letter spacing (no sizes,\n * margins or borders).\n */\n previewDeclarations(id: string): Record<string, string> {\n return Object.fromEntries(\n Object.entries(this.cssDeclarations(id)).filter(([property]) => PREVIEW_PROPERTIES.has(property)),\n );\n }\n\n /**\n * A stylesheet for the styles: `[data-style=\"Id\"]` rules for paragraph\n * styles (plus the plain element of blocks that use their default style,\n * e.g. `h2:not([data-style])`), `[data-char-style=\"Id\"]` for character\n * styles and the defaults on the scope element.\n */\n toCSS(options: StyleCSSOptions = {}): string {\n const scope = options.scope ?? \".ProseMirror\";\n const tagFor = options.tagFor ?? defaultTagFor;\n const rules: string[] = [];\n const rule = (selectors: string[], declarations: Record<string, string>) => {\n const body = Object.entries(declarations)\n .map(([property, value]) => `${property}: ${value};`)\n .join(\" \");\n if (body) rules.push(`${selectors.join(\", \")} { ${body} }`);\n };\n rule([scope], {\n ...paragraphCSS(this.defaults.paragraph ?? {}),\n ...characterCSS(this.defaults.character ?? {}),\n });\n this.list().forEach((style) => {\n if (style.kind === \"character\") {\n rule([`${scope} [data-char-style=\"${style.id}\"]`], this.cssDeclarations(style.id));\n return;\n }\n const selectors = [`${scope} [data-style=\"${style.id}\"]`];\n const block = this.resolve(style.id).block;\n if (this.defaultStyleFor(block.type, block.attrs ?? {}) === style.id) {\n const tag = tagFor(block);\n if (tag) selectors.push(`${scope} ${tag}:not([data-style])`);\n }\n // Defaults already apply to the scope; repeat only what the chain sets.\n const resolved = this.resolve(style.id);\n const own = {\n ...paragraphCSS(withoutDefaults(resolved.paragraph, this.defaults.paragraph)),\n ...characterCSS(withoutDefaults(resolved.character, this.defaults.character)),\n };\n rule(selectors, own);\n });\n return rules.join(\"\\n\");\n }\n\n // -- Internals --------------------------------------------------------------\n\n private put(style: StyleDefinition): StyleDefinition {\n if (!isValidStyleId(style.id)) throw new Error(`Invalid style id: ${String(style.id)}`);\n if (style.kind !== \"paragraph\" && style.kind !== \"character\") {\n throw new Error(`Invalid style kind: ${String(style.kind)}`);\n }\n const stored = clone({ ...style, name: style.name || style.id });\n this.styles.set(style.id, stored);\n return stored;\n }\n\n private changed(): void {\n this.version++;\n this.snapshot = null;\n const snapshot = this.getSnapshot();\n this.listeners.forEach((listener) => {\n try {\n listener(snapshot);\n } catch (err) {\n console.error(\"[StyleRegistry] Error in listener:\", err);\n }\n });\n }\n}\n\nfunction withoutDefaults<T extends object>(format: T, defaults: T | undefined): T {\n if (!defaults) return format;\n const out: Record<string, unknown> = {};\n Object.entries(format).forEach(([key, value]) => {\n if ((defaults as Record<string, unknown>)[key] !== value) out[key] = value;\n });\n return out as T;\n}\n\nfunction defaultTagFor(block: StyleBlock): string | null {\n if (block.type === \"paragraph\") return \"p\";\n if (block.type === \"heading\") {\n const level = Number(block.attrs?.level);\n return level >= 1 && level <= 6 ? `h${level}` : null;\n }\n if (block.type === \"codeBlock\") return \"pre\";\n return null;\n}\n\n/** A CSS value, or `undefined` when it is unsafe or empty. */\nexport function safeCSSValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > 200 || UNSAFE_CSS.test(trimmed)) return undefined;\n return trimmed;\n}\n\nfunction paragraphCSS(format: ParagraphFormat): Record<string, string> {\n const out: Record<string, string> = {};\n const set = (property: string, value: unknown) => {\n const safe = safeCSSValue(value);\n if (safe) out[property] = safe;\n };\n set(\"text-align\", format.textAlign);\n set(\"line-height\", format.lineHeight);\n set(\"margin-top\", format.spaceBefore);\n set(\"margin-bottom\", format.spaceAfter);\n set(\"margin-left\", format.indentLeft);\n set(\"margin-right\", format.indentRight);\n set(\"text-indent\", format.indentFirstLine);\n set(\"border-left\", format.borderLeft);\n set(\"padding-left\", format.paddingLeft);\n set(\"background-color\", format.backgroundColor);\n return out;\n}\n\nfunction characterCSS(format: CharacterFormat): Record<string, string> {\n const out: Record<string, string> = {};\n const set = (property: string, value: unknown) => {\n const safe = safeCSSValue(value);\n if (safe) out[property] = safe;\n };\n set(\"font-family\", format.fontFamily);\n set(\"font-size\", format.fontSize);\n if (format.bold !== undefined) out[\"font-weight\"] = format.bold ? \"700\" : \"400\";\n if (format.italic !== undefined) out[\"font-style\"] = format.italic ? \"italic\" : \"normal\";\n const lines = [format.underline && \"underline\", format.strike && \"line-through\"].filter(Boolean);\n if (format.underline !== undefined || format.strike !== undefined) {\n out[\"text-decoration-line\"] = lines.length ? lines.join(\" \") : \"none\";\n }\n set(\"color\", format.color);\n set(\"background-color\", format.backgroundColor);\n set(\"letter-spacing\", format.letterSpacing);\n set(\"text-transform\", format.textTransform);\n if (format.smallCaps !== undefined) out[\"font-variant-caps\"] = format.smallCaps ? \"small-caps\" : \"normal\";\n return out;\n}\n\n/** Creates a style registry with the built-in styles (unless `builtins: false`) and `styles`. */\nexport function createStyleRegistry(options: StyleRegistryOptions | StyleRegistryJSON = {}): StyleRegistry {\n return new StyleRegistry(options as StyleRegistryOptions);\n}\n","/**\n * Minimal, dependency-free ZIP reader used by the DOCX and zipped-export\n * import adapters.\n *\n * - Reads the central directory (including ZIP64 end records and extra\n * fields), so sizes come from the authoritative directory rather than local\n * headers or data descriptors.\n * - Supports stored (method 0) and deflate (method 8) entries; deflate is\n * inflated with the platform `DecompressionStream(\"deflate-raw\")` (modern\n * browsers, Node ≥ 18).\n * - Guards against zip bombs (entry-count and total-uncompressed-size caps,\n * enforced on the bytes actually inflated, not only the declared sizes),\n * path traversal in entry names and encrypted entries.\n * - Verifies CRC-32 checksums of extracted entries.\n */\n\nexport type ZipErrorCode =\n /** Not a ZIP archive, or its directory is truncated / inconsistent. */\n | \"invalid_archive\"\n /** Compression method other than stored/deflate, multi-disk archives, … */\n | \"unsupported_feature\"\n /** The entry is encrypted (general-purpose flag bit 0). */\n | \"encrypted\"\n /** An entry name is absolute or contains `..` segments. */\n | \"unsafe_path\"\n /** More entries than `maxEntries`. */\n | \"too_many_entries\"\n /** Extracting would exceed `maxTotalSize` uncompressed bytes. */\n | \"too_large\"\n /** The entry data is corrupt (bad header, size or CRC mismatch, bad deflate stream). */\n | \"corrupt_entry\"\n /** No entry with the requested name. */\n | \"entry_not_found\"\n /** `DecompressionStream` is unavailable in this environment. */\n | \"unsupported_environment\";\n\nexport class ZipError extends Error {\n readonly code: ZipErrorCode;\n readonly entryName?: string;\n\n constructor(code: ZipErrorCode, message: string, details: { entryName?: string; cause?: unknown } = {}) {\n super(message, details.cause !== undefined ? { cause: details.cause } : undefined);\n this.name = \"ZipError\";\n this.code = code;\n this.entryName = details.entryName;\n }\n}\n\nexport interface ZipEntry {\n /** Entry path with `/` separators (backslashes are normalized). */\n name: string;\n /** Whether the entry is a directory (name ends with `/`). */\n isDirectory: boolean;\n /** Whether the entry is encrypted; reading it throws `ZipError(\"encrypted\")`. */\n encrypted: boolean;\n /** Compression method (0 = stored, 8 = deflate). */\n method: number;\n /** Declared compressed size in bytes. */\n compressedSize: number;\n /** Declared uncompressed size in bytes. */\n size: number;\n /** CRC-32 of the uncompressed data. */\n crc32: number;\n /** Offset of the entry's local file header. */\n localHeaderOffset: number;\n}\n\nexport interface ZipReadOptions {\n /** Maximum number of entries in the central directory (default 10 000). */\n maxEntries?: number;\n /**\n * Maximum number of uncompressed bytes extracted from the archive, summed\n * over every `read` call (default 256 MiB). Enforced while inflating.\n */\n maxTotalSize?: number;\n /**\n * What to do with entries whose names are absolute or contain `..`\n * segments: `\"error\"` (default) rejects the archive, `\"skip\"` leaves them\n * out of `entries`.\n */\n unsafePaths?: \"error\" | \"skip\";\n}\n\nexport const DEFAULT_ZIP_MAX_ENTRIES = 10_000;\nexport const DEFAULT_ZIP_MAX_TOTAL_SIZE = 256 * 1024 * 1024;\n\nconst SIG_EOCD = 0x06054b50;\nconst SIG_ZIP64_EOCD = 0x06064b50;\nconst SIG_ZIP64_LOCATOR = 0x07064b50;\nconst SIG_CENTRAL = 0x02014b50;\nconst SIG_LOCAL = 0x04034b50;\nconst EOCD_SIZE = 22;\nconst MAX_COMMENT = 0xffff;\n\nlet crcTable: Uint32Array | null = null;\n\n/** CRC-32 (IEEE 802.3), as used by ZIP. */\nexport function zipCrc32(data: Uint8Array): number {\n if (!crcTable) {\n crcTable = new Uint32Array(256);\n for (let n = 0; n < 256; n++) {\n let c = n;\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n crcTable[n] = c >>> 0;\n }\n }\n let crc = 0xffffffff;\n for (let i = 0; i < data.length; i++) crc = crcTable[(crc ^ data[i]) & 0xff] ^ (crc >>> 8);\n return (crc ^ 0xffffffff) >>> 0;\n}\n\nfunction toBytes(data: ArrayBuffer | ArrayBufferView): Uint8Array {\n // Duck-typed so ArrayBuffers from other realms (iframes, jsdom) work too.\n if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return new Uint8Array(data as ArrayBuffer);\n}\n\n/** Whether `name` is absolute, has a drive letter, or contains `..` / NUL. */\nexport function isUnsafeZipPath(name: string): boolean {\n if (!name || name.includes(\"\\0\")) return true;\n const normalized = name.replace(/\\\\/g, \"/\");\n if (normalized.startsWith(\"/\") || /^[a-zA-Z]:/.test(normalized)) return true;\n return normalized.split(\"/\").some((segment) => segment === \"..\");\n}\n\nconst utf8 = new TextDecoder(\"utf-8\");\n\n/** CP437 high half, used for names without the UTF-8 flag. */\nconst CP437_HIGH =\n \"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ \";\n\nfunction decodeName(bytes: Uint8Array, isUtf8: boolean): string {\n if (isUtf8 || bytes.every((b) => b < 0x80)) return utf8.decode(bytes);\n let out = \"\";\n for (const b of bytes) out += b < 0x80 ? String.fromCharCode(b) : CP437_HIGH[b - 0x80];\n return out;\n}\n\n/**\n * A parsed ZIP archive. Entry data is extracted lazily with {@link read}.\n * Create it with {@link readZip}.\n */\nexport class ZipArchive {\n /** Entries in central-directory order. */\n readonly entries: readonly ZipEntry[];\n private readonly byName = new Map<string, ZipEntry>();\n private extracted = 0;\n\n constructor(\n private readonly bytes: Uint8Array,\n entries: ZipEntry[],\n private readonly maxTotalSize: number,\n ) {\n this.entries = entries;\n entries.forEach((entry) => {\n if (!this.byName.has(entry.name)) this.byName.set(entry.name, entry);\n });\n }\n\n /** Looks up an entry by exact name (a leading `/` is ignored). */\n get(name: string): ZipEntry | undefined {\n return this.byName.get(name.replace(/^\\/+/, \"\"));\n }\n\n has(name: string): boolean {\n return !!this.get(name);\n }\n\n /** Uncompressed bytes extracted so far (counted against `maxTotalSize`). */\n get extractedSize(): number {\n return this.extracted;\n }\n\n /** Extracts an entry's data, verifying its size and CRC-32. */\n async read(entryOrName: ZipEntry | string): Promise<Uint8Array> {\n const entry = typeof entryOrName === \"string\" ? this.get(entryOrName) : entryOrName;\n if (!entry) {\n throw new ZipError(\"entry_not_found\", `ZIP entry \"${String(entryOrName)}\" not found.`, {\n entryName: String(entryOrName),\n });\n }\n const name = entry.name;\n if (entry.encrypted) {\n throw new ZipError(\"encrypted\", `ZIP entry \"${name}\" is encrypted; encrypted archives are not supported.`, {\n entryName: name,\n });\n }\n if (entry.isDirectory) return new Uint8Array(0);\n const remaining = this.maxTotalSize - this.extracted;\n if (entry.size > remaining) {\n throw new ZipError(\n \"too_large\",\n `Extracting \"${name}\" (${entry.size} bytes) would exceed the ${this.maxTotalSize}-byte limit.`,\n { entryName: name },\n );\n }\n\n const { bytes } = this;\n const offset = entry.localHeaderOffset;\n if (offset + 30 > bytes.length || readU32(bytes, offset) !== SIG_LOCAL) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" has no valid local header.`, { entryName: name });\n }\n const dataStart = offset + 30 + readU16(bytes, offset + 26) + readU16(bytes, offset + 28);\n const dataEnd = dataStart + entry.compressedSize;\n if (dataEnd > bytes.length) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" is truncated.`, { entryName: name });\n }\n const raw = bytes.subarray(dataStart, dataEnd);\n\n let data: Uint8Array;\n if (entry.method === 0) {\n if (entry.compressedSize !== entry.size) {\n throw new ZipError(\"corrupt_entry\", `Stored ZIP entry \"${name}\" has inconsistent sizes.`, { entryName: name });\n }\n data = raw.slice();\n } else if (entry.method === 8) {\n // Cap at the declared size: more output means a lying header (or a bomb).\n data = await inflateRaw(raw, entry.size, name);\n } else {\n throw new ZipError(\n \"unsupported_feature\",\n `ZIP entry \"${name}\" uses unsupported compression method ${entry.method}; only stored and deflate are supported.`,\n { entryName: name },\n );\n }\n if (data.length !== entry.size) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" size does not match the directory.`, { entryName: name });\n }\n this.extracted += data.length;\n if (zipCrc32(data) !== entry.crc32) {\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${name}\" failed its CRC-32 check.`, { entryName: name });\n }\n return data;\n }\n\n /** Extracts an entry and decodes it as UTF-8 (a leading BOM is removed). */\n async readText(entryOrName: ZipEntry | string): Promise<string> {\n const text = utf8.decode(await this.read(entryOrName));\n return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;\n }\n}\n\nfunction readU16(bytes: Uint8Array, offset: number): number {\n return bytes[offset] | (bytes[offset + 1] << 8);\n}\n\nfunction readU32(bytes: Uint8Array, offset: number): number {\n return (bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24)) >>> 0;\n}\n\nfunction readU64(bytes: Uint8Array, offset: number): number {\n const value = readU32(bytes, offset) + readU32(bytes, offset + 4) * 0x100000000;\n if (!Number.isSafeInteger(value)) {\n throw new ZipError(\"unsupported_feature\", \"ZIP64 value exceeds the supported range.\");\n }\n return value;\n}\n\n/** Inflates a raw deflate stream, failing as soon as output exceeds `limit` bytes. */\nasync function inflateRaw(raw: Uint8Array, limit: number, entryName: string): Promise<Uint8Array> {\n const Stream: typeof DecompressionStream | undefined = (globalThis as any).DecompressionStream;\n if (typeof Stream !== \"function\") {\n throw new ZipError(\n \"unsupported_environment\",\n \"Inflating ZIP entries needs DecompressionStream (modern browsers, Node 18+).\",\n { entryName },\n );\n }\n const stream = new Stream(\"deflate-raw\");\n const writer = stream.writable.getWriter();\n const reader = stream.readable.getReader();\n // Feed the input in slices so output is pulled (and checked) incrementally.\n const CHUNK = 64 * 1024;\n const feeding = (async () => {\n for (let i = 0; i < raw.length; i += CHUNK) await writer.write(raw.subarray(i, i + CHUNK) as unknown as BufferSource);\n await writer.close();\n })();\n feeding.catch(() => {});\n\n const chunks: Uint8Array[] = [];\n let total = 0;\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.length;\n if (total > limit) {\n throw new ZipError(\n \"corrupt_entry\",\n `ZIP entry \"${entryName}\" inflates beyond its declared size of ${limit} bytes.`,\n { entryName },\n );\n }\n chunks.push(value);\n }\n } catch (error) {\n reader.cancel().catch(() => {});\n writer.abort().catch(() => {});\n if (error instanceof ZipError) throw error;\n throw new ZipError(\"corrupt_entry\", `ZIP entry \"${entryName}\" has an invalid deflate stream.`, {\n entryName,\n cause: error,\n });\n }\n await feeding.catch(() => {});\n const out = new Uint8Array(total);\n let pos = 0;\n for (const chunk of chunks) {\n out.set(chunk, pos);\n pos += chunk.length;\n }\n return out;\n}\n\nfunction findEndOfCentralDirectory(bytes: Uint8Array): number {\n const min = Math.max(0, bytes.length - EOCD_SIZE - MAX_COMMENT);\n for (let i = bytes.length - EOCD_SIZE; i >= min; i--) {\n if (readU32(bytes, i) === SIG_EOCD && i + EOCD_SIZE + readU16(bytes, i + 20) <= bytes.length) return i;\n }\n return -1;\n}\n\n/**\n * Parses a ZIP archive's central directory. Entry data is not extracted until\n * {@link ZipArchive.read} is called. Throws {@link ZipError}.\n */\nexport async function readZip(data: ArrayBuffer | ArrayBufferView, options: ZipReadOptions = {}): Promise<ZipArchive> {\n const bytes = toBytes(data);\n const maxEntries = options.maxEntries ?? DEFAULT_ZIP_MAX_ENTRIES;\n const maxTotalSize = options.maxTotalSize ?? DEFAULT_ZIP_MAX_TOTAL_SIZE;\n\n const eocd = findEndOfCentralDirectory(bytes);\n if (eocd < 0) throw new ZipError(\"invalid_archive\", \"Not a ZIP archive (no end of central directory record).\");\n\n let diskNumber = readU16(bytes, eocd + 4);\n let cdDisk = readU16(bytes, eocd + 6);\n let count = readU16(bytes, eocd + 10);\n let cdSize = readU32(bytes, eocd + 12);\n let cdOffset = readU32(bytes, eocd + 16);\n\n if (count === 0xffff || cdSize === 0xffffffff || cdOffset === 0xffffffff) {\n const locator = eocd - 20;\n if (locator < 0 || readU32(bytes, locator) !== SIG_ZIP64_LOCATOR) {\n throw new ZipError(\"invalid_archive\", \"ZIP64 archive is missing its end of central directory locator.\");\n }\n const record = readU64(bytes, locator + 8);\n if (record + 56 > bytes.length || readU32(bytes, record) !== SIG_ZIP64_EOCD) {\n throw new ZipError(\"invalid_archive\", \"ZIP64 end of central directory record not found.\");\n }\n diskNumber = readU32(bytes, record + 16);\n cdDisk = readU32(bytes, record + 20);\n count = readU64(bytes, record + 32);\n cdSize = readU64(bytes, record + 40);\n cdOffset = readU64(bytes, record + 48);\n }\n if (diskNumber !== 0 || cdDisk !== 0) {\n throw new ZipError(\"unsupported_feature\", \"Multi-disk (spanned) ZIP archives are not supported.\");\n }\n if (count > maxEntries) {\n throw new ZipError(\"too_many_entries\", `ZIP archive has ${count} entries; the limit is ${maxEntries}.`);\n }\n if (cdOffset + cdSize > bytes.length) {\n throw new ZipError(\"invalid_archive\", \"ZIP central directory lies outside the file.\");\n }\n\n const entries: ZipEntry[] = [];\n let p = cdOffset;\n for (let i = 0; i < count; i++) {\n if (p + 46 > bytes.length || readU32(bytes, p) !== SIG_CENTRAL) {\n throw new ZipError(\"invalid_archive\", \"ZIP central directory is corrupt.\");\n }\n const flags = readU16(bytes, p + 8);\n const method = readU16(bytes, p + 10);\n const crc32 = readU32(bytes, p + 16);\n let compressedSize = readU32(bytes, p + 20);\n let size = readU32(bytes, p + 24);\n const nameLength = readU16(bytes, p + 28);\n const extraLength = readU16(bytes, p + 30);\n const commentLength = readU16(bytes, p + 32);\n let localHeaderOffset = readU32(bytes, p + 42);\n const nameStart = p + 46;\n const extraStart = nameStart + nameLength;\n const next = extraStart + extraLength + commentLength;\n if (next > bytes.length) throw new ZipError(\"invalid_archive\", \"ZIP central directory is truncated.\");\n\n // ZIP64 extended information: only the fields that overflowed are present, in order.\n for (let e = extraStart; e + 4 <= extraStart + extraLength; ) {\n const id = readU16(bytes, e);\n const len = readU16(bytes, e + 2);\n if (id === 0x0001) {\n let f = e + 4;\n const end = f + len;\n if (size === 0xffffffff && f + 8 <= end) {\n size = readU64(bytes, f);\n f += 8;\n }\n if (compressedSize === 0xffffffff && f + 8 <= end) {\n compressedSize = readU64(bytes, f);\n f += 8;\n }\n if (localHeaderOffset === 0xffffffff && f + 8 <= end) localHeaderOffset = readU64(bytes, f);\n }\n e += 4 + len;\n }\n\n const rawName = decodeName(bytes.subarray(nameStart, extraStart), (flags & 0x0800) !== 0);\n const name = rawName.replace(/\\\\/g, \"/\");\n p = next;\n if (isUnsafeZipPath(rawName)) {\n if (options.unsafePaths === \"skip\") continue;\n throw new ZipError(\"unsafe_path\", `ZIP entry name \"${rawName}\" is absolute or escapes the archive root.`, {\n entryName: rawName,\n });\n }\n entries.push({\n name,\n isDirectory: name.endsWith(\"/\"),\n encrypted: (flags & 0x0001) !== 0,\n method,\n compressedSize,\n size,\n crc32,\n localHeaderOffset,\n });\n }\n return new ZipArchive(bytes, entries, maxTotalSize);\n}\n"],"mappings":";AAmHA,IAAM,YAAY;AAClB,IAAM,WAAW;AAEjB,IAAM,aAAa;AAEZ,IAAM,kBAAkB;AAE/B,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,SAAS,eAAe,IAA2B;AACxD,SAAO,OAAO,OAAO,YAAY,SAAS,KAAK,EAAE;AACnD;AAEA,IAAM,QAAQ;AACd,IAAM,gBAAgB,CAAC,OAAO,SAAS,UAAU,SAAS,OAAO,OAAO;AAExE,SAAS,gBAAmC;AAC1C,QAAM,SAA4B;AAAA,IAChC;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO,EAAE,MAAM,YAAY;AAAA,MAC3B,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,WAAW,EAAE,YAAY,UAAU,YAAY,OAAO;AAAA,MACtD,WAAW,EAAE,UAAU,SAAS,MAAM,MAAM,eAAe,UAAU;AAAA,MACrE,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,WAAW,EAAE,YAAY,SAAS;AAAA,MAClC,WAAW,EAAE,UAAU,UAAU,OAAO,MAAM;AAAA,MAC9C,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,EACF;AACA,gBAAc,QAAQ,CAAC,UAAU,MAAM;AACrC,UAAM,QAAQ,IAAI;AAClB,WAAO,KAAK;AAAA,MACV,IAAI,UAAU,KAAK;AAAA,MACnB,MAAM,WAAW,KAAK;AAAA,MACtB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ,UAAU,KAAK;AAAA,MACvB,OAAO,EAAE,MAAM,WAAW,OAAO,EAAE,MAAM,EAAE;AAAA,MAC3C,WAAW,EAAE,aAAa,SAAS,IAAI,QAAQ,UAAU,YAAY,SAAS;AAAA,MAC9E,WAAW,EAAE,UAAU,MAAM,KAAK;AAAA,MAClC,UAAU,KAAK;AAAA,MACf,OAAO,SAAS;AAAA,MAChB,SAAS;AAAA,IACX,CAAC;AAAA,EACH,CAAC;AACD,SAAO;AAAA,IACL;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,WAAW,EAAE,YAAY,OAAO,aAAa,UAAU,YAAY,yBAAyB;AAAA,MAC5F,WAAW,EAAE,QAAQ,MAAM,OAAO,MAAM;AAAA,MACxC,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,OAAO,EAAE,MAAM,YAAY;AAAA,MAC3B,WAAW;AAAA,QACT,YAAY;AAAA,QACZ,UAAU;AAAA,MACZ;AAAA,MACA,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,WAAW,EAAE,YAAY,MAAM;AAAA,MAC/B,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,SAAS,CAAC,SAAS,YAAY,SAAS,GAAG,cAAc,IAAI,CAAC,GAAG,MAAM,UAAU,IAAI,CAAC,EAAE,CAAC;AAC/F,SAAO,QAAQ,CAAC,gBAAgB;AAC9B,UAAM,OAAO,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,WAAW,EAAG;AACvD,WAAO,KAAK;AAAA,MACV,IAAI,GAAG,WAAW;AAAA,MAClB,MAAM,GAAG,IAAI;AAAA,MACb,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AAAA,EACH,CAAC;AACD,SAAO;AAAA,IACL;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAW,EAAE,QAAQ,KAAK;AAAA,MAC1B,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAW,EAAE,MAAM,KAAK;AAAA,MACxB,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO;AACT;AAGO,IAAM,iBAA6C,OAAO,OAAO,cAAc,CAAC;AAEvF,IAAM,QAAQ,CAAI,UAAiB,UAAU,SAAY,QAAQ,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AAGjG,SAAS,QAA0B,MAAS,OAAgC;AAC1E,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,MAA+B,EAAE,GAAI,KAAiC;AAC5E,SAAO,QAAQ,KAAK,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC9C,QAAI,UAAU,UAAa,UAAU,KAAM,KAAI,GAAG,IAAI;AAAA,EACxD,CAAC;AACD,SAAO;AACT;AAEA,SAAS,UAAU,GAAe,MAAc,OAAqC;AACnF,MAAI,EAAE,SAAS,KAAM,QAAO;AAC5B,SAAO,OAAO,QAAQ,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,KAAK,MAAM,MAAM,GAAG,MAAM,KAAK;AACnF;AAUO,IAAM,gBAAN,MAAoB;AAAA,EACjB,SAAS,oBAAI,IAA6B;AAAA,EAC1C;AAAA,EACA,UAAU;AAAA,EACV,WAAyC;AAAA,EACzC,YAAY,oBAAI,IAA+C;AAAA,EAEvE,YAAY,UAAgC,CAAC,GAAG;AAC9C,SAAK,WAAW,MAAM,QAAQ,YAAY,CAAC,CAAC;AAC5C,QAAI,QAAQ,aAAa,MAAO,gBAAe,QAAQ,CAAC,UAAU,KAAK,OAAO,IAAI,MAAM,IAAI,MAAM,KAAK,CAAC,CAAC;AACzG,KAAC,QAAQ,UAAU,CAAC,GAAG,QAAQ,CAAC,UAAU,KAAK,IAAI,KAAK,CAAC;AAAA,EAC3D;AAAA;AAAA,EAIA,IAAI,IAA4D;AAC9D,WAAO,KAAK,KAAK,OAAO,IAAI,EAAE,IAAI;AAAA,EACpC;AAAA;AAAA,EAGA,KAAK,UAA+C;AAClD,UAAM,SAAS,KAAK,OAAO,IAAI,QAAQ;AACvC,QAAI,OAAQ,QAAO;AACnB,UAAM,QAAQ,SAAS,YAAY;AACnC,WAAO,KAAK,KAAK,EAAE,KAAK,CAAC,UAAU,MAAM,KAAK,YAAY,MAAM,KAAK;AAAA,EACvE;AAAA;AAAA,EAGA,KAAK,MAAqC;AACxC,WAAO,MAAM,KAAK,KAAK,OAAO,OAAO,CAAC,EACnC,OAAO,CAAC,UAAU,CAAC,QAAQ,MAAM,SAAS,IAAI,EAC9C,KAAK,CAAC,GAAG,OAAO,EAAE,YAAY,OAAO,EAAE,YAAY,OAAO,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA,EAC3F;AAAA;AAAA,EAGA,QAAQ,OAAkB,aAAgC;AACxD,WAAO,KAAK,KAAK,IAAI,EAAE,OAAO,CAAC,UAAU,MAAM,SAAS,CAAC,MAAM,MAAM;AAAA,EACvE;AAAA;AAAA,EAGA,MAAM,IAA+B;AACnC,UAAM,MAAyB,CAAC;AAChC,QAAI,UAAU,KAAK,OAAO,IAAI,EAAE;AAChC,WAAO,WAAW,IAAI,SAAS,aAAa,CAAC,IAAI,SAAS,OAAO,GAAG;AAClE,UAAI,KAAK,OAAO;AAChB,gBAAU,QAAQ,UAAU,KAAK,OAAO,IAAI,QAAQ,OAAO,IAAI;AAAA,IACjE;AACA,WAAO,IAAI,QAAQ;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,IAA2B;AACjC,QAAI,YAAY,QAAyB,CAAC,GAAG,KAAK,SAAS,SAAS;AACpE,QAAI,YAAY,QAAyB,CAAC,GAAG,KAAK,SAAS,SAAS;AACpE,QAAI,QAAoB,EAAE,MAAM,YAAY;AAC5C,SAAK,MAAM,EAAE,EAAE,QAAQ,CAAC,UAAU;AAChC,UAAI,MAAM,SAAS,YAAa;AAChC,kBAAY,QAAQ,WAAW,MAAM,SAAS;AAC9C,kBAAY,QAAQ,WAAW,MAAM,SAAS;AAC9C,UAAI,MAAM,MAAO,SAAQ,MAAM,MAAM,KAAK;AAAA,IAC5C,CAAC;AACD,WAAO,EAAE,IAAI,WAAW,WAAW,OAAO,MAAM,KAAK,YAAY,EAAE,EAAE;AAAA,EACvE;AAAA;AAAA,EAGQ,mBAAmB,IAA6B;AACtD,QAAI,YAA6B,CAAC;AAClC,SAAK,MAAM,EAAE,EAAE,QAAQ,CAAC,UAAU;AAChC,UAAI,MAAM,SAAS,YAAa,aAAY,QAAQ,WAAW,MAAM,SAAS;AAAA,IAChF,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB,IAA6B;AACjD,QAAI,YAA6B,CAAC;AAClC,SAAK,MAAM,EAAE,EAAE,QAAQ,CAAC,UAAU;AAChC,UAAI,MAAM,SAAS,eAAe,MAAM,UAAU,KAAK,IAAI,MAAM,MAAM,GAAG,SAAS,aAAa;AAC9F,oBAAY,QAAQ,WAAW,KAAK,mBAAmB,MAAM,MAAM,CAAC;AAAA,MACtE;AACA,kBAAY,QAAQ,WAAW,MAAM,SAAS;AAAA,IAChD,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,OAIQ;AAClB,QAAI,YAAY,KAAK,QAAQ,MAAM,kBAAkB,eAAe,EAAE;AACtE,QAAI,MAAM,eAAgB,aAAY,QAAQ,WAAW,KAAK,sBAAsB,MAAM,cAAc,CAAC;AACzG,WAAO,QAAQ,WAAW,MAAM,MAAM;AAAA,EACxC;AAAA;AAAA,EAGA,YAAY,IAAoB;AAC9B,UAAM,OAAO,KAAK,OAAO,IAAI,EAAE,GAAG;AAClC,WAAO,QAAQ,KAAK,OAAO,IAAI,IAAI,GAAG,SAAS,cAAc,OAAO;AAAA,EACtE;AAAA;AAAA,EAGA,qBAAqB,IAAyC;AAC5D,UAAM,QAAQ,KAAK,OAAO,IAAI,EAAE;AAChC,UAAM,SAAS,OAAO,SAAS,KAAK,OAAO,IAAI,MAAM,MAAM,IAAI;AAC/D,WAAO,OAAO,SAAS,eAAe,QAAQ,SAAS,cAAc,SAAS;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB,MAAc,QAA6B,CAAC,GAAkB;AAC5E,QAAI,SAAS,eAAe,KAAK,OAAO,IAAI,eAAe,EAAG,QAAO;AACrE,UAAM,aAAa,KAAK,KAAK,WAAW,EAAE;AAAA,MACxC,CAAC,UAAU,MAAM,SAAS,UAAU,MAAM,OAAO,MAAM,KAAK;AAAA,IAC9D;AACA,YAAQ,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,WAAW,CAAC,IAAI,MAAM;AAAA,EACrE;AAAA;AAAA,EAGA,aAAa,MAAc,QAA6B,CAAC,GAAkB;AACzE,UAAM,KAAK,MAAM;AACjB,QAAI,MAAM,KAAK,OAAO,IAAI,EAAE,GAAG,SAAS,YAAa,QAAO;AAC5D,WAAO,KAAK,gBAAgB,MAAM,KAAK;AAAA,EACzC;AAAA,EAEA,cAAc,MAA6B;AACzC,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW,OAAO,OAAO;AAAA,QAC5B,QAAQ,OAAO,OAAO,KAAK,KAAK,CAAC;AAAA,QACjC,UAAU,KAAK;AAAA,QACf,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IACH;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,YAAY,CAAC,aAAsE;AACjF,SAAK,UAAU,IAAI,QAAQ;AAC3B,aAAS,KAAK,YAAY,CAAC;AAC3B,WAAO,MAAM;AACX,WAAK,UAAU,OAAO,QAAQ;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,SAA4B;AAC1B,WAAO,EAAE,QAAQ,MAAM,MAAM,KAAK,KAAK,OAAO,OAAO,CAAC,CAAC,GAAG,UAAU,MAAM,KAAK,QAAQ,EAAE;AAAA,EAC3F;AAAA;AAAA;AAAA,EAKA,OAAO,OAAyC;AAC9C,UAAM,SAAS,KAAK,IAAI,KAAK;AAC7B,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,IAAY,OAA0E;AAC3F,UAAM,UAAU,KAAK,OAAO,IAAI,EAAE;AAClC,QAAI,CAAC,QAAS,QAAO;AACrB,UAAM,OAAwB;AAAA,MAC5B,GAAG;AAAA,MACH,GAAG;AAAA,MACH;AAAA,MACA,WAAW,MAAM,YAAY,EAAE,GAAG,QAAQ,WAAW,GAAG,MAAM,UAAU,IAAI,QAAQ;AAAA,MACpF,WAAW,MAAM,YAAY,EAAE,GAAG,QAAQ,WAAW,GAAG,MAAM,UAAU,IAAI,QAAQ;AAAA,IACtF;AACA,WAAO,KAAK,OAAO,IAAI;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,IAAyC;AAC9C,UAAM,OAAO,KAAK,OAAO,IAAI,EAAE;AAC/B,QAAI,CAAC,QAAQ,KAAK,QAAS,QAAO;AAClC,SAAK,OAAO,OAAO,EAAE;AACrB,SAAK,OAAO,QAAQ,CAAC,OAAO,QAAQ;AAClC,UAAI,UAAU;AACd,UAAI,MAAM,YAAY,IAAI;AACxB,kBAAU,EAAE,GAAG,SAAS,SAAS,KAAK,WAAW,KAAK,YAAY,MAAM,KAAK,UAAU,KAAK;AAAA,MAC9F;AACA,UAAI,MAAM,SAAS,GAAI,WAAU,EAAE,GAAG,SAAS,MAAM,KAAK;AAC1D,UAAI,MAAM,WAAW,GAAI,WAAU,EAAE,GAAG,SAAS,QAAQ,KAAK;AAC9D,UAAI,YAAY,MAAO,MAAK,OAAO,IAAI,KAAK,OAAO;AAAA,IACrD,CAAC;AACD,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,YAAY,UAA+B;AACzC,SAAK,WAAW,MAAM,QAAQ;AAC9B,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA,EAGA,MAAM,MAAsB;AAC1B,QAAI,OAAO,KAAK,QAAQ,oBAAoB,EAAE,EAAE,QAAQ,eAAe,EAAE,EAAE,MAAM,GAAG,EAAE;AACtF,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI,CAAC,KAAK,OAAO,IAAI,IAAI,EAAG,QAAO;AACnC,aAAS,IAAI,GAAG,IAAI,KAAQ,KAAK;AAC/B,YAAM,KAAK,GAAG,IAAI,GAAG,CAAC;AACtB,UAAI,CAAC,KAAK,OAAO,IAAI,EAAE,EAAG,QAAO;AAAA,IACnC;AACA,WAAO,GAAG,IAAI,GAAG,KAAK,IAAI,CAAC;AAAA,EAC7B;AAAA;AAAA;AAAA,EAKA,gBAAgB,IAAoC;AAClD,UAAM,QAAQ,KAAK,OAAO,IAAI,EAAE;AAChC,QAAI,OAAO,SAAS,YAAa,QAAO,aAAa,KAAK,sBAAsB,EAAE,CAAC;AACnF,UAAM,WAAW,KAAK,QAAQ,EAAE;AAChC,WAAO,EAAE,GAAG,aAAa,SAAS,SAAS,GAAG,GAAG,aAAa,SAAS,SAAS,EAAE;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAoB,IAAoC;AACtD,WAAO,OAAO;AAAA,MACZ,OAAO,QAAQ,KAAK,gBAAgB,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,QAAQ,MAAM,mBAAmB,IAAI,QAAQ,CAAC;AAAA,IAClG;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAA2B,CAAC,GAAW;AAC3C,UAAM,QAAQ,QAAQ,SAAS;AAC/B,UAAM,SAAS,QAAQ,UAAU;AACjC,UAAM,QAAkB,CAAC;AACzB,UAAM,OAAO,CAAC,WAAqB,iBAAyC;AAC1E,YAAM,OAAO,OAAO,QAAQ,YAAY,EACrC,IAAI,CAAC,CAAC,UAAU,KAAK,MAAM,GAAG,QAAQ,KAAK,KAAK,GAAG,EACnD,KAAK,GAAG;AACX,UAAI,KAAM,OAAM,KAAK,GAAG,UAAU,KAAK,IAAI,CAAC,MAAM,IAAI,IAAI;AAAA,IAC5D;AACA,SAAK,CAAC,KAAK,GAAG;AAAA,MACZ,GAAG,aAAa,KAAK,SAAS,aAAa,CAAC,CAAC;AAAA,MAC7C,GAAG,aAAa,KAAK,SAAS,aAAa,CAAC,CAAC;AAAA,IAC/C,CAAC;AACD,SAAK,KAAK,EAAE,QAAQ,CAAC,UAAU;AAC7B,UAAI,MAAM,SAAS,aAAa;AAC9B,aAAK,CAAC,GAAG,KAAK,sBAAsB,MAAM,EAAE,IAAI,GAAG,KAAK,gBAAgB,MAAM,EAAE,CAAC;AACjF;AAAA,MACF;AACA,YAAM,YAAY,CAAC,GAAG,KAAK,iBAAiB,MAAM,EAAE,IAAI;AACxD,YAAM,QAAQ,KAAK,QAAQ,MAAM,EAAE,EAAE;AACrC,UAAI,KAAK,gBAAgB,MAAM,MAAM,MAAM,SAAS,CAAC,CAAC,MAAM,MAAM,IAAI;AACpE,cAAM,MAAM,OAAO,KAAK;AACxB,YAAI,IAAK,WAAU,KAAK,GAAG,KAAK,IAAI,GAAG,oBAAoB;AAAA,MAC7D;AAEA,YAAM,WAAW,KAAK,QAAQ,MAAM,EAAE;AACtC,YAAM,MAAM;AAAA,QACV,GAAG,aAAa,gBAAgB,SAAS,WAAW,KAAK,SAAS,SAAS,CAAC;AAAA,QAC5E,GAAG,aAAa,gBAAgB,SAAS,WAAW,KAAK,SAAS,SAAS,CAAC;AAAA,MAC9E;AACA,WAAK,WAAW,GAAG;AAAA,IACrB,CAAC;AACD,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAAA;AAAA,EAIQ,IAAI,OAAyC;AACnD,QAAI,CAAC,eAAe,MAAM,EAAE,EAAG,OAAM,IAAI,MAAM,qBAAqB,OAAO,MAAM,EAAE,CAAC,EAAE;AACtF,QAAI,MAAM,SAAS,eAAe,MAAM,SAAS,aAAa;AAC5D,YAAM,IAAI,MAAM,uBAAuB,OAAO,MAAM,IAAI,CAAC,EAAE;AAAA,IAC7D;AACA,UAAM,SAAS,MAAM,EAAE,GAAG,OAAO,MAAM,MAAM,QAAQ,MAAM,GAAG,CAAC;AAC/D,SAAK,OAAO,IAAI,MAAM,IAAI,MAAM;AAChC,WAAO;AAAA,EACT;AAAA,EAEQ,UAAgB;AACtB,SAAK;AACL,SAAK,WAAW;AAChB,UAAM,WAAW,KAAK,YAAY;AAClC,SAAK,UAAU,QAAQ,CAAC,aAAa;AACnC,UAAI;AACF,iBAAS,QAAQ;AAAA,MACnB,SAAS,KAAK;AACZ,gBAAQ,MAAM,sCAAsC,GAAG;AAAA,MACzD;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,SAAS,gBAAkC,QAAW,UAA4B;AAChF,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,MAA+B,CAAC;AACtC,SAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC/C,QAAK,SAAqC,GAAG,MAAM,MAAO,KAAI,GAAG,IAAI;AAAA,EACvE,CAAC;AACD,SAAO;AACT;AAEA,SAAS,cAAc,OAAkC;AACvD,MAAI,MAAM,SAAS,YAAa,QAAO;AACvC,MAAI,MAAM,SAAS,WAAW;AAC5B,UAAM,QAAQ,OAAO,MAAM,OAAO,KAAK;AACvC,WAAO,SAAS,KAAK,SAAS,IAAI,IAAI,KAAK,KAAK;AAAA,EAClD;AACA,MAAI,MAAM,SAAS,YAAa,QAAO;AACvC,SAAO;AACT;AAGO,SAAS,aAAa,OAAoC;AAC/D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,WAAW,QAAQ,SAAS,OAAO,WAAW,KAAK,OAAO,EAAG,QAAO;AACzE,SAAO;AACT;AAEA,SAAS,aAAa,QAAiD;AACrE,QAAM,MAA8B,CAAC;AACrC,QAAM,MAAM,CAAC,UAAkB,UAAmB;AAChD,UAAM,OAAO,aAAa,KAAK;AAC/B,QAAI,KAAM,KAAI,QAAQ,IAAI;AAAA,EAC5B;AACA,MAAI,cAAc,OAAO,SAAS;AAClC,MAAI,eAAe,OAAO,UAAU;AACpC,MAAI,cAAc,OAAO,WAAW;AACpC,MAAI,iBAAiB,OAAO,UAAU;AACtC,MAAI,eAAe,OAAO,UAAU;AACpC,MAAI,gBAAgB,OAAO,WAAW;AACtC,MAAI,eAAe,OAAO,eAAe;AACzC,MAAI,eAAe,OAAO,UAAU;AACpC,MAAI,gBAAgB,OAAO,WAAW;AACtC,MAAI,oBAAoB,OAAO,eAAe;AAC9C,SAAO;AACT;AAEA,SAAS,aAAa,QAAiD;AACrE,QAAM,MAA8B,CAAC;AACrC,QAAM,MAAM,CAAC,UAAkB,UAAmB;AAChD,UAAM,OAAO,aAAa,KAAK;AAC/B,QAAI,KAAM,KAAI,QAAQ,IAAI;AAAA,EAC5B;AACA,MAAI,eAAe,OAAO,UAAU;AACpC,MAAI,aAAa,OAAO,QAAQ;AAChC,MAAI,OAAO,SAAS,OAAW,KAAI,aAAa,IAAI,OAAO,OAAO,QAAQ;AAC1E,MAAI,OAAO,WAAW,OAAW,KAAI,YAAY,IAAI,OAAO,SAAS,WAAW;AAChF,QAAM,QAAQ,CAAC,OAAO,aAAa,aAAa,OAAO,UAAU,cAAc,EAAE,OAAO,OAAO;AAC/F,MAAI,OAAO,cAAc,UAAa,OAAO,WAAW,QAAW;AACjE,QAAI,sBAAsB,IAAI,MAAM,SAAS,MAAM,KAAK,GAAG,IAAI;AAAA,EACjE;AACA,MAAI,SAAS,OAAO,KAAK;AACzB,MAAI,oBAAoB,OAAO,eAAe;AAC9C,MAAI,kBAAkB,OAAO,aAAa;AAC1C,MAAI,kBAAkB,OAAO,aAAa;AAC1C,MAAI,OAAO,cAAc,OAAW,KAAI,mBAAmB,IAAI,OAAO,YAAY,eAAe;AACjG,SAAO;AACT;AAGO,SAAS,oBAAoB,UAAoD,CAAC,GAAkB;AACzG,SAAO,IAAI,cAAc,OAA+B;AAC1D;;;ACzoBO,IAAM,WAAN,cAAuB,MAAM;AAAA,EACzB;AAAA,EACA;AAAA,EAET,YAAY,MAAoB,SAAiB,UAAmD,CAAC,GAAG;AACtG,UAAM,SAAS,QAAQ,UAAU,SAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,MAAS;AACjF,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,YAAY,QAAQ;AAAA,EAC3B;AACF;AAqCO,IAAM,0BAA0B;AAChC,IAAM,6BAA6B,MAAM,OAAO;AAEvD,IAAM,WAAW;AACjB,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAC1B,IAAM,cAAc;AACpB,IAAM,YAAY;AAClB,IAAM,YAAY;AAClB,IAAM,cAAc;AAEpB,IAAI,WAA+B;AAG5B,SAAS,SAAS,MAA0B;AACjD,MAAI,CAAC,UAAU;AACb,eAAW,IAAI,YAAY,GAAG;AAC9B,aAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,UAAI,IAAI;AACR,eAAS,IAAI,GAAG,IAAI,GAAG,IAAK,KAAI,IAAI,IAAI,aAAc,MAAM,IAAK,MAAM;AACvE,eAAS,CAAC,IAAI,MAAM;AAAA,IACtB;AAAA,EACF;AACA,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,IAAK,OAAM,UAAU,MAAM,KAAK,CAAC,KAAK,GAAI,IAAK,QAAQ;AACxF,UAAQ,MAAM,gBAAgB;AAChC;AAEA,SAAS,QAAQ,MAAiD;AAEhE,MAAI,YAAY,OAAO,IAAI,EAAG,QAAO,IAAI,WAAW,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACjG,SAAO,IAAI,WAAW,IAAmB;AAC3C;AAGO,SAAS,gBAAgB,MAAuB;AACrD,MAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAG,QAAO;AACzC,QAAM,aAAa,KAAK,QAAQ,OAAO,GAAG;AAC1C,MAAI,WAAW,WAAW,GAAG,KAAK,aAAa,KAAK,UAAU,EAAG,QAAO;AACxE,SAAO,WAAW,MAAM,GAAG,EAAE,KAAK,CAAC,YAAY,YAAY,IAAI;AACjE;AAEA,IAAM,OAAO,IAAI,YAAY,OAAO;AAGpC,IAAM,aACJ;AAEF,SAAS,WAAW,OAAmB,QAAyB;AAC9D,MAAI,UAAU,MAAM,MAAM,CAAC,MAAM,IAAI,GAAI,EAAG,QAAO,KAAK,OAAO,KAAK;AACpE,MAAI,MAAM;AACV,aAAW,KAAK,MAAO,QAAO,IAAI,MAAO,OAAO,aAAa,CAAC,IAAI,WAAW,IAAI,GAAI;AACrF,SAAO;AACT;AAMO,IAAM,aAAN,MAAiB;AAAA,EAMtB,YACmB,OACjB,SACiB,cACjB;AAHiB;AAEA;AAEjB,SAAK,UAAU;AACf,YAAQ,QAAQ,CAAC,UAAU;AACzB,UAAI,CAAC,KAAK,OAAO,IAAI,MAAM,IAAI,EAAG,MAAK,OAAO,IAAI,MAAM,MAAM,KAAK;AAAA,IACrE,CAAC;AAAA,EACH;AAAA,EARmB;AAAA,EAEA;AAAA;AAAA,EAPV;AAAA,EACQ,SAAS,oBAAI,IAAsB;AAAA,EAC5C,YAAY;AAAA;AAAA,EAcpB,IAAI,MAAoC;AACtC,WAAO,KAAK,OAAO,IAAI,KAAK,QAAQ,QAAQ,EAAE,CAAC;AAAA,EACjD;AAAA,EAEA,IAAI,MAAuB;AACzB,WAAO,CAAC,CAAC,KAAK,IAAI,IAAI;AAAA,EACxB;AAAA;AAAA,EAGA,IAAI,gBAAwB;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,KAAK,aAAqD;AAC9D,UAAM,QAAQ,OAAO,gBAAgB,WAAW,KAAK,IAAI,WAAW,IAAI;AACxE,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,SAAS,mBAAmB,cAAc,OAAO,WAAW,CAAC,gBAAgB;AAAA,QACrF,WAAW,OAAO,WAAW;AAAA,MAC/B,CAAC;AAAA,IACH;AACA,UAAM,OAAO,MAAM;AACnB,QAAI,MAAM,WAAW;AACnB,YAAM,IAAI,SAAS,aAAa,cAAc,IAAI,yDAAyD;AAAA,QACzG,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AACA,QAAI,MAAM,YAAa,QAAO,IAAI,WAAW,CAAC;AAC9C,UAAM,YAAY,KAAK,eAAe,KAAK;AAC3C,QAAI,MAAM,OAAO,WAAW;AAC1B,YAAM,IAAI;AAAA,QACR;AAAA,QACA,eAAe,IAAI,MAAM,MAAM,IAAI,4BAA4B,KAAK,YAAY;AAAA,QAChF,EAAE,WAAW,KAAK;AAAA,MACpB;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,IAAI;AAClB,UAAM,SAAS,MAAM;AACrB,QAAI,SAAS,KAAK,MAAM,UAAU,QAAQ,OAAO,MAAM,MAAM,WAAW;AACtE,YAAM,IAAI,SAAS,iBAAiB,cAAc,IAAI,gCAAgC,EAAE,WAAW,KAAK,CAAC;AAAA,IAC3G;AACA,UAAM,YAAY,SAAS,KAAK,QAAQ,OAAO,SAAS,EAAE,IAAI,QAAQ,OAAO,SAAS,EAAE;AACxF,UAAM,UAAU,YAAY,MAAM;AAClC,QAAI,UAAU,MAAM,QAAQ;AAC1B,YAAM,IAAI,SAAS,iBAAiB,cAAc,IAAI,mBAAmB,EAAE,WAAW,KAAK,CAAC;AAAA,IAC9F;AACA,UAAM,MAAM,MAAM,SAAS,WAAW,OAAO;AAE7C,QAAI;AACJ,QAAI,MAAM,WAAW,GAAG;AACtB,UAAI,MAAM,mBAAmB,MAAM,MAAM;AACvC,cAAM,IAAI,SAAS,iBAAiB,qBAAqB,IAAI,6BAA6B,EAAE,WAAW,KAAK,CAAC;AAAA,MAC/G;AACA,aAAO,IAAI,MAAM;AAAA,IACnB,WAAW,MAAM,WAAW,GAAG;AAE7B,aAAO,MAAM,WAAW,KAAK,MAAM,MAAM,IAAI;AAAA,IAC/C,OAAO;AACL,YAAM,IAAI;AAAA,QACR;AAAA,QACA,cAAc,IAAI,yCAAyC,MAAM,MAAM;AAAA,QACvE,EAAE,WAAW,KAAK;AAAA,MACpB;AAAA,IACF;AACA,QAAI,KAAK,WAAW,MAAM,MAAM;AAC9B,YAAM,IAAI,SAAS,iBAAiB,cAAc,IAAI,wCAAwC,EAAE,WAAW,KAAK,CAAC;AAAA,IACnH;AACA,SAAK,aAAa,KAAK;AACvB,QAAI,SAAS,IAAI,MAAM,MAAM,OAAO;AAClC,YAAM,IAAI,SAAS,iBAAiB,cAAc,IAAI,8BAA8B,EAAE,WAAW,KAAK,CAAC;AAAA,IACzG;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,SAAS,aAAiD;AAC9D,UAAM,OAAO,KAAK,OAAO,MAAM,KAAK,KAAK,WAAW,CAAC;AACrD,WAAO,KAAK,WAAW,CAAC,MAAM,QAAS,KAAK,MAAM,CAAC,IAAI;AAAA,EACzD;AACF;AAEA,SAAS,QAAQ,OAAmB,QAAwB;AAC1D,SAAO,MAAM,MAAM,IAAK,MAAM,SAAS,CAAC,KAAK;AAC/C;AAEA,SAAS,QAAQ,OAAmB,QAAwB;AAC1D,UAAQ,MAAM,MAAM,IAAK,MAAM,SAAS,CAAC,KAAK,IAAM,MAAM,SAAS,CAAC,KAAK,KAAO,MAAM,SAAS,CAAC,KAAK,QAAS;AAChH;AAEA,SAAS,QAAQ,OAAmB,QAAwB;AAC1D,QAAM,QAAQ,QAAQ,OAAO,MAAM,IAAI,QAAQ,OAAO,SAAS,CAAC,IAAI;AACpE,MAAI,CAAC,OAAO,cAAc,KAAK,GAAG;AAChC,UAAM,IAAI,SAAS,uBAAuB,0CAA0C;AAAA,EACtF;AACA,SAAO;AACT;AAGA,eAAe,WAAW,KAAiB,OAAe,WAAwC;AAChG,QAAM,SAAkD,WAAmB;AAC3E,MAAI,OAAO,WAAW,YAAY;AAChC,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,EAAE,UAAU;AAAA,IACd;AAAA,EACF;AACA,QAAM,SAAS,IAAI,OAAO,aAAa;AACvC,QAAM,SAAS,OAAO,SAAS,UAAU;AACzC,QAAM,SAAS,OAAO,SAAS,UAAU;AAEzC,QAAM,QAAQ,KAAK;AACnB,QAAM,WAAW,YAAY;AAC3B,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK,MAAO,OAAM,OAAO,MAAM,IAAI,SAAS,GAAG,IAAI,KAAK,CAA4B;AACpH,UAAM,OAAO,MAAM;AAAA,EACrB,GAAG;AACH,UAAQ,MAAM,MAAM;AAAA,EAAC,CAAC;AAEtB,QAAM,SAAuB,CAAC;AAC9B,MAAI,QAAQ;AACZ,MAAI;AACF,eAAS;AACP,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,eAAS,MAAM;AACf,UAAI,QAAQ,OAAO;AACjB,cAAM,IAAI;AAAA,UACR;AAAA,UACA,cAAc,SAAS,0CAA0C,KAAK;AAAA,UACtE,EAAE,UAAU;AAAA,QACd;AAAA,MACF;AACA,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF,SAAS,OAAO;AACd,WAAO,OAAO,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC9B,WAAO,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC7B,QAAI,iBAAiB,SAAU,OAAM;AACrC,UAAM,IAAI,SAAS,iBAAiB,cAAc,SAAS,oCAAoC;AAAA,MAC7F;AAAA,MACA,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACA,QAAM,QAAQ,MAAM,MAAM;AAAA,EAAC,CAAC;AAC5B,QAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,MAAM;AACV,aAAW,SAAS,QAAQ;AAC1B,QAAI,IAAI,OAAO,GAAG;AAClB,WAAO,MAAM;AAAA,EACf;AACA,SAAO;AACT;AAEA,SAAS,0BAA0B,OAA2B;AAC5D,QAAM,MAAM,KAAK,IAAI,GAAG,MAAM,SAAS,YAAY,WAAW;AAC9D,WAAS,IAAI,MAAM,SAAS,WAAW,KAAK,KAAK,KAAK;AACpD,QAAI,QAAQ,OAAO,CAAC,MAAM,YAAY,IAAI,YAAY,QAAQ,OAAO,IAAI,EAAE,KAAK,MAAM,OAAQ,QAAO;AAAA,EACvG;AACA,SAAO;AACT;AAMA,eAAsB,QAAQ,MAAqC,UAA0B,CAAC,GAAwB;AACpH,QAAM,QAAQ,QAAQ,IAAI;AAC1B,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,eAAe,QAAQ,gBAAgB;AAE7C,QAAM,OAAO,0BAA0B,KAAK;AAC5C,MAAI,OAAO,EAAG,OAAM,IAAI,SAAS,mBAAmB,yDAAyD;AAE7G,MAAI,aAAa,QAAQ,OAAO,OAAO,CAAC;AACxC,MAAI,SAAS,QAAQ,OAAO,OAAO,CAAC;AACpC,MAAI,QAAQ,QAAQ,OAAO,OAAO,EAAE;AACpC,MAAI,SAAS,QAAQ,OAAO,OAAO,EAAE;AACrC,MAAI,WAAW,QAAQ,OAAO,OAAO,EAAE;AAEvC,MAAI,UAAU,SAAU,WAAW,cAAc,aAAa,YAAY;AACxE,UAAM,UAAU,OAAO;AACvB,QAAI,UAAU,KAAK,QAAQ,OAAO,OAAO,MAAM,mBAAmB;AAChE,YAAM,IAAI,SAAS,mBAAmB,gEAAgE;AAAA,IACxG;AACA,UAAM,SAAS,QAAQ,OAAO,UAAU,CAAC;AACzC,QAAI,SAAS,KAAK,MAAM,UAAU,QAAQ,OAAO,MAAM,MAAM,gBAAgB;AAC3E,YAAM,IAAI,SAAS,mBAAmB,kDAAkD;AAAA,IAC1F;AACA,iBAAa,QAAQ,OAAO,SAAS,EAAE;AACvC,aAAS,QAAQ,OAAO,SAAS,EAAE;AACnC,YAAQ,QAAQ,OAAO,SAAS,EAAE;AAClC,aAAS,QAAQ,OAAO,SAAS,EAAE;AACnC,eAAW,QAAQ,OAAO,SAAS,EAAE;AAAA,EACvC;AACA,MAAI,eAAe,KAAK,WAAW,GAAG;AACpC,UAAM,IAAI,SAAS,uBAAuB,sDAAsD;AAAA,EAClG;AACA,MAAI,QAAQ,YAAY;AACtB,UAAM,IAAI,SAAS,oBAAoB,mBAAmB,KAAK,0BAA0B,UAAU,GAAG;AAAA,EACxG;AACA,MAAI,WAAW,SAAS,MAAM,QAAQ;AACpC,UAAM,IAAI,SAAS,mBAAmB,8CAA8C;AAAA,EACtF;AAEA,QAAM,UAAsB,CAAC;AAC7B,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,QAAI,IAAI,KAAK,MAAM,UAAU,QAAQ,OAAO,CAAC,MAAM,aAAa;AAC9D,YAAM,IAAI,SAAS,mBAAmB,mCAAmC;AAAA,IAC3E;AACA,UAAM,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAClC,UAAM,SAAS,QAAQ,OAAO,IAAI,EAAE;AACpC,UAAM,QAAQ,QAAQ,OAAO,IAAI,EAAE;AACnC,QAAI,iBAAiB,QAAQ,OAAO,IAAI,EAAE;AAC1C,QAAI,OAAO,QAAQ,OAAO,IAAI,EAAE;AAChC,UAAM,aAAa,QAAQ,OAAO,IAAI,EAAE;AACxC,UAAM,cAAc,QAAQ,OAAO,IAAI,EAAE;AACzC,UAAM,gBAAgB,QAAQ,OAAO,IAAI,EAAE;AAC3C,QAAI,oBAAoB,QAAQ,OAAO,IAAI,EAAE;AAC7C,UAAM,YAAY,IAAI;AACtB,UAAM,aAAa,YAAY;AAC/B,UAAM,OAAO,aAAa,cAAc;AACxC,QAAI,OAAO,MAAM,OAAQ,OAAM,IAAI,SAAS,mBAAmB,qCAAqC;AAGpG,aAAS,IAAI,YAAY,IAAI,KAAK,aAAa,eAAe;AAC5D,YAAM,KAAK,QAAQ,OAAO,CAAC;AAC3B,YAAM,MAAM,QAAQ,OAAO,IAAI,CAAC;AAChC,UAAI,OAAO,GAAQ;AACjB,YAAI,IAAI,IAAI;AACZ,cAAM,MAAM,IAAI;AAChB,YAAI,SAAS,cAAc,IAAI,KAAK,KAAK;AACvC,iBAAO,QAAQ,OAAO,CAAC;AACvB,eAAK;AAAA,QACP;AACA,YAAI,mBAAmB,cAAc,IAAI,KAAK,KAAK;AACjD,2BAAiB,QAAQ,OAAO,CAAC;AACjC,eAAK;AAAA,QACP;AACA,YAAI,sBAAsB,cAAc,IAAI,KAAK,IAAK,qBAAoB,QAAQ,OAAO,CAAC;AAAA,MAC5F;AACA,WAAK,IAAI;AAAA,IACX;AAEA,UAAM,UAAU,WAAW,MAAM,SAAS,WAAW,UAAU,IAAI,QAAQ,UAAY,CAAC;AACxF,UAAM,OAAO,QAAQ,QAAQ,OAAO,GAAG;AACvC,QAAI;AACJ,QAAI,gBAAgB,OAAO,GAAG;AAC5B,UAAI,QAAQ,gBAAgB,OAAQ;AACpC,YAAM,IAAI,SAAS,eAAe,mBAAmB,OAAO,8CAA8C;AAAA,QACxG,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AACA,YAAQ,KAAK;AAAA,MACX;AAAA,MACA,aAAa,KAAK,SAAS,GAAG;AAAA,MAC9B,YAAY,QAAQ,OAAY;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO,IAAI,WAAW,OAAO,SAAS,YAAY;AACpD;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/chart/color.ts","../src/chart/spec.ts"],"sourcesContent":["// Portions ported from gridcraft-main/crates/chart/src/resolve.rs (palette tint cycle) and\n// crates/chart/src/render.rs (`on`: label colour from the fill), and designcraft-main/crates/color/src/cms/mod.rs\n// (`simulate_cvd`, Machado–Oliveira–Fernandes 2009 matrices) (MIT OR Apache-2.0, © ArtCraft Team and contributors).\n// See THIRD_PARTY_NOTICES.md.\n\n/** An sRGB colour with channels from 0 to 1. */\nexport type ChartRgb = [number, number, number];\n\nconst NAMED: Record<string, string> = {\n\tblack: '#000000',\n\twhite: '#ffffff',\n\tred: '#ff0000',\n\tgreen: '#008000',\n\tblue: '#0000ff',\n\tyellow: '#ffff00',\n\torange: '#ffa500',\n\tpurple: '#800080',\n\tgray: '#808080',\n\tgrey: '#808080',\n\tteal: '#008080',\n\tnavy: '#000080',\n\tmaroon: '#800000',\n\tolive: '#808000',\n\tsilver: '#c0c0c0',\n\tlime: '#00ff00',\n\taqua: '#00ffff',\n\tcyan: '#00ffff',\n\tfuchsia: '#ff00ff',\n\tmagenta: '#ff00ff',\n\tpink: '#ffc0cb',\n\tbrown: '#a52a2a'\n};\n\n/**\n * Reads `#rgb`, `#rrggbb`, `#rrggbbaa`, `rgb()` / `rgba()` and a few colour names. Returns\n * `null` for anything else (CSS variables, `hsl()`, …), so callers can leave such colours alone.\n */\nexport function parseChartColor(color: string): ChartRgb | null {\n\tconst text = color.trim().toLowerCase();\n\tconst hex = NAMED[text] ?? text;\n\tlet m = /^#([0-9a-f]{3})$/.exec(hex);\n\tif (m) return [...m[1]].map((c) => parseInt(c + c, 16) / 255) as ChartRgb;\n\tm = /^#([0-9a-f]{6})([0-9a-f]{2})?$/.exec(hex);\n\tif (m) return [0, 2, 4].map((i) => parseInt(m![1].slice(i, i + 2), 16) / 255) as ChartRgb;\n\tm = /^rgba?\\(\\s*([\\d.]+)%?[\\s,]+([\\d.]+)%?[\\s,]+([\\d.]+)%?(?:[\\s,/]+[\\d.]+%?)?\\s*\\)$/.exec(text);\n\tif (m) {\n\t\tconst pct = text.includes('%');\n\t\treturn [m[1], m[2], m[3]].map((v) => Math.max(0, Math.min(1, Number(v) / (pct ? 100 : 255)))) as ChartRgb;\n\t}\n\treturn null;\n}\n\nexport function chartRgbToHex(rgb: ChartRgb): string {\n\treturn `#${rgb.map((c) => Math.round(Math.max(0, Math.min(1, c)) * 255).toString(16).padStart(2, '0')).join('')}`;\n}\n\n/**\n * A lighter (`amount` > 0, towards white) or darker (`amount` < 0, towards black) shade of\n * `color`. Colours it cannot read (CSS variables) come back unchanged.\n */\nexport function shadeChartColor(color: string, amount: number): string {\n\tconst rgb = parseChartColor(color);\n\tif (!rgb || !amount) return color;\n\tconst t = Math.max(-1, Math.min(1, amount));\n\treturn chartRgbToHex(rgb.map((c) => (t > 0 ? c + (1 - c) * t : c * (1 + t))) as ChartRgb);\n}\n\n/** Shades used once a palette is used up: the same hues, lighter then darker (GridCraft's cycle). */\nexport const CHART_PALETTE_SHADES: readonly number[] = [0, 0.4, -0.25, 0.6, -0.5, 0.2];\n\n/** The palette colour for the `index`-th item: the palette in order, then lighter and darker rounds of it. */\nexport function cyclePaletteColor(palette: readonly string[], index: number): string {\n\tconst base = palette[index % palette.length];\n\tconst round = Math.floor(index / palette.length) % CHART_PALETTE_SHADES.length;\n\treturn shadeChartColor(base, CHART_PALETTE_SHADES[round]);\n}\n\nconst toLinear = (c: number) => (c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));\nconst fromLinear = (c: number) => (c <= 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055);\n\n/** WCAG relative luminance (0 black – 1 white). */\nexport function chartLuminance(rgb: ChartRgb): number {\n\tconst [r, g, b] = rgb.map(toLinear);\n\treturn 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\n/** WCAG contrast ratio (1–21) between two colours, or `null` when either cannot be read. */\nexport function chartContrastRatio(a: string, b: string): number | null {\n\tconst ra = parseChartColor(a);\n\tconst rb = parseChartColor(b);\n\tif (!ra || !rb) return null;\n\tconst la = chartLuminance(ra);\n\tconst lb = chartLuminance(rb);\n\treturn (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);\n}\n\n/**\n * Dark or white text, whichever reads better on `fill`; `fallback` when the fill cannot be\n * read (a CSS variable).\n */\nexport function chartTextOn(fill: string, fallback: string, dark = '#0f172a', light = '#ffffff'): string {\n\tconst rgb = parseChartColor(fill);\n\tif (!rgb) return fallback;\n\tconst darkRatio = chartContrastRatio(fill, dark)!;\n\tconst lightRatio = chartContrastRatio(fill, light)!;\n\treturn darkRatio >= lightRatio ? dark : light;\n}\n\n/** OKLab (Ottosson) from sRGB. */\nexport function chartRgbToOklab(rgb: ChartRgb): [number, number, number] {\n\tconst [r, g, b] = rgb.map(toLinear);\n\tconst l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);\n\tconst m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);\n\tconst s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);\n\treturn [\n\t\t0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n\t\t1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n\t\t0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s\n\t];\n}\n\n/** Perceptual distance between two colours (Euclidean in OKLab; ≈0.02 is just noticeable). */\nexport function chartColorDistance(a: ChartRgb, b: ChartRgb): number {\n\tconst p = chartRgbToOklab(a);\n\tconst q = chartRgbToOklab(b);\n\treturn Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);\n}\n\nexport type ChartVision = 'normal' | 'protanopia' | 'deuteranopia' | 'tritanopia';\n\n// Machado, Oliveira & Fernandes (2009), severity 1.0, applied in linear RGB.\nconst CVD: Record<Exclude<ChartVision, 'normal'>, number[][]> = {\n\tprotanopia: [\n\t\t[0.152286, 1.052583, -0.204868],\n\t\t[0.114503, 0.786281, 0.099216],\n\t\t[-0.003882, -0.048116, 1.051998]\n\t],\n\tdeuteranopia: [\n\t\t[0.367322, 0.860646, -0.227968],\n\t\t[0.280085, 0.672501, 0.047413],\n\t\t[-0.01182, 0.04294, 0.968881]\n\t],\n\ttritanopia: [\n\t\t[1.255528, -0.076749, -0.178779],\n\t\t[-0.078411, 0.930809, 0.147602],\n\t\t[0.004733, 0.691367, 0.3039]\n\t]\n};\n\n/** How a colour looks with a colour-vision deficiency (Machado et al. 2009, full severity). */\nexport function simulateChartVision(rgb: ChartRgb, vision: ChartVision): ChartRgb {\n\tif (vision === 'normal') return rgb;\n\tconst lin = rgb.map(toLinear);\n\tconst m = CVD[vision];\n\treturn m.map((row) => fromLinear(Math.max(0, Math.min(1, row[0] * lin[0] + row[1] * lin[1] + row[2] * lin[2])))) as ChartRgb;\n}\n\nexport interface ChartColorPair {\n\ta: number;\n\tb: number;\n\tcolors: [string, string];\n\tdistance: number;\n}\n\nexport interface ChartColorCheck {\n\t/** No problems found. */\n\tok: boolean;\n\t/** Per vision: the closest pair of colours and their OKLab distance. */\n\tclosest: Partial<Record<ChartVision, ChartColorPair>>;\n\t/** Contrast ratio of each colour against the surface (null when unreadable). */\n\tcontrast: (number | null)[];\n\t/** Problems, as sentences. */\n\tissues: string[];\n\t/** Colours that could not be read (CSS variables, `hsl()`); they are skipped. */\n\tskipped: string[];\n}\n\nexport interface ChartColorCheckOptions {\n\t/** The page colour behind the marks (default white). */\n\tsurface?: string;\n\t/** Smallest OKLab distance two series may have (default 0.08). */\n\tminDistance?: number;\n\t/** Smallest contrast ratio against the surface (default 1.5; WCAG asks 3 for graphics). */\n\tminContrast?: number;\n\t/** Visions to check (default all four). */\n\tvisions?: readonly ChartVision[];\n}\n\n/**\n * Checks that series colours can be told apart, with normal vision and the three\n * colour-vision deficiencies, and stand out from the surface. Returns the closest pair per\n * vision and problems as sentences.\n */\nexport function checkChartColors(colors: readonly string[], options: ChartColorCheckOptions = {}): ChartColorCheck {\n\tconst surface = options.surface ?? '#ffffff';\n\tconst minDistance = options.minDistance ?? 0.08;\n\tconst minContrast = options.minContrast ?? 1.5;\n\tconst visions = options.visions ?? (['normal', 'protanopia', 'deuteranopia', 'tritanopia'] as const);\n\tconst parsed = colors.map(parseChartColor);\n\tconst skipped = colors.filter((_, i) => !parsed[i]);\n\tconst issues: string[] = [];\n\tconst closest: ChartColorCheck['closest'] = {};\n\tfor (const vision of visions) {\n\t\tconst seen = parsed.map((c) => (c ? simulateChartVision(c, vision) : null));\n\t\tlet best: ChartColorPair | undefined;\n\t\tfor (let a = 0; a < seen.length; a++) {\n\t\t\tfor (let b = a + 1; b < seen.length; b++) {\n\t\t\t\tif (!seen[a] || !seen[b]) continue;\n\t\t\t\tconst distance = chartColorDistance(seen[a]!, seen[b]!);\n\t\t\t\tif (!best || distance < best.distance) best = { a, b, colors: [colors[a], colors[b]], distance: Math.round(distance * 1000) / 1000 };\n\t\t\t}\n\t\t}\n\t\tif (best) {\n\t\t\tclosest[vision] = best;\n\t\t\tif (best.distance < minDistance) {\n\t\t\t\tconst who = vision === 'normal' ? '' : ` with ${vision}`;\n\t\t\t\tissues.push(`Colours ${best.a + 1} (${best.colors[0]}) and ${best.b + 1} (${best.colors[1]}) are hard to tell apart${who} (distance ${best.distance}, want at least ${minDistance}).`);\n\t\t\t}\n\t\t}\n\t}\n\tconst contrast = colors.map((c) => {\n\t\tconst ratio = chartContrastRatio(c, surface);\n\t\treturn ratio === null ? null : Math.round(ratio * 100) / 100;\n\t});\n\tcontrast.forEach((ratio, i) => {\n\t\tif (ratio !== null && ratio < minContrast) issues.push(`Colour ${i + 1} (${colors[i]}) barely stands out from the background ${surface} (contrast ${ratio}:1, want at least ${minContrast}:1).`);\n\t});\n\treturn { ok: issues.length === 0, closest, contrast, issues, skipped };\n}\n","import { cyclePaletteColor } from './color.js';\nimport type {\n\tChartAxis,\n\tChartCurve,\n\tChartIssue,\n\tChartLabelPosition,\n\tChartLegend,\n\tChartLegendPosition,\n\tChartMarker,\n\tChartNumberFormat,\n\tChartOrientation,\n\tChartSeries,\n\tChartSeriesType,\n\tChartSpec,\n\tChartStacking,\n\tChartTheme,\n\tChartTrendline,\n\tChartTrendlineType,\n\tChartType,\n\tChartValue\n} from './types.js';\n\nexport const CHART_TYPES: readonly ChartType[] = ['bar', 'line', 'area', 'scatter', 'bubble', 'pie', 'donut', 'radar', 'waterfall', 'histogram', 'box', 'funnel', 'treemap'];\nexport const CHART_MARKERS: readonly ChartMarker[] = ['circle', 'square', 'diamond', 'triangle', 'cross', 'none'];\nexport const CHART_TRENDLINE_TYPES: readonly ChartTrendlineType[] = ['linear', 'exponential', 'logarithmic', 'power', 'polynomial', 'moving-average'];\nexport const CHART_LABEL_POSITIONS: readonly ChartLabelPosition[] = ['auto', 'inside', 'outside', 'center'];\nexport const CHART_AXIS_KINDS: readonly NonNullable<ChartAxis['kind']>[] = ['category', 'date'];\nexport const CHART_SERIES_TYPES: readonly ChartSeriesType[] = ['bar', 'line', 'area', 'scatter'];\nexport const CHART_STACKINGS: readonly ChartStacking[] = ['none', 'stacked', 'percent'];\nexport const CHART_CURVES: readonly ChartCurve[] = ['linear', 'smooth', 'step'];\nexport const CHART_ORIENTATIONS: readonly ChartOrientation[] = ['vertical', 'horizontal'];\nexport const CHART_LEGEND_POSITIONS: readonly ChartLegendPosition[] = ['top', 'bottom', 'left', 'right'];\nexport const CHART_NUMBER_STYLES: readonly NonNullable<ChartNumberFormat['style']>[] = ['number', 'percent', 'currency', 'compact'];\n\n/** Labels for pickers, shared by the React and Svelte components. */\nexport const CHART_TYPE_LABELS: Readonly<Record<ChartType, string>> = {\n\tbar: 'Bar',\n\tline: 'Line',\n\tarea: 'Area',\n\tscatter: 'Scatter',\n\tbubble: 'Bubble',\n\tpie: 'Pie',\n\tdonut: 'Donut',\n\tradar: 'Radar',\n\twaterfall: 'Waterfall',\n\thistogram: 'Histogram',\n\tbox: 'Box plot',\n\tfunnel: 'Funnel',\n\ttreemap: 'Treemap'\n};\n\n/** How a chart type is laid out. */\nexport type ChartFamily = 'cartesian' | 'xy' | 'pie' | 'radar' | 'waterfall' | 'histogram' | 'box' | 'funnel' | 'treemap';\n\n/** A colour-blind-friendly categorical palette (Okabe–Ito order, tuned for light and dark backgrounds). */\nexport const DEFAULT_CHART_PALETTE: readonly string[] = ['#4269d0', '#efb118', '#ff725c', '#6cc5b0', '#3ca951', '#ff8ab7', '#a463f2', '#97bbf5', '#9c6b4e', '#9498a0'];\n\nexport const DEFAULT_CHART_THEME: ChartTheme = {\n\tbackground: '#ffffff',\n\tsurface: '#ffffff',\n\ttext: '#0f172a',\n\tmutedText: '#64748b',\n\tgrid: '#e2e8f0',\n\taxis: '#94a3b8',\n\tselection: '#2563eb',\n\tpositive: '#3ca951',\n\tnegative: '#e5484d',\n\tfontFamily: 'system-ui, -apple-system, \"Segoe UI\", sans-serif',\n\tfontSize: 11,\n\ttitleSize: 15\n};\n\n/**\n * A theme that reads the page's `--background`, `--foreground`, `--muted-foreground`,\n * `--border` and `--primary` colour variables (full colours, as the other components'\n * inline styles use them), with light fallbacks. The React and Svelte canvases use it.\n */\nexport const CSS_VARIABLE_CHART_THEME: ChartTheme = {\n\t...DEFAULT_CHART_THEME,\n\tbackground: 'transparent',\n\tsurface: 'var(--background, #ffffff)',\n\ttext: 'var(--foreground, #0f172a)',\n\tmutedText: 'var(--muted-foreground, #64748b)',\n\tgrid: 'var(--border, #e2e8f0)',\n\taxis: 'var(--muted-foreground, #94a3b8)',\n\tselection: 'var(--primary, #2563eb)',\n\tfontFamily: 'inherit'\n};\n\n/** Bar, line, area and scatter: categories (or numeric x) against values, series may mix. */\nexport function isCartesianChart(type: ChartType): boolean {\n\treturn type === 'bar' || type === 'line' || type === 'area' || type === 'scatter';\n}\n\n/** Whether the chart plots series against a numeric x axis (bubble charts, and scatter charts with x values). */\nexport function isXyChart(spec: Pick<ChartSpec, 'type' | 'series'>): boolean {\n\tif (spec.type === 'bubble') return true;\n\treturn spec.type === 'scatter' && spec.series.some((s) => !s.hidden && Array.isArray(s.x) && s.x.some((v) => v !== null));\n}\n\n/** How a chart is laid out (see `ChartType`). */\nexport function chartFamily(spec: Pick<ChartSpec, 'type' | 'series'>): ChartFamily {\n\tif (isXyChart(spec)) return 'xy';\n\tswitch (spec.type) {\n\t\tcase 'pie':\n\t\tcase 'donut':\n\t\t\treturn 'pie';\n\t\tcase 'radar':\n\t\tcase 'waterfall':\n\t\tcase 'histogram':\n\t\tcase 'box':\n\t\tcase 'funnel':\n\t\tcase 'treemap':\n\t\t\treturn spec.type;\n\t\tcase 'bubble':\n\t\t\treturn 'xy';\n\t\tdefault:\n\t\t\treturn 'cartesian';\n\t}\n}\n\n/** Chart types whose legend lists categories (one colour per category) rather than series. */\nexport function chartColorsByCategory(type: ChartType): boolean {\n\treturn type === 'pie' || type === 'donut' || type === 'funnel' || type === 'treemap';\n}\n\nexport function defaultChartAxis(value: boolean): ChartAxis {\n\treturn { show: true, title: '', min: null, max: null, step: null, gridlines: value, format: {} };\n}\n\n/** A complete spec with every default filled in. */\nexport function createChartSpec(partial: Partial<ChartSpec> = {}): ChartSpec {\n\treturn normalizeChartSpec(partial).spec;\n}\n\n/** The colour a series is drawn with. */\nexport function chartSeriesColor(spec: Pick<ChartSpec, 'palette' | 'series'>, seriesIndex: number): string {\n\tconst series = spec.series[seriesIndex];\n\tif (series?.color) return series.color;\n\treturn cyclePaletteColor(spec.palette.length ? spec.palette : DEFAULT_CHART_PALETTE, seriesIndex);\n}\n\n/** The colour a pie slice is drawn with (by category). */\nexport function chartSliceColor(spec: Pick<ChartSpec, 'palette'>, index: number): string {\n\treturn cyclePaletteColor(spec.palette.length ? spec.palette : DEFAULT_CHART_PALETTE, index);\n}\n\n/** The colour of one bar or point: its override, else the series colour. */\nexport function chartPointColor(spec: Pick<ChartSpec, 'palette' | 'series'>, seriesIndex: number, index: number): string {\n\treturn spec.series[seriesIndex]?.pointColors?.[index] || chartSeriesColor(spec, seriesIndex);\n}\n\n/** How a series is drawn in a cartesian chart. */\nexport function chartSeriesType(spec: Pick<ChartSpec, 'type'>, series: ChartSeries): ChartSeriesType {\n\tif (series.type) return series.type;\n\tif (spec.type === 'bubble') return 'scatter';\n\treturn isCartesianChart(spec.type) ? (spec.type as ChartSeriesType) : 'bar';\n}\n\n/** An id not used by any series (`series-1`, `series-2`, …). */\nexport function uniqueChartSeriesId(series: readonly Pick<ChartSeries, 'id'>[], base = 'series'): string {\n\tconst used = new Set(series.map((s) => s.id));\n\tfor (let i = series.length + 1; ; i++) {\n\t\tconst id = `${base}-${i}`;\n\t\tif (!used.has(id)) return id;\n\t}\n}\n\n/**\n * Reads a number the way people type it in a data grid: `1,234.5`, `12%` (→ 0.12),\n * `$40`, `(3)` (→ -3). Blank → `null`. Returns `undefined` when it is not a number.\n */\nexport function parseChartValue(input: unknown): ChartValue | undefined {\n\tif (input === null || input === undefined) return null;\n\tif (typeof input === 'number') return Number.isFinite(input) ? input : undefined;\n\tif (typeof input !== 'string') return undefined;\n\tlet text = input.trim();\n\tif (!text || text === '-' || text === '—') return null;\n\tlet negative = false;\n\tif (/^\\(.*\\)$/.test(text)) {\n\t\tnegative = true;\n\t\ttext = text.slice(1, -1).trim();\n\t}\n\tconst percent = text.endsWith('%');\n\tif (percent) text = text.slice(0, -1).trim();\n\ttext = text.replace(/^[$€£¥]/, '').replace(/,/g, '').replace(/\\s+/g, '');\n\tif (!/^[-+]?(\\d+\\.?\\d*|\\.\\d+)(e[-+]?\\d+)?$/i.test(text)) return undefined;\n\tlet value = Number(text);\n\tif (percent) value /= 100;\n\tif (negative) value = -value;\n\treturn Number.isFinite(value) ? value : undefined;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null && !Array.isArray(value);\n\nfunction pick<T extends string>(value: unknown, options: readonly T[], fallback: T, path: string, issues: ChartIssue[]): T {\n\tif (value === undefined) return fallback;\n\tif (typeof value === 'string' && (options as readonly string[]).includes(value)) return value as T;\n\tissues.push({ path, message: `${path} must be one of ${options.map((o) => `\"${o}\"`).join(', ')}; got ${JSON.stringify(value)}.` });\n\treturn fallback;\n}\n\nfunction text(value: unknown, fallback: string, path: string, issues: ChartIssue[]): string {\n\tif (value === undefined || value === null) return fallback;\n\tif (typeof value === 'string') return value;\n\tif (typeof value === 'number' || typeof value === 'boolean') return String(value);\n\tissues.push({ path, message: `${path} must be text.` });\n\treturn fallback;\n}\n\nfunction flag(value: unknown, fallback: boolean, path: string, issues: ChartIssue[]): boolean {\n\tif (value === undefined) return fallback;\n\tif (typeof value === 'boolean') return value;\n\tissues.push({ path, message: `${path} must be true or false.` });\n\treturn fallback;\n}\n\nfunction bound(value: unknown, path: string, issues: ChartIssue[]): number | null {\n\tif (value === undefined || value === null || value === '') return null;\n\tconst n = typeof value === 'string' ? Number(value) : value;\n\tif (typeof n === 'number' && Number.isFinite(n)) return n;\n\tissues.push({ path, message: `${path} must be a number or null.` });\n\treturn null;\n}\n\nfunction normalizeFormat(value: unknown, path: string, issues: ChartIssue[]): ChartNumberFormat {\n\tif (value === undefined || value === null) return {};\n\tif (!isRecord(value)) {\n\t\tissues.push({ path, message: `${path} must be an object.` });\n\t\treturn {};\n\t}\n\tconst out: ChartNumberFormat = {};\n\tif (value.style !== undefined) out.style = pick(value.style, CHART_NUMBER_STYLES, 'number', `${path}.style`, issues);\n\tif (value.decimals !== undefined) {\n\t\tconst d = Number(value.decimals);\n\t\tif (Number.isInteger(d) && d >= 0 && d <= 10) out.decimals = d;\n\t\telse issues.push({ path: `${path}.decimals`, message: `${path}.decimals must be a whole number from 0 to 10.` });\n\t}\n\tfor (const key of ['currency', 'prefix', 'suffix', 'code'] as const) {\n\t\tif (value[key] !== undefined) out[key] = text(value[key], '', `${path}.${key}`, issues);\n\t}\n\treturn out;\n}\n\nexport function normalizeChartAxis(value: unknown, fallback: ChartAxis, path: string, issues: ChartIssue[] = []): ChartAxis {\n\tif (value === undefined) return { ...fallback, format: { ...fallback.format } };\n\tif (!isRecord(value)) {\n\t\tissues.push({ path, message: `${path} must be an object.` });\n\t\treturn { ...fallback, format: { ...fallback.format } };\n\t}\n\tlet min = 'min' in value ? bound(value.min, `${path}.min`, issues) : fallback.min;\n\tlet max = 'max' in value ? bound(value.max, `${path}.max`, issues) : fallback.max;\n\tif (min !== null && max !== null && min >= max) {\n\t\tissues.push({ path: `${path}.max`, message: `${path}.max (${max}) must be greater than ${path}.min (${min}).` });\n\t\tmin = fallback.min;\n\t\tmax = fallback.max;\n\t}\n\tlet step = 'step' in value ? bound(value.step, `${path}.step`, issues) : fallback.step;\n\tif (step !== null && !(step > 0)) {\n\t\tissues.push({ path: `${path}.step`, message: `${path}.step must be greater than 0 (or null for automatic).` });\n\t\tstep = fallback.step;\n\t}\n\tconst axis: ChartAxis = {\n\t\tshow: flag(value.show, fallback.show, `${path}.show`, issues),\n\t\ttitle: text(value.title, fallback.title, `${path}.title`, issues),\n\t\tmin,\n\t\tmax,\n\t\tstep,\n\t\tgridlines: flag(value.gridlines, fallback.gridlines, `${path}.gridlines`, issues),\n\t\tformat: 'format' in value ? normalizeFormat(value.format, `${path}.format`, issues) : { ...fallback.format }\n\t};\n\tconst kind = 'kind' in value ? (value.kind === null ? undefined : pick(value.kind, CHART_AXIS_KINDS, 'category', `${path}.kind`, issues)) : fallback.kind;\n\tif (kind && kind !== 'category') axis.kind = kind;\n\treturn axis;\n}\n\nfunction normalizeLegend(value: unknown, issues: ChartIssue[]): ChartLegend {\n\tconst fallback: ChartLegend = { show: true, position: 'bottom' };\n\tif (value === undefined) return fallback;\n\tif (!isRecord(value)) {\n\t\tissues.push({ path: 'legend', message: 'legend must be an object.' });\n\t\treturn fallback;\n\t}\n\treturn {\n\t\tshow: flag(value.show, fallback.show, 'legend.show', issues),\n\t\tposition: pick(value.position, CHART_LEGEND_POSITIONS, fallback.position, 'legend.position', issues)\n\t};\n}\n\n/** Values as numbers or nulls; bad entries become null and are reported. */\nexport function normalizeChartValues(value: unknown, length: number | undefined, path: string, issues: ChartIssue[] = []): ChartValue[] {\n\tif (value === undefined) return length ? Array(length).fill(null) : [];\n\tif (!Array.isArray(value)) {\n\t\tissues.push({ path, message: `${path} must be an array of numbers.` });\n\t\treturn length ? Array(length).fill(null) : [];\n\t}\n\tconst out = value.map((v, i) => {\n\t\tconst parsed = parseChartValue(v);\n\t\tif (parsed === undefined) {\n\t\t\tissues.push({ path: `${path}[${i}]`, message: `${path}[${i}] is not a number: ${JSON.stringify(v)}.` });\n\t\t\treturn null;\n\t\t}\n\t\treturn parsed;\n\t});\n\tif (length === undefined) return out;\n\tif (out.length > length) return out.slice(0, length);\n\twhile (out.length < length) out.push(null);\n\treturn out;\n}\n\nfunction normalizeSeries(value: unknown, length: number, used: Set<string>, index: number, issues: ChartIssue[]): ChartSeries | null {\n\tconst path = `series[${index}]`;\n\tif (!isRecord(value)) {\n\t\tissues.push({ path, message: `${path} must be an object with a name and values.` });\n\t\treturn null;\n\t}\n\tlet id = typeof value.id === 'string' && value.id.trim() ? value.id.trim() : '';\n\tif (!id || used.has(id)) {\n\t\tif (id) issues.push({ path: `${path}.id`, message: `Series id \"${id}\" is used twice; the second was renamed.` });\n\t\tfor (let n = index + 1; ; n++) {\n\t\t\tid = `series-${n}`;\n\t\t\tif (!used.has(id)) break;\n\t\t}\n\t}\n\tused.add(id);\n\tconst series: ChartSeries = {\n\t\tid,\n\t\tname: text(value.name, `Series ${index + 1}`, `${path}.name`, issues),\n\t\tvalues: normalizeChartValues(value.values, length, `${path}.values`, issues)\n\t};\n\tif (typeof value.color === 'string' && value.color.trim()) series.color = value.color.trim();\n\tif (value.type !== undefined && value.type !== null) series.type = pick(value.type, CHART_SERIES_TYPES, 'bar', `${path}.type`, issues);\n\tif (value.hidden === true) series.hidden = true;\n\tif (value.axis !== undefined && value.axis !== null && pick(value.axis, ['primary', 'secondary'] as const, 'primary', `${path}.axis`, issues) === 'secondary') series.axis = 'secondary';\n\tfor (const key of ['x', 'sizes'] as const) {\n\t\tif (value[key] === undefined || value[key] === null) continue;\n\t\tconst list = normalizeChartValues(value[key], length, `${path}.${key}`, issues);\n\t\tif (list.some((v) => v !== null)) series[key] = list;\n\t}\n\tif (key(value, 'sizes') && series.sizes?.some((v) => v !== null && v < 0)) {\n\t\tissues.push({ path: `${path}.sizes`, message: `${path}.sizes must not be negative.` });\n\t\tseries.sizes = series.sizes.map((v) => (v !== null && v < 0 ? null : v));\n\t}\n\tif (value.pointColors !== undefined && value.pointColors !== null) {\n\t\tif (!Array.isArray(value.pointColors)) issues.push({ path: `${path}.pointColors`, message: `${path}.pointColors must be an array of colours or nulls.` });\n\t\telse {\n\t\t\tconst colors = Array.from({ length }, (_, i) => {\n\t\t\t\tconst c = (value.pointColors as unknown[])[i];\n\t\t\t\treturn typeof c === 'string' && c.trim() ? c.trim() : null;\n\t\t\t});\n\t\t\tif (colors.some((c) => c !== null)) series.pointColors = colors;\n\t\t}\n\t}\n\tif (value.marker !== undefined && value.marker !== null) series.marker = pick(value.marker, CHART_MARKERS, 'circle', `${path}.marker`, issues);\n\tif (value.curve !== undefined && value.curve !== null) series.curve = pick(value.curve, CHART_CURVES, 'linear', `${path}.curve`, issues);\n\tif (value.dataLabels !== undefined && value.dataLabels !== null) series.dataLabels = flag(value.dataLabels, false, `${path}.dataLabels`, issues);\n\tif (value.format !== undefined && value.format !== null) {\n\t\tconst format = normalizeFormat(value.format, `${path}.format`, issues);\n\t\tif (Object.keys(format).length) series.format = format;\n\t}\n\tif (value.trendlines !== undefined && value.trendlines !== null) {\n\t\tif (!Array.isArray(value.trendlines)) issues.push({ path: `${path}.trendlines`, message: `${path}.trendlines must be an array.` });\n\t\telse {\n\t\t\tconst lines = value.trendlines.map((t, i) => normalizeChartTrendline(t, `${path}.trendlines[${i}]`, issues)).filter((t): t is ChartTrendline => t !== null);\n\t\t\tif (lines.length) series.trendlines = lines;\n\t\t}\n\t}\n\treturn series;\n}\n\nconst key = (value: Record<string, unknown>, name: string) => value[name] !== undefined && value[name] !== null;\n\n/** Checks one trendline; `null` (reported) when it is unusable. */\nexport function normalizeChartTrendline(value: unknown, path: string, issues: ChartIssue[] = []): ChartTrendline | null {\n\tif (!isRecord(value)) {\n\t\tissues.push({ path, message: `${path} must be an object with a type.` });\n\t\treturn null;\n\t}\n\tconst type = pick(value.type, CHART_TRENDLINE_TYPES, 'linear', `${path}.type`, issues);\n\tconst line: ChartTrendline = { type };\n\tconst whole = (name: 'order' | 'period', min: number, max: number) => {\n\t\tif (!key(value, name)) return;\n\t\tconst n = Number(value[name]);\n\t\tif (Number.isInteger(n) && n >= min && n <= max) line[name] = n;\n\t\telse issues.push({ path: `${path}.${name}`, message: `${path}.${name} must be a whole number from ${min} to ${max}.` });\n\t};\n\tif (type === 'polynomial') whole('order', 2, 6);\n\tif (type === 'moving-average') whole('period', 2, 1000);\n\tfor (const name of ['forward', 'backward'] as const) {\n\t\tif (!key(value, name)) continue;\n\t\tconst n = Number(value[name]);\n\t\tif (Number.isFinite(n) && n >= 0) {\n\t\t\tif (n > 0) line[name] = n;\n\t\t} else issues.push({ path: `${path}.${name}`, message: `${path}.${name} must be a number of x units, 0 or more.` });\n\t}\n\tif (key(value, 'intercept')) {\n\t\tconst n = Number(value.intercept);\n\t\tif (!Number.isFinite(n)) issues.push({ path: `${path}.intercept`, message: `${path}.intercept must be a number or null.` });\n\t\telse if (type === 'linear' || type === 'polynomial' || type === 'exponential') {\n\t\t\tif (type === 'exponential' && n <= 0) issues.push({ path: `${path}.intercept`, message: `${path}.intercept must be greater than 0 for an exponential trendline.` });\n\t\t\telse line.intercept = n;\n\t\t} else issues.push({ path: `${path}.intercept`, message: `A ${type} trendline cannot have a fixed intercept; use linear, polynomial or exponential.` });\n\t}\n\tfor (const name of ['showEquation', 'showR2'] as const) if (key(value, name) && flag(value[name], false, `${path}.${name}`, issues)) line[name] = true;\n\tfor (const name of ['name', 'color'] as const) {\n\t\tif (!key(value, name)) continue;\n\t\tconst t = text(value[name], '', `${path}.${name}`, issues).trim();\n\t\tif (t) line[name] = t;\n\t}\n\treturn line;\n}\n\n/**\n * Turns any input (a partial spec, saved JSON, an agent's arguments) into a complete,\n * valid `ChartSpec`. Every value is checked; problems are reported as sentences in\n * `issues` and replaced by defaults, so the result is always drawable. Series values are\n * padded or trimmed to the number of categories.\n */\nexport function normalizeChartSpec(input: unknown): { spec: ChartSpec; issues: ChartIssue[] } {\n\tconst issues: ChartIssue[] = [];\n\tconst value = isRecord(input) ? input : {};\n\tif (input !== undefined && !isRecord(input)) issues.push({ path: '', message: 'A chart must be an object.' });\n\tconst type = pick(value.type, CHART_TYPES, 'bar', 'type', issues);\n\tconst rawSeries = Array.isArray(value.series) ? value.series : [];\n\tif (value.series !== undefined && !Array.isArray(value.series)) issues.push({ path: 'series', message: 'series must be an array.' });\n\n\tlet categories: string[];\n\tif (Array.isArray(value.categories)) categories = value.categories.map((c, i) => text(c, '', `categories[${i}]`, issues));\n\telse {\n\t\tif (value.categories !== undefined) issues.push({ path: 'categories', message: 'categories must be an array of labels.' });\n\t\tconst longest = rawSeries.reduce<number>((n, s) => Math.max(n, isRecord(s) && Array.isArray(s.values) ? s.values.length : 0), 0);\n\t\tcategories = Array.from({ length: longest }, (_, i) => `${i + 1}`);\n\t}\n\n\tconst used = new Set<string>();\n\tconst series = rawSeries.map((s, i) => normalizeSeries(s, categories.length, used, i, issues)).filter((s): s is ChartSeries => s !== null);\n\n\tlet palette = [...DEFAULT_CHART_PALETTE];\n\tif (Array.isArray(value.palette)) {\n\t\tconst colors = value.palette.filter((c): c is string => typeof c === 'string' && c.trim() !== '');\n\t\tif (colors.length) palette = colors;\n\t\telse issues.push({ path: 'palette', message: 'palette must list at least one colour.' });\n\t} else if (value.palette !== undefined) issues.push({ path: 'palette', message: 'palette must be an array of colours.' });\n\n\tconst fraction = (name: string, fallback: number, min: number, max: number) => {\n\t\tif (value[name] === undefined) return fallback;\n\t\tconst r = Number(value[name]);\n\t\tif (value[name] !== null && Number.isFinite(r) && r >= min && r <= max) return r;\n\t\tissues.push({ path: name, message: `${name} must be a number from ${min} to ${max}.` });\n\t\treturn fallback;\n\t};\n\tconst innerRadius = fraction('innerRadius', 0.55, 0, 0.9);\n\tconst gapWidth = fraction('gapWidth', 0.28, 0, 0.9);\n\tconst overlap = fraction('overlap', -0.12, -1, 1);\n\tlet bins: number | null = null;\n\tif (value.bins !== undefined && value.bins !== null) {\n\t\tconst b = Number(value.bins);\n\t\tif (Number.isInteger(b) && b >= 1 && b <= 500) bins = b;\n\t\telse issues.push({ path: 'bins', message: 'bins must be a whole number from 1 to 500, or null for automatic.' });\n\t}\n\n\tconst spec: ChartSpec = {\n\t\tversion: 1,\n\t\ttype,\n\t\ttitle: text(value.title, '', 'title', issues),\n\t\tsubtitle: text(value.subtitle, '', 'subtitle', issues),\n\t\tcategories,\n\t\tseries,\n\t\txAxis: normalizeChartAxis(value.xAxis, defaultChartAxis(false), 'xAxis', issues),\n\t\tyAxis: normalizeChartAxis(value.yAxis, defaultChartAxis(true), 'yAxis', issues),\n\t\tyAxis2: normalizeChartAxis(value.yAxis2, defaultChartAxis(false), 'yAxis2', issues),\n\t\tlegend: normalizeLegend(value.legend, issues),\n\t\tstacking: pick(value.stacking, CHART_STACKINGS, 'none', 'stacking', issues),\n\t\torientation: pick(value.orientation, CHART_ORIENTATIONS, 'vertical', 'orientation', issues),\n\t\tcurve: pick(value.curve, CHART_CURVES, 'linear', 'curve', issues),\n\t\tpoints: flag(value.points, true, 'points', issues),\n\t\tdataLabels: flag(value.dataLabels, false, 'dataLabels', issues),\n\t\tlabelPosition: pick(value.labelPosition, CHART_LABEL_POSITIONS, 'auto', 'labelPosition', issues),\n\t\tpalette,\n\t\tinnerRadius,\n\t\tgapWidth,\n\t\toverlap,\n\t\tbins,\n\t\tshowTotal: flag(value.showTotal, true, 'showTotal', issues)\n\t};\n\treturn { spec, issues };\n}\n\n/** A deep copy (specs are plain JSON). */\nexport function cloneChartSpec(spec: ChartSpec): ChartSpec {\n\treturn {\n\t\t...spec,\n\t\tcategories: [...spec.categories],\n\t\tseries: spec.series.map(cloneChartSeries),\n\t\txAxis: { ...spec.xAxis, format: { ...spec.xAxis.format } },\n\t\tyAxis: { ...spec.yAxis, format: { ...spec.yAxis.format } },\n\t\tyAxis2: { ...spec.yAxis2, format: { ...spec.yAxis2.format } },\n\t\tlegend: { ...spec.legend },\n\t\tpalette: [...spec.palette]\n\t};\n}\n\nexport function cloneChartSeries(series: ChartSeries): ChartSeries {\n\tconst copy: ChartSeries = { ...series, values: [...series.values] };\n\tif (series.x) copy.x = [...series.x];\n\tif (series.sizes) copy.sizes = [...series.sizes];\n\tif (series.pointColors) copy.pointColors = [...series.pointColors];\n\tif (series.format) copy.format = { ...series.format };\n\tif (series.trendlines) copy.trendlines = series.trendlines.map((t) => ({ ...t }));\n\treturn copy;\n}\n\nexport interface ChartTableOptions {\n\t/**\n\t * `columns` (default): the first column holds categories and each other column is a\n\t * series. `rows`: the first row holds categories and each other row is a series.\n\t */\n\tseriesIn?: 'columns' | 'rows';\n\t/**\n\t * The first row (or column for `rows`) holds series names (default `true`). `auto`: only\n\t * when one of its value cells is not a number.\n\t */\n\theader?: boolean | 'auto';\n\t/**\n\t * Read the first column as numeric x values (scatter and bubble charts): every series gets\n\t * them as `x`, and the categories are their labels.\n\t */\n\txFromFirstColumn?: boolean;\n}\n\nexport interface ChartTableData {\n\tcategories: string[];\n\tseries: ChartSeries[];\n\tissues: ChartIssue[];\n}\n\n/**\n * Reads a grid of cells (from CSV, a spreadsheet range or the clipboard) as categories and\n * series. Cells that are not numbers become gaps and are reported.\n */\nexport function chartDataFromTable(rows: ReadonlyArray<ReadonlyArray<unknown>>, options: ChartTableOptions = {}): ChartTableData {\n\tlet grid = rows.map((r) => [...r]).filter((r) => r.some((c) => c !== null && c !== undefined && String(c).trim() !== ''));\n\tif (options.seriesIn === 'rows') {\n\t\tconst width = Math.max(0, ...grid.map((r) => r.length));\n\t\tgrid = Array.from({ length: width }, (_, c) => grid.map((r) => r[c]));\n\t}\n\tconst issues: ChartIssue[] = [];\n\tif (!grid.length) return { categories: [], series: [], issues };\n\tconst width = Math.max(...grid.map((r) => r.length));\n\tconst header = options.header === 'auto' ? grid[0].slice(1).some((c) => c !== null && c !== undefined && String(c).trim() !== '' && parseChartValue(c) === undefined) : (options.header ?? true);\n\tconst names = header ? grid[0] : [];\n\tconst body = header ? grid.slice(1) : grid;\n\tconst categories = body.map((r, i) => {\n\t\tconst c = r[0];\n\t\treturn c === null || c === undefined || String(c).trim() === '' ? `${i + 1}` : String(c).trim();\n\t});\n\tconst series: ChartSeries[] = [];\n\tfor (let col = 1; col < width; col++) {\n\t\tconst name = names[col] !== undefined && String(names[col]).trim() ? String(names[col]).trim() : `Series ${col}`;\n\t\tconst values = body.map((r, i) => {\n\t\t\tconst parsed = parseChartValue(r[col] ?? null);\n\t\t\tif (parsed === undefined) {\n\t\t\t\tissues.push({ path: `${name}[${i}]`, message: `\"${String(r[col])}\" in ${name} (${categories[i]}) is not a number; it was left blank.` });\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn parsed;\n\t\t});\n\t\tseries.push({ id: `series-${col}`, name, values });\n\t}\n\tif (options.xFromFirstColumn) {\n\t\tconst x = body.map((r, i) => {\n\t\t\tconst parsed = parseChartValue(r[0] ?? null);\n\t\t\tif (parsed === undefined) issues.push({ path: `x[${i}]`, message: `\"${String(r[0])}\" in the first column is not a number; that point has no x.` });\n\t\t\treturn parsed ?? null;\n\t\t});\n\t\tfor (const s of series) s.x = [...x];\n\t}\n\treturn { categories, series, issues };\n}\n\n/** The chart's data as a grid: a header row of series names, then one row per category. */\nexport function chartDataToTable(spec: Pick<ChartSpec, 'categories' | 'series'>, options: { categoryHeader?: string } = {}): (string | number | null)[][] {\n\treturn [\n\t\t[options.categoryHeader ?? '', ...spec.series.map((s) => s.name)],\n\t\t...spec.categories.map((category, i) => [category, ...spec.series.map((s) => s.values[i] ?? null)])\n\t];\n}\n\n/** A colour input value (`#rrggbb`) for a CSS colour: `#abc` expands, non-hex colours show as black. */\nexport function chartColorInputValue(color: string): string {\n\tif (/^#[0-9a-f]{6}$/i.test(color)) return color.toLowerCase();\n\tif (/^#[0-9a-f]{3}$/i.test(color)) return `#${[...color.slice(1)].map((c) => c + c).join('')}`.toLowerCase();\n\treturn '#000000';\n}\n"],"mappings":"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","names":["text","text","key","width"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/chunk-TGBCBQFV.cjs","../src/chart/schemas.ts"],"names":[],"mappings":"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","file":"/home/runner/work/editor/editor/packages/core/dist/chunk-TGBCBQFV.cjs","sourcesContent":[null,"import type { JsonSchema } from '../tools/schema.js';\nimport {\n\tCHART_AXIS_KINDS,\n\tCHART_CURVES,\n\tCHART_LABEL_POSITIONS,\n\tCHART_LEGEND_POSITIONS,\n\tCHART_MARKERS,\n\tCHART_NUMBER_STYLES,\n\tCHART_ORIENTATIONS,\n\tCHART_SERIES_TYPES,\n\tCHART_STACKINGS,\n\tCHART_TRENDLINE_TYPES,\n\tCHART_TYPES\n} from './spec.js';\n\n// JSON Schema fragments shared by the chart commands and the chart agent tools.\n\nexport const VALUE: JsonSchema = { type: ['number', 'string', 'null'], description: 'A number, numeric text (\"1,200\", \"12%\", \"$40\", \"(3)\") or null for a gap.' };\nexport const SERIES_REF: JsonSchema = { type: 'string', description: 'Series id (from get_chart) or exact series name.' };\nexport const CATEGORY_REF: JsonSchema = { type: ['string', 'integer'], description: 'Category index (0-based) or exact category label.' };\nexport const WIDTH: JsonSchema = { type: 'number', minimum: 50, maximum: 4096, description: 'Width in pixels (default 640).' };\nexport const HEIGHT: JsonSchema = { type: 'number', minimum: 50, maximum: 4096, description: 'Height in pixels (default 400).' };\n\nexport const FORMAT: JsonSchema = {\n\ttype: 'object',\n\tdescription: 'How numbers are written on this axis or series.',\n\tproperties: {\n\t\tstyle: { type: 'string', enum: [...CHART_NUMBER_STYLES], description: 'number (default), percent (0.25 → 25%), currency or compact (1.2K).' },\n\t\tdecimals: { type: 'integer', minimum: 0, maximum: 10, description: 'Fixed decimals (default: what the ticks need).' },\n\t\tcurrency: { type: 'string', description: 'ISO currency code for style \"currency\", e.g. \"EUR\" (default USD).' },\n\t\tprefix: { type: 'string', description: 'Text before every number.' },\n\t\tsuffix: { type: 'string', description: 'Text after every number.' },\n\t\tcode: { type: 'string', description: 'Spreadsheet format code such as \"#,##0.0,,\\\\\"M\\\\\"\" or \"0.0%\"; wins over the other fields.' }\n\t},\n\tadditionalProperties: false\n};\n\nexport const AXIS = (what: string): JsonSchema => ({\n\ttype: 'object',\n\tdescription: what,\n\tproperties: {\n\t\tshow: { type: 'boolean', description: 'Draw the axis labels (default true).' },\n\t\ttitle: { type: 'string', description: 'Axis title (\"\" for none).' },\n\t\tmin: { type: ['number', 'null'], description: 'Fixed lower bound, or null for automatic.' },\n\t\tmax: { type: ['number', 'null'], description: 'Fixed upper bound, or null for automatic.' },\n\t\tstep: { type: ['number', 'null'], exclusiveMinimum: 0, description: 'Fixed distance between ticks, or null for automatic.' },\n\t\tgridlines: { type: 'boolean', description: 'Grid lines at each tick.' },\n\t\tformat: FORMAT,\n\t\tkind: { type: ['string', 'null'], enum: [...CHART_AXIS_KINDS, null], description: 'Category axis only: \"date\" reads categories as dates and labels them by calendar steps.' }\n\t},\n\tadditionalProperties: false\n});\n\nexport const TRENDLINE_PROPS: Record<string, JsonSchema> = {\n\ttype: { type: 'string', enum: [...CHART_TRENDLINE_TYPES], description: 'Fit: linear, exponential, logarithmic, power, polynomial or moving-average.' },\n\torder: { type: 'integer', minimum: 2, maximum: 6, description: 'Polynomial order (default 2).' },\n\tperiod: { type: 'integer', minimum: 2, description: 'Moving-average period in points (default 2).' },\n\tforward: { type: 'number', minimum: 0, description: 'Extend the line this many x units past the last point (default 0).' },\n\tbackward: { type: 'number', minimum: 0, description: 'Extend the line this many x units before the first point (default 0).' },\n\tintercept: { type: ['number', 'null'], description: 'Force the fit through this y at x = 0 (linear, polynomial, exponential).' },\n\tshowEquation: { type: 'boolean', description: 'Write the fitted equation on the chart.' },\n\tshowR2: { type: 'boolean', description: 'Write R² on the chart.' },\n\tname: { type: 'string', description: 'Legend name (default e.g. \"Linear (Sales)\").' },\n\tcolor: { type: 'string', description: 'CSS colour (default: the series colour).' }\n};\n\nexport const SERIES_PROPS: Record<string, JsonSchema> = {\n\tname: { type: 'string', description: 'Series name (legend and data grid header).' },\n\tvalues: { type: 'array', items: VALUE, description: 'One value per category, in category order (padded with gaps).' },\n\tcolor: { type: ['string', 'null'], description: 'CSS colour, or null for the palette colour.' },\n\ttype: { type: ['string', 'null'], enum: [...CHART_SERIES_TYPES, null], description: 'Draw this series as bar, line, area or scatter (a combo chart); null follows the chart type.' },\n\thidden: { type: 'boolean', description: 'Hide the series (its data is kept).' },\n\taxis: { type: ['string', 'null'], enum: ['primary', 'secondary', null], description: 'Value axis: secondary is drawn on the right with its own scale.' },\n\tx: { type: ['array', 'null'], items: VALUE, description: 'Numeric x per category, for scatter and bubble charts.' },\n\tsizes: { type: ['array', 'null'], items: VALUE, description: 'Bubble sizes per category (area is proportional to size).' },\n\tpointColors: { type: ['array', 'null'], items: { type: ['string', 'null'] }, description: 'Colour per category (null keeps the series colour).' },\n\tmarker: { type: ['string', 'null'], enum: [...CHART_MARKERS, null], description: 'Point marker shape for line, area and scatter series.' },\n\tcurve: { type: ['string', 'null'], enum: [...CHART_CURVES, null], description: 'Line shape for this series: linear, smooth or step.' },\n\tdataLabels: { type: ['boolean', 'null'], description: 'Value labels for this series (null follows the chart).' },\n\tformat: { ...FORMAT, type: ['object', 'null'], description: 'How this series\\' labels are written (null follows the value axis).' }\n};\n\n\nexport const CHART_UPDATE_PROPERTIES: Record<string, JsonSchema> = {\n\t\t\t\ttype: { type: 'string', enum: [...CHART_TYPES], description: 'Chart type.' },\n\t\t\t\ttitle: { type: 'string', description: 'Title (\"\" for none).' },\n\t\t\t\tsubtitle: { type: 'string', description: 'Subtitle (\"\" for none).' },\n\t\t\t\txAxis: AXIS('Category axis (or numeric x axis of scatter / bubble charts).'),\n\t\t\t\tyAxis: AXIS('Value axis.'),\n\t\t\t\tyAxis2: AXIS('Secondary value axis (for series with axis \"secondary\").'),\n\t\t\t\tlegend: {\n\t\t\t\t\ttype: 'object',\n\t\t\t\t\tdescription: 'Legend.',\n\t\t\t\t\tproperties: { show: { type: 'boolean', description: 'Show the legend.' }, position: { type: 'string', enum: [...CHART_LEGEND_POSITIONS], description: 'Where the legend goes.' } },\n\t\t\t\t\tadditionalProperties: false\n\t\t\t\t},\n\t\t\t\tstacking: { type: 'string', enum: [...CHART_STACKINGS], description: 'none, stacked, or percent (each category scaled to 100%).' },\n\t\t\t\torientation: { type: 'string', enum: [...CHART_ORIENTATIONS], description: 'horizontal draws bars sideways.' },\n\t\t\t\tcurve: { type: 'string', enum: [...CHART_CURVES], description: 'Line shape: linear, smooth or step.' },\n\t\t\t\tpoints: { type: 'boolean', description: 'Dots on line and area series.' },\n\t\t\t\tdataLabels: { type: 'boolean', description: 'Value labels on bars, points and slices.' },\n\t\t\t\tlabelPosition: { type: 'string', enum: [...CHART_LABEL_POSITIONS], description: 'Bar label position; auto drops labels that do not fit.' },\n\t\t\t\tpalette: { type: 'array', items: { type: 'string' }, minItems: 1, description: 'Series colours in order (CSS colours).' },\n\t\t\t\tinnerRadius: { type: 'number', minimum: 0, maximum: 0.9, description: 'Donut hole as a fraction of the radius.' },\n\t\t\t\tgapWidth: { type: 'number', minimum: 0, maximum: 0.9, description: 'Space between bar groups as a fraction of the category (default 0.28).' },\n\t\t\t\toverlap: { type: 'number', minimum: -1, maximum: 1, description: 'Bar overlap within a group as a fraction of a bar (negative: a gap; default -0.12).' },\n\t\t\t\tbins: { type: ['integer', 'null'], minimum: 1, maximum: 500, description: 'Histogram bin count, or null for √n.' },\n\t\t\t\tshowTotal: { type: 'boolean', description: 'Waterfall: append a total bar.' }\n\t\t\t};\n"]}