tempest-react-sdk 0.26.1 → 0.28.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 (132) hide show
  1. package/README.md +25 -1
  2. package/bin/lib/css/analyze.mjs +149 -0
  3. package/bin/lib/css/analyze.test.mjs +136 -0
  4. package/bin/lib/css/collect.mjs +152 -0
  5. package/bin/lib/css/findings.mjs +79 -0
  6. package/bin/lib/css/fix.e2e.test.mjs +99 -0
  7. package/bin/lib/css/fix.mjs +138 -0
  8. package/bin/lib/css/fix.test.mjs +108 -0
  9. package/bin/lib/css/index.mjs +16 -0
  10. package/bin/lib/css/parse.mjs +398 -0
  11. package/bin/lib/css/parse.test.mjs +146 -0
  12. package/bin/lib/css/properties.mjs +399 -0
  13. package/bin/lib/css/repetition.mjs +213 -0
  14. package/bin/lib/css/repetition.test.mjs +166 -0
  15. package/bin/lib/css/semantic.mjs +327 -0
  16. package/bin/lib/css/semantic.test.mjs +201 -0
  17. package/bin/lib/css/tokens.mjs +119 -0
  18. package/bin/lib/doctor/doctor.e2e.test.mjs +246 -0
  19. package/bin/tempest.mjs +272 -36
  20. package/dist/charts/scales.cjs +2 -0
  21. package/dist/charts/scales.cjs.map +1 -0
  22. package/dist/charts/scales.js +29 -0
  23. package/dist/charts/scales.js.map +1 -0
  24. package/dist/charts.cjs +1 -1
  25. package/dist/charts.d.ts +91 -0
  26. package/dist/charts.js +9 -8
  27. package/dist/components/BottomNavigation/BottomNavigation.module.cjs.map +1 -1
  28. package/dist/components/BottomNavigation/BottomNavigation.module.js.map +1 -1
  29. package/dist/components/Carousel/Carousel.module.cjs.map +1 -1
  30. package/dist/components/Carousel/Carousel.module.js.map +1 -1
  31. package/dist/components/CodeBlock/CodeBlock.cjs +3 -0
  32. package/dist/components/CodeBlock/CodeBlock.cjs.map +1 -0
  33. package/dist/components/CodeBlock/CodeBlock.js +53 -0
  34. package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
  35. package/dist/components/CodeBlock/CodeBlock.module.cjs +2 -0
  36. package/dist/components/CodeBlock/CodeBlock.module.cjs.map +1 -0
  37. package/dist/components/CodeBlock/CodeBlock.module.js +29 -0
  38. package/dist/components/CodeBlock/CodeBlock.module.js.map +1 -0
  39. package/dist/components/CodeBlock/tokenize.cjs +3 -0
  40. package/dist/components/CodeBlock/tokenize.cjs.map +1 -0
  41. package/dist/components/CodeBlock/tokenize.js +267 -0
  42. package/dist/components/CodeBlock/tokenize.js.map +1 -0
  43. package/dist/components/ImageCropper/ImageCropper.cjs +2 -0
  44. package/dist/components/ImageCropper/ImageCropper.cjs.map +1 -0
  45. package/dist/components/ImageCropper/ImageCropper.js +240 -0
  46. package/dist/components/ImageCropper/ImageCropper.js.map +1 -0
  47. package/dist/components/ImageCropper/ImageCropper.module.cjs +2 -0
  48. package/dist/components/ImageCropper/ImageCropper.module.cjs.map +1 -0
  49. package/dist/components/ImageCropper/ImageCropper.module.js +15 -0
  50. package/dist/components/ImageCropper/ImageCropper.module.js.map +1 -0
  51. package/dist/components/ImageCropper/crop-geometry.cjs +2 -0
  52. package/dist/components/ImageCropper/crop-geometry.cjs.map +1 -0
  53. package/dist/components/ImageCropper/crop-geometry.js +52 -0
  54. package/dist/components/ImageCropper/crop-geometry.js.map +1 -0
  55. package/dist/components/Navbar/Navbar.module.cjs.map +1 -1
  56. package/dist/components/Navbar/Navbar.module.js.map +1 -1
  57. package/dist/components/QRCode/QRCode.cjs +2 -0
  58. package/dist/components/QRCode/QRCode.cjs.map +1 -0
  59. package/dist/components/QRCode/QRCode.js +49 -0
  60. package/dist/components/QRCode/QRCode.js.map +1 -0
  61. package/dist/components/QRCode/QRCode.module.cjs +2 -0
  62. package/dist/components/QRCode/QRCode.module.cjs.map +1 -0
  63. package/dist/components/QRCode/QRCode.module.js +9 -0
  64. package/dist/components/QRCode/QRCode.module.js.map +1 -0
  65. package/dist/components/QRCode/qr-encode.cjs +2 -0
  66. package/dist/components/QRCode/qr-encode.cjs.map +1 -0
  67. package/dist/components/QRCode/qr-encode.js +295 -0
  68. package/dist/components/QRCode/qr-encode.js.map +1 -0
  69. package/dist/components/QRCode/qr-tables.cjs +2 -0
  70. package/dist/components/QRCode/qr-tables.cjs.map +1 -0
  71. package/dist/components/QRCode/qr-tables.js +366 -0
  72. package/dist/components/QRCode/qr-tables.js.map +1 -0
  73. package/dist/components/Scheduler/Scheduler.cjs +2 -0
  74. package/dist/components/Scheduler/Scheduler.cjs.map +1 -0
  75. package/dist/components/Scheduler/Scheduler.js +134 -0
  76. package/dist/components/Scheduler/Scheduler.js.map +1 -0
  77. package/dist/components/Scheduler/Scheduler.module.cjs +2 -0
  78. package/dist/components/Scheduler/Scheduler.module.cjs.map +1 -0
  79. package/dist/components/Scheduler/Scheduler.module.js +26 -0
  80. package/dist/components/Scheduler/Scheduler.module.js.map +1 -0
  81. package/dist/components/Scheduler/scheduler-layout.cjs +2 -0
  82. package/dist/components/Scheduler/scheduler-layout.cjs.map +1 -0
  83. package/dist/components/Scheduler/scheduler-layout.js +97 -0
  84. package/dist/components/Scheduler/scheduler-layout.js.map +1 -0
  85. package/dist/components/ScrollArea/ScrollArea.cjs +1 -1
  86. package/dist/components/ScrollArea/ScrollArea.cjs.map +1 -1
  87. package/dist/components/ScrollArea/ScrollArea.js +22 -16
  88. package/dist/components/ScrollArea/ScrollArea.js.map +1 -1
  89. package/dist/components/ScrollArea/ScrollArea.module.cjs.map +1 -1
  90. package/dist/components/ScrollArea/ScrollArea.module.js.map +1 -1
  91. package/dist/components/Sparkline/Sparkline.cjs +2 -0
  92. package/dist/components/Sparkline/Sparkline.cjs.map +1 -0
  93. package/dist/components/Sparkline/Sparkline.js +64 -0
  94. package/dist/components/Sparkline/Sparkline.js.map +1 -0
  95. package/dist/components/Sparkline/Sparkline.module.cjs +2 -0
  96. package/dist/components/Sparkline/Sparkline.module.cjs.map +1 -0
  97. package/dist/components/Sparkline/Sparkline.module.js +10 -0
  98. package/dist/components/Sparkline/Sparkline.module.js.map +1 -0
  99. package/dist/components/Sparkline/sparkline-geometry.cjs +2 -0
  100. package/dist/components/Sparkline/sparkline-geometry.cjs.map +1 -0
  101. package/dist/components/Sparkline/sparkline-geometry.js +56 -0
  102. package/dist/components/Sparkline/sparkline-geometry.js.map +1 -0
  103. package/dist/components/Table/Table.cjs +1 -1
  104. package/dist/components/Table/Table.cjs.map +1 -1
  105. package/dist/components/Table/Table.js +37 -30
  106. package/dist/components/Table/Table.js.map +1 -1
  107. package/dist/components/Table/Table.module.cjs.map +1 -1
  108. package/dist/components/Table/Table.module.js.map +1 -1
  109. package/dist/components/VirtualList/VirtualList.cjs +1 -1
  110. package/dist/components/VirtualList/VirtualList.cjs.map +1 -1
  111. package/dist/components/VirtualList/VirtualList.js +13 -11
  112. package/dist/components/VirtualList/VirtualList.js.map +1 -1
  113. package/dist/components/VirtualList/VirtualList.module.cjs.map +1 -1
  114. package/dist/components/VirtualList/VirtualList.module.js.map +1 -1
  115. package/dist/hooks/use-scroll-overflow.cjs +2 -0
  116. package/dist/hooks/use-scroll-overflow.cjs.map +1 -0
  117. package/dist/hooks/use-scroll-overflow.js +22 -0
  118. package/dist/hooks/use-scroll-overflow.js.map +1 -0
  119. package/dist/styles.css +1 -1
  120. package/dist/tempest-react-sdk.cjs +1 -1
  121. package/dist/tempest-react-sdk.d.ts +607 -2
  122. package/dist/tempest-react-sdk.js +197 -188
  123. package/dist/theme/create-theme.cjs +3 -3
  124. package/dist/theme/create-theme.cjs.map +1 -1
  125. package/dist/theme/create-theme.js +52 -28
  126. package/dist/theme/create-theme.js.map +1 -1
  127. package/dist/theme/data-viz-ramps.cjs +2 -0
  128. package/dist/theme/data-viz-ramps.cjs.map +1 -0
  129. package/dist/theme/data-viz-ramps.js +58 -0
  130. package/dist/theme/data-viz-ramps.js.map +1 -0
  131. package/package.json +2 -1
  132. package/template/package.json +1 -1
