@silverpoint/core 0.6.0 → 0.8.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 (46) hide show
  1. package/README.md +14 -0
  2. package/dist/catalog.d.ts +2 -2
  3. package/dist/catalog.js +4 -2
  4. package/dist/catalog.js.map +1 -1
  5. package/dist/{chunk-OLYKR5PS.js → chunk-46QELMCG.js} +8 -213
  6. package/dist/chunk-46QELMCG.js.map +1 -0
  7. package/dist/chunk-5MP3BLZK.js +48 -0
  8. package/dist/chunk-5MP3BLZK.js.map +1 -0
  9. package/dist/chunk-6YFO7OP3.js +84 -0
  10. package/dist/chunk-6YFO7OP3.js.map +1 -0
  11. package/dist/chunk-ANJSW5JX.js +93 -0
  12. package/dist/chunk-ANJSW5JX.js.map +1 -0
  13. package/dist/{chunk-PD4MD7JU.js → chunk-E5CC2NNQ.js} +5 -3
  14. package/dist/chunk-E5CC2NNQ.js.map +1 -0
  15. package/dist/chunk-G7N4X5XD.js +12 -0
  16. package/dist/chunk-G7N4X5XD.js.map +1 -0
  17. package/dist/chunk-NI7B6UEO.js +24 -0
  18. package/dist/chunk-NI7B6UEO.js.map +1 -0
  19. package/dist/chunk-WYFRHI4S.js +179 -0
  20. package/dist/chunk-WYFRHI4S.js.map +1 -0
  21. package/dist/contrast-siWF_R5o.d.ts +30 -0
  22. package/dist/dashboard-demos.d.ts +2 -2
  23. package/dist/index.d.ts +13 -10
  24. package/dist/index.js +20 -9
  25. package/dist/index.js.map +1 -1
  26. package/dist/{model-CLhtoG75.d.ts → model-DVVt59AB.d.ts} +1 -1
  27. package/dist/palettes.d.ts +29 -0
  28. package/dist/palettes.js +79 -0
  29. package/dist/palettes.js.map +1 -0
  30. package/dist/{props-Dq8FC8GG.d.ts → props-BZ9CcrGv.d.ts} +53 -1
  31. package/dist/timeline.d.ts +90 -0
  32. package/dist/timeline.js +125 -0
  33. package/dist/timeline.js.map +1 -0
  34. package/dist/{types-B81k-s9_.d.ts → types-BT3Xm7fP.d.ts} +3 -1
  35. package/dist/types-D5ys35fF.d.ts +576 -0
  36. package/dist/types-DHBJ0PzV.d.ts +57 -0
  37. package/dist/ui-demos.d.ts +14 -3
  38. package/dist/ui-demos.js +163 -1
  39. package/dist/ui-demos.js.map +1 -1
  40. package/dist/ui.d.ts +346 -325
  41. package/dist/ui.js +932 -118
  42. package/dist/ui.js.map +1 -1
  43. package/dist/view-DteS9glE.d.ts +82 -0
  44. package/package.json +13 -1
  45. package/dist/chunk-OLYKR5PS.js.map +0 -1
  46. package/dist/chunk-PD4MD7JU.js.map +0 -1
@@ -1,50 +1,6 @@
1
+ import { diagnose } from './chunk-WYFRHI4S.js';
1
2
  import { scaleLinear, scaleBand } from 'd3-scale';
2
3
 
3
- // src/render/round.ts
4
- function round2(value) {
5
- const rounded = Math.round(value * 100) / 100;
6
- return Object.is(rounded, -0) ? 0 : rounded;
7
- }
8
- var NUMBER = /-?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?/g;
9
- function roundPathData(d) {
10
- return d.replace(NUMBER, (token) => String(round2(Number(token))));
11
- }
12
- function roundRect(rect) {
13
- return {
14
- x: round2(rect.x),
15
- y: round2(rect.y),
16
- width: round2(rect.width),
17
- height: round2(rect.height)
18
- };
19
- }
20
- function roundStroke(stroke) {
21
- return { ...stroke, d: roundPathData(stroke.d) };
22
- }
23
- function roundTile(tile) {
24
- return {
25
- ...tile,
26
- width: round2(tile.width),
27
- height: round2(tile.height),
28
- angle: round2(tile.angle),
29
- strokes: tile.strokes.map(roundStroke)
30
- };
31
- }
32
- function roundGeometry(geometry) {
33
- return {
34
- viewBox: roundRect(geometry.viewBox),
35
- plot: roundRect(geometry.plot),
36
- strokes: geometry.strokes.map(roundStroke),
37
- labels: geometry.labels.map((label) => ({ ...label, x: round2(label.x), y: round2(label.y) })),
38
- hitAreas: geometry.hitAreas.map((hit) => ({
39
- ...hit,
40
- x: round2(hit.x),
41
- y: round2(hit.y),
42
- ...hit.box ? { box: roundRect(hit.box) } : {}
43
- })),
44
- defs: geometry.defs.map(roundTile)
45
- };
46
- }
47
-
48
4
  // src/render/seed.ts
49
5
  var FNV_OFFSET_BASIS = 2166136261;
50
6
  var FNV_PRIME = 16777619;
@@ -86,167 +42,6 @@ function resolveSeed(seed, id) {
86
42
  return Number.isFinite(seed) ? Math.trunc(seed) >>> 0 : 0;
87
43
  }
88
44
 
89
- // src/diagnostics/diagnose.ts
90
- var SilverpointError = class extends Error {
91
- code;
92
- constructor(code, message) {
93
- super(message);
94
- this.name = "SilverpointError";
95
- this.code = code;
96
- }
97
- };
98
- var consoleSink = (_code, message) => {
99
- console.warn(message);
100
- };
101
- var sink = consoleSink;
102
- var reported = /* @__PURE__ */ new Set();
103
- function __setDiagnosticSink(next) {
104
- sink = next ?? consoleSink;
105
- reported.clear();
106
- return () => {
107
- sink = consoleSink;
108
- reported.clear();
109
- };
110
- }
111
- function format(code, chart, detail, template) {
112
- const specifics = detail.message ? ` ${detail.message}` : "";
113
- return `[${code}] ${chart}: ${template.what} (\`${detail.property}\`).${specifics} ${template.todo}. (${template.req})`;
114
- }
115
- var ERRORS = {
116
- SP009: {
117
- req: "REQ-097",
118
- what: "a scale bound cannot be derived from the data and was not supplied",
119
- todo: "Pass the named property explicitly"
120
- },
121
- SP012: {
122
- req: "REQ-127",
123
- what: "the ground does not reach the minimum contrast",
124
- todo: "Recompute the palette; colours are not chosen by eye"
125
- }
126
- };
127
- function diagnose(code, chart, detail) {
128
- const error = ERRORS[code];
129
- if (error) {
130
- throw new SilverpointError(code, format(code, chart, detail, error));
131
- }
132
- if (process.env.NODE_ENV !== "production") {
133
- developmentDiagnose(code, chart, detail);
134
- }
135
- }
136
- function developmentDiagnose(code, chart, detail) {
137
- const template = WARNINGS[code];
138
- if (!template) return;
139
- const message = format(code, chart, detail, template);
140
- if (code === "SP005") {
141
- throw new SilverpointError(code, message);
142
- }
143
- if (reported.has(message)) return;
144
- reported.add(message);
145
- sink(code, message);
146
- }
147
- var WARNINGS = {
148
- SP001: {
149
- req: "REQ-007",
150
- what: "the dataset is empty; the ground's empty state is drawn",
151
- todo: "Pass at least one row, or omit `data` to see the demo dataset"
152
- },
153
- SP002: {
154
- req: "REQ-008",
155
- what: "a value cannot be drawn as given (null, not finite, or outside the data contract); it is corrected or omitted",
156
- todo: "Check the value against the chart's data contract (Data Model \xA72)"
157
- },
158
- SP003: {
159
- req: "REQ-009",
160
- what: "the container measures 0 px; the render is deferred",
161
- todo: "Give the container a size, or pin `width` and `height`"
162
- },
163
- SP004: {
164
- req: "REQ-010",
165
- what: "the scale domain has zero length; it is expanded with the ground's domainPadding",
166
- todo: "Nothing to do if the data is constant; otherwise check the accessor"
167
- },
168
- SP005: {
169
- req: "REQ-025",
170
- what: "more than one element is marked with white heightening; only the first is applied",
171
- todo: "Heighten a single element per chart"
172
- },
173
- SP006: {
174
- req: "REQ-026",
175
- what: "the inker is not registered; falling back to NullInker",
176
- todo: "Register the inker or fix the ground's `inker` token"
177
- },
178
- SP007: {
179
- req: "REQ-045",
180
- what: "the ground is not registered; falling back to silverpoint",
181
- todo: "Call registerGround() before rendering, or fix the name"
182
- },
183
- SP008: {
184
- req: "REQ-096",
185
- what: "the data volume is above the family's threshold",
186
- todo: "Aggregate the data before charting it"
187
- },
188
- SP010: {
189
- req: "REQ-091",
190
- what: "the chord ring has more than 12 categories",
191
- todo: "Group the smaller categories"
192
- },
193
- SP011: {
194
- req: "NFR \xA77",
195
- what: "the path byte budget of 40 KB is exceeded",
196
- todo: "Use `hatchFill: 'tile'` or a larger hatch gap"
197
- },
198
- SP014: {
199
- req: "REQ-204",
200
- what: "a dashboard cell spans more columns than the breakpoint has; it is clamped",
201
- todo: "Lower the span, or give that breakpoint more columns"
202
- },
203
- SP015: {
204
- req: "REQ-205",
205
- what: "the dashboard layout and its children disagree; unmatched children are placed in source order, span 1",
206
- todo: "Give every child a `cell` the layout declares, once"
207
- },
208
- SP016: {
209
- req: "REQ-217",
210
- what: "a chart in a linked dashboard has no field named by `link.key`; it shows no linked mark",
211
- todo: "Link on a field every linked chart carries, or leave this chart out of the link"
212
- },
213
- SP017: {
214
- req: "REQ-324",
215
- what: "a value or a range cannot be drawn as given; it is clamped, rounded to its step or defaulted",
216
- todo: "Keep the value within `min`..`max` and on `step`, with `min < max` and `step > 0`"
217
- },
218
- SP018: {
219
- req: "REQ-319",
220
- what: "the component has no accessible name: no text content and no `label`",
221
- todo: "Give it visible text, or a `label` for an icon-only control"
222
- },
223
- SP019: {
224
- req: "REQ-325",
225
- what: "items share a key, or have none; the first is kept and the later ones are skipped",
226
- todo: "Give every item a unique, non-empty `key`"
227
- },
228
- SP020: {
229
- req: "REQ-437",
230
- what: "the hierarchy is invalid (a duplicate or empty `id`, a missing `parent`, a cycle, or several roots); the offending rows are dropped",
231
- todo: "Give every row a unique `id` and an existing `parent`, under a single root"
232
- },
233
- SP021: {
234
- req: "REQ-433",
235
- what: "a statistic parameter is invalid; its default is used",
236
- todo: "Keep the parameter in its documented range"
237
- },
238
- SP022: {
239
- req: "REQ-434",
240
- what: "a group has too few observations for its statistic; they are drawn as points",
241
- todo: "Give the group more observations, or expect it drawn as points"
242
- },
243
- SP013: {
244
- req: "REQ-032",
245
- what: "the @silverpoint/fonts face failed to load; rendering fell back to the system stack",
246
- todo: "Install @silverpoint/fonts and import its stylesheet; golden images will not match until then"
247
- }
248
- };
249
-
250
45
  // src/scales/util.ts