@@ -0,0 +1,29 @@
1
+ //#region src/charts/scales.ts
2
+ var e = 7, t = 9, n = 3;
3
+ function r(e) {
4
+ return `var(--tempest-chart-${e})`;
5
+ }
6
+ function i(e, t, n) {
7
+ if (!Number.isFinite(e)) return 0;
8
+ let r = Math.min(t, n), i = Math.max(t, n);
9
+ return i === r ? .5 : Math.min(1, Math.max(0, (e - r) / (i - r)));
10
+ }
11
+ function a(e, t) {
12
+ return Math.min(t, Math.max(1, Math.round(e * (t - 1)) + 1));
13
+ }
14
+ function o(e) {
15
+ let { min: t, max: n, ordinal: o = !1 } = e, s = o ? 3 : 1, c = 7 - s + 1;
16
+ return (e) => r(`sequential-${s + a(i(e, t, n), c) - 1}`);
17
+ }
18
+ function s(e) {
19
+ let { min: t, max: n, center: i = 0 } = e, o = Math.abs(i - Math.min(t, n)), s = Math.abs(Math.max(t, n) - i);
20
+ return (e) => r(!Number.isFinite(e) || e === i ? "diverging-5" : e < i ? o === 0 ? "diverging-5" : `diverging-${5 - a(Math.min(1, (i - e) / o), 4)}` : s === 0 ? "diverging-5" : `diverging-${5 + a(Math.min(1, (e - i) / s), 4)}`);
21
+ }
22
+ function c(e) {
23
+ let t = e === "sequential" ? 7 : 9;
24
+ return Array.from({ length: t }, (t, n) => r(`${e}-${n + 1}`));
25
+ }
26
+ //#endregion
27
+ export { t as DIVERGING_STEP_COUNT, n as ORDINAL_START_STEP, e as SEQUENTIAL_STEP_COUNT, s as divergingScale, c as scaleSteps, o as sequentialScale };
28
+
29
+ //# sourceMappingURL=scales.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scales.js","names":[],"sources":["../../src/charts/scales.ts"],"sourcesContent":["/** How many steps the sequential token scale has. */\nexport const SEQUENTIAL_STEP_COUNT = 7;\n\n/** How many steps the diverging token scale has, midpoint included. */\nexport const DIVERGING_STEP_COUNT = 9;\n\n/**\n * First sequential step that clears 2:1 against the chart surface.\n *\n * A sequential scale may let its near-zero end recede into the surface — on a\n * heatmap that is exactly what \"almost nothing\" should look like. An **ordinal**\n * scale may not: every step is a discrete mark someone has to see. Starting an\n * ordinal ramp here is the difference.\n */\nexport const ORDINAL_START_STEP = 3;\n\n/** A `var(--tempest-chart-…)` reference, so the value follows the active theme. */\nexport type ChartColorToken = string;\n\n/** Reference a token by name rather than interpolating the string at each call site. */\nfunction token(name: string): ChartColorToken {\n return `var(--tempest-chart-${name})`;\n}\n\n/**\n * Clamp `value` into `0…1` against a domain, tolerating a reversed or empty one.\n *\n * A zero-width domain (every datum equal) would otherwise divide by zero and paint\n * the whole chart `NaN`; it resolves to the middle of the scale instead, which is\n * the honest reading of \"no variation\".\n */\nfunction normalize(value: number, min: number, max: number): number {\n if (!Number.isFinite(value)) return 0;\n const lo = Math.min(min, max);\n const hi = Math.max(min, max);\n if (hi === lo) return 0.5;\n return Math.min(1, Math.max(0, (value - lo) / (hi - lo)));\n}\n\n/** Map a `0…1` position onto `1…steps`, inclusive. */\nfunction stepOf(t: number, steps: number): number {\n return Math.min(steps, Math.max(1, Math.round(t * (steps - 1)) + 1));\n}\n\nexport interface SequentialScaleOptions {\n /** Lowest value in the data. */\n min: number;\n /** Highest value in the data. */\n max: number;\n /**\n * Keep every step visible against the surface, for discrete ordered marks.\n *\n * Off by default: a heatmap *wants* its near-zero cells to recede. Turn it on\n * for tiers, funnel stages or anything where each step is its own mark.\n */\n ordinal?: boolean;\n}\n\n/**\n * Build a magnitude scale over the sequential tokens.\n *\n * Returns `var(--tempest-chart-sequential-N)` rather than a hex string, so a\n * heatmap painted once follows the theme — including dark mode, whose steps are\n * chosen for the dark surface rather than flipped.\n *\n * @example\n * const color = sequentialScale({ min: 0, max: 250 });\n * <rect fill={color(value)} />\n *\n * @param options - The data domain, and whether every step must stay visible.\n * @returns A function from value to a CSS colour reference.\n */\nexport function sequentialScale(\n options: SequentialScaleOptions,\n): (value: number) => ChartColorToken {\n const { min, max, ordinal = false } = options;\n const first = ordinal ? ORDINAL_START_STEP : 1;\n const span = SEQUENTIAL_STEP_COUNT - first + 1;\n return (value) => token(`sequential-${first + stepOf(normalize(value, min, max), span) - 1}`);\n}\n\nexport interface DivergingScaleOptions {\n /** Lowest value in the data. */\n min: number;\n /** Highest value in the data. */\n max: number;\n /**\n * The value that means \"no deviation\". Default `0`.\n *\n * It is a parameter because the interesting midpoint is often not zero — a\n * budget variance diverges around the target, not around nothing.\n */\n center?: number;\n}\n\n/**\n * Build a polarity scale over the diverging tokens.\n *\n * Each arm is scaled against its **own** distance from the centre, so an asymmetric\n * domain (say −5…+80) still uses the full cool arm for its small negatives. Scaling\n * both arms by the wider one — the easy mistake — would collapse every negative\n * into the step next to the midpoint and hide the sign entirely.\n *\n * @example\n * const color = divergingScale({ min: -12, max: 40 }); // centre 0\n * const budget = divergingScale({ min: 80, max: 130, center: 100 });\n *\n * @param options - The data domain and the neutral centre.\n * @returns A function from value to a CSS colour reference.\n */\nexport function divergingScale(options: DivergingScaleOptions): (value: number) => ChartColorToken {\n const { min, max, center = 0 } = options;\n const mid = Math.ceil(DIVERGING_STEP_COUNT / 2);\n const armSteps = mid - 1;\n const coolSpan = Math.abs(center - Math.min(min, max));\n const warmSpan = Math.abs(Math.max(min, max) - center);\n\n return (value) => {\n if (!Number.isFinite(value) || value === center) return token(`diverging-${mid}`);\n if (value < center) {\n if (coolSpan === 0) return token(`diverging-${mid}`);\n const t = Math.min(1, (center - value) / coolSpan);\n // Step 1 is the cool extreme, so a bigger deviation walks toward it.\n return token(`diverging-${mid - stepOf(t, armSteps)}`);\n }\n if (warmSpan === 0) return token(`diverging-${mid}`);\n const t = Math.min(1, (value - center) / warmSpan);\n return token(`diverging-${mid + stepOf(t, armSteps)}`);\n };\n}\n\n/**\n * Every step of a token scale, in order — for rendering a legend.\n *\n * A continuous scale needs a legend showing the ramp with its end labels; without\n * one the reader has no way to turn a colour back into a number.\n *\n * @param kind - Which scale.\n * @returns The token references, lightest/coolest first.\n */\nexport function scaleSteps(kind: \"sequential\" | \"diverging\"): ChartColorToken[] {\n const count = kind === \"sequential\" ? SEQUENTIAL_STEP_COUNT : DIVERGING_STEP_COUNT;\n return Array.from({ length: count }, (_, i) => token(`${kind}-${i + 1}`));\n}\n"],"mappings":";AACA,IAAa,IAAwB,GAGxB,IAAuB,GAUvB,IAAqB;AAMlC,SAAS,EAAM,GAA+B;CAC1C,OAAO,uBAAuB,EAAK;AACvC;AASA,SAAS,EAAU,GAAe,GAAa,GAAqB;CAChE,IAAI,CAAC,OAAO,SAAS,CAAK,GAAG,OAAO;CACpC,IAAM,IAAK,KAAK,IAAI,GAAK,CAAG,GACtB,IAAK,KAAK,IAAI,GAAK,CAAG;CAE5B,OADI,MAAO,IAAW,KACf,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,IAAQ,MAAO,IAAK,EAAG,CAAC;AAC5D;AAGA,SAAS,EAAO,GAAW,GAAuB;CAC9C,OAAO,KAAK,IAAI,GAAO,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,IAAQ,EAAE,IAAI,CAAC,CAAC;AACvE;AA8BA,SAAgB,EACZ,GACkC;CAClC,IAAM,EAAE,QAAK,QAAK,aAAU,OAAU,GAChC,IAAQ,IAAA,IAA+B,GACvC,IAAA,IAA+B,IAAQ;CAC7C,QAAQ,MAAU,EAAM,cAAc,IAAQ,EAAO,EAAU,GAAO,GAAK,CAAG,GAAG,CAAI,IAAI,GAAG;AAChG;AA+BA,SAAgB,EAAe,GAAoE;CAC/F,IAAM,EAAE,QAAK,QAAK,YAAS,MAAM,GAG3B,IAAW,KAAK,IAAI,IAAS,KAAK,IAAI,GAAK,CAAG,CAAC,GAC/C,IAAW,KAAK,IAAI,KAAK,IAAI,GAAK,CAAG,IAAI,CAAM;CAErD,QAAQ,MACoD,EAApD,CAAC,OAAO,SAAS,CAAK,KAAK,MAAU,IAAqB,gBAC1D,IAAQ,IACJ,MAAa,IAAgB,gBAGpB,aAAa,IAAM,EAFtB,KAAK,IAAI,IAAI,IAAS,KAAS,CAEF,GAAG,CAAQ,MAElD,MAAa,IAAgB,gBAEpB,aAAa,IAAM,EADtB,KAAK,IAAI,IAAI,IAAQ,KAAU,CACF,GAAG,CAAQ,GAT8B;AAWxF;AAWA,SAAgB,EAAW,GAAqD;CAC5E,IAAM,IAAQ,MAAS,eAAA,IAAA;CACvB,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAM,IAAI,GAAG,MAAM,EAAM,GAAG,EAAK,GAAG,IAAI,GAAG,CAAC;AAC5E"}
package/dist/charts.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./charts/palette.cjs"),t=require("./charts/use-chart-colors.cjs"),n=require("./charts/AreaChart.cjs"),r=require("./charts/BarChart.cjs"),i=require("./charts/LineChart.cjs"),a=require("./charts/PieChart.cjs"),o=require("./charts/RadarChart.cjs");exports.AreaChart=n.AreaChart,exports.BarChart=r.BarChart,exports.CHART_COLOR_TOKEN_COUNT=e.CHART_COLOR_TOKEN_COUNT,exports.DEFAULT_CHART_COLORS=e.DEFAULT_CHART_COLORS,exports.LineChart=i.LineChart,exports.PieChart=a.PieChart,exports.RadarChart=o.RadarChart,exports.resolveChartChrome=e.resolveChartChrome,exports.resolveChartColors=e.resolveChartColors,exports.useChartColors=t.useChartColors;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./charts/scales.cjs"),t=require("./charts/palette.cjs"),n=require("./charts/use-chart-colors.cjs"),r=require("./charts/AreaChart.cjs"),i=require("./charts/BarChart.cjs"),a=require("./charts/LineChart.cjs"),o=require("./charts/PieChart.cjs"),s=require("./charts/RadarChart.cjs");exports.AreaChart=r.AreaChart,exports.BarChart=i.BarChart,exports.CHART_COLOR_TOKEN_COUNT=t.CHART_COLOR_TOKEN_COUNT,exports.DEFAULT_CHART_COLORS=t.DEFAULT_CHART_COLORS,exports.DIVERGING_STEP_COUNT=e.DIVERGING_STEP_COUNT,exports.LineChart=a.LineChart,exports.ORDINAL_START_STEP=e.ORDINAL_START_STEP,exports.PieChart=o.PieChart,exports.RadarChart=s.RadarChart,exports.SEQUENTIAL_STEP_COUNT=e.SEQUENTIAL_STEP_COUNT,exports.divergingScale=e.divergingScale,exports.resolveChartChrome=t.resolveChartChrome,exports.resolveChartColors=t.resolveChartColors,exports.scaleSteps=e.scaleSteps,exports.sequentialScale=e.sequentialScale,exports.useChartColors=n.useChartColors;
package/dist/charts.d.ts CHANGED
@@ -60,6 +60,9 @@ export declare interface CartesianChartProps {
60
60
  /** How many `--tempest-chart-N` tokens the SDK ships. */
61
61
  export declare const CHART_COLOR_TOKEN_COUNT = 8;
62
62
 
63
+ /** A `var(--tempest-chart-…)` reference, so the value follows the active theme. */
64
+ export declare type ChartColorToken = string;
65
+
63
66
  /**
64
67
  * Tabular data consumed by every chart: an array of rows, where each row maps a
65
68
  * column key to a string (label) or number (value).
@@ -77,6 +80,40 @@ export declare type ChartData = Array<Record<string, string | number>>;
77
80
  */
78
81
  export declare const DEFAULT_CHART_COLORS: string[];
79
82
 
83
+ /** How many steps the diverging token scale has, midpoint included. */
84
+ export declare const DIVERGING_STEP_COUNT = 9;
85
+
86
+ /**
87
+ * Build a polarity scale over the diverging tokens.
88
+ *
89
+ * Each arm is scaled against its **own** distance from the centre, so an asymmetric
90
+ * domain (say −5…+80) still uses the full cool arm for its small negatives. Scaling
91
+ * both arms by the wider one — the easy mistake — would collapse every negative
92
+ * into the step next to the midpoint and hide the sign entirely.
93
+ *
94
+ * @example
95
+ * const color = divergingScale({ min: -12, max: 40 }); // centre 0
96
+ * const budget = divergingScale({ min: 80, max: 130, center: 100 });
97
+ *
98
+ * @param options - The data domain and the neutral centre.
99
+ * @returns A function from value to a CSS colour reference.
100
+ */
101
+ export declare function divergingScale(options: DivergingScaleOptions): (value: number) => ChartColorToken;
102
+
103
+ export declare interface DivergingScaleOptions {
104
+ /** Lowest value in the data. */
105
+ min: number;
106
+ /** Highest value in the data. */
107
+ max: number;
108
+ /**
109
+ * The value that means "no deviation". Default `0`.
110
+ *
111
+ * It is a parameter because the interesting midpoint is often not zero — a
112
+ * budget variance diverges around the target, not around nothing.
113
+ */
114
+ center?: number;
115
+ }
116
+
80
117
  /**
81
118
  * LineChart — themed wrapper over recharts `LineChart`.
82
119
  *
@@ -88,6 +125,16 @@ export declare const DEFAULT_CHART_COLORS: string[];
88
125
  */
89
126
  export declare function LineChart({ data, index, categories, colors, height, width, showLegend, showGrid, showTooltip, valueFormatter, className, }: CartesianChartProps): JSX.Element;
90
127
 
128
+ /**
129
+ * First sequential step that clears 2:1 against the chart surface.
130
+ *
131
+ * A sequential scale may let its near-zero end recede into the surface — on a
132
+ * heatmap that is exactly what "almost nothing" should look like. An **ordinal**
133
+ * scale may not: every step is a discrete mark someone has to see. Starting an
134
+ * ordinal ramp here is the difference.
135
+ */
136
+ export declare const ORDINAL_START_STEP = 3;
137
+
91
138
  /**
92
139
  * PieChart — themed wrapper over recharts `PieChart`.
93
140
  *
@@ -165,6 +212,50 @@ export declare function resolveChartChrome(part: "grid" | "axis", element?: Elem
165
212
  */
166
213
  export declare function resolveChartColors(element?: Element | null): string[];
167
214
 
215
+ /**
216
+ * Every step of a token scale, in order — for rendering a legend.
217
+ *
218
+ * A continuous scale needs a legend showing the ramp with its end labels; without
219
+ * one the reader has no way to turn a colour back into a number.
220
+ *
221
+ * @param kind - Which scale.
222
+ * @returns The token references, lightest/coolest first.
223
+ */
224
+ export declare function scaleSteps(kind: "sequential" | "diverging"): ChartColorToken[];
225
+
226
+ /** How many steps the sequential token scale has. */
227
+ export declare const SEQUENTIAL_STEP_COUNT = 7;
228
+
229
+ /**
230
+ * Build a magnitude scale over the sequential tokens.
231
+ *
232
+ * Returns `var(--tempest-chart-sequential-N)` rather than a hex string, so a
233
+ * heatmap painted once follows the theme — including dark mode, whose steps are
234
+ * chosen for the dark surface rather than flipped.
235
+ *
236
+ * @example
237
+ * const color = sequentialScale({ min: 0, max: 250 });
238
+ * <rect fill={color(value)} />
239
+ *
240
+ * @param options - The data domain, and whether every step must stay visible.
241
+ * @returns A function from value to a CSS colour reference.
242
+ */
243
+ export declare function sequentialScale(options: SequentialScaleOptions): (value: number) => ChartColorToken;
244
+
245
+ export declare interface SequentialScaleOptions {
246
+ /** Lowest value in the data. */
247
+ min: number;
248
+ /** Highest value in the data. */
249
+ max: number;
250
+ /**
251
+ * Keep every step visible against the surface, for discrete ordered marks.
252
+ *
253
+ * Off by default: a heatmap *wants* its near-zero cells to recede. Turn it on
254
+ * for tiers, funnel stages or anything where each step is its own mark.
255
+ */
256
+ ordinal?: boolean;
257
+ }
258
+
168
259
  /**
169
260
  * Theme-aware series colors for a chart.
170
261
  *
package/dist/charts.js CHANGED
@@ -1,8 +1,9 @@
1
- import { CHART_COLOR_TOKEN_COUNT as e, DEFAULT_CHART_COLORS as t, resolveChartChrome as n, resolveChartColors as r } from "./charts/palette.js";
2
- import { useChartColors as i } from "./charts/use-chart-colors.js";
3
- import { AreaChart as a } from "./charts/AreaChart.js";
4
- import { BarChart as o } from "./charts/BarChart.js";
5
- import { LineChart as s } from "./charts/LineChart.js";
6
- import { PieChart as c } from "./charts/PieChart.js";
7
- import { RadarChart as l } from "./charts/RadarChart.js";
8
- export { a as AreaChart, o as BarChart, e as CHART_COLOR_TOKEN_COUNT, t as DEFAULT_CHART_COLORS, s as LineChart, c as PieChart, l as RadarChart, n as resolveChartChrome, r as resolveChartColors, i as useChartColors };
1
+ import { DIVERGING_STEP_COUNT as e, ORDINAL_START_STEP as t, SEQUENTIAL_STEP_COUNT as n, divergingScale as r, scaleSteps as i, sequentialScale as a } from "./charts/scales.js";
2
+ import { CHART_COLOR_TOKEN_COUNT as o, DEFAULT_CHART_COLORS as s, resolveChartChrome as c, resolveChartColors as l } from "./charts/palette.js";
3
+ import { useChartColors as u } from "./charts/use-chart-colors.js";
4
+ import { AreaChart as d } from "./charts/AreaChart.js";
5
+ import { BarChart as f } from "./charts/BarChart.js";
6
+ import { LineChart as p } from "./charts/LineChart.js";
7
+ import { PieChart as m } from "./charts/PieChart.js";
8
+ import { RadarChart as h } from "./charts/RadarChart.js";
9
+ export { d as AreaChart, f as BarChart, o as CHART_COLOR_TOKEN_COUNT, s as DEFAULT_CHART_COLORS, e as DIVERGING_STEP_COUNT, p as LineChart, t as ORDINAL_START_STEP, m as PieChart, h as RadarChart, n as SEQUENTIAL_STEP_COUNT, r as divergingScale, c as resolveChartChrome, l as resolveChartColors, i as scaleSteps, a as sequentialScale, u as useChartColors };
@@ -1 +1 @@
1
- {"version":3,"file":"BottomNavigation.module.cjs","names":[],"sources":["../../../src/components/BottomNavigation/BottomNavigation.module.css"],"sourcesContent":[".bar {\n display: flex;\n width: 100%;\n background: var(--tempest-surface);\n border-top: 1px solid var(--tempest-border);\n padding-bottom: env(safe-area-inset-bottom, 0);\n font-family: var(--tempest-font-sans);\n}\n\n.item {\n flex: 1 1 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 2px;\n padding: 8px 4px;\n background: none;\n border: 0;\n cursor: pointer;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-2xs);\n transition: color var(--tempest-duration-fast, 120ms) var(--tempest-ease-out, ease-out);\n min-height: 56px;\n}\n\n.item:hover {\n color: var(--tempest-text);\n}\n\n.item.active {\n color: var(--tempest-primary);\n}\n\n.item:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.iconWrap {\n position: relative;\n display: inline-flex;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n font-size: 20px;\n}\n\n.badge {\n position: absolute;\n top: -4px;\n right: -8px;\n min-width: 14px;\n height: 14px;\n padding: 0 4px;\n border-radius: var(--tempest-radius-full);\n background: var(--tempest-danger-solid);\n color: var(--tempest-danger-on);\n font-size: 10px;\n line-height: 14px;\n text-align: center;\n font-weight: var(--tempest-weight-semibold);\n}\n\n.label {\n line-height: 1;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"BottomNavigation.module.cjs","names":[],"sources":["../../../src/components/BottomNavigation/BottomNavigation.module.css"],"sourcesContent":[".bar {\n display: flex;\n width: 100%;\n background: var(--tempest-surface);\n border-top: 1px solid var(--tempest-border);\n padding-bottom: env(safe-area-inset-bottom, 0);\n font-family: var(--tempest-font-sans);\n}\n\n.item {\n flex: 1 1 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 2px;\n padding: 8px 4px;\n background: none;\n border: 0;\n cursor: pointer;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-2xs);\n transition: color var(--tempest-duration-fast, 120ms) var(--tempest-ease-out, ease-out);\n min-height: 56px;\n}\n\n.item:hover {\n color: var(--tempest-text);\n}\n\n.item.active {\n color: var(--tempest-primary);\n}\n\n.item:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.iconWrap {\n position: relative;\n display: inline-flex;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n font-size: 20px;\n}\n\n.badge {\n position: absolute;\n top: -4px;\n right: -8px;\n min-width: 14px;\n height: 14px;\n padding: 0 4px;\n border-radius: var(--tempest-radius-full);\n background: var(--tempest-danger-solid);\n color: var(--tempest-danger-on, #fff);\n font-size: 10px;\n line-height: 14px;\n text-align: center;\n font-weight: var(--tempest-weight-semibold);\n}\n\n.label {\n line-height: 1;\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"BottomNavigation.module.js","names":[],"sources":["../../../src/components/BottomNavigation/BottomNavigation.module.css"],"sourcesContent":[".bar {\n display: flex;\n width: 100%;\n background: var(--tempest-surface);\n border-top: 1px solid var(--tempest-border);\n padding-bottom: env(safe-area-inset-bottom, 0);\n font-family: var(--tempest-font-sans);\n}\n\n.item {\n flex: 1 1 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 2px;\n padding: 8px 4px;\n background: none;\n border: 0;\n cursor: pointer;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-2xs);\n transition: color var(--tempest-duration-fast, 120ms) var(--tempest-ease-out, ease-out);\n min-height: 56px;\n}\n\n.item:hover {\n color: var(--tempest-text);\n}\n\n.item.active {\n color: var(--tempest-primary);\n}\n\n.item:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.iconWrap {\n position: relative;\n display: inline-flex;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n font-size: 20px;\n}\n\n.badge {\n position: absolute;\n top: -4px;\n right: -8px;\n min-width: 14px;\n height: 14px;\n padding: 0 4px;\n border-radius: var(--tempest-radius-full);\n background: var(--tempest-danger-solid);\n color: var(--tempest-danger-on);\n font-size: 10px;\n line-height: 14px;\n text-align: center;\n font-weight: var(--tempest-weight-semibold);\n}\n\n.label {\n line-height: 1;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"BottomNavigation.module.js","names":[],"sources":["../../../src/components/BottomNavigation/BottomNavigation.module.css"],"sourcesContent":[".bar {\n display: flex;\n width: 100%;\n background: var(--tempest-surface);\n border-top: 1px solid var(--tempest-border);\n padding-bottom: env(safe-area-inset-bottom, 0);\n font-family: var(--tempest-font-sans);\n}\n\n.item {\n flex: 1 1 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 2px;\n padding: 8px 4px;\n background: none;\n border: 0;\n cursor: pointer;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-2xs);\n transition: color var(--tempest-duration-fast, 120ms) var(--tempest-ease-out, ease-out);\n min-height: 56px;\n}\n\n.item:hover {\n color: var(--tempest-text);\n}\n\n.item.active {\n color: var(--tempest-primary);\n}\n\n.item:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.iconWrap {\n position: relative;\n display: inline-flex;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n font-size: 20px;\n}\n\n.badge {\n position: absolute;\n top: -4px;\n right: -8px;\n min-width: 14px;\n height: 14px;\n padding: 0 4px;\n border-radius: var(--tempest-radius-full);\n background: var(--tempest-danger-solid);\n color: var(--tempest-danger-on, #fff);\n font-size: 10px;\n line-height: 14px;\n text-align: center;\n font-weight: var(--tempest-weight-semibold);\n}\n\n.label {\n line-height: 1;\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Carousel.module.cjs","names":[],"sources":["../../../src/components/Carousel/Carousel.module.css"],"sourcesContent":[".root {\n position: relative;\n width: 100%;\n font-family: var(--tempest-font-sans);\n}\n\n.root:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.viewport {\n overflow: hidden;\n border-radius: var(--tempest-radius-lg);\n}\n\n.track {\n display: flex;\n transition: transform var(--tempest-duration-normal) var(--tempest-ease-out);\n}\n\n.slide {\n flex: 0 0 100%;\n min-width: 0;\n}\n\n.arrow {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n background-color: var(--tempest-bg);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-full);\n box-shadow: var(--tempest-shadow-md);\n color: var(--tempest-text);\n font-size: var(--tempest-text-xl);\n line-height: 1;\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .arrow:hover:not(:disabled) {\n background-color: var(--tempest-surface);\n }\n}\n\n.arrow:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.arrow:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.prev {\n left: var(--tempest-space-2);\n}\n\n.next {\n right: var(--tempest-space-2);\n}\n\n.dots {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n margin-top: var(--tempest-space-3);\n}\n\n.dot {\n width: 0.5rem;\n height: 0.5rem;\n padding: 0;\n background-color: var(--tempest-border);\n border: none;\n border-radius: var(--tempest-radius-full);\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n.dotActive {\n background-color: var(--tempest-primary);\n}\n\n.dot:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .track {\n transition: none;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Carousel.module.cjs","names":[],"sources":["../../../src/components/Carousel/Carousel.module.css"],"sourcesContent":[".root {\n position: relative;\n width: 100%;\n font-family: var(--tempest-font-sans);\n}\n\n.root:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.viewport {\n overflow: hidden;\n border-radius: var(--tempest-radius-lg);\n}\n\n.track {\n display: flex;\n transition: transform var(--tempest-duration-base) var(--tempest-ease-out);\n}\n\n.slide {\n flex: 0 0 100%;\n min-width: 0;\n}\n\n.arrow {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n background-color: var(--tempest-bg);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-full);\n box-shadow: var(--tempest-shadow-md);\n color: var(--tempest-text);\n font-size: var(--tempest-text-xl);\n line-height: 1;\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .arrow:hover:not(:disabled) {\n background-color: var(--tempest-surface);\n }\n}\n\n.arrow:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.arrow:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.prev {\n left: var(--tempest-space-2);\n}\n\n.next {\n right: var(--tempest-space-2);\n}\n\n.dots {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n margin-top: var(--tempest-space-3);\n}\n\n.dot {\n width: 0.5rem;\n height: 0.5rem;\n padding: 0;\n background-color: var(--tempest-border);\n border: none;\n border-radius: var(--tempest-radius-full);\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n.dotActive {\n background-color: var(--tempest-primary);\n}\n\n.dot:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .track {\n transition: none;\n }\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Carousel.module.js","names":[],"sources":["../../../src/components/Carousel/Carousel.module.css"],"sourcesContent":[".root {\n position: relative;\n width: 100%;\n font-family: var(--tempest-font-sans);\n}\n\n.root:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.viewport {\n overflow: hidden;\n border-radius: var(--tempest-radius-lg);\n}\n\n.track {\n display: flex;\n transition: transform var(--tempest-duration-normal) var(--tempest-ease-out);\n}\n\n.slide {\n flex: 0 0 100%;\n min-width: 0;\n}\n\n.arrow {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n background-color: var(--tempest-bg);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-full);\n box-shadow: var(--tempest-shadow-md);\n color: var(--tempest-text);\n font-size: var(--tempest-text-xl);\n line-height: 1;\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .arrow:hover:not(:disabled) {\n background-color: var(--tempest-surface);\n }\n}\n\n.arrow:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.arrow:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.prev {\n left: var(--tempest-space-2);\n}\n\n.next {\n right: var(--tempest-space-2);\n}\n\n.dots {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n margin-top: var(--tempest-space-3);\n}\n\n.dot {\n width: 0.5rem;\n height: 0.5rem;\n padding: 0;\n background-color: var(--tempest-border);\n border: none;\n border-radius: var(--tempest-radius-full);\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n.dotActive {\n background-color: var(--tempest-primary);\n}\n\n.dot:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .track {\n transition: none;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Carousel.module.js","names":[],"sources":["../../../src/components/Carousel/Carousel.module.css"],"sourcesContent":[".root {\n position: relative;\n width: 100%;\n font-family: var(--tempest-font-sans);\n}\n\n.root:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.viewport {\n overflow: hidden;\n border-radius: var(--tempest-radius-lg);\n}\n\n.track {\n display: flex;\n transition: transform var(--tempest-duration-base) var(--tempest-ease-out);\n}\n\n.slide {\n flex: 0 0 100%;\n min-width: 0;\n}\n\n.arrow {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n background-color: var(--tempest-bg);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-full);\n box-shadow: var(--tempest-shadow-md);\n color: var(--tempest-text);\n font-size: var(--tempest-text-xl);\n line-height: 1;\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .arrow:hover:not(:disabled) {\n background-color: var(--tempest-surface);\n }\n}\n\n.arrow:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.arrow:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.prev {\n left: var(--tempest-space-2);\n}\n\n.next {\n right: var(--tempest-space-2);\n}\n\n.dots {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n margin-top: var(--tempest-space-3);\n}\n\n.dot {\n width: 0.5rem;\n height: 0.5rem;\n padding: 0;\n background-color: var(--tempest-border);\n border: none;\n border-radius: var(--tempest-radius-full);\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n.dotActive {\n background-color: var(--tempest-primary);\n}\n\n.dot:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .track {\n transition: none;\n }\n}\n"],"mappings":""}
@@ -0,0 +1,3 @@
1
+ const e=require("../../utils/cn.cjs"),t=require("../CopyButton/CopyButton.cjs"),n=require("./tokenize.cjs"),r=require("./CodeBlock.module.cjs");let i=require("react"),a=require("react/jsx-runtime");function o({code:o,language:s,filename:c,showLineNumbers:l=!1,highlightLines:u,copyable:d=!0,maxHeight:f,wrap:p=!1,label:m,className:h,...g}){let _=(0,i.useMemo)(()=>o.replace(/^\n+/,``).replace(/\s+$/,``),[o]),v=(0,i.useMemo)(()=>n.tokenizeLines(_,s),[_,s]),y=n.resolveLanguage(s),b=(0,i.useMemo)(()=>new Set(u??[]),[u]),x=m??(c&&typeof c==`string`?`Código: ${c}`:`Bloco de código${y===`plain`?``:` em ${y}`}`),S=!!c||d;return(0,a.jsxs)(`div`,{className:e.cn(r.default.wrapper,h),...g,children:[S&&(0,a.jsxs)(`div`,{className:r.default.header,children:[(0,a.jsx)(`span`,{className:r.default.filename,children:c??(y===`plain`?``:y)}),d&&(0,a.jsx)(t.CopyButton,{value:_,className:r.default.copy})]}),(0,a.jsx)(`pre`,{className:e.cn(r.default.pre,p&&r.default.wrap),style:{maxHeight:f},tabIndex:0,role:`group`,"aria-label":x,children:(0,a.jsx)(`code`,{className:r.default.code,"data-language":y,children:v.map((t,n)=>(0,a.jsxs)(i.Fragment,{children:[(0,a.jsxs)(`span`,{className:e.cn(r.default.line,b.has(n+1)&&r.default.marked),children:[l&&(0,a.jsx)(`span`,{className:r.default.lineNumber,"aria-hidden":`true`,children:n+1}),(0,a.jsx)(`span`,{className:r.default.lineContent,children:t.map((e,t)=>(0,a.jsx)(`span`,{className:r.default[e.kind],"data-token":e.kind,children:e.value},t))})]}),n<v.length-1?`
2
+ `:null]},n))})})]})}exports.CodeBlock=o;
3
+ //# sourceMappingURL=CodeBlock.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeBlock.cjs","names":[],"sources":["../../../src/components/CodeBlock/CodeBlock.tsx"],"sourcesContent":["import { Fragment, useMemo } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { CopyButton } from \"../CopyButton\";\nimport { resolveLanguage, tokenizeLines } from \"./tokenize\";\nimport styles from \"./CodeBlock.module.css\";\n\nexport interface CodeBlockProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The source to display. Leading and trailing blank lines are trimmed. */\n code: string;\n /** Grammar name or alias (`ts`, `bash`, `json`…). Unknown values render plain. */\n language?: string;\n /** Shown in the header, usually a file path. */\n filename?: ReactNode;\n /** Number the lines. Default `false`. */\n showLineNumbers?: boolean;\n /** 1-based line numbers to mark as the point of the snippet. */\n highlightLines?: readonly number[];\n /** Offer a copy button. Default `true`. */\n copyable?: boolean;\n /** Cap the height in px or any CSS length; the body scrolls past it. */\n maxHeight?: number | string;\n /** Wrap long lines instead of scrolling sideways. Default `false`. */\n wrap?: boolean;\n /**\n * Accessible name for the code region. Defaults to naming the language, and\n * to the filename when there is one.\n */\n label?: string;\n}\n\n/**\n * A read-only code sample: syntax colours, optional line numbers, copy button.\n *\n * The `<pre>` is always focusable. A code block is scrollable and holds nothing\n * focusable inside, so without a tab stop a keyboard user can see there is more\n * code past the edge and has no way to reach it. It is the one scroll container\n * where the stop is unconditional rather than measured — a code sample is\n * expected to be reachable, read and selected on its own.\n *\n * Colours come from an approximate scanner, not a parser — see {@link tokenize}.\n *\n * @example\n * <CodeBlock code={snippet} language=\"ts\" filename=\"src/main.ts\" showLineNumbers />\n * <CodeBlock code={log} language=\"bash\" maxHeight={280} />\n */\nexport function CodeBlock({\n code,\n language,\n filename,\n showLineNumbers = false,\n highlightLines,\n copyable = true,\n maxHeight,\n wrap = false,\n label,\n className,\n ...rest\n}: CodeBlockProps) {\n const trimmed = useMemo(() => code.replace(/^\\n+/, \"\").replace(/\\s+$/, \"\"), [code]);\n const lines = useMemo(() => tokenizeLines(trimmed, language), [trimmed, language]);\n const resolved = resolveLanguage(language);\n const marked = useMemo(() => new Set(highlightLines ?? []), [highlightLines]);\n\n const name =\n label ??\n (filename && typeof filename === \"string\"\n ? `Código: ${filename}`\n : `Bloco de código${resolved === \"plain\" ? \"\" : ` em ${resolved}`}`);\n\n const hasHeader = Boolean(filename) || copyable;\n\n return (\n <div className={cn(styles.wrapper, className)} {...rest}>\n {hasHeader && (\n <div className={styles.header}>\n <span className={styles.filename}>\n {filename ?? (resolved === \"plain\" ? \"\" : resolved)}\n </span>\n {copyable && <CopyButton value={trimmed} className={styles.copy} />}\n </div>\n )}\n\n <pre\n className={cn(styles.pre, wrap && styles.wrap)}\n style={{ maxHeight }}\n tabIndex={0}\n role=\"group\"\n aria-label={name}\n >\n <code className={styles.code} data-language={resolved}>\n {lines.map((tokens, index) => (\n <Fragment key={index}>\n <span\n className={cn(styles.line, marked.has(index + 1) && styles.marked)}\n >\n {showLineNumbers && (\n /*\n * The number is decoration: it must not land in the\n * clipboard when the reader selects the snippet, and a\n * screen reader announcing \"one const two import\" adds\n * nothing. `user-select: none` in CSS plus this.\n */\n <span className={styles.lineNumber} aria-hidden=\"true\">\n {index + 1}\n </span>\n )}\n <span className={styles.lineContent}>\n {tokens.map((token, tokenIndex) => (\n <span\n key={tokenIndex}\n className={styles[token.kind]}\n data-token={token.kind}\n >\n {token.value}\n </span>\n ))}\n </span>\n </span>\n {/*\n * A real newline character, and outside the line box.\n * It has to be real so that selecting the snippet by\n * hand and copying yields the source instead of one\n * run-together line. It has to be outside because the\n * line is an inline-block: a newline within one is\n * consumed inside that box, and every line ends up\n * side by side on a single row. The last one is\n * dropped so the block does not end in blank space.\n */}\n {index < lines.length - 1 ? \"\\n\" : null}\n </Fragment>\n ))}\n </code>\n </pre>\n </div>\n );\n}\n"],"mappings":"sMAgDA,SAAgB,EAAU,CACtB,OACA,WACA,WACA,kBAAkB,GAClB,iBACA,WAAW,GACX,YACA,OAAO,GACP,QACA,YACA,GAAG,GACY,CACf,IAAM,GAAA,EAAA,EAAA,QAAA,KAAwB,EAAK,QAAQ,OAAQ,EAAE,CAAC,CAAC,QAAQ,OAAQ,EAAE,EAAG,CAAC,CAAI,CAAC,EAC5E,GAAA,EAAA,EAAA,QAAA,KAAsB,EAAA,cAAc,EAAS,CAAQ,EAAG,CAAC,EAAS,CAAQ,CAAC,EAC3E,EAAW,EAAA,gBAAgB,CAAQ,EACnC,GAAA,EAAA,EAAA,QAAA,KAAuB,IAAI,IAAI,GAAkB,CAAC,CAAC,EAAG,CAAC,CAAc,CAAC,EAEtE,EACF,IACC,GAAY,OAAO,GAAa,SAC3B,WAAW,IACX,kBAAkB,IAAa,QAAU,GAAK,OAAO,OAEzD,EAAY,EAAQ,GAAa,EAEvC,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,EAAG,GAAI,WAAnD,CACK,IACG,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,gBAAvB,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,kBACnB,IAAa,IAAa,QAAU,GAAK,EACxC,CAAA,EACL,IAAY,EAAA,EAAA,IAAA,CAAC,EAAA,WAAD,CAAY,MAAO,EAAS,UAAW,EAAA,QAAO,IAAO,CAAA,CACjE,KAGT,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,IAAK,GAAQ,EAAA,QAAO,IAAI,EAC7C,MAAO,CAAE,WAAU,EACnB,SAAU,EACV,KAAK,QACL,aAAY,YAEZ,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,KAAM,gBAAe,WACxC,EAAM,KAAK,EAAQ,KAChB,EAAA,EAAA,KAAA,CAAC,EAAA,SAAD,CAAA,SAAA,EACI,EAAA,EAAA,KAAA,CAAC,OAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,EAAO,IAAI,EAAQ,CAAC,GAAK,EAAA,QAAO,MAAM,WADrE,CAGK,IAOG,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,WAAY,cAAY,gBAC3C,EAAQ,CACP,CAAA,GAEV,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,qBACnB,EAAO,KAAK,EAAO,KAChB,EAAA,EAAA,IAAA,CAAC,OAAD,CAEI,UAAW,EAAA,QAAO,EAAM,MACxB,aAAY,EAAM,cAEjB,EAAM,KACL,EALG,CAKH,CACT,CACC,CAAA,CACJ,IAWL,EAAQ,EAAM,OAAS,EAAI;EAAO,IAC7B,CAAA,EAtCK,CAsCL,CACb,CACC,CAAA,CACL,CAAA,CACJ,GAEb"}
@@ -0,0 +1,53 @@
1
+ import { cn as e } from "../../utils/cn.js";
2
+ import { CopyButton as t } from "../CopyButton/CopyButton.js";
3
+ import { resolveLanguage as n, tokenizeLines as r } from "./tokenize.js";
4
+ import i from "./CodeBlock.module.js";
5
+ import { Fragment as a, useMemo as o } from "react";
6
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
7
+ //#region src/components/CodeBlock/CodeBlock.tsx
8
+ function l({ code: l, language: u, filename: d, showLineNumbers: f = !1, highlightLines: p, copyable: m = !0, maxHeight: h, wrap: g = !1, label: _, className: v, ...y }) {
9
+ let b = o(() => l.replace(/^\n+/, "").replace(/\s+$/, ""), [l]), x = o(() => r(b, u), [b, u]), S = n(u), C = o(() => new Set(p ?? []), [p]), w = _ ?? (d && typeof d == "string" ? `Código: ${d}` : `Bloco de código${S === "plain" ? "" : ` em ${S}`}`), T = !!d || m;
10
+ return /* @__PURE__ */ c("div", {
11
+ className: e(i.wrapper, v),
12
+ ...y,
13
+ children: [T && /* @__PURE__ */ c("div", {
14
+ className: i.header,
15
+ children: [/* @__PURE__ */ s("span", {
16
+ className: i.filename,
17
+ children: d ?? (S === "plain" ? "" : S)
18
+ }), m && /* @__PURE__ */ s(t, {
19
+ value: b,
20
+ className: i.copy
21
+ })]
22
+ }), /* @__PURE__ */ s("pre", {
23
+ className: e(i.pre, g && i.wrap),
24
+ style: { maxHeight: h },
25
+ tabIndex: 0,
26
+ role: "group",
27
+ "aria-label": w,
28
+ children: /* @__PURE__ */ s("code", {
29
+ className: i.code,
30
+ "data-language": S,
31
+ children: x.map((t, n) => /* @__PURE__ */ c(a, { children: [/* @__PURE__ */ c("span", {
32
+ className: e(i.line, C.has(n + 1) && i.marked),
33
+ children: [f && /* @__PURE__ */ s("span", {
34
+ className: i.lineNumber,
35
+ "aria-hidden": "true",
36
+ children: n + 1
37
+ }), /* @__PURE__ */ s("span", {
38
+ className: i.lineContent,
39
+ children: t.map((e, t) => /* @__PURE__ */ s("span", {
40
+ className: i[e.kind],
41
+ "data-token": e.kind,
42
+ children: e.value
43
+ }, t))
44
+ })]
45
+ }), n < x.length - 1 ? "\n" : null] }, n))
46
+ })
47
+ })]
48
+ });
49
+ }
50
+ //#endregion
51
+ export { l as CodeBlock };
52
+
53
+ //# sourceMappingURL=CodeBlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeBlock.js","names":[],"sources":["../../../src/components/CodeBlock/CodeBlock.tsx"],"sourcesContent":["import { Fragment, useMemo } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { CopyButton } from \"../CopyButton\";\nimport { resolveLanguage, tokenizeLines } from \"./tokenize\";\nimport styles from \"./CodeBlock.module.css\";\n\nexport interface CodeBlockProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The source to display. Leading and trailing blank lines are trimmed. */\n code: string;\n /** Grammar name or alias (`ts`, `bash`, `json`…). Unknown values render plain. */\n language?: string;\n /** Shown in the header, usually a file path. */\n filename?: ReactNode;\n /** Number the lines. Default `false`. */\n showLineNumbers?: boolean;\n /** 1-based line numbers to mark as the point of the snippet. */\n highlightLines?: readonly number[];\n /** Offer a copy button. Default `true`. */\n copyable?: boolean;\n /** Cap the height in px or any CSS length; the body scrolls past it. */\n maxHeight?: number | string;\n /** Wrap long lines instead of scrolling sideways. Default `false`. */\n wrap?: boolean;\n /**\n * Accessible name for the code region. Defaults to naming the language, and\n * to the filename when there is one.\n */\n label?: string;\n}\n\n/**\n * A read-only code sample: syntax colours, optional line numbers, copy button.\n *\n * The `<pre>` is always focusable. A code block is scrollable and holds nothing\n * focusable inside, so without a tab stop a keyboard user can see there is more\n * code past the edge and has no way to reach it. It is the one scroll container\n * where the stop is unconditional rather than measured — a code sample is\n * expected to be reachable, read and selected on its own.\n *\n * Colours come from an approximate scanner, not a parser — see {@link tokenize}.\n *\n * @example\n * <CodeBlock code={snippet} language=\"ts\" filename=\"src/main.ts\" showLineNumbers />\n * <CodeBlock code={log} language=\"bash\" maxHeight={280} />\n */\nexport function CodeBlock({\n code,\n language,\n filename,\n showLineNumbers = false,\n highlightLines,\n copyable = true,\n maxHeight,\n wrap = false,\n label,\n className,\n ...rest\n}: CodeBlockProps) {\n const trimmed = useMemo(() => code.replace(/^\\n+/, \"\").replace(/\\s+$/, \"\"), [code]);\n const lines = useMemo(() => tokenizeLines(trimmed, language), [trimmed, language]);\n const resolved = resolveLanguage(language);\n const marked = useMemo(() => new Set(highlightLines ?? []), [highlightLines]);\n\n const name =\n label ??\n (filename && typeof filename === \"string\"\n ? `Código: ${filename}`\n : `Bloco de código${resolved === \"plain\" ? \"\" : ` em ${resolved}`}`);\n\n const hasHeader = Boolean(filename) || copyable;\n\n return (\n <div className={cn(styles.wrapper, className)} {...rest}>\n {hasHeader && (\n <div className={styles.header}>\n <span className={styles.filename}>\n {filename ?? (resolved === \"plain\" ? \"\" : resolved)}\n </span>\n {copyable && <CopyButton value={trimmed} className={styles.copy} />}\n </div>\n )}\n\n <pre\n className={cn(styles.pre, wrap && styles.wrap)}\n style={{ maxHeight }}\n tabIndex={0}\n role=\"group\"\n aria-label={name}\n >\n <code className={styles.code} data-language={resolved}>\n {lines.map((tokens, index) => (\n <Fragment key={index}>\n <span\n className={cn(styles.line, marked.has(index + 1) && styles.marked)}\n >\n {showLineNumbers && (\n /*\n * The number is decoration: it must not land in the\n * clipboard when the reader selects the snippet, and a\n * screen reader announcing \"one const two import\" adds\n * nothing. `user-select: none` in CSS plus this.\n */\n <span className={styles.lineNumber} aria-hidden=\"true\">\n {index + 1}\n </span>\n )}\n <span className={styles.lineContent}>\n {tokens.map((token, tokenIndex) => (\n <span\n key={tokenIndex}\n className={styles[token.kind]}\n data-token={token.kind}\n >\n {token.value}\n </span>\n ))}\n </span>\n </span>\n {/*\n * A real newline character, and outside the line box.\n * It has to be real so that selecting the snippet by\n * hand and copying yields the source instead of one\n * run-together line. It has to be outside because the\n * line is an inline-block: a newline within one is\n * consumed inside that box, and every line ends up\n * side by side on a single row. The last one is\n * dropped so the block does not end in blank space.\n */}\n {index < lines.length - 1 ? \"\\n\" : null}\n </Fragment>\n ))}\n </code>\n </pre>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAgDA,SAAgB,EAAU,EACtB,SACA,aACA,aACA,qBAAkB,IAClB,mBACA,cAAW,IACX,cACA,UAAO,IACP,UACA,cACA,GAAG,KACY;CACf,IAAM,IAAU,QAAc,EAAK,QAAQ,QAAQ,EAAE,CAAC,CAAC,QAAQ,QAAQ,EAAE,GAAG,CAAC,CAAI,CAAC,GAC5E,IAAQ,QAAc,EAAc,GAAS,CAAQ,GAAG,CAAC,GAAS,CAAQ,CAAC,GAC3E,IAAW,EAAgB,CAAQ,GACnC,IAAS,QAAc,IAAI,IAAI,KAAkB,CAAC,CAAC,GAAG,CAAC,CAAc,CAAC,GAEtE,IACF,MACC,KAAY,OAAO,KAAa,WAC3B,WAAW,MACX,kBAAkB,MAAa,UAAU,KAAK,OAAO,QAEzD,IAAY,EAAQ,KAAa;CAEvC,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,CAAS;EAAG,GAAI;YAAnD,CACK,KACG,kBAAC,OAAD;GAAK,WAAW,EAAO;aAAvB,CACI,kBAAC,QAAD;IAAM,WAAW,EAAO;cACnB,MAAa,MAAa,UAAU,KAAK;GACxC,CAAA,GACL,KAAY,kBAAC,GAAD;IAAY,OAAO;IAAS,WAAW,EAAO;GAAO,CAAA,CACjE;MAGT,kBAAC,OAAD;GACI,WAAW,EAAG,EAAO,KAAK,KAAQ,EAAO,IAAI;GAC7C,OAAO,EAAE,aAAU;GACnB,UAAU;GACV,MAAK;GACL,cAAY;aAEZ,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAM,iBAAe;cACxC,EAAM,KAAK,GAAQ,MAChB,kBAAC,GAAD,EAAA,UAAA,CACI,kBAAC,QAAD;KACI,WAAW,EAAG,EAAO,MAAM,EAAO,IAAI,IAAQ,CAAC,KAAK,EAAO,MAAM;eADrE,CAGK,KAOG,kBAAC,QAAD;MAAM,WAAW,EAAO;MAAY,eAAY;gBAC3C,IAAQ;KACP,CAAA,GAEV,kBAAC,QAAD;MAAM,WAAW,EAAO;gBACnB,EAAO,KAAK,GAAO,MAChB,kBAAC,QAAD;OAEI,WAAW,EAAO,EAAM;OACxB,cAAY,EAAM;iBAEjB,EAAM;MACL,GALG,CAKH,CACT;KACC,CAAA,CACJ;QAWL,IAAQ,EAAM,SAAS,IAAI,OAAO,IAC7B,EAAA,GAtCK,CAsCL,CACb;GACC,CAAA;EACL,CAAA,CACJ;;AAEb"}
@@ -0,0 +1,2 @@
1
+ var e=`tempest_wrapper_xdAwS`,t=`tempest_header_8LI5O`,n=`tempest_filename_IJaOa`,r=`tempest_copy_1sWYD`,i=`tempest_pre_1FhUD`,a=`tempest_code_LzjrW`,o=`tempest_wrap_ZMMcG`,s=`tempest_lineContent_pmXXV`,c=`tempest_line_oMdOA`,l=`tempest_marked_uYt-k`,u=`tempest_lineNumber_QnG-9`,d=`tempest_comment_SXwoI`,f=`tempest_string_KlC9t`,p=`tempest_number_xT7lt`,m=`tempest_keyword_PrsZ5`,h=`tempest_literal_7mCqM`,g=`tempest_tag_YF1kB`,_=`tempest_attribute_1O6-k`,v=`tempest_property_bLrIs`,y=`tempest_punctuation_teKJo`,b=`tempest_plain_KdCB1`,x={wrapper:e,header:t,filename:n,copy:r,pre:i,code:a,wrap:o,lineContent:s,line:c,marked:l,lineNumber:u,comment:d,string:f,number:p,keyword:m,literal:h,function:`tempest_function_c2AFf`,tag:g,attribute:_,property:v,punctuation:y,plain:b};exports.attribute=_,exports.code=a,exports.comment=d,exports.copy=r,exports.default=x,exports.filename=n,exports.header=t,exports.keyword=m,exports.line=c,exports.lineContent=s,exports.lineNumber=u,exports.literal=h,exports.marked=l,exports.number=p,exports.plain=b,exports.pre=i,exports.property=v,exports.punctuation=y,exports.string=f,exports.tag=g,exports.wrap=o,exports.wrapper=e;
2
+ //# sourceMappingURL=CodeBlock.module.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeBlock.module.cjs","names":[],"sources":["../../../src/components/CodeBlock/CodeBlock.module.css"],"sourcesContent":[".wrapper {\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n background-color: var(--tempest-surface);\n overflow: hidden;\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--tempest-space-2);\n padding: var(--tempest-space-2) var(--tempest-space-3);\n border-bottom: 1px solid var(--tempest-border);\n background-color: var(--tempest-bg);\n}\n\n.filename {\n font-family: var(--tempest-font-mono);\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.copy {\n flex-shrink: 0;\n}\n\n.pre {\n margin: 0;\n padding: var(--tempest-space-3) 0;\n overflow: auto;\n font-family: var(--tempest-font-mono);\n font-size: var(--tempest-text-sm);\n line-height: 1.6;\n tab-size: 4;\n}\n\n.pre:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: -2px;\n}\n\n.code {\n display: block;\n font: inherit;\n min-width: max-content;\n}\n\n.wrap .code {\n min-width: 0;\n}\n\n.wrap .lineContent {\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n/*\n * `inline-block` with a full-width box, not `flex`: the line break comes from\n * the real newline character inside the line, and a flex item would wrap on it\n * and render every line twice as tall. Full width is what lets the marked-line\n * background span the whole row rather than stopping at the last character.\n */\n.line {\n display: inline-block;\n width: 100%;\n padding-inline: var(--tempest-space-3);\n}\n\n/*\n * The marked line is called out with a left bar and a tinted ground rather than\n * a different text colour: the syntax colours already carry meaning, and\n * recolouring the text would collide with them.\n *\n * The tint is a thin wash of the primary rather than `--tempest-primary-soft`,\n * because it sits *behind text*. The soft token is a solid ground and moved the\n * effective background far enough to drop a keyword to 3.94:1 in dark mode —\n * the syntax colours are solved against the code surface, so the highlight has\n * to leave that surface roughly where it was. The bar carries the emphasis.\n */\n.marked {\n background-color: color-mix(in srgb, var(--tempest-primary) 10%, transparent);\n box-shadow: inset 2px 0 0 var(--tempest-primary);\n}\n\n/*\n * The gutter wears the comment colour, not `--tempest-text-subtle`: subtle is\n * tuned to recede against the page and measures 4.04:1 on the dark code\n * surface, which is below AA. The comment token recedes the same way and is\n * solved for that surface.\n */\n.lineNumber {\n display: inline-block;\n width: 2.5ch;\n margin-right: var(--tempest-space-3);\n text-align: right;\n color: var(--tempest-code-comment);\n user-select: none;\n}\n\n.lineContent {\n white-space: pre;\n}\n\n/*\n * Syntax colours come from their own `--tempest-code-*` tokens, not from the\n * chart ramp. The ramp is validated for marks, where the contrast floor is 3:1;\n * this is text and needs 4.5:1, and measuring the ramp as text fails in both\n * modes (a keyword came out at 3.47 on the dark surface, a string at 2.03 on\n * the light one). The code tokens are solved for that floor instead.\n */\n.comment {\n color: var(--tempest-code-comment);\n font-style: italic;\n}\n\n.string {\n color: var(--tempest-code-string);\n}\n\n.number {\n color: var(--tempest-code-number);\n}\n\n.keyword {\n color: var(--tempest-code-keyword);\n font-weight: 600;\n}\n\n.literal {\n color: var(--tempest-code-literal);\n}\n\n.function {\n color: var(--tempest-code-function);\n}\n\n.tag {\n color: var(--tempest-code-tag);\n}\n\n.attribute {\n color: var(--tempest-code-attribute);\n}\n\n.property {\n color: var(--tempest-code-property);\n}\n\n.punctuation {\n color: var(--tempest-code-punctuation);\n}\n\n.plain {\n color: var(--tempest-text);\n}\n"],"mappings":""}
@@ -0,0 +1,29 @@
1
+ //#region src/components/CodeBlock/CodeBlock.module.css
2
+ var e = "tempest_wrapper_xdAwS", t = "tempest_header_8LI5O", n = "tempest_filename_IJaOa", r = "tempest_copy_1sWYD", i = "tempest_pre_1FhUD", a = "tempest_code_LzjrW", o = "tempest_wrap_ZMMcG", s = "tempest_lineContent_pmXXV", c = "tempest_line_oMdOA", l = "tempest_marked_uYt-k", u = "tempest_lineNumber_QnG-9", d = "tempest_comment_SXwoI", f = "tempest_string_KlC9t", p = "tempest_number_xT7lt", m = "tempest_keyword_PrsZ5", h = "tempest_literal_7mCqM", g = "tempest_tag_YF1kB", _ = "tempest_attribute_1O6-k", v = "tempest_property_bLrIs", y = "tempest_punctuation_teKJo", b = "tempest_plain_KdCB1", x = {
3
+ wrapper: e,
4
+ header: t,
5
+ filename: n,
6
+ copy: r,
7
+ pre: i,
8
+ code: a,
9
+ wrap: o,
10
+ lineContent: s,
11
+ line: c,
12
+ marked: l,
13
+ lineNumber: u,
14
+ comment: d,
15
+ string: f,
16
+ number: p,
17
+ keyword: m,
18
+ literal: h,
19
+ function: "tempest_function_c2AFf",
20
+ tag: g,
21
+ attribute: _,
22
+ property: v,
23
+ punctuation: y,
24
+ plain: b
25
+ };
26
+ //#endregion
27
+ export { _ as attribute, a as code, d as comment, r as copy, x as default, n as filename, t as header, m as keyword, c as line, s as lineContent, u as lineNumber, h as literal, l as marked, p as number, b as plain, i as pre, v as property, y as punctuation, f as string, g as tag, o as wrap, e as wrapper };
28
+
29
+ //# sourceMappingURL=CodeBlock.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeBlock.module.js","names":[],"sources":["../../../src/components/CodeBlock/CodeBlock.module.css"],"sourcesContent":[".wrapper {\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n background-color: var(--tempest-surface);\n overflow: hidden;\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--tempest-space-2);\n padding: var(--tempest-space-2) var(--tempest-space-3);\n border-bottom: 1px solid var(--tempest-border);\n background-color: var(--tempest-bg);\n}\n\n.filename {\n font-family: var(--tempest-font-mono);\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.copy {\n flex-shrink: 0;\n}\n\n.pre {\n margin: 0;\n padding: var(--tempest-space-3) 0;\n overflow: auto;\n font-family: var(--tempest-font-mono);\n font-size: var(--tempest-text-sm);\n line-height: 1.6;\n tab-size: 4;\n}\n\n.pre:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: -2px;\n}\n\n.code {\n display: block;\n font: inherit;\n min-width: max-content;\n}\n\n.wrap .code {\n min-width: 0;\n}\n\n.wrap .lineContent {\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n/*\n * `inline-block` with a full-width box, not `flex`: the line break comes from\n * the real newline character inside the line, and a flex item would wrap on it\n * and render every line twice as tall. Full width is what lets the marked-line\n * background span the whole row rather than stopping at the last character.\n */\n.line {\n display: inline-block;\n width: 100%;\n padding-inline: var(--tempest-space-3);\n}\n\n/*\n * The marked line is called out with a left bar and a tinted ground rather than\n * a different text colour: the syntax colours already carry meaning, and\n * recolouring the text would collide with them.\n *\n * The tint is a thin wash of the primary rather than `--tempest-primary-soft`,\n * because it sits *behind text*. The soft token is a solid ground and moved the\n * effective background far enough to drop a keyword to 3.94:1 in dark mode —\n * the syntax colours are solved against the code surface, so the highlight has\n * to leave that surface roughly where it was. The bar carries the emphasis.\n */\n.marked {\n background-color: color-mix(in srgb, var(--tempest-primary) 10%, transparent);\n box-shadow: inset 2px 0 0 var(--tempest-primary);\n}\n\n/*\n * The gutter wears the comment colour, not `--tempest-text-subtle`: subtle is\n * tuned to recede against the page and measures 4.04:1 on the dark code\n * surface, which is below AA. The comment token recedes the same way and is\n * solved for that surface.\n */\n.lineNumber {\n display: inline-block;\n width: 2.5ch;\n margin-right: var(--tempest-space-3);\n text-align: right;\n color: var(--tempest-code-comment);\n user-select: none;\n}\n\n.lineContent {\n white-space: pre;\n}\n\n/*\n * Syntax colours come from their own `--tempest-code-*` tokens, not from the\n * chart ramp. The ramp is validated for marks, where the contrast floor is 3:1;\n * this is text and needs 4.5:1, and measuring the ramp as text fails in both\n * modes (a keyword came out at 3.47 on the dark surface, a string at 2.03 on\n * the light one). The code tokens are solved for that floor instead.\n */\n.comment {\n color: var(--tempest-code-comment);\n font-style: italic;\n}\n\n.string {\n color: var(--tempest-code-string);\n}\n\n.number {\n color: var(--tempest-code-number);\n}\n\n.keyword {\n color: var(--tempest-code-keyword);\n font-weight: 600;\n}\n\n.literal {\n color: var(--tempest-code-literal);\n}\n\n.function {\n color: var(--tempest-code-function);\n}\n\n.tag {\n color: var(--tempest-code-tag);\n}\n\n.attribute {\n color: var(--tempest-code-attribute);\n}\n\n.property {\n color: var(--tempest-code-property);\n}\n\n.punctuation {\n color: var(--tempest-code-punctuation);\n}\n\n.plain {\n color: var(--tempest-text);\n}\n"],"mappings":""}
@@ -0,0 +1,3 @@
1
+ var e={ts:`typescript`,typescript:`typescript`,js:`javascript`,javascript:`javascript`,mjs:`javascript`,cjs:`javascript`,tsx:`tsx`,jsx:`jsx`,json:`json`,jsonc:`json`,css:`css`,scss:`css`,html:`html`,xml:`html`,svg:`html`,sh:`bash`,bash:`bash`,shell:`bash`,zsh:`bash`,console:`bash`,py:`python`,python:`python`,sql:`sql`};function t(t){return t?e[t.toLowerCase()]??`plain`:`plain`}var n=`as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|keyof|let|new|of|private|protected|public|readonly|return|satisfies|set|static|super|switch|this|throw|try|type|typeof|var|void|while|with|yield`,r=`true|false|null|undefined|NaN|Infinity`,i={typescript:a(!1),javascript:a(!1),tsx:a(!0),jsx:a(!0),json:[{kind:`property`,pattern:/"(?:[^"\\]|\\.)*"(?=\s*:)/y},{kind:`string`,pattern:/"(?:[^"\\]|\\.)*"/y},{kind:`number`,pattern:/-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/y},{kind:`literal`,pattern:/\b(?:true|false|null)\b/y},{kind:`punctuation`,pattern:/[{}[\],:]/y}],css:[{kind:`comment`,pattern:/\/\*[\s\S]*?\*\//y},{kind:`string`,pattern:/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/y},{kind:`keyword`,pattern:/@[a-zA-Z-]+/y},{kind:`property`,pattern:/--?[a-zA-Z][\w-]*(?=\s*:)/y},{kind:`function`,pattern:/[a-zA-Z-]+(?=\()/y},{kind:`number`,pattern:/-?\d+(?:\.\d+)?(?:px|rem|em|%|s|ms|vh|vw|fr|deg)?/y},{kind:`punctuation`,pattern:/[{}();:,>+~]/y}],html:[{kind:`comment`,pattern:/<!--[\s\S]*?-->/y},{kind:`string`,pattern:/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/y},{kind:`tag`,pattern:/<\/?[a-zA-Z][\w:-]*/y},{kind:`attribute`,pattern:/[a-zA-Z][\w:-]*(?==)/y},{kind:`punctuation`,pattern:/\/?>|=/y}],bash:[{kind:`comment`,pattern:/#[^\n]*/y},{kind:`string`,pattern:/"(?:[^"\\]|\\.)*"|'[^']*'/y},{kind:`keyword`,pattern:/\b(?:if|then|else|elif|fi|for|while|do|done|case|esac|function|return|export|local|source|set|cd|echo)\b/y},{kind:`property`,pattern:/\$\{?[A-Za-z_][\w]*\}?/y},{kind:`attribute`,pattern:/(?<=\s)--?[a-zA-Z][\w-]*/y},{kind:`punctuation`,pattern:/[|&;()<>]/y}],python:[{kind:`comment`,pattern:/#[^\n]*/y},{kind:`string`,pattern:/"""[\s\S]*?"""|'''[\s\S]*?'''|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/y},{kind:`keyword`,pattern:/\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|raise|return|try|while|with|yield)\b/y},{kind:`literal`,pattern:/\b(?:True|False|None|self)\b/y},{kind:`number`,pattern:/\b\d+(?:\.\d+)?\b/y},{kind:`function`,pattern:/[A-Za-z_]\w*(?=\()/y},{kind:`punctuation`,pattern:/[{}[\]().,:;=+\-*/<>!]/y}],sql:[{kind:`comment`,pattern:/--[^\n]*|\/\*[\s\S]*?\*\//y},{kind:`string`,pattern:/'(?:[^']|'')*'/y},{kind:`keyword`,pattern:/\b(?:select|from|where|insert|into|values|update|set|delete|create|table|alter|drop|index|join|inner|left|right|outer|on|group|by|order|having|limit|offset|as|and|or|not|in|is|null|distinct|union|all|with|returning|primary|key|foreign|references|default)\b/iy},{kind:`number`,pattern:/\b\d+(?:\.\d+)?\b/y},{kind:`punctuation`,pattern:/[(),;*=<>]/y}],plain:[]};function a(e){let t=[{kind:`comment`,pattern:/\/\/[^\n]*|\/\*[\s\S]*?\*\//y},{kind:`string`,pattern:/`(?:[^`\\]|\\.)*`|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/y},{kind:`keyword`,pattern:RegExp(`\\b(?:${n})\\b`,`y`)},{kind:`literal`,pattern:RegExp(`\\b(?:${r})\\b`,`y`)},{kind:`number`,pattern:/\b(?:0[xX][\da-fA-F_]+|\d[\d_]*(?:\.[\d_]+)?(?:[eE][+-]?\d+)?)\b/y},{kind:`function`,pattern:/[A-Za-z_$][\w$]*(?=\s*\()/y},{kind:`punctuation`,pattern:/[{}[\]().,;:?!=<>+\-*/%&|^~]/y}];return e&&t.splice(2,0,{kind:`tag`,pattern:/<\/?[A-Za-z][\w.]*|\/>/y}),t}function o(e,n){let r=i[t(n)];if(r.length===0)return e===``?[]:[{kind:`plain`,value:e}];let a=[],o=0,s=0,c=t=>{t>o&&a.push({kind:`plain`,value:e.slice(o,t)})};for(;s<e.length;){let t=null;for(let n of r){n.pattern.lastIndex=s;let r=n.pattern.exec(e);if(r&&r[0].length>0){t={kind:n.kind,value:r[0]};break}}t?(c(s),a.push(t),s+=t.value.length,o=s):s++}return c(e.length),a}function s(e,t){let n=[[]];for(let r of o(e,t))r.value.split(`
2
+ `).forEach((e,t)=>{t>0&&n.push([]),e!==``&&n[n.length-1].push({kind:r.kind,value:e})});return n}exports.resolveLanguage=t,exports.tokenize=o,exports.tokenizeLines=s;
3
+ //# sourceMappingURL=tokenize.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenize.cjs","names":[],"sources":["../../../src/components/CodeBlock/tokenize.ts"],"sourcesContent":["/** What a token is painted as. */\nexport type TokenKind =\n | \"plain\"\n | \"comment\"\n | \"string\"\n | \"number\"\n | \"keyword\"\n | \"literal\"\n | \"function\"\n | \"punctuation\"\n | \"tag\"\n | \"attribute\"\n | \"property\";\n\nexport interface Token {\n kind: TokenKind;\n value: string;\n}\n\n/** Languages the tokenizer knows. Anything else renders as plain text. */\nexport type CodeLanguage =\n | \"typescript\"\n | \"javascript\"\n | \"tsx\"\n | \"jsx\"\n | \"json\"\n | \"css\"\n | \"html\"\n | \"bash\"\n | \"python\"\n | \"sql\"\n | \"plain\";\n\n/** Aliases people actually type, mapped onto the grammars above. */\nconst ALIASES: Record<string, CodeLanguage> = {\n ts: \"typescript\",\n typescript: \"typescript\",\n js: \"javascript\",\n javascript: \"javascript\",\n mjs: \"javascript\",\n cjs: \"javascript\",\n tsx: \"tsx\",\n jsx: \"jsx\",\n json: \"json\",\n jsonc: \"json\",\n css: \"css\",\n scss: \"css\",\n html: \"html\",\n xml: \"html\",\n svg: \"html\",\n sh: \"bash\",\n bash: \"bash\",\n shell: \"bash\",\n zsh: \"bash\",\n console: \"bash\",\n py: \"python\",\n python: \"python\",\n sql: \"sql\",\n};\n\n/**\n * Normalise a language name onto a known grammar.\n *\n * @param language - Whatever the caller passed, e.g. `\"ts\"` or `\"Shell\"`.\n * @returns The grammar to use; `\"plain\"` when there is no match.\n */\nexport function resolveLanguage(language: string | undefined): CodeLanguage {\n if (!language) return \"plain\";\n return ALIASES[language.toLowerCase()] ?? \"plain\";\n}\n\n/** One grammar rule: a sticky pattern and the kind it produces. */\ninterface Rule {\n kind: TokenKind;\n pattern: RegExp;\n}\n\nconst JS_KEYWORDS =\n \"as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|keyof|let|new|of|private|protected|public|readonly|return|satisfies|set|static|super|switch|this|throw|try|type|typeof|var|void|while|with|yield\";\n\nconst JS_LITERALS = \"true|false|null|undefined|NaN|Infinity\";\n\n/**\n * Rules per grammar, tried in order at each position.\n *\n * Order carries meaning: comments and strings come first so a keyword inside a\n * string stays a string. Every pattern is sticky (`y`) and anchored by\n * `lastIndex`, so a rule can only match where the scanner currently stands.\n */\nconst GRAMMARS: Record<CodeLanguage, Rule[]> = {\n typescript: jsRules(false),\n javascript: jsRules(false),\n tsx: jsRules(true),\n jsx: jsRules(true),\n json: [\n { kind: \"property\", pattern: /\"(?:[^\"\\\\]|\\\\.)*\"(?=\\s*:)/y },\n { kind: \"string\", pattern: /\"(?:[^\"\\\\]|\\\\.)*\"/y },\n { kind: \"number\", pattern: /-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?/y },\n { kind: \"literal\", pattern: /\\b(?:true|false|null)\\b/y },\n { kind: \"punctuation\", pattern: /[{}[\\],:]/y },\n ],\n css: [\n { kind: \"comment\", pattern: /\\/\\*[\\s\\S]*?\\*\\//y },\n { kind: \"string\", pattern: /\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'/y },\n { kind: \"keyword\", pattern: /@[a-zA-Z-]+/y },\n { kind: \"property\", pattern: /--?[a-zA-Z][\\w-]*(?=\\s*:)/y },\n { kind: \"function\", pattern: /[a-zA-Z-]+(?=\\()/y },\n { kind: \"number\", pattern: /-?\\d+(?:\\.\\d+)?(?:px|rem|em|%|s|ms|vh|vw|fr|deg)?/y },\n { kind: \"punctuation\", pattern: /[{}();:,>+~]/y },\n ],\n html: [\n { kind: \"comment\", pattern: /<!--[\\s\\S]*?-->/y },\n { kind: \"string\", pattern: /\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'/y },\n { kind: \"tag\", pattern: /<\\/?[a-zA-Z][\\w:-]*/y },\n { kind: \"attribute\", pattern: /[a-zA-Z][\\w:-]*(?==)/y },\n { kind: \"punctuation\", pattern: /\\/?>|=/y },\n ],\n bash: [\n { kind: \"comment\", pattern: /#[^\\n]*/y },\n { kind: \"string\", pattern: /\"(?:[^\"\\\\]|\\\\.)*\"|'[^']*'/y },\n {\n kind: \"keyword\",\n pattern:\n /\\b(?:if|then|else|elif|fi|for|while|do|done|case|esac|function|return|export|local|source|set|cd|echo)\\b/y,\n },\n { kind: \"property\", pattern: /\\$\\{?[A-Za-z_][\\w]*\\}?/y },\n { kind: \"attribute\", pattern: /(?<=\\s)--?[a-zA-Z][\\w-]*/y },\n { kind: \"punctuation\", pattern: /[|&;()<>]/y },\n ],\n python: [\n { kind: \"comment\", pattern: /#[^\\n]*/y },\n {\n kind: \"string\",\n pattern: /\"\"\"[\\s\\S]*?\"\"\"|'''[\\s\\S]*?'''|\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'/y,\n },\n {\n kind: \"keyword\",\n pattern:\n /\\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|raise|return|try|while|with|yield)\\b/y,\n },\n { kind: \"literal\", pattern: /\\b(?:True|False|None|self)\\b/y },\n { kind: \"number\", pattern: /\\b\\d+(?:\\.\\d+)?\\b/y },\n { kind: \"function\", pattern: /[A-Za-z_]\\w*(?=\\()/y },\n { kind: \"punctuation\", pattern: /[{}[\\]().,:;=+\\-*/<>!]/y },\n ],\n sql: [\n { kind: \"comment\", pattern: /--[^\\n]*|\\/\\*[\\s\\S]*?\\*\\//y },\n { kind: \"string\", pattern: /'(?:[^']|'')*'/y },\n {\n kind: \"keyword\",\n // Case-insensitive: SQL is written both ways and both should paint.\n pattern:\n /\\b(?:select|from|where|insert|into|values|update|set|delete|create|table|alter|drop|index|join|inner|left|right|outer|on|group|by|order|having|limit|offset|as|and|or|not|in|is|null|distinct|union|all|with|returning|primary|key|foreign|references|default)\\b/iy,\n },\n { kind: \"number\", pattern: /\\b\\d+(?:\\.\\d+)?\\b/y },\n { kind: \"punctuation\", pattern: /[(),;*=<>]/y },\n ],\n plain: [],\n};\n\n/** The shared JavaScript-family rules, with JSX tags added for tsx/jsx. */\nfunction jsRules(withJsx: boolean): Rule[] {\n const rules: Rule[] = [\n { kind: \"comment\", pattern: /\\/\\/[^\\n]*|\\/\\*[\\s\\S]*?\\*\\//y },\n {\n kind: \"string\",\n pattern: /`(?:[^`\\\\]|\\\\.)*`|\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'/y,\n },\n { kind: \"keyword\", pattern: new RegExp(`\\\\b(?:${JS_KEYWORDS})\\\\b`, \"y\") },\n { kind: \"literal\", pattern: new RegExp(`\\\\b(?:${JS_LITERALS})\\\\b`, \"y\") },\n {\n kind: \"number\",\n pattern: /\\b(?:0[xX][\\da-fA-F_]+|\\d[\\d_]*(?:\\.[\\d_]+)?(?:[eE][+-]?\\d+)?)\\b/y,\n },\n { kind: \"function\", pattern: /[A-Za-z_$][\\w$]*(?=\\s*\\()/y },\n { kind: \"punctuation\", pattern: /[{}[\\]().,;:?!=<>+\\-*/%&|^~]/y },\n ];\n if (withJsx) {\n // Before the keyword rule, so `<Button` reads as a tag and not as `<`.\n rules.splice(2, 0, { kind: \"tag\", pattern: /<\\/?[A-Za-z][\\w.]*|\\/>/y });\n }\n return rules;\n}\n\n/**\n * Split source into coloured tokens.\n *\n * This is a **scanner, not a parser**: it recognises comments, strings, numbers,\n * keywords and punctuation by pattern, and knows nothing about scope, types or\n * grammar. That is a deliberate ceiling. A real parser per language is a\n * dependency the size of the rest of the SDK, and the payoff — being right about\n * the corner cases in a documentation snippet — is small. Where it is unsure it\n * emits `plain`, which renders as ordinary text rather than as something wrong.\n *\n * Unknown languages produce a single `plain` token, so an unhighlighted block is\n * a normal outcome and never an error.\n *\n * @param code - The source.\n * @param language - Grammar name or alias.\n * @returns Tokens covering the input exactly, in order.\n *\n * @example\n * tokenize(\"const x = 1;\", \"ts\");\n * // [{kind: \"keyword\", value: \"const\"}, {kind: \"plain\", value: \" x \"}, …]\n */\nexport function tokenize(code: string, language: string | undefined): Token[] {\n const rules = GRAMMARS[resolveLanguage(language)];\n if (rules.length === 0) return code === \"\" ? [] : [{ kind: \"plain\", value: code }];\n\n const tokens: Token[] = [];\n let plainFrom = 0;\n let at = 0;\n\n const flushPlain = (until: number) => {\n if (until > plainFrom) tokens.push({ kind: \"plain\", value: code.slice(plainFrom, until) });\n };\n\n while (at < code.length) {\n let matched: Token | null = null;\n for (const rule of rules) {\n rule.pattern.lastIndex = at;\n const found = rule.pattern.exec(code);\n if (found && found[0].length > 0) {\n matched = { kind: rule.kind, value: found[0] };\n break;\n }\n }\n if (matched) {\n flushPlain(at);\n tokens.push(matched);\n at += matched.value.length;\n plainFrom = at;\n } else {\n at++;\n }\n }\n flushPlain(code.length);\n return tokens;\n}\n\n/**\n * The same tokens, split at newlines so each line can be rendered on its own.\n *\n * Line numbers and highlighted lines both need a per-line structure, and a token\n * is free to span a line break — a block comment usually does. Splitting here\n * keeps that out of the component.\n *\n * @param code - The source.\n * @param language - Grammar name or alias.\n * @returns One token array per line. Always at least one line.\n */\nexport function tokenizeLines(code: string, language: string | undefined): Token[][] {\n const lines: Token[][] = [[]];\n for (const token of tokenize(code, language)) {\n const pieces = token.value.split(\"\\n\");\n pieces.forEach((piece, index) => {\n if (index > 0) lines.push([]);\n if (piece !== \"\") lines[lines.length - 1].push({ kind: token.kind, value: piece });\n });\n }\n return lines;\n}\n"],"mappings":"AAkCA,IAAM,EAAwC,CAC1C,GAAI,aACJ,WAAY,aACZ,GAAI,aACJ,WAAY,aACZ,IAAK,aACL,IAAK,aACL,IAAK,MACL,IAAK,MACL,KAAM,OACN,MAAO,OACP,IAAK,MACL,KAAM,MACN,KAAM,OACN,IAAK,OACL,IAAK,OACL,GAAI,OACJ,KAAM,OACN,MAAO,OACP,IAAK,OACL,QAAS,OACT,GAAI,SACJ,OAAQ,SACR,IAAK,KACT,EAQA,SAAgB,EAAgB,EAA4C,CAExE,OADK,EACE,EAAQ,EAAS,YAAY,IAAM,QADpB,OAE1B,CAQA,IAAM,EACF,uUAEE,EAAc,yCASd,EAAyC,CAC3C,WAAY,EAAQ,EAAK,EACzB,WAAY,EAAQ,EAAK,EACzB,IAAK,EAAQ,EAAI,EACjB,IAAK,EAAQ,EAAI,EACjB,KAAM,CACF,CAAE,KAAM,WAAY,QAAS,4BAA6B,EAC1D,CAAE,KAAM,SAAU,QAAS,oBAAqB,EAChD,CAAE,KAAM,SAAU,QAAS,mCAAoC,EAC/D,CAAE,KAAM,UAAW,QAAS,0BAA2B,EACvD,CAAE,KAAM,cAAe,QAAS,YAAa,CACjD,EACA,IAAK,CACD,CAAE,KAAM,UAAW,QAAS,mBAAoB,EAChD,CAAE,KAAM,SAAU,QAAS,sCAAuC,EAClE,CAAE,KAAM,UAAW,QAAS,cAAe,EAC3C,CAAE,KAAM,WAAY,QAAS,4BAA6B,EAC1D,CAAE,KAAM,WAAY,QAAS,mBAAoB,EACjD,CAAE,KAAM,SAAU,QAAS,oDAAqD,EAChF,CAAE,KAAM,cAAe,QAAS,eAAgB,CACpD,EACA,KAAM,CACF,CAAE,KAAM,UAAW,QAAS,kBAAmB,EAC/C,CAAE,KAAM,SAAU,QAAS,sCAAuC,EAClE,CAAE,KAAM,MAAO,QAAS,sBAAuB,EAC/C,CAAE,KAAM,YAAa,QAAS,uBAAwB,EACtD,CAAE,KAAM,cAAe,QAAS,SAAU,CAC9C,EACA,KAAM,CACF,CAAE,KAAM,UAAW,QAAS,UAAW,EACvC,CAAE,KAAM,SAAU,QAAS,4BAA6B,EACxD,CACI,KAAM,UACN,QACI,2GACR,EACA,CAAE,KAAM,WAAY,QAAS,yBAA0B,EACvD,CAAE,KAAM,YAAa,QAAS,2BAA4B,EAC1D,CAAE,KAAM,cAAe,QAAS,YAAa,CACjD,EACA,OAAQ,CACJ,CAAE,KAAM,UAAW,QAAS,UAAW,EACvC,CACI,KAAM,SACN,QAAS,oEACb,EACA,CACI,KAAM,UACN,QACI,wLACR,EACA,CAAE,KAAM,UAAW,QAAS,+BAAgC,EAC5D,CAAE,KAAM,SAAU,QAAS,oBAAqB,EAChD,CAAE,KAAM,WAAY,QAAS,qBAAsB,EACnD,CAAE,KAAM,cAAe,QAAS,yBAA0B,CAC9D,EACA,IAAK,CACD,CAAE,KAAM,UAAW,QAAS,4BAA6B,EACzD,CAAE,KAAM,SAAU,QAAS,iBAAkB,EAC7C,CACI,KAAM,UAEN,QACI,oQACR,EACA,CAAE,KAAM,SAAU,QAAS,oBAAqB,EAChD,CAAE,KAAM,cAAe,QAAS,aAAc,CAClD,EACA,MAAO,CAAC,CACZ,EAGA,SAAS,EAAQ,EAA0B,CACvC,IAAM,EAAgB,CAClB,CAAE,KAAM,UAAW,QAAS,8BAA+B,EAC3D,CACI,KAAM,SACN,QAAS,wDACb,EACA,CAAE,KAAM,UAAW,QAAa,OAAO,SAAS,EAAY,MAAO,GAAG,CAAE,EACxE,CAAE,KAAM,UAAW,QAAa,OAAO,SAAS,EAAY,MAAO,GAAG,CAAE,EACxE,CACI,KAAM,SACN,QAAS,mEACb,EACA,CAAE,KAAM,WAAY,QAAS,4BAA6B,EAC1D,CAAE,KAAM,cAAe,QAAS,+BAAgC,CACpE,EAKA,OAJI,GAEA,EAAM,OAAO,EAAG,EAAG,CAAE,KAAM,MAAO,QAAS,yBAA0B,CAAC,EAEnE,CACX,CAuBA,SAAgB,EAAS,EAAc,EAAuC,CAC1E,IAAM,EAAQ,EAAS,EAAgB,CAAQ,GAC/C,GAAI,EAAM,SAAW,EAAG,OAAO,IAAS,GAAK,CAAC,EAAI,CAAC,CAAE,KAAM,QAAS,MAAO,CAAK,CAAC,EAEjF,IAAM,EAAkB,CAAC,EACrB,EAAY,EACZ,EAAK,EAEH,EAAc,GAAkB,CAC9B,EAAQ,GAAW,EAAO,KAAK,CAAE,KAAM,QAAS,MAAO,EAAK,MAAM,EAAW,CAAK,CAAE,CAAC,CAC7F,EAEA,KAAO,EAAK,EAAK,QAAQ,CACrB,IAAI,EAAwB,KAC5B,IAAK,IAAM,KAAQ,EAAO,CACtB,EAAK,QAAQ,UAAY,EACzB,IAAM,EAAQ,EAAK,QAAQ,KAAK,CAAI,EACpC,GAAI,GAAS,EAAM,EAAE,CAAC,OAAS,EAAG,CAC9B,EAAU,CAAE,KAAM,EAAK,KAAM,MAAO,EAAM,EAAG,EAC7C,KACJ,CACJ,CACI,GACA,EAAW,CAAE,EACb,EAAO,KAAK,CAAO,EACnB,GAAM,EAAQ,MAAM,OACpB,EAAY,GAEZ,GAER,CAEA,OADA,EAAW,EAAK,MAAM,EACf,CACX,CAaA,SAAgB,EAAc,EAAc,EAAyC,CACjF,IAAM,EAAmB,CAAC,CAAC,CAAC,EAC5B,IAAK,IAAM,KAAS,EAAS,EAAM,CAAQ,EAEvC,EADqB,MAAM,MAAM;CACjC,CAAA,CAAO,SAAS,EAAO,IAAU,CACzB,EAAQ,GAAG,EAAM,KAAK,CAAC,CAAC,EACxB,IAAU,IAAI,EAAM,EAAM,OAAS,EAAE,CAAC,KAAK,CAAE,KAAM,EAAM,KAAM,MAAO,CAAM,CAAC,CACrF,CAAC,EAEL,OAAO,CACX"}