251
46
  function min(values) {
252
47
  let result;
@@ -345,10 +140,10 @@ function formatCategory(value, locale) {
345
140
  function circlePath(cx, cy, r) {
346
141
  return `M${cx - r},${cy}A${r},${r},0,1,0,${cx + r},${cy}A${r},${r},0,1,0,${cx - r},${cy}Z`;
347
142
  }
348
- function signedChange(change, format2) {
349
- if (change > 0) return `+${format2(change)}`;
350
- if (change < 0) return `\u2212${format2(-change)}`;
351
- return format2(0);
143
+ function signedChange(change, format) {
144
+ if (change > 0) return `+${format(change)}`;
145
+ if (change < 0) return `\u2212${format(-change)}`;
146
+ return format(0);
352
147
  }
353
148
  var CHAR = 5.2;
354
149
  function fitText(text, width) {
@@ -627,6 +422,6 @@ function sectorLegend(area, entries) {
627
422
  return { strokes, labels };
628
423
  }
629
424
 
630
- export { AXIS_BAND, LEGEND_BAND, PLOT_INSET, RIM_LABELS, SilverpointError, TICK_CHAR, TONE_SCALE, __setDiagnosticSink, accessorName, arcPath, bandScale, cartesianPlot, categoryAxis, categoryLabels, checkCount, checkSectors, checkVolume, circlePath, deriveSeed, diagnose, expandDomain, extent, finite, fitText, fnv1a32, formatCategory, formatNumber, formatValue, horizontalValueAxis, inset, legend, linearScale, max, min, numberFormatter, pillPath, pointAt, polarFrame, polarLabel, read, readSectors, readSeries, rectPath, resolveSeed, rimLabels, ringTone, ringTones, round2, roundGeometry, roundPathData, sectorLegend, sectorPath, seriesValues, signedChange, spreadLabels, toneLevel, toneOf, valueAxis, warnValue };
631
- //# sourceMappingURL=chunk-OLYKR5PS.js.map
632
- //# sourceMappingURL=chunk-OLYKR5PS.js.map
425
+ export { AXIS_BAND, LEGEND_BAND, PLOT_INSET, RIM_LABELS, TICK_CHAR, TONE_SCALE, accessorName, arcPath, bandScale, cartesianPlot, categoryAxis, categoryLabels, checkCount, checkSectors, checkVolume, circlePath, deriveSeed, expandDomain, extent, finite, fitText, fnv1a32, formatCategory, formatNumber, formatValue, horizontalValueAxis, inset, legend, linearScale, max, min, numberFormatter, pillPath, pointAt, polarFrame, polarLabel, read, readSectors, readSeries, rectPath, resolveSeed, rimLabels, ringTone, ringTones, sectorLegend, sectorPath, seriesValues, signedChange, spreadLabels, toneLevel, toneOf, valueAxis, warnValue };
426
+ //# sourceMappingURL=chunk-46QELMCG.js.map
427
+ //# sourceMappingURL=chunk-46QELMCG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/render/seed.ts","../src/scales/util.ts","../src/scales/scales.ts","../src/charts/shared/format.ts","../src/charts/shared/cells.ts","../src/charts/shared/cartesian.ts","../src/charts/shared/polar.ts"],"names":["read","at"],"mappings":"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","file":"chunk-46QELMCG.js","sourcesContent":["import type { Seed } from '../types';\n\nconst FNV_OFFSET_BASIS = 0x811c9dc5;\nconst FNV_PRIME = 0x01000193;\n\nfunction utf8Bytes(input: string): number[] {\n const bytes: number[] = [];\n for (const char of input) {\n const code = char.codePointAt(0) ?? 0;\n if (code < 0x80) {\n bytes.push(code);\n } else if (code < 0x800) {\n bytes.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f));\n } else if (code < 0x10000) {\n bytes.push(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));\n } else {\n bytes.push(\n 0xf0 | (code >> 18),\n 0x80 | ((code >> 12) & 0x3f),\n 0x80 | ((code >> 6) & 0x3f),\n 0x80 | (code & 0x3f),\n );\n }\n }\n return bytes;\n}\n\n/**\n * 32-bit FNV-1a over the UTF-8 bytes of the input (DD-006).\n *\n * Frozen by SemVer: changing it changes every derived seed, and with it every golden image.\n */\nexport function fnv1a32(input: string): number {\n let hash = FNV_OFFSET_BASIS;\n for (const byte of utf8Bytes(input)) {\n hash ^= byte;\n hash = Math.imul(hash, FNV_PRIME);\n }\n return hash >>> 0;\n}\n\n/** Derives the seed of a chart from its identifier (REQ-003). */\nexport function deriveSeed(id: string): number {\n return fnv1a32(id);\n}\n\n/** `seed ?? derive(id)`, with string seeds hashed and numbers taken as unsigned 32-bit. */\nexport function resolveSeed(seed: Seed | undefined, id: string): number {\n if (seed === undefined) return deriveSeed(id);\n if (typeof seed === 'string') return fnv1a32(seed);\n return Number.isFinite(seed) ? Math.trunc(seed) >>> 0 : 0;\n}\n","/**\n * `extent`, `min` and `max` are owned here instead of imported from `d3-array`, which is\n * not in the allowlist (TD §5.3).\n */\n\nexport function min(values: readonly number[]): number | undefined {\n let result: number | undefined;\n for (const value of values) {\n if (Number.isFinite(value) && (result === undefined || value < result)) result = value;\n }\n return result;\n}\n\nexport function max(values: readonly number[]): number | undefined {\n let result: number | undefined;\n for (const value of values) {\n if (Number.isFinite(value) && (result === undefined || value > result)) result = value;\n }\n return result;\n}\n\nexport function extent(values: readonly number[]): [number, number] | undefined {\n const low = min(values);\n const high = max(values);\n return low === undefined || high === undefined ? undefined : [low, high];\n}\n","import { scaleBand, scaleLinear } from 'd3-scale';\nimport { diagnose } from '../diagnostics/diagnose';\n\nexport interface ScaleSite {\n /** Chart name, for diagnostics. */\n readonly chart: string;\n /** Property the domain comes from, for diagnostics. */\n readonly property: string;\n}\n\n/**\n * Expands a zero-length domain by the ground's `domainPadding` instead of dividing by zero\n * (REQ-010). A constant `v` becomes `[v - |v|·p, v + |v|·p]`, or `[-p, p]` around zero — `[0, 2p]`\n * on a zero-based axis, which never shows a value below zero that no datum has.\n */\nexport function expandDomain(\n domain: readonly [number, number],\n padding: number,\n site: ScaleSite,\n /** A zero-based axis (bars, areas): a flat zero domain grows upward only, never below zero. */\n fromZero = false,\n): [number, number] {\n const [low, high] = domain;\n if (low !== high) return [low, high];\n const spread = low === 0 ? padding : Math.abs(low) * padding;\n if (fromZero && low === 0) {\n if (process.env.NODE_ENV !== 'production') {\n diagnose('SP004', site.chart, { property: site.property, message: `Domain [0, 0] became [0, ${2 * spread}].` });\n }\n return [0, 2 * spread];\n }\n if (process.env.NODE_ENV !== 'production') {\n diagnose('SP004', site.chart, {\n property: site.property,\n message: `Domain [${low}, ${high}] became [${low - spread}, ${high + spread}].`,\n });\n }\n return [low - spread, high + spread];\n}\n\nexport interface LinearScale {\n (value: number): number;\n readonly domain: readonly [number, number];\n ticks(count: number): number[];\n}\n\n/** Linear scale over `d3-scale`, with degenerate-domain expansion. */\nexport function linearScale(\n domain: readonly [number, number],\n range: readonly [number, number],\n options: ScaleSite & { readonly padding: number; readonly nice?: boolean; readonly fromZero?: boolean },\n): LinearScale {\n const expanded = expandDomain(domain, options.padding, options, options.fromZero);\n const scale = scaleLinear().domain(expanded).range(range);\n if (options.nice) scale.nice(4);\n const [low, high] = scale.domain() as [number, number];\n const result = ((value: number) => scale(value)) as LinearScale;\n Object.defineProperty(result, 'domain', { value: [low, high] as const });\n (result as { ticks: LinearScale['ticks'] }).ticks = (count) => scale.ticks(count);\n return result;\n}\n\nexport interface BandScale {\n /** Start of the band, or `undefined` for a value outside the domain. */\n (value: string): number | undefined;\n readonly bandwidth: number;\n /** Centre of the band. */\n center(value: string): number | undefined;\n}\n\n/** Band scale over `d3-scale`. */\nexport function bandScale(\n domain: readonly string[],\n range: readonly [number, number],\n options: { readonly paddingInner?: number; readonly paddingOuter?: number } = {},\n): BandScale {\n const scale = scaleBand<string>()\n .domain(domain)\n .range(range)\n .paddingInner(options.paddingInner ?? 0)\n .paddingOuter(options.paddingOuter ?? 0);\n const bandwidth = scale.bandwidth();\n const result = ((value: string) => scale(value)) as BandScale;\n Object.defineProperty(result, 'bandwidth', { value: bandwidth });\n (result as { center: BandScale['center'] }).center = (value) => {\n const start = scale(value);\n return start === undefined ? undefined : start + bandwidth / 2;\n };\n return result;\n}\n","import type { Accessor, Datum } from '../../types';\n\n/** Reads a field through an accessor. */\nexport function read<T>(accessor: Accessor<T>, datum: Datum, index: number): T {\n return typeof accessor === 'function' ? accessor(datum, index) : (datum[accessor] as T);\n}\n\n/** Human name of an accessor, for tables and descriptions. */\nexport function accessorName(accessor: Accessor<unknown>, fallback: string): string {\n return typeof accessor === 'string' ? accessor : fallback;\n}\n\n/** Formatters already built, by locale and options: building one costs more than a label (TD §2). */\nconst FORMATTERS = /* @__PURE__ */ new Map<string, Intl.NumberFormat>();\n/** Distinct locale-and-options pairs kept; past it the cache starts over, so it stays bounded. */\nconst MAX_FORMATTERS = 64;\n\n/** Formats a number with the resolved locale. Formatting lives in the core so both adapters agree. */\nexport function formatNumber(\n value: number,\n locale: string,\n options: Intl.NumberFormatOptions | undefined,\n): string {\n const resolved = options ?? { maximumFractionDigits: 2 };\n // Every option Intl reads, inherited ones included: JSON.stringify sees own properties only.\n const read: string[] = [];\n for (const name in resolved) read.push(`${name}=${JSON.stringify(resolved[name as keyof Intl.NumberFormatOptions])}`);\n const key = `${locale}|${read.sort().join('&')}`;\n let formatter = FORMATTERS.get(key);\n if (!formatter) {\n if (FORMATTERS.size >= MAX_FORMATTERS) FORMATTERS.clear();\n formatter = new Intl.NumberFormat(locale, resolved);\n FORMATTERS.set(key, formatter);\n }\n return formatter.format(value);\n}\n\n/**\n * `formatNumber` with its formatter resolved once, for a column of many values — a table with a\n * row per observation (REQ-445): the same constructor and arguments, so the same text, without\n * rebuilding the cache key for every cell.\n */\nexport function numberFormatter(locale: string, options: Intl.NumberFormatOptions | undefined): (value: number) => string {\n const formatter = new Intl.NumberFormat(locale, options ?? { maximumFractionDigits: 2 });\n return (value) => formatter.format(value);\n}\n\n/** Formats a label that may be a number or free text. */\nexport function formatValue(\n value: unknown,\n locale: string,\n options: Intl.NumberFormatOptions | undefined,\n): string {\n if (typeof value === 'number') {\n return Number.isFinite(value) ? formatNumber(value, locale, options) : '—';\n }\n return value === null || value === undefined ? '—' : String(value);\n}\n\n/**\n * Formats a category — an x value, a time, a stage, a name. A number here is an identifier such as\n * a year, so it is printed without grouping: 2020, never 2,020.\n */\nexport function formatCategory(value: unknown, locale: string): string {\n return formatValue(value, locale, typeof value === 'number' ? { useGrouping: false, maximumFractionDigits: 2 } : undefined);\n}\n\n/** SVG path of a circle, drawn as two arcs so it survives inking as a closed path. */\nexport function circlePath(cx: number, cy: number, r: number): string {\n return `M${cx - r},${cy}A${r},${r},0,1,0,${cx + r},${cy}A${r},${r},0,1,0,${cx - r},${cy}Z`;\n}\n\n/** A change with its sign written out — `+4`, `−8` (U+2212), `0` — so direction never rests on shape alone (REQ-440). */\nexport function signedChange(change: number, format: (value: number) => string): string {\n if (change > 0) return `+${format(change)}`;\n if (change < 0) return `−${format(-change)}`;\n return format(0);\n}\n\n/** Advance of one character at the tick size, as `TICK_CHAR` in cartesian.ts measures it. */\nconst CHAR = 5.2;\n\n/**\n * Text cut with an ellipsis to fit `width` px at the tick size. A name cut on the drawing is still\n * whole in the table and the readout (REQ-121), so nothing is lost to the reader.\n */\nexport function fitText(text: string, width: number): string {\n const fits = Math.max(Math.floor(width / CHAR), 2);\n return text.length > fits ? `${text.slice(0, fits - 1)}…` : text;\n}\n","import { diagnose } from '../../diagnostics/diagnose';\nimport type { Rect, ToneLevel } from '../../types';\n\n/** Closed path of a rectangle, clockwise from its top-left corner. */\nexport function rectPath(rect: Rect): string {\n const { x, y, width, height } = rect;\n return `M${x},${y}H${x + width}V${y + height}H${x}Z`;\n}\n\n/** A rectangle shrunk by `by` on every side, never below zero size. */\nexport function inset(rect: Rect, by: number): Rect {\n return {\n x: rect.x + by,\n y: rect.y + by,\n width: Math.max(rect.width - 2 * by, 0),\n height: Math.max(rect.height - 2 * by, 0),\n };\n}\n\n/** A finite number, or `undefined`. */\nexport function finite(raw: unknown): number | undefined {\n return typeof raw === 'number' && Number.isFinite(raw) ? raw : undefined;\n}\n\n/**\n * Tonal level of a value normalised to 0-1: none at or below 0, then quarters (Data Model §3.4).\n * The tone always repeats a value the chart also prints or draws by length or size (REQ-124).\n */\nexport function toneOf(ratio: number): ToneLevel {\n if (!(ratio > 0)) return 0;\n if (ratio <= 0.25) return 1;\n if (ratio <= 0.5) return 2;\n if (ratio <= 0.75) return 3;\n return 4;\n}\n\n/**\n * Side of a mark, as a share of its slot, per tone: where a value cannot be printed, its size\n * carries the level the tone shows, so it survives `precision` mode (REQ-124). The heatmap's cells\n * when their values do not fit, the density bins always.\n */\nexport const TONE_SCALE: Readonly<Record<ToneLevel, number>> = { 0: 0.4, 1: 0.55, 2: 0.7, 3: 0.85, 4: 1 };\n\n/** A consumer-supplied tone, rounded and held to 0-4. */\nexport function toneLevel(raw: number): ToneLevel {\n return Math.min(Math.max(Math.round(raw), 0), 4) as ToneLevel;\n}\n\n/** A value outside what the chart can draw: it is corrected or dropped, and warned (SP002). */\nexport function warnValue(chart: string, property: string, message: string): void {\n if (process.env.NODE_ENV !== 'production') diagnose('SP002', chart, { property, message });\n}\n\nconst RING_TONES: readonly ToneLevel[] = [1, 2, 3, 4];\n\n/**\n * The tone of sector `index` of `count` around a closed ring: the ramp in turn, and the last sector\n * never repeats the first, its neighbour across 12 o'clock. Tone only repeats what the legend and\n * the printed shares say (REQ-124). Every chart with categories tones them this way — a ring, a\n * waffle, a mosaic, a hierarchy's first level, a network's groups (DD-032, REQ-440).\n */\nexport function ringTone(index: number, count: number): ToneLevel {\n const tone = RING_TONES[index % RING_TONES.length] as ToneLevel;\n if (count > 1 && index === count - 1 && tone === RING_TONES[0]) return RING_TONES[2] as ToneLevel;\n return tone;\n}\n\n/**\n * The tones of a ring's sectors, counted over the drawn ones only: a zero sector is not drawn, so it\n * must not hold a place in the ramp, or two drawn neighbours could share a tone. A zero sector takes\n * the tone its place would have, for its legend swatch.\n */\nexport function ringTones(values: readonly number[]): ToneLevel[] {\n const drawn = values.filter((v) => v > 0).length;\n let k = 0;\n return values.map((v) => (v > 0 ? ringTone(k++, drawn) : ringTone(Math.min(k, Math.max(drawn - 1, 0)), drawn)));\n}\n","import { bandScale, linearScale, type LinearScale } from '../../scales/scales';\nimport { extent } from '../../scales/util';\nimport type { Accessor, Datum, Rect, Stroke, TextLabel, ToneLevel } from '../../types';\nimport { rectPath } from './cells';\nimport { diagnose } from '../../diagnostics/diagnose';\nimport { accessorName, formatNumber, read } from './format';\n\n/** Room under the plot for the category labels. */\nexport const AXIS_BAND = 20;\n/** Room around the plot so a heightened point or a pill end is never clipped. */\nexport const PLOT_INSET = 6;\n/** Minimum horizontal room per category label. */\nconst LABEL_SPACING = 48;\n\n/** The plot of a cartesian chart inside its drawing area: inset, with the axis band below. */\nexport function cartesianPlot(area: Rect): Rect {\n return {\n x: area.x + PLOT_INSET,\n y: area.y + PLOT_INSET,\n width: Math.max(area.width - 2 * PLOT_INSET, 1),\n height: Math.max(area.height - AXIS_BAND - PLOT_INSET, 1),\n };\n}\n\nexport interface SeriesPoint {\n readonly index: number;\n readonly datum: Datum;\n readonly value: number | undefined;\n}\n\nexport interface Series {\n readonly key: string;\n readonly points: readonly SeriesPoint[];\n /** Points whose value is not a finite number. */\n readonly missing: number;\n}\n\n/** Reads one numeric series through an accessor; non-finite values become gaps. */\nexport function readSeries(data: readonly Datum[], accessor: Accessor<number | null | undefined>, fallbackName: string): Series {\n let missing = 0;\n const points = data.map((datum, index) => {\n const raw = read(accessor, datum, index);\n const value = typeof raw === 'number' && Number.isFinite(raw) ? raw : undefined;\n if (value === undefined) missing += 1;\n return { index, datum, value };\n });\n return { key: accessorName(accessor, fallbackName), points, missing };\n}\n\n/** Points per series a cartesian chart draws before it recommends aggregation (API Spec §12). */\nexport const POINTS_PER_SERIES = 500;\n\n/**\n * Warns SP008 when a series runs past the family's ceiling. The series is still drawn in full:\n * the warning recommends aggregation, it never degrades silently (REQ-096).\n */\nexport function checkVolume(chart: string, series: readonly Series[]): void {\n for (const s of series) checkCount(chart, s.key, s.points.length);\n}\n\n/** The same ceiling, for a chart whose points are not read as a `Series`. */\nexport function checkCount(chart: string, property: string, count: number): void {\n if (process.env.NODE_ENV === 'production' || count <= POINTS_PER_SERIES) return;\n diagnose('SP008', chart, { property, message: `${count} points; the ceiling is ${POINTS_PER_SERIES} per series.` });\n}\n\n/** The finite values of a set of series. */\nexport function seriesValues(series: readonly Series[]): number[] {\n return series.flatMap((s) => s.points.flatMap((p) => (p.value === undefined ? [] : [p.value])));\n}\n\nexport interface ValueAxis {\n readonly scale: LinearScale;\n readonly strokes: readonly Stroke[];\n readonly labels: readonly TextLabel[];\n}\n\n/**\n * The vertical value scale of a cartesian chart, niced, with its grid lines and tick labels and\n * the base rule. The domain always reaches zero when `zero` is set, as bars and areas need.\n */\nexport function valueAxis(\n plot: Rect,\n domain: readonly [number, number],\n options: {\n readonly chart: string;\n readonly property: string;\n readonly padding: number;\n readonly locale: string;\n readonly numberFormat: Intl.NumberFormatOptions | undefined;\n readonly zero?: boolean;\n /** Round the domain out to tick values; `true` by default. Pinned bounds pass `false`. */\n readonly nice?: boolean;\n },\n): ValueAxis {\n const bottom = plot.y + plot.height;\n const low = options.zero === false ? domain[0] : Math.min(0, domain[0]);\n const high = options.zero === false ? domain[1] : Math.max(0, domain[1]);\n const scale = linearScale([low, high], [bottom, plot.y], {\n chart: options.chart,\n property: options.property,\n padding: options.padding,\n nice: options.nice !== false,\n fromZero: options.zero !== false,\n });\n const strokes: Stroke[] = [];\n const labels: TextLabel[] = [];\n for (const tick of scale.ticks(4)) {\n const ty = scale(tick);\n if (tick === scale.domain[0]) continue;\n strokes.push({ d: `M${plot.x},${ty}H${plot.x + plot.width}`, role: 'ornament', part: 'grid' });\n labels.push({ x: plot.x, y: ty - 3, text: formatNumber(tick, options.locale, options.numberFormat), kind: 'tick', part: 'axis', anchor: 'start' });\n }\n strokes.push({ d: `M${plot.x},${bottom}H${plot.x + plot.width}`, role: 'ornament', part: 'rule' });\n return { scale, strokes, labels };\n}\n\nexport interface CategoryAxis {\n /** Centre of item `index` along x. */\n at(index: number): number;\n /** Width of one category's band; 0 on a numeric axis. */\n readonly bandwidth: number;\n}\n\n/**\n * Positions along x: a linear scale when every x value is a finite number, otherwise one band per\n * row, whose centre is the item's position.\n */\nexport function categoryAxis(\n xValues: readonly unknown[],\n plot: Rect,\n options: { readonly chart: string; readonly property: string; readonly padding: number; readonly paddingInner?: number; readonly paddingOuter?: number; readonly numeric?: boolean },\n): CategoryAxis {\n const numeric = options.numeric !== false && xValues.length > 0 && xValues.every((v) => typeof v === 'number' && Number.isFinite(v));\n if (numeric) {\n const numbers = xValues as number[];\n const x = linearScale(extent(numbers) ?? [0, 0], [plot.x, plot.x + plot.width], {\n chart: options.chart,\n property: options.property,\n padding: options.padding,\n });\n return { at: (index) => x(numbers[index] ?? 0), bandwidth: 0 };\n }\n const keys = xValues.map((_, index) => String(index));\n const band = bandScale(keys, [plot.x, plot.x + plot.width], { paddingInner: options.paddingInner, paddingOuter: options.paddingOuter });\n return { at: (index) => band.center(String(index)) ?? plot.x, bandwidth: band.bandwidth };\n}\n\n/** Category labels under the plot, thinned so they never crowd: one every `step` items. */\nexport function categoryLabels(texts: readonly string[], at: (index: number) => number, area: Rect, plot: Rect): TextLabel[] {\n const count = texts.length;\n const step = Math.max(1, Math.ceil(count / Math.max(2, Math.floor(plot.width / LABEL_SPACING))));\n const labels: TextLabel[] = [];\n for (let index = 0; index < count; index += step) {\n labels.push({\n x: at(index),\n y: area.y + area.height - 5,\n text: texts[index] ?? '',\n kind: 'tick',\n part: 'axis',\n anchor: index === 0 ? 'start' : 'middle',\n });\n }\n return labels;\n}\n\n/** Height of the legend row at the top of the drawing area: a full line above the top value tick. */\nexport const LEGEND_BAND = 22;\n/** Advance of one character of tick or legend text at the 9.5 px tick size. */\nexport const TICK_CHAR = 5.2;\nconst LEGEND_CHAR = TICK_CHAR;\n\nexport interface LegendEntry {\n readonly name: string;\n readonly part: 'ink' | 'ink-secondary';\n readonly tone?: ToneLevel;\n readonly dash?: 'dotted';\n}\n\n/**\n * A legend row at the top of the area: a swatch drawn like its series — outline, dash and tone —\n * and the series' name. The swatch carries no data, so it is an ornament; the name is what tells\n * the series apart, never the tone alone (REQ-124). Returns the area left below it.\n */\nexport function legend(area: Rect, entries: readonly LegendEntry[]): { area: Rect; strokes: Stroke[]; labels: TextLabel[] } {\n const strokes: Stroke[] = [];\n const labels: TextLabel[] = [];\n let x = area.x + PLOT_INSET;\n for (const entry of entries) {\n const swatch = { x, y: area.y + 4, width: 12, height: 7 };\n strokes.push({ d: rectPath(swatch), role: 'ornament', part: entry.part, ...(entry.tone ? { tone: entry.tone } : {}), ...(entry.dash ? { dash: entry.dash } : {}) });\n labels.push({ x: x + 16, y: area.y + 11, text: entry.name, kind: 'tick', part: 'axis', anchor: 'start' });\n x += 16 + entry.name.length * LEGEND_CHAR + 12;\n }\n return { area: { x: area.x, y: area.y + LEGEND_BAND, width: area.width, height: Math.max(area.height - LEGEND_BAND, 1) }, strokes, labels };\n}\n\n/** A rectangle with fully rounded ends — a pill — as a closed path of lines and arcs. */\nexport function pillPath(rect: Rect): string {\n const { x, y, width, height } = rect;\n const r = Math.min(width, height) / 2;\n if (r <= 0) return `M${x},${y}H${x + width}V${y + height}H${x}Z`;\n return (\n `M${x},${y + r}A${r},${r},0,0,1,${x + r},${y}H${x + width - r}A${r},${r},0,0,1,${x + width},${y + r}` +\n `V${y + height - r}A${r},${r},0,0,1,${x + width - r},${y + height}H${x + r}A${r},${r},0,0,1,${x},${y + height - r}Z`\n );\n}\n\n/**\n * The horizontal value scale of a chart laid out in rows: niced, zero in the domain, with vertical\n * grid lines and tick labels under the plot, and the base rule at zero.\n */\nexport function horizontalValueAxis(\n plot: Rect,\n area: Rect,\n domain: readonly [number, number],\n options: { readonly chart: string; readonly property: string; readonly padding: number; readonly locale: string; readonly numberFormat: Intl.NumberFormatOptions | undefined },\n): ValueAxis {\n const scale = linearScale([Math.min(0, domain[0]), Math.max(0, domain[1])], [plot.x, plot.x + plot.width], {\n chart: options.chart,\n property: options.property,\n padding: options.padding,\n nice: true,\n fromZero: true,\n });\n const strokes: Stroke[] = [];\n const labels: TextLabel[] = [];\n for (const tick of scale.ticks(4)) {\n const tx = scale(tick);\n if (tick !== 0) strokes.push({ d: `M${tx},${plot.y}V${plot.y + plot.height}`, role: 'ornament', part: 'grid' });\n labels.push({ x: tx, y: area.y + area.height - 5, text: formatNumber(tick, options.locale, options.numberFormat), kind: 'tick', part: 'axis', anchor: 'middle' });\n }\n strokes.push({ d: `M${scale(0)},${plot.y}V${plot.y + plot.height}`, role: 'ornament', part: 'rule' });\n return { scale, strokes, labels };\n}\n\n/**\n * Label baselines for points at `ys`, moved apart to at least `gap` and kept within\n * `[top, bottom]`: the labels move, the segments never do (Art. 1).\n */\nexport function spreadLabels(ys: readonly number[], gap: number, top: number, bottom: number): number[] {\n const order = ys.map((y, i) => [y, i] as const).sort((a, b) => a[0] - b[0] || a[1] - b[1]);\n const placed = order.map(([y]) => y);\n for (let k = 0; k < placed.length; k += 1) placed[k] = Math.max(placed[k] as number, k === 0 ? top : (placed[k - 1] as number) + gap);\n for (let k = placed.length - 1; k >= 0; k -= 1) placed[k] = Math.min(placed[k] as number, k === placed.length - 1 ? bottom : (placed[k + 1] as number) - gap);\n const result = new Array<number>(ys.length);\n order.forEach(([, i], k) => {\n result[i] = placed[k] as number;\n });\n return result;\n}\n","import type { Accessor, Datum, Rect, Stroke, TextLabel, ToneLevel } from '../../types';\nimport { diagnose } from '../../diagnostics/diagnose';\nimport { PLOT_INSET } from './cartesian';\nimport { finite, rectPath, warnValue } from './cells';\nimport { accessorName, formatCategory, read } from './format';\n\n/**\n * The polar frame (T-071): a circle centred in the drawing area. Angles are radians measured\n * clockwise from 12 o'clock — d3-shape's convention — so a sweep reads like a clock face.\n */\nexport interface PolarFrame {\n readonly cx: number;\n readonly cy: number;\n /** Largest radius that fits the area's shorter side, inset so no stroke is clipped. */\n readonly radius: number;\n}\n\n/** `labelRoom` keeps a margin around the circle for names printed outside it. */\nexport function polarFrame(area: Rect, labelRoom = 0): PolarFrame {\n return {\n cx: area.x + area.width / 2,\n cy: area.y + area.height / 2,\n radius: Math.max(Math.min(area.width, area.height) / 2 - PLOT_INSET - labelRoom, 1),\n };\n}\n\n/** Room outside a circle for the names printed around it. */\nexport const RIM_LABELS = 14;\n\n/**\n * Names around the rim, one per slot at its middle angle, thinned so no more than `most` are\n * printed; the table and the readout name every slot.\n */\nexport function rimLabels(frame: PolarFrame, entries: readonly { readonly angle: number; readonly text: string }[], most = 24): TextLabel[] {\n const step = Math.max(1, Math.ceil(entries.length / most));\n return entries.filter((_, i) => i % step === 0).map((e) => polarLabel(frame, e.angle, frame.radius + 8, e.text));\n}\n\n/** The point at `angle` on the circle of radius `r`. */\nexport function pointAt(frame: PolarFrame, angle: number, r: number): { x: number; y: number } {\n return { x: frame.cx + r * Math.sin(angle), y: frame.cy - r * Math.cos(angle) };\n}\n\n/** Below this sweep an arc has no extent to draw. */\nconst EPSILON = 1e-9;\n\nconst at = (frame: PolarFrame, angle: number, r: number) => {\n const p = pointAt(frame, angle, r);\n return `${p.x},${p.y}`;\n};\n\n/** An arc command of at most half a turn from the current point to `end` along radius `r`. */\nfunction arcTo(frame: PolarFrame, r: number, end: number, clockwise: boolean): string {\n return `A${r},${r},0,0,${clockwise ? 1 : 0},${at(frame, end, r)}`;\n}\n\n/**\n * An arc along radius `r` from `start` to `end` that never degenerates: past half a turn it is drawn\n * as two halves, so a sweep near a full turn never rounds to an arc that ends where it starts.\n */\nfunction sweep(frame: PolarFrame, r: number, start: number, end: number, clockwise: boolean): string {\n if (Math.abs(end - start) <= Math.PI) return arcTo(frame, r, end, clockwise);\n const middle = (start + end) / 2;\n return arcTo(frame, r, middle, clockwise) + arcTo(frame, r, end, clockwise);\n}\n\n/** An open arc along one radius, from `start` to `end` (clockwise when `end > start`). */\nexport function arcPath(frame: PolarFrame, r: number, start: number, end: number): string {\n if (Math.abs(end - start) < EPSILON || r <= 0) return '';\n return `M${at(frame, start, r)}${sweep(frame, r, start, end, end > start)}`;\n}\n\nexport interface SectorShape {\n readonly inner: number;\n readonly outer: number;\n readonly start: number;\n readonly end: number;\n}\n\n/**\n * A closed ring slice: out along the outer arc, across, and back along the inner arc. With no\n * inner radius it is a wedge from the centre. The arcs are exact SVG arcs, never polylines.\n */\nexport function sectorPath(frame: PolarFrame, shape: SectorShape): string {\n const { inner, outer, start, end } = shape;\n if (Math.abs(end - start) < EPSILON || outer <= 0) return '';\n const clockwise = end > start;\n const outerArc = `M${at(frame, start, outer)}${sweep(frame, outer, start, end, clockwise)}`;\n if (inner <= 0) return `${outerArc}L${frame.cx},${frame.cy}Z`;\n return `${outerArc}L${at(frame, end, inner)}${sweep(frame, inner, end, start, !clockwise)}Z`;\n}\n\n/** Half-width of the band around the poles where a label is centred rather than side-anchored. */\nconst POLE = 0.1;\n\n/** A label on the circle of radius `r` at `angle`, anchored so it reads away from the circle. */\nexport function polarLabel(frame: PolarFrame, angle: number, r: number, text: string, kind: TextLabel['kind'] = 'tick'): TextLabel {\n const p = pointAt(frame, angle, r);\n const side = Math.sin(angle);\n const anchor = side > POLE ? 'start' : side < -POLE ? 'end' : 'middle';\n // Baseline a third of the cap height below the point, so the text sits centred on it.\n return { x: p.x, y: p.y + 3, text, kind, part: 'axis', anchor };\n}\n\nexport interface Sector {\n readonly index: number;\n readonly datum: Datum;\n readonly name: string;\n readonly value: number;\n}\n\n/**\n * Reads a sector series (Data Model §2.2): a value must be finite and `≥ 0` — a negative angle does\n * not exist — or the row is warned `SP002` and dropped; a repeated name is made unique.\n */\nexport function readSectors(\n data: readonly Datum[],\n nameKey: Accessor<string | number>,\n valueKey: Accessor<number | null | undefined>,\n chart: string,\n locale: string,\n): Sector[] {\n const valueName = accessorName(valueKey, 'value');\n const seen = new Map<string, number>();\n const sectors: Sector[] = [];\n data.forEach((datum, index) => {\n const value = finite(read(valueKey, datum, index));\n if (value === undefined || value < 0) {\n warnValue(chart, valueName, `Row ${index} has a ${valueName} of ${String(read(valueKey, datum, index))}; a sector needs a finite value ≥ 0, so it is omitted.`);\n return;\n }\n const given = read(nameKey, datum, index);\n if (given === undefined || given === null || given === '') warnValue(chart, accessorName(nameKey, 'name'), `Row ${index} has no name; it is shown as \"—\".`);\n const raw = formatCategory(given, locale);\n const count = (seen.get(raw) ?? 0) + 1;\n seen.set(raw, count);\n if (count > 1) warnValue(chart, accessorName(nameKey, 'name'), `The name \"${raw}\" repeats; row ${index} is shown as \"${raw} (${count})\".`);\n sectors.push({ index, datum, name: count > 1 ? `${raw} (${count})` : raw, value });\n });\n return sectors;\n}\n\n/** Sectors a polar chart draws before it recommends aggregation (API Spec §12). */\nexport const SECTORS_PER_CHART = 60;\n\n/** Warns SP008 above the polar ceiling; the chart is still drawn in full (REQ-096). */\nexport function checkSectors(chart: string, property: string, count: number): void {\n if (process.env.NODE_ENV === 'production' || count <= SECTORS_PER_CHART) return;\n diagnose('SP008', chart, { property, message: `${count} sectors; the ceiling is ${SECTORS_PER_CHART}.` });\n}\n\n// The ring's tones serve every family with categories (DD-032); they live in cells.ts.\nexport { ringTone, ringTones } from './cells';\n\n/** Height of one legend row. */\nconst LEGEND_ROW = 14;\n\nexport interface SectorLegendEntry {\n readonly name: string;\n readonly share: string;\n readonly tone: ToneLevel;\n}\n\n/**\n * A legend column: a toned swatch (ornament: it carries no data), the sector's name and its share,\n * in the ring's clockwise order. Rows that do not fit end in \"+N more\"; the table lists them all.\n */\nexport function sectorLegend(area: Rect, entries: readonly SectorLegendEntry[]): { strokes: Stroke[]; labels: TextLabel[] } {\n const strokes: Stroke[] = [];\n const labels: TextLabel[] = [];\n const fits = Math.max(Math.floor(area.height / LEGEND_ROW), 1);\n const shown = entries.length > fits ? fits - 1 : entries.length;\n const top = area.y + (area.height - Math.min(entries.length, fits) * LEGEND_ROW) / 2;\n entries.slice(0, shown).forEach((entry, row) => {\n const y = top + row * LEGEND_ROW;\n strokes.push({ d: rectPath({ x: area.x, y: y + 3, width: 9, height: 7 }), role: 'ornament', part: 'ink', tone: entry.tone });\n labels.push({ x: area.x + 14, y: y + 10, text: entry.name, kind: 'tick', part: 'text', anchor: 'start' });\n labels.push({ x: area.x + area.width, y: y + 10, text: entry.share, kind: 'tick', part: 'axis', anchor: 'end' });\n });\n if (shown < entries.length) {\n labels.push({ x: area.x + 14, y: top + shown * LEGEND_ROW + 10, text: `+${entries.length - shown} more`, kind: 'tick', part: 'axis', anchor: 'start' });\n }\n return { strokes, labels };\n}\n"]}
@@ -0,0 +1,48 @@
1
+ // src/render/round.ts
2
+ function round2(value) {
3
+ const rounded = Math.round(value * 100) / 100;
4
+ return Object.is(rounded, -0) ? 0 : rounded;
5
+ }
6
+ var NUMBER = /-?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?/g;
7
+ function roundPathData(d) {
8
+ return d.replace(NUMBER, (token) => String(round2(Number(token))));
9
+ }
10
+ function roundRect(rect) {
11
+ return {
12
+ x: round2(rect.x),
13
+ y: round2(rect.y),
14
+ width: round2(rect.width),
15
+ height: round2(rect.height)
16
+ };
17
+ }
18
+ function roundStroke(stroke) {
19
+ return { ...stroke, d: roundPathData(stroke.d) };
20
+ }
21
+ function roundTile(tile) {
22
+ return {
23
+ ...tile,
24
+ width: round2(tile.width),
25
+ height: round2(tile.height),
26
+ angle: round2(tile.angle),
27
+ strokes: tile.strokes.map(roundStroke)
28
+ };
29
+ }
30
+ function roundGeometry(geometry) {
31
+ return {
32
+ viewBox: roundRect(geometry.viewBox),
33
+ plot: roundRect(geometry.plot),
34
+ strokes: geometry.strokes.map(roundStroke),
35
+ labels: geometry.labels.map((label) => ({ ...label, x: round2(label.x), y: round2(label.y) })),
36
+ hitAreas: geometry.hitAreas.map((hit) => ({
37
+ ...hit,
38
+ x: round2(hit.x),
39
+ y: round2(hit.y),
40
+ ...hit.box ? { box: roundRect(hit.box) } : {}
41
+ })),
42
+ defs: geometry.defs.map(roundTile)
43
+ };
44
+ }
45
+
46
+ export { round2, roundGeometry, roundPathData };
47
+ //# sourceMappingURL=chunk-5MP3BLZK.js.map
48
+ //# sourceMappingURL=chunk-5MP3BLZK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/render/round.ts"],"names":[],"mappings":";AAGO,SAAS,OAAO,KAAA,EAAuB;AAC5C,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,GAAG,CAAA,GAAI,GAAA;AAC1C,EAAA,OAAO,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,EAAE,IAAI,CAAA,GAAI,OAAA;AACtC;AAEA,IAAM,MAAA,GAAS,yCAAA;AAGR,SAAS,cAAc,CAAA,EAAmB;AAC/C,EAAA,OAAO,CAAA,CAAE,OAAA,CAAQ,MAAA,EAAQ,CAAC,KAAA,KAAU,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,KAAK,CAAC,CAAC,CAAC,CAAA;AACnE;AAEA,SAAS,UAAU,IAAA,EAAkB;AACnC,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAAA,IAChB,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAAA,IAChB,KAAA,EAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AAAA,IACxB,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,MAAM;AAAA,GAC5B;AACF;AAEA,SAAS,YAAY,MAAA,EAAwB;AAC3C,EAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,GAAG,aAAA,CAAc,MAAA,CAAO,CAAC,CAAA,EAAE;AACjD;AAEA,SAAS,UAAU,IAAA,EAAkB;AACnC,EAAA,OAAO;AAAA,IACL,GAAG,IAAA;AAAA,IACH,KAAA,EAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AAAA,IACxB,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA;AAAA,IAC1B,KAAA,EAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AAAA,IACxB,OAAA,EAAS,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,WAAW;AAAA,GACvC;AACF;AAGO,SAAS,cAAc,QAAA,EAA8B;AAC1D,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,SAAA,CAAU,QAAA,CAAS,OAAO,CAAA;AAAA,IACnC,IAAA,EAAM,SAAA,CAAU,QAAA,CAAS,IAAI,CAAA;AAAA,IAC7B,OAAA,EAAS,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,WAAW,CAAA;AAAA,IACzC,QAAQ,QAAA,CAAS,MAAA,CAAO,IAAI,CAAC,KAAA,MAAW,EAAE,GAAG,KAAA,EAAO,GAAG,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,EAAG,OAAO,KAAA,CAAM,CAAC,GAAE,CAAE,CAAA;AAAA,IAC7F,QAAA,EAAU,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MACxC,GAAG,GAAA;AAAA,MACH,CAAA,EAAG,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA;AAAA,MACf,CAAA,EAAG,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA;AAAA,MACf,GAAI,GAAA,CAAI,GAAA,GAAM,EAAE,GAAA,EAAK,UAAU,GAAA,CAAI,GAAG,CAAA,EAAE,GAAI;AAAC,KAC/C,CAAE,CAAA;AAAA,IACF,IAAA,EAAM,QAAA,CAAS,IAAA,CAAK,GAAA,CAAI,SAAS;AAAA,GACnC;AACF","file":"chunk-5MP3BLZK.js","sourcesContent":["import type { Geometry, Rect, Stroke, Tile } from '../types';\n\n/** Rounds to 2 decimals, the precision of every emitted coordinate (REQ-002). */\nexport function round2(value: number): number {\n const rounded = Math.round(value * 100) / 100;\n return Object.is(rounded, -0) ? 0 : rounded;\n}\n\nconst NUMBER = /-?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][-+]?\\d+)?/g;\n\n/** Rounds every number inside SVG path data to 2 decimals. */\nexport function roundPathData(d: string): string {\n return d.replace(NUMBER, (token) => String(round2(Number(token))));\n}\n\nfunction roundRect(rect: Rect): Rect {\n return {\n x: round2(rect.x),\n y: round2(rect.y),\n width: round2(rect.width),\n height: round2(rect.height),\n };\n}\n\nfunction roundStroke(stroke: Stroke): Stroke {\n return { ...stroke, d: roundPathData(stroke.d) };\n}\n\nfunction roundTile(tile: Tile): Tile {\n return {\n ...tile,\n width: round2(tile.width),\n height: round2(tile.height),\n angle: round2(tile.angle),\n strokes: tile.strokes.map(roundStroke),\n };\n}\n\n/** Rounds all coordinates of a geometry to 2 decimals, returning a new object (REQ-002). */\nexport function roundGeometry(geometry: Geometry): Geometry {\n return {\n viewBox: roundRect(geometry.viewBox),\n plot: roundRect(geometry.plot),\n strokes: geometry.strokes.map(roundStroke),\n labels: geometry.labels.map((label) => ({ ...label, x: round2(label.x), y: round2(label.y) })),\n hitAreas: geometry.hitAreas.map((hit) => ({\n ...hit,\n x: round2(hit.x),\n y: round2(hit.y),\n ...(hit.box ? { box: roundRect(hit.box) } : {}),\n })),\n defs: geometry.defs.map(roundTile),\n };\n}\n"]}
@@ -0,0 +1,84 @@
1
+ import { diagnose } from './chunk-WYFRHI4S.js';
2
+
3
+ // src/ui/view-kit.ts
4
+ function clean(attrs) {
5
+ const out = {};
6
+ for (const [name, value] of Object.entries(attrs)) if (value !== void 0 && value !== false) out[name] = value;
7
+ return out;
8
+ }
9
+ var el = (tag, attrs, children = [], bind) => ({
10
+ tag,
11
+ attrs: clean(attrs),
12
+ children,
13
+ ...bind ? { bind } : {}
14
+ });
15
+ var text = (value) => ({ text: value });
16
+ var slot = (name) => ({ slot: name });
17
+ function root(slug, props, r, attrs = {}) {
18
+ const own = typeof attrs.style === "string" ? attrs.style : "";
19
+ return {
20
+ class: ["sp-ui", `sp-${slug}`, `sp-ground-${r.ground}`, props.className].filter(Boolean).join(" "),
21
+ "data-ground": r.ground,
22
+ "data-substrate": r.substrate,
23
+ "data-mode": r.mode,
24
+ "data-size": r.size,
25
+ "data-frame": String(r.frame),
26
+ ...attrs,
27
+ style: [r.palette, own].filter(Boolean).join(";") || void 0
28
+ };
29
+ }
30
+ var frame = (kind) => el("span", { part: "sp-frame", "data-kind": kind, "aria-hidden": "true" });
31
+ var tone = (value, kind) => el("span", { part: "sp-tone", "data-tone": value, "data-kind": kind, "aria-hidden": "true" });
32
+ var UI_GLYPHS = Object.freeze({
33
+ tick: "M3.5,8.5L6.5,11.5L12.5,4.5",
34
+ dash: "M4,8H12",
35
+ cross: "M4.5,4.5L11.5,11.5M11.5,4.5L4.5,11.5",
36
+ warning: "M8,2.5L14.5,13.5H1.5Z M8,6.5V9.5 M8,11.5V11.5",
37
+ /** A radio's selection: filled by ui.css. */
38
+ dot: "M11,8A3,3 0 1,1 5,8A3,3 0 1,1 11,8Z",
39
+ /** A Rate mark (C-2). */
40
+ lozenge: "M8,1.5L14.5,8L8,14.5L1.5,8Z",
41
+ info: "M14.5,8A6.5,6.5 0 1,1 1.5,8A6.5,6.5 0 1,1 14.5,8Z M8,7.5V11.5 M8,4.75V4.75",
42
+ // The composed components' own (REQ-472), Reflex 0.7's paths.
43
+ plus: "M8,3.5V12.5M3.5,8H12.5",
44
+ chevronDown: "M4,6L8,10L12,6",
45
+ chevronRight: "M6,4L10,8L6,12",
46
+ chevronLeft: "M10,4L6,8L10,12",
47
+ arrowUp: "M8,12.5V3.5M4.5,7L8,3.5L11.5,7",
48
+ arrowDown: "M8,3.5V12.5M4.5,9L8,12.5L11.5,9",
49
+ sortUp: "M5,9.5L8,5.5L11,9.5Z",
50
+ sortDown: "M5,6.5L8,10.5L11,6.5Z",
51
+ sort: "M5,7L8,3.5L11,7Z M5,9L8,12.5L11,9Z",
52
+ ellipsis: "M3.5,8V8 M8,8V8 M12.5,8V8"
53
+ });
54
+ var glyph = (name) => el("svg", { part: "sp-mark", "data-glyph": name, viewBox: "0 0 16 16", "aria-hidden": "true" }, [el("path", { d: UI_GLYPHS[name] })]);
55
+ var sr = (value) => el("span", { class: "sp-ui-sr" }, [text(value)]);
56
+ var baseOf = (props) => props.id ?? props.name;
57
+ function nativeInput(type, attrs) {
58
+ return el("input", { type, class: "sp-ui-native", ...attrs }, [], "native");
59
+ }
60
+ var LENGTH = /^\d+(?:\.\d+)?(?:px|%|em|rem|ch|vw|vh)$/;
61
+ function cssLength(value, component, property) {
62
+ if (value === void 0 || LENGTH.test(value)) return value;
63
+ if (process.env.NODE_ENV !== "production") diagnose("SP017", component, { property, message: `${JSON.stringify(value)} is not a plain length; it is dropped.` });
64
+ return void 0;
65
+ }
66
+ var iconClose = (label) => el("button", { type: "button", class: "sp-ui-icon-button", "aria-label": label }, [glyph("cross")], "close");
67
+ var SAFE_SCHEMES = /* @__PURE__ */ new Set(["http", "https", "mailto", "tel"]);
68
+ function safeHref(href, component, property = "href") {
69
+ if (href === void 0) return void 0;
70
+ const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(href.replace(/[\u0000-\u0020\u007f]/g, ""))?.[1];
71
+ if (scheme === void 0 || SAFE_SCHEMES.has(scheme.toLowerCase())) return href;
72
+ if (process.env.NODE_ENV !== "production") diagnose("SP017", component, { property, message: `The scheme "${scheme}:" is not allowed; the link is dropped.` });
73
+ return void 0;
74
+ }
75
+ function headingTag(level, component) {
76
+ if (level === void 0) return "h3";
77
+ if (level === 2 || level === 3 || level === 4 || level === 5 || level === 6) return `h${level}`;
78
+ if (process.env.NODE_ENV !== "production") diagnose("SP017", component, { property: "headingLevel", message: `${JSON.stringify(level)} is not a level in 2..6; h3 is drawn.` });
79
+ return "h3";
80
+ }
81
+
82
+ export { UI_GLYPHS, baseOf, cssLength, el, frame, glyph, headingTag, iconClose, nativeInput, root, safeHref, slot, sr, text, tone };
83
+ //# sourceMappingURL=chunk-6YFO7OP3.js.map
84
+ //# sourceMappingURL=chunk-6YFO7OP3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/view-kit.ts"],"names":[],"mappings":"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","file":"chunk-6YFO7OP3.js","sourcesContent":["import { diagnose } from '../diagnostics/diagnose';\nimport type { CommonUiProps } from './types';\nimport type { UiAttrValue, UiBind, UiElement, UiNode, UiResolved, UiSlot } from './view';\n\nexport type Attrs = Record<string, UiAttrValue | undefined | false>;\n\n/** Drops absent attributes: `undefined` and `false` are never written. */\nfunction clean(attrs: Attrs): Record<string, UiAttrValue> {\n const out: Record<string, UiAttrValue> = {};\n for (const [name, value] of Object.entries(attrs)) if (value !== undefined && value !== false) out[name] = value;\n return out;\n}\n\nexport const el = (tag: string, attrs: Attrs, children: readonly UiNode[] = [], bind?: UiBind): UiElement => ({\n tag,\n attrs: clean(attrs),\n children,\n ...(bind ? { bind } : {}),\n});\nexport const text = (value: string): UiNode => ({ text: value });\nexport const slot = (name: UiSlot): UiNode => ({ slot: name });\n\n/** A root's attributes; a palette is the first declaration of its `style`, the component's own follow (REQ-461). */\nexport function root(slug: string, props: CommonUiProps, r: UiResolved, attrs: Attrs = {}): Attrs {\n const own = typeof attrs.style === 'string' ? attrs.style : '';\n return {\n class: ['sp-ui', `sp-${slug}`, `sp-ground-${r.ground}`, props.className].filter(Boolean).join(' '),\n 'data-ground': r.ground,\n 'data-substrate': r.substrate,\n 'data-mode': r.mode,\n 'data-size': r.size,\n 'data-frame': String(r.frame),\n ...attrs,\n style: [r.palette, own].filter(Boolean).join(';') || undefined,\n };\n}\n\nexport type FrameKind = 'control' | 'pill' | 'box' | 'card' | 'round';\nexport const frame = (kind: FrameKind) => el('span', { part: 'sp-frame', 'data-kind': kind, 'aria-hidden': 'true' });\n/** A tone by state (`primary`, `selected`…) or ramp level; ui.css maps a state to its ground's level. */\nexport const tone = (value: string, kind: FrameKind) => el('span', { part: 'sp-tone', 'data-tone': value, 'data-kind': kind, 'aria-hidden': 'true' });\n\n/** Exact glyphs in a 16 × 16 box: their strokes are values, never inked (REQ-304, REQ-310). */\nexport const UI_GLYPHS = Object.freeze({\n tick: 'M3.5,8.5L6.5,11.5L12.5,4.5',\n dash: 'M4,8H12',\n cross: 'M4.5,4.5L11.5,11.5M11.5,4.5L4.5,11.5',\n warning: 'M8,2.5L14.5,13.5H1.5Z M8,6.5V9.5 M8,11.5V11.5',\n /** A radio's selection: filled by ui.css. */\n dot: 'M11,8A3,3 0 1,1 5,8A3,3 0 1,1 11,8Z',\n /** A Rate mark (C-2). */\n lozenge: 'M8,1.5L14.5,8L8,14.5L1.5,8Z',\n info: 'M14.5,8A6.5,6.5 0 1,1 1.5,8A6.5,6.5 0 1,1 14.5,8Z M8,7.5V11.5 M8,4.75V4.75',\n // The composed components' own (REQ-472), Reflex 0.7's paths.\n plus: 'M8,3.5V12.5M3.5,8H12.5',\n chevronDown: 'M4,6L8,10L12,6',\n chevronRight: 'M6,4L10,8L6,12',\n chevronLeft: 'M10,4L6,8L10,12',\n arrowUp: 'M8,12.5V3.5M4.5,7L8,3.5L11.5,7',\n arrowDown: 'M8,3.5V12.5M4.5,9L8,12.5L11.5,9',\n sortUp: 'M5,9.5L8,5.5L11,9.5Z',\n sortDown: 'M5,6.5L8,10.5L11,6.5Z',\n sort: 'M5,7L8,3.5L11,7Z M5,9L8,12.5L11,9Z',\n ellipsis: 'M3.5,8V8 M8,8V8 M12.5,8V8',\n});\nexport type UiGlyph = keyof typeof UI_GLYPHS;\nexport const glyph = (name: UiGlyph) => el('svg', { part: 'sp-mark', 'data-glyph': name, viewBox: '0 0 16 16', 'aria-hidden': 'true' }, [el('path', { d: UI_GLYPHS[name] })]);\n\n\n/** Text for assistive technology only, hidden for sight as a native input is (REQ-314). */\nexport const sr = (value: string) => el('span', { class: 'sp-ui-sr' }, [text(value)]);\n\n/** The id relations of a control derive from its `id`, else its `name` (REQ-329). */\nexport const baseOf = (props: { readonly id?: string; readonly name?: string }) => props.id ?? props.name;\n\n/** A native radio or checkbox, hidden for sight: the control the adapter binds (REQ-314). */\nexport function nativeInput(type: 'checkbox' | 'radio', attrs: Attrs): UiElement {\n return el('input', { type, class: 'sp-ui-native', ...attrs }, [], 'native');\n}\n\n/** A length a component may write inline (a width, an extent), and nothing else. */\nconst LENGTH = /^\\d+(?:\\.\\d+)?(?:px|%|em|rem|ch|vw|vh)$/;\n\n/** The length, or `undefined` with `SP017` when it is not a plain CSS length (REQ-486). */\nexport function cssLength(value: string | undefined, component: string, property: string): string | undefined {\n if (value === undefined || LENGTH.test(value)) return value;\n if (process.env.NODE_ENV !== 'production') diagnose('SP017', component, { property, message: `${JSON.stringify(value)} is not a plain length; it is dropped.` });\n return undefined;\n}\n\n/** A native button that emits `close`, its only content the exact ✕. */\nexport const iconClose = (label: string) => el('button', { type: 'button', class: 'sp-ui-icon-button', 'aria-label': label }, [glyph('cross')], 'close');\n\n/** The schemes a link may carry; a URL without one is relative and always allowed. */\nconst SAFE_SCHEMES = new Set(['http', 'https', 'mailto', 'tel']);\n\n/**\n * The href, or `undefined` with `SP017` when it names a scheme other than http(s), mailto or tel\n * (`javascript:`, `data:`…). Read as a browser does: control characters and spaces are ignored.\n */\nexport function safeHref(href: string | undefined, component: string, property = 'href'): string | undefined {\n if (href === undefined) return undefined;\n const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(href.replace(/[\\u0000-\\u0020\\u007f]/g, ''))?.[1];\n if (scheme === undefined || SAFE_SCHEMES.has(scheme.toLowerCase())) return href;\n if (process.env.NODE_ENV !== 'production') diagnose('SP017', component, { property, message: `The scheme \"${scheme}:\" is not allowed; the link is dropped.` });\n return undefined;\n}\n\n/** A heading's tag from `headingLevel`: `h2`..`h6`, `h3` when unset, else `h3` with `SP017`. */\nexport function headingTag(level: unknown, component: string): string {\n if (level === undefined) return 'h3';\n if (level === 2 || level === 3 || level === 4 || level === 5 || level === 6) return `h${level}`;\n if (process.env.NODE_ENV !== 'production') diagnose('SP017', component, { property: 'headingLevel', message: `${JSON.stringify(level)} is not a level in 2..6; h3 is drawn.` });\n return 'h3';\n}\n"]}
@@ -0,0 +1,93 @@
1
+ import { round2 } from './chunk-5MP3BLZK.js';
2
+ import { diagnose } from './chunk-WYFRHI4S.js';
3
+
4
+ // src/palette/contrast.ts
5
+ var PALETTE_PAIRS = /* @__PURE__ */ Object.freeze([
6
+ { pair: "ink", threshold: 4.5, foreground: (p) => p.ink },
7
+ { pair: "ink-secondary", threshold: 4.5, foreground: (p) => p.inkSecondary },
8
+ { pair: "text", threshold: 4.5, foreground: (p) => p.text },
9
+ { pair: "text-muted", threshold: 4.5, foreground: (p) => p.textMuted },
10
+ { pair: "rule", threshold: 3, foreground: (p) => p.rule },
11
+ { pair: "grid", threshold: 3, foreground: (p) => p.grid },
12
+ { pair: "focus", threshold: 3, foreground: (p) => p.focus ?? p.ink },
13
+ { pair: "heighten-outline", threshold: 3, foreground: (p) => p.ink, background: (p) => p.heighten },
14
+ { pair: "heighten-text", threshold: 4.5, foreground: (p) => p.text, background: (p) => p.heighten }
15
+ ]);
16
+ var CREAM = "#EDE7DA";
17
+ var HEX = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
18
+ function luminance(hex) {
19
+ let value = hex.slice(1);
20
+ if (value.length === 3) value = [...value].map((c) => c + c).join("");
21
+ const [r, g, b] = [0, 2, 4].map((i) => {
22
+ const c = parseInt(value.slice(i, i + 2), 16) / 255;
23
+ return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
24
+ });
25
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
26
+ }
27
+ function contrastRatio(foreground, background) {
28
+ const a = luminance(foreground);
29
+ const b = luminance(background);
30
+ return (Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05);
31
+ }
32
+ function checkPalette(palette, substrate) {
33
+ const ground = palette.substrate ?? substrate ?? CREAM;
34
+ const findings = [];
35
+ for (const { pair, threshold, foreground, background } of PALETTE_PAIRS) {
36
+ const fg = foreground(palette);
37
+ const bg = background ? background(palette) : ground;
38
+ if (!fg || !bg || !HEX.test(fg) || !HEX.test(bg)) continue;
39
+ const ratio = contrastRatio(fg, bg);
40
+ if (ratio < threshold) findings.push({ pair, foreground: fg, background: bg, ratio: round2(ratio), threshold });
41
+ }
42
+ return findings;
43
+ }
44
+
45
+ // src/palette/palette.ts
46
+ var FIELDS = ["substrate", "ink", "inkSecondary", "heighten", "rule", "grid", "text", "textMuted", "focus"];
47
+ var property = (field) => field === "focus" ? "--sp-ui-focus-color" : `--sp-${field.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)}`;
48
+ var PALETTE_PROPERTIES = /* @__PURE__ */ Object.freeze(
49
+ Object.fromEntries(FIELDS.map((field) => [field, property(field)]))
50
+ );
51
+ var COLOUR_CHARS = /^[\w\s#%.,/()+-]+$/;
52
+ var COLOUR_FUNCTIONS = /* @__PURE__ */ new Set(["rgb", "rgba", "hsl", "hsla", "hwb", "lab", "lch", "oklab", "oklch", "color", "color-mix", "light-dark", "var"]);
53
+ var isColour = (value) => COLOUR_CHARS.test(value) && [...value.matchAll(/([\w-]*)\(/g)].every(([, name]) => COLOUR_FUNCTIONS.has(name.toLowerCase()));
54
+ function resolvePalette(...layers) {
55
+ const out = {};
56
+ for (const layer of layers) {
57
+ if (!layer) continue;
58
+ for (const [field, value] of Object.entries(layer)) {
59
+ if (value === void 0) continue;
60
+ const colour = typeof value === "string" ? value.trim() : "";
61
+ if (!FIELDS.includes(field) || !colour || !isColour(colour)) {
62
+ if (process.env.NODE_ENV !== "production") diagnose("SP024", "Palette", { property: field, message: `${JSON.stringify(value)} is dropped.` });
63
+ continue;
64
+ }
65
+ out[field] = colour;
66
+ }
67
+ }
68
+ if (Object.keys(out).length === 0) return void 0;
69
+ if (process.env.NODE_ENV !== "production") {
70
+ for (const finding of checkPalette(out)) {
71
+ diagnose("SP023", "Palette", {
72
+ property: finding.pair,
73
+ message: `${finding.foreground} on ${finding.background} is ${finding.ratio.toFixed(2)}:1, below ${finding.threshold}:1.`
74
+ });
75
+ }
76
+ }
77
+ return out;
78
+ }
79
+ function paletteStyle(palette) {
80
+ if (!palette) return "";
81
+ return FIELDS.filter((field) => typeof palette[field] === "string" && isColour(palette[field].trim())).map((field) => `${property(field)}:${palette[field].trim()}`).join(";");
82
+ }
83
+ function nestProvider(outer, own) {
84
+ const out = { ...outer };
85
+ for (const [key, value] of Object.entries(own)) if (value !== void 0) out[key] = value;
86
+ if (outer?.palette && own.palette) out.palette = { ...outer.palette, ...defined(own.palette) };
87
+ return out;
88
+ }
89
+ var defined = (palette) => Object.fromEntries(Object.entries(palette).filter(([, value]) => value !== void 0));
90
+
91
+ export { PALETTE_PAIRS, PALETTE_PROPERTIES, checkPalette, contrastRatio, nestProvider, paletteStyle, resolvePalette };
92
+ //# sourceMappingURL=chunk-ANJSW5JX.js.map
93
+ //# sourceMappingURL=chunk-ANJSW5JX.js.map