@kanzo-tech/ui 0.12.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/analytics.d.ts +1 -0
  2. package/dist/analytics.d.ts.map +1 -1
  3. package/dist/charts/chart-inputs.d.ts +6 -5
  4. package/dist/charts/chart-inputs.d.ts.map +1 -1
  5. package/dist/charts/chart-inputs.js +78 -77
  6. package/dist/charts/chart-inputs.js.map +1 -1
  7. package/dist/charts/chart-marks.d.ts +2 -1
  8. package/dist/charts/chart-marks.d.ts.map +1 -1
  9. package/dist/charts/chart-marks.js.map +1 -1
  10. package/dist/charts/chart-root.d.ts +8 -3
  11. package/dist/charts/chart-root.d.ts.map +1 -1
  12. package/dist/charts/chart-root.js +60 -60
  13. package/dist/charts/chart-root.js.map +1 -1
  14. package/dist/charts/chart-spec.d.ts +11 -4
  15. package/dist/charts/chart-spec.d.ts.map +1 -1
  16. package/dist/charts/chart-spec.js +44 -40
  17. package/dist/charts/chart-spec.js.map +1 -1
  18. package/dist/charts/chart-stat.d.ts +3 -2
  19. package/dist/charts/chart-stat.d.ts.map +1 -1
  20. package/dist/charts/chart-stat.js +10 -9
  21. package/dist/charts/chart-stat.js.map +1 -1
  22. package/dist/composites/language-picker.d.ts +7 -0
  23. package/dist/composites/language-picker.d.ts.map +1 -1
  24. package/dist/composites/language-picker.js +38 -36
  25. package/dist/composites/language-picker.js.map +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +661 -660
  29. package/dist/lib/control-size.d.ts +26 -0
  30. package/dist/lib/control-size.d.ts.map +1 -0
  31. package/dist/lib/control-size.js +11 -0
  32. package/dist/lib/control-size.js.map +1 -0
  33. package/dist/simples/button.d.ts.map +1 -1
  34. package/dist/simples/button.js +34 -33
  35. package/dist/simples/button.js.map +1 -1
  36. package/dist/simples/checkbox.d.ts.map +1 -1
  37. package/dist/simples/checkbox.js +42 -42
  38. package/dist/simples/checkbox.js.map +1 -1
  39. package/dist/simples/combobox.d.ts.map +1 -1
  40. package/dist/simples/combobox.js +48 -49
  41. package/dist/simples/combobox.js.map +1 -1
  42. package/dist/simples/date-picker.d.ts +58 -2
  43. package/dist/simples/date-picker.d.ts.map +1 -1
  44. package/dist/simples/date-picker.js +207 -76
  45. package/dist/simples/date-picker.js.map +1 -1
  46. package/dist/simples/input-group.d.ts +9 -9
  47. package/dist/simples/input-group.d.ts.map +1 -1
  48. package/dist/simples/input-group.js +68 -78
  49. package/dist/simples/input-group.js.map +1 -1
  50. package/dist/simples/input.d.ts +9 -9
  51. package/dist/simples/input.d.ts.map +1 -1
  52. package/dist/simples/input.js +13 -14
  53. package/dist/simples/input.js.map +1 -1
  54. package/dist/simples/native-select.d.ts +9 -9
  55. package/dist/simples/native-select.d.ts.map +1 -1
  56. package/dist/simples/native-select.js +29 -28
  57. package/dist/simples/native-select.js.map +1 -1
  58. package/dist/simples/number-input.d.ts +9 -9
  59. package/dist/simples/number-input.d.ts.map +1 -1
  60. package/dist/simples/number-input.js +27 -27
  61. package/dist/simples/number-input.js.map +1 -1
  62. package/dist/simples/password-input.d.ts.map +1 -1
  63. package/dist/simples/password-input.js +24 -20
  64. package/dist/simples/password-input.js.map +1 -1
  65. package/dist/simples/pin-input.d.ts +9 -9
  66. package/dist/simples/pin-input.d.ts.map +1 -1
  67. package/dist/simples/pin-input.js +30 -29
  68. package/dist/simples/pin-input.js.map +1 -1
  69. package/dist/simples/radio-group.d.ts.map +1 -1
  70. package/dist/simples/radio-group.js +44 -43
  71. package/dist/simples/radio-group.js.map +1 -1
  72. package/dist/simples/segment-group.d.ts +8 -0
  73. package/dist/simples/segment-group.d.ts.map +1 -1
  74. package/dist/simples/segment-group.js +55 -47
  75. package/dist/simples/segment-group.js.map +1 -1
  76. package/dist/simples/switch.d.ts.map +1 -1
  77. package/dist/simples/switch.js +18 -12
  78. package/dist/simples/switch.js.map +1 -1
  79. package/dist/simples/tags-input.d.ts.map +1 -1
  80. package/dist/simples/tags-input.js +44 -39
  81. package/dist/simples/tags-input.js.map +1 -1
  82. package/dist/simples/toggle.d.ts +9 -9
  83. package/dist/simples/toggle.d.ts.map +1 -1
  84. package/dist/simples/toggle.js +24 -23
  85. package/dist/simples/toggle.js.map +1 -1
  86. package/package.json +5 -5
@@ -1,31 +1,34 @@
1
- import { isValidElement as y, Fragment as k } from "react";
2
- import { isAggregateExpression as v } from "@uwdata/mosaic-sql";
3
- import { chartColorScale as w, isColorToken as $ } from "./chart-config.js";
4
- function B(t, e) {
1
+ import { isValidElement as m, Fragment as k } from "react";
2
+ import { asTableRef as v, isAggregateExpression as w } from "@uwdata/mosaic-sql";
3
+ import { chartColorScale as $, isColorToken as C } from "./chart-config.js";
4
+ function B(t) {
5
+ return t === void 0 ? void 0 : String(typeof t == "string" ? v(t) : t);
6
+ }
7
+ function G(t, e) {
5
8
  return Object.assign(() => null, { displayName: t, __chart: e });
6
9
  }
7
- function C(t) {
10
+ function S(t) {
8
11
  return typeof t == "function" && typeof t.__chart == "function";
9
12
  }
10
- const m = 16;
11
- function f(t, e, r, i) {
12
- if (t == null || typeof t == "boolean" || i > m) return;
13
+ const y = 16;
14
+ function u(t, e, r, i) {
15
+ if (t == null || typeof t == "boolean" || i > y) return;
13
16
  if (Array.isArray(t)) {
14
- for (const o of t) f(o, e, r, i + 1);
17
+ for (const o of t) u(o, e, r, i + 1);
15
18
  return;
16
19
  }
17
- if (!y(t)) return;
20
+ if (!m(t)) return;
18
21
  if (t.type === k) {
19
- f(t.props.children, e, r, i + 1);
22
+ u(t.props.children, e, r, i + 1);
20
23
  return;
21
24
  }
22
- if (!C(t.type)) return;
25
+ if (!S(t.type)) return;
23
26
  const n = t.type.__chart(t.props, e);
24
27
  Array.isArray(n) ? r.push(...n) : r.push(n);
25
28
  }
26
29
  function A(t, e) {
27
30
  const r = [];
28
- return f(t, e, r, 0), r;
31
+ return u(t, e, r, 0), r;
29
32
  }
30
33
  const d = { top: "Top", right: "Right", bottom: "Bottom", left: "Left" };
31
34
  function g(t, e) {
@@ -33,7 +36,7 @@ function g(t, e) {
33
36
  const r = typeof e == "number" ? { top: e, right: e, bottom: e, left: e } : e;
34
37
  return Object.keys(d).filter((i) => r[i] !== void 0).map((i) => ({ kind: "attribute", name: `${t}${d[i]}`, value: r[i] }));
35
38
  }
36
- function G(t, e) {
39
+ function U(t, e) {
37
40
  const r = [
38
41
  { kind: "attribute", name: "width", value: t.width },
39
42
  { kind: "attribute", name: "height", value: t.height },
@@ -41,11 +44,11 @@ function G(t, e) {
41
44
  ...g("facetMargin", t.facetMargin)
42
45
  ];
43
46
  t.aspectRatio !== void 0 && r.push({ kind: "attribute", name: "aspectRatio", value: t.aspectRatio }), t.facetGrid !== void 0 && r.push({ kind: "attribute", name: "facetGrid", value: t.facetGrid }), t.facetLabel !== void 0 && r.push({ kind: "attribute", name: "facetLabel", value: t.facetLabel });
44
- const i = w(e.config);
47
+ const i = $(e.config);
45
48
  i && (r.push({ kind: "attribute", name: "colorDomain", value: i.domain }), r.push({
46
49
  kind: "attribute",
47
50
  name: "colorRange",
48
- value: i.range.map((n) => $(n) ? e.resolveColor(n) : n)
51
+ value: i.range.map((n) => C(n) ? e.resolveColor(n) : n)
49
52
  })), r.push(...A(t.children, e));
50
53
  for (const n of t.attributes ?? []) r.push({ kind: "raw", value: n });
51
54
  return r;
@@ -61,29 +64,29 @@ const O = {
61
64
  function c(t) {
62
65
  return `<Chart${t[0].toUpperCase()}${t.slice(1)}>`;
63
66
  }
64
- function S(t) {
67
+ function j(t) {
65
68
  return Object.values(t.options).some(
66
- (e) => v(e) !== 0
69
+ (e) => w(e) !== 0
67
70
  );
68
71
  }
69
- function j(t) {
72
+ function D(t) {
70
73
  var e;
71
74
  return !!((e = t.resolver) != null && e.cross);
72
75
  }
73
- function U(t, e) {
76
+ function Y(t, e) {
74
77
  const r = [], i = t.filter((o) => o.kind === "mark"), n = (e == null ? void 0 : e.shared) ?? [];
75
78
  for (const o of t) {
76
79
  if (o.kind !== "interactor") continue;
77
80
  if (o.interactor === "highlight") {
78
81
  const s = o.options.by;
79
82
  if (!s) continue;
80
- if (j(s)) {
83
+ if (D(s)) {
81
84
  r.push(
82
85
  "<ChartHighlight> reads a cross-filtered selection, which by definition hides a clause from the client that published it — so the predicate comes back empty and nothing is ever dimmed. Drop `by` to use the root's own selection, or point it at a plain union."
83
86
  );
84
87
  continue;
85
88
  }
86
- const p = i.find(S);
89
+ const p = i.find(j);
87
90
  n.includes(s) && p && r.push(
88
91
  `<ChartHighlight by={…}> targets a selection shared by the whole <MosaicProvider>, and ${c(p.mark)} aggregates. The highlight appends its predicate as a column on that GROUP BY query, so as soon as another chart publishes a clause over a column this plot does not group by, DuckDB answers "must appear in the GROUP BY clause", the query dies and this plot silently keeps its previous render. Drop \`by\` — the root's own selection only ever names columns this plot groups by.`
89
92
  );
@@ -91,43 +94,44 @@ function U(t, e) {
91
94
  }
92
95
  const a = o.interactor === "intervalX" ? "x" : o.interactor === "intervalY" ? "y" : null;
93
96
  if (!a) continue;
94
- const h = i.find((s) => O[s.mark] === a);
95
- h && r.push(
96
- `${c(o.interactor)} brushes a band scale (${c(h.mark)} makes ${a} categorical). Mosaic throws "Unrecognized scale type: band" on hover and blanks every other chart sharing the coordinator. Use <ChartToggle${a.toUpperCase()}> for categories, or bin ${a} first.`
97
+ const l = i.find((s) => O[s.mark] === a);
98
+ l && r.push(
99
+ `${c(o.interactor)} brushes a band scale (${c(l.mark)} makes ${a} categorical). Mosaic throws "Unrecognized scale type: band" on hover and blanks every other chart sharing the coordinator. Use <ChartToggle${a.toUpperCase()}> for categories, or bin ${a} first.`
97
100
  );
98
101
  }
99
102
  return r;
100
103
  }
101
104
  const b = /* @__PURE__ */ new WeakMap();
102
- let D = 0;
103
- function u(t) {
105
+ let R = 0;
106
+ function f(t) {
104
107
  let e = b.get(t);
105
- return e === void 0 && (e = ++D, b.set(t, e)), e;
108
+ return e === void 0 && (e = ++R, b.set(t, e)), e;
106
109
  }
107
- function l(t, e) {
108
- if (typeof t == "function") return `fn#${u(t)}`;
110
+ function h(t, e) {
111
+ if (typeof t == "function") return `fn#${f(t)}`;
109
112
  if (typeof t == "symbol") return `sym#${String(t.description)}`;
110
113
  if (t === null || typeof t != "object") return t;
111
- if (e > m) return `deep#${u(t)}`;
112
- if (Array.isArray(t)) return t.map((n) => l(n, e + 1));
114
+ if (e > y) return `deep#${f(t)}`;
115
+ if (Array.isArray(t)) return t.map((n) => h(n, e + 1));
113
116
  const r = Object.getPrototypeOf(t);
114
117
  if (r === Object.prototype || r === null)
115
- return Object.fromEntries(Object.entries(t).map(([n, o]) => [n, l(o, e + 1)]));
118
+ return Object.fromEntries(Object.entries(t).map(([n, o]) => [n, h(o, e + 1)]));
116
119
  let i = "[object]";
117
120
  try {
118
121
  i = String(t);
119
122
  } catch {
120
123
  }
121
- return i.startsWith("[object") ? `obj#${u(t)}` : i;
124
+ return i.startsWith("[object") ? `obj#${f(t)}` : i;
122
125
  }
123
- function Y(t) {
124
- return JSON.stringify(l(t, 0));
126
+ function E(t) {
127
+ return JSON.stringify(h(t, 0));
125
128
  }
126
129
  export {
127
- G as buildChartSpec,
128
- B as chartDescriptor,
129
- Y as chartSpecSignature,
130
- U as chartSpecWarnings,
130
+ U as buildChartSpec,
131
+ G as chartDescriptor,
132
+ E as chartSpecSignature,
133
+ Y as chartSpecWarnings,
134
+ B as chartTableKey,
131
135
  A as compileChartSpec
132
136
  };
133
137
  //# sourceMappingURL=chart-spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-spec.js","sources":["../../src/charts/chart-spec.ts"],"sourcesContent":["import { Fragment, isValidElement, type ReactNode } from \"react\";\nimport type { Selection } from \"@uwdata/mosaic-core\";\nimport { isAggregateExpression } from \"@uwdata/mosaic-sql\";\nimport { chartColorScale, isColorToken, type ChartConfig } from \"./chart-config.js\";\n\n/**\n * The plot spec as plain data.\n *\n * `ChartRoot` compiles its descriptor children to this list and only then maps it onto `vg.*`.\n * The indirection is what makes the compiler pure: no coordinator, no DOM, no vgplot — so the\n * grammar is unit-testable and the vgplot binding is a single switch. (`isAggregateExpression` is\n * the one import, a pure AST predicate mosaic-sql exports for exactly this question.)\n */\n\nexport type ChartMarkSource =\n | { readonly kind: \"table\"; readonly table: string; readonly filterBy: Selection | null }\n | { readonly kind: \"values\"; readonly values: readonly unknown[] }\n /** A decorator mark (`frame`, `gridX`, `gridY`) — takes options only, never data. */\n | null;\n\nexport interface ChartMarkDirective {\n readonly kind: \"mark\";\n readonly mark: string;\n readonly source: ChartMarkSource;\n readonly options: Readonly<Record<string, unknown>>;\n}\n\nexport interface ChartInteractorDirective {\n readonly kind: \"interactor\";\n readonly interactor: string;\n readonly options: Readonly<Record<string, unknown>>;\n}\n\nexport interface ChartAttributeDirective {\n readonly kind: \"attribute\";\n readonly name: string;\n readonly value: unknown;\n}\n\n/** The escape hatch: a `vg.*` directive the layer does not wrap, passed through untouched. */\nexport interface ChartRawDirective {\n readonly kind: \"raw\";\n readonly value: unknown;\n}\n\nexport type ChartDirective =\n | ChartMarkDirective\n | ChartInteractorDirective\n | ChartAttributeDirective\n | ChartRawDirective;\n\nexport interface ChartSpecContext {\n /** The relation every table-backed mark reads from. */\n readonly table?: string;\n /** What marks filter by; `null` means \"the full relation\". */\n readonly filterBy: Selection | null;\n /** Where interactors publish. */\n readonly as: Selection | null;\n readonly config: ChartConfig;\n /** Turns a `var(--token)` / `--token` reference into a Plot-safe colour. */\n readonly resolveColor: (token: string) => string;\n}\n\nexport type ChartCompile<P> = (props: P, ctx: ChartSpecContext) => ChartDirective | ChartDirective[];\n\n/** An inert child: renders nothing, carries its compilation on a static. */\nexport interface ChartDescriptor<P> {\n (props: P): null;\n readonly displayName: string;\n readonly __chart: ChartCompile<P>;\n}\n\nexport function chartDescriptor<P>(displayName: string, compile: ChartCompile<P>): ChartDescriptor<P> {\n return Object.assign(() => null, { displayName, __chart: compile }) as ChartDescriptor<P>;\n}\n\nfunction isChartDescriptor(type: unknown): type is ChartDescriptor<unknown> {\n return typeof type === \"function\" && typeof (type as { __chart?: unknown }).__chart === \"function\";\n}\n\n/** Guards against a pathological tree; nothing legitimate nests fragments this deep. */\nconst MAX_DEPTH = 16;\n\nfunction collect(node: ReactNode, ctx: ChartSpecContext, out: ChartDirective[], depth: number): void {\n if (node == null || typeof node === \"boolean\" || depth > MAX_DEPTH) return;\n if (Array.isArray(node)) {\n for (const child of node) collect(child as ReactNode, ctx, out, depth + 1);\n return;\n }\n if (!isValidElement(node)) return;\n if (node.type === Fragment) {\n collect((node.props as { children?: ReactNode }).children, ctx, out, depth + 1);\n return;\n }\n // Anything else is a DOM child (ChartLegend, a caption…) — rendered, never compiled. A\n // descriptor hidden inside a consumer's own component is invisible here, as in Recharts.\n if (!isChartDescriptor(node.type)) return;\n const produced = node.type.__chart(node.props, ctx);\n if (Array.isArray(produced)) out.push(...produced);\n else out.push(produced);\n}\n\n/** The descriptor children, in source order. Fragments and arrays flatten; `null`/`false` vanish. */\nexport function compileChartSpec(children: ReactNode, ctx: ChartSpecContext): ChartDirective[] {\n const out: ChartDirective[] = [];\n collect(children, ctx, out, 0);\n return out;\n}\n\nexport interface ChartMargin {\n top?: number;\n right?: number;\n bottom?: number;\n left?: number;\n}\n\n/**\n * The plot-wide half of faceting. The panels themselves come from a mark's `fx` / `fy` channels\n * (`<ChartBarY fx=\"region\" />`); per-scale options go on `ChartFacetX` / `ChartFacetY`.\n */\nexport interface ChartFacetOptions {\n /**\n * Space around each facet panel — the gutter *between* small multiples.\n *\n * Not where the panel titles go: those are drawn in the **plot's** top margin, so a `margin`\n * with a small `top` renders them into nothing and the panels come out anonymous. Leave ~26px.\n */\n facetMargin?: number | ChartMargin;\n /** Draw the grid across the facet panels. */\n facetGrid?: boolean;\n /** The shared label for the facet axes; `null` removes it. */\n facetLabel?: string | null;\n}\n\nexport interface ChartSpecOptions extends ChartFacetOptions {\n children: ReactNode;\n /** Measured from the container by `TokenizedPlot`; vgplot defaults to 640 without it. */\n width: number;\n height: number;\n margin?: number | ChartMargin;\n aspectRatio?: number;\n attributes?: readonly unknown[];\n}\n\nconst MARGIN_SIDES = { top: \"Top\", right: \"Right\", bottom: \"Bottom\", left: \"Left\" } as const;\n\nfunction marginDirectives(\n prefix: \"margin\" | \"facetMargin\",\n margin: number | ChartMargin | undefined,\n): ChartAttributeDirective[] {\n if (margin === undefined) return [];\n const sides: ChartMargin =\n typeof margin === \"number\" ? { top: margin, right: margin, bottom: margin, left: margin } : margin;\n return (Object.keys(MARGIN_SIDES) as (keyof ChartMargin)[])\n .filter((side) => sides[side] !== undefined)\n .map((side) => ({ kind: \"attribute\", name: `${prefix}${MARGIN_SIDES[side]}`, value: sides[side] }));\n}\n\n/**\n * The whole plot: frame attributes, the config's colour scale, the children, then the raw\n * escape hatch last so a consumer directive can override anything the layer decided.\n */\nexport function buildChartSpec(options: ChartSpecOptions, ctx: ChartSpecContext): ChartDirective[] {\n const directives: ChartDirective[] = [\n { kind: \"attribute\", name: \"width\", value: options.width },\n { kind: \"attribute\", name: \"height\", value: options.height },\n ...marginDirectives(\"margin\", options.margin),\n ...marginDirectives(\"facetMargin\", options.facetMargin),\n ];\n if (options.aspectRatio !== undefined) {\n directives.push({ kind: \"attribute\", name: \"aspectRatio\", value: options.aspectRatio });\n }\n if (options.facetGrid !== undefined) {\n directives.push({ kind: \"attribute\", name: \"facetGrid\", value: options.facetGrid });\n }\n if (options.facetLabel !== undefined) {\n directives.push({ kind: \"attribute\", name: \"facetLabel\", value: options.facetLabel });\n }\n const scale = chartColorScale(ctx.config);\n if (scale) {\n directives.push({ kind: \"attribute\", name: \"colorDomain\", value: scale.domain });\n directives.push({\n kind: \"attribute\",\n name: \"colorRange\",\n value: scale.range.map((c) => (isColorToken(c) ? ctx.resolveColor(c) : c)),\n });\n }\n directives.push(...compileChartSpec(options.children, ctx));\n for (const raw of options.attributes ?? []) directives.push({ kind: \"raw\", value: raw });\n return directives;\n}\n\n/** Marks whose primary channel is a band scale, which an interval brush cannot read. */\nconst BAND_MARKS: Record<string, \"x\" | \"y\"> = {\n barY: \"x\", waffleY: \"x\", cellX: \"x\",\n barX: \"y\", waffleX: \"y\", cellY: \"y\",\n};\n\nfunction component(name: string): string {\n return `<Chart${name[0]!.toUpperCase()}${name.slice(1)}>`;\n}\n\n/** A mark whose query carries a `GROUP BY` — any channel holding an aggregate expression. */\nfunction isAggregating(mark: ChartMarkDirective): boolean {\n // `isAggregateExpression` walks a SQL AST and answers 0 for anything that is not a node, so a\n // plain `y=\"region\"` costs one type check rather than a guard here.\n return Object.values(mark.options).some(\n (value) => isAggregateExpression(value as Parameters<typeof isAggregateExpression>[0]) !== 0,\n );\n}\n\n/** A cross-filtered selection never reports its own clause back to the client that published it. */\nfunction isCross(selection: Selection): boolean {\n return Boolean(selection.resolver?.cross);\n}\n\nexport interface ChartSpecWarningContext {\n /**\n * Selections shared by the whole `<MosaicProvider>` — anyone's clause can land in these, so they\n * are never safe as a `ChartHighlight` target on an aggregating mark.\n */\n readonly shared?: readonly unknown[];\n}\n\n/**\n * Combinations that fail at *runtime*, reported at build time.\n *\n * Both entries here are silent failures — the kind that costs an afternoon because nothing on\n * screen says anything is wrong.\n *\n * 1. An interval brush over a band scale throws `Unrecognized scale type: band` from Mosaic's\n * pre-aggregator on pointer-enter — and because that pre-aggregator is coordinator-scoped, the\n * blast radius is every other chart on the page, which go blank with no error of their own.\n * 2. A `ChartHighlight` pointed at a page-wide selection over an aggregating mark. The highlight\n * appends its predicate as an extra column on the mark's own `GROUP BY` query, so the first\n * clause naming a column this plot does not group by is a DuckDB binder error; the query dies\n * and the plot silently keeps its previous render. The default `by` is the root's own selection\n * and cannot hit this — only an explicit `by`/`as` naming a shared selection can.\n */\nexport function chartSpecWarnings(spec: ChartDirective[], context?: ChartSpecWarningContext): string[] {\n const warnings: string[] = [];\n const marks = spec.filter((d): d is ChartMarkDirective => d.kind === \"mark\");\n const shared = context?.shared ?? [];\n\n for (const d of spec) {\n if (d.kind !== \"interactor\") continue;\n\n if (d.interactor === \"highlight\") {\n const by = d.options.by as Selection | null | undefined;\n if (!by) continue;\n if (isCross(by)) {\n warnings.push(\n \"<ChartHighlight> reads a cross-filtered selection, which by definition hides a clause \" +\n \"from the client that published it — so the predicate comes back empty and nothing is \" +\n \"ever dimmed. Drop `by` to use the root's own selection, or point it at a plain union.\",\n );\n continue;\n }\n const aggregating = marks.find(isAggregating);\n if (shared.includes(by) && aggregating) {\n warnings.push(\n `<ChartHighlight by={…}> targets a selection shared by the whole <MosaicProvider>, and ` +\n `${component(aggregating.mark)} aggregates. The highlight appends its predicate as a ` +\n \"column on that GROUP BY query, so as soon as another chart publishes a clause over a \" +\n \"column this plot does not group by, DuckDB answers \\\"must appear in the GROUP BY \" +\n \"clause\\\", the query dies and this plot silently keeps its previous render. Drop `by` \" +\n \"— the root's own selection only ever names columns this plot groups by.\",\n );\n }\n continue;\n }\n\n const axis = d.interactor === \"intervalX\" ? \"x\" : d.interactor === \"intervalY\" ? \"y\" : null;\n if (!axis) continue;\n const clash = marks.find((m) => BAND_MARKS[m.mark] === axis);\n if (clash) {\n warnings.push(\n `${component(d.interactor)} brushes a band scale ` +\n `(${component(clash.mark)} makes ${axis} categorical). ` +\n \"Mosaic throws \\\"Unrecognized scale type: band\\\" on hover and blanks every other chart \" +\n `sharing the coordinator. Use <ChartToggle${axis.toUpperCase()}> for categories, or bin ${axis} first.`,\n );\n }\n }\n return warnings;\n}\n\n/**\n * A stable fingerprint of a compiled spec, for `TokenizedPlot`'s dependency list — the plot is\n * rebuilt (and its queries re-run) only when the grammar actually changed, not on every render.\n * SQL expression nodes (`count()`, `bin(x)`) stringify to their SQL; selections, params and\n * functions fall back to identity, which is stable as long as the caller does not rebuild them.\n */\nconst identities = new WeakMap<object, number>();\nlet nextIdentity = 0;\n\nfunction identityOf(value: object): number {\n let id = identities.get(value);\n if (id === undefined) {\n id = ++nextIdentity;\n identities.set(value, id);\n }\n return id;\n}\n\nfunction tag(value: unknown, depth: number): unknown {\n if (typeof value === \"function\") return `fn#${identityOf(value)}`;\n if (typeof value === \"symbol\") return `sym#${String(value.description)}`;\n if (value === null || typeof value !== \"object\") return value;\n if (depth > MAX_DEPTH) return `deep#${identityOf(value)}`;\n if (Array.isArray(value)) return value.map((v) => tag(v, depth + 1));\n const proto: unknown = Object.getPrototypeOf(value);\n if (proto === Object.prototype || proto === null) {\n return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, tag(v, depth + 1)]));\n }\n let text = \"[object]\";\n try {\n text = String(value);\n } catch {\n /* a toString that throws is no worse than no toString */\n }\n return text.startsWith(\"[object\") ? `obj#${identityOf(value)}` : text;\n}\n\nexport function chartSpecSignature(directives: readonly ChartDirective[]): string {\n return JSON.stringify(tag(directives, 0));\n}\n"],"names":["chartDescriptor","displayName","compile","isChartDescriptor","type","MAX_DEPTH","collect","node","ctx","out","depth","child","isValidElement","Fragment","produced","compileChartSpec","children","MARGIN_SIDES","marginDirectives","prefix","margin","sides","side","buildChartSpec","options","directives","scale","chartColorScale","c","isColorToken","raw","BAND_MARKS","component","name","isAggregating","mark","value","isAggregateExpression","isCross","selection","_a","chartSpecWarnings","spec","context","warnings","marks","d","shared","by","aggregating","axis","clash","m","identities","nextIdentity","identityOf","id","tag","v","proto","k","text","chartSpecSignature"],"mappings":"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"}
1
+ {"version":3,"file":"chart-spec.js","sources":["../../src/charts/chart-spec.ts"],"sourcesContent":["import { Fragment, isValidElement, type ReactNode } from \"react\";\nimport type { Selection } from \"@uwdata/mosaic-core\";\nimport type { TableExpr } from \"@kanzo-tech/mosaic\";\nimport { asTableRef, isAggregateExpression } from \"@uwdata/mosaic-sql\";\nimport { chartColorScale, isColorToken, type ChartConfig } from \"./chart-config.js\";\n\n/**\n * The plot spec as plain data.\n *\n * `ChartRoot` compiles its descriptor children to this list and only then maps it onto `vg.*`.\n * The indirection is what makes the compiler pure: no coordinator, no DOM, no vgplot — so the\n * grammar is unit-testable and the vgplot binding is a single switch. (mosaic-sql is the one\n * engine import: `isAggregateExpression` and `asTableRef`, both pure AST.)\n */\n\n/**\n * A relation's SQL, which is also its identity. A host that writes `verbatim(sql)` inline builds a\n * new node every render and still names the same relation, so the plot and every query key on this\n * and not on the node.\n */\nexport function chartTableKey(table: TableExpr | undefined): string | undefined {\n return table === undefined ? undefined : String(typeof table === \"string\" ? asTableRef(table) : table);\n}\n\nexport type ChartMarkSource =\n | { readonly kind: \"table\"; readonly table: TableExpr; readonly filterBy: Selection | null }\n | { readonly kind: \"values\"; readonly values: readonly unknown[] }\n /** A decorator mark (`frame`, `gridX`, `gridY`) — takes options only, never data. */\n | null;\n\nexport interface ChartMarkDirective {\n readonly kind: \"mark\";\n readonly mark: string;\n readonly source: ChartMarkSource;\n readonly options: Readonly<Record<string, unknown>>;\n}\n\nexport interface ChartInteractorDirective {\n readonly kind: \"interactor\";\n readonly interactor: string;\n readonly options: Readonly<Record<string, unknown>>;\n}\n\nexport interface ChartAttributeDirective {\n readonly kind: \"attribute\";\n readonly name: string;\n readonly value: unknown;\n}\n\n/** The escape hatch: a `vg.*` directive the layer does not wrap, passed through untouched. */\nexport interface ChartRawDirective {\n readonly kind: \"raw\";\n readonly value: unknown;\n}\n\nexport type ChartDirective =\n | ChartMarkDirective\n | ChartInteractorDirective\n | ChartAttributeDirective\n | ChartRawDirective;\n\nexport interface ChartSpecContext {\n /** The relation every table-backed mark reads from. */\n readonly table?: TableExpr;\n /** What marks filter by; `null` means \"the full relation\". */\n readonly filterBy: Selection | null;\n /** Where interactors publish. */\n readonly as: Selection | null;\n readonly config: ChartConfig;\n /** Turns a `var(--token)` / `--token` reference into a Plot-safe colour. */\n readonly resolveColor: (token: string) => string;\n}\n\nexport type ChartCompile<P> = (props: P, ctx: ChartSpecContext) => ChartDirective | ChartDirective[];\n\n/** An inert child: renders nothing, carries its compilation on a static. */\nexport interface ChartDescriptor<P> {\n (props: P): null;\n readonly displayName: string;\n readonly __chart: ChartCompile<P>;\n}\n\nexport function chartDescriptor<P>(displayName: string, compile: ChartCompile<P>): ChartDescriptor<P> {\n return Object.assign(() => null, { displayName, __chart: compile }) as ChartDescriptor<P>;\n}\n\nfunction isChartDescriptor(type: unknown): type is ChartDescriptor<unknown> {\n return typeof type === \"function\" && typeof (type as { __chart?: unknown }).__chart === \"function\";\n}\n\n/** Guards against a pathological tree; nothing legitimate nests fragments this deep. */\nconst MAX_DEPTH = 16;\n\nfunction collect(node: ReactNode, ctx: ChartSpecContext, out: ChartDirective[], depth: number): void {\n if (node == null || typeof node === \"boolean\" || depth > MAX_DEPTH) return;\n if (Array.isArray(node)) {\n for (const child of node) collect(child as ReactNode, ctx, out, depth + 1);\n return;\n }\n if (!isValidElement(node)) return;\n if (node.type === Fragment) {\n collect((node.props as { children?: ReactNode }).children, ctx, out, depth + 1);\n return;\n }\n // Anything else is a DOM child (ChartLegend, a caption…) — rendered, never compiled. A\n // descriptor hidden inside a consumer's own component is invisible here, as in Recharts.\n if (!isChartDescriptor(node.type)) return;\n const produced = node.type.__chart(node.props, ctx);\n if (Array.isArray(produced)) out.push(...produced);\n else out.push(produced);\n}\n\n/** The descriptor children, in source order. Fragments and arrays flatten; `null`/`false` vanish. */\nexport function compileChartSpec(children: ReactNode, ctx: ChartSpecContext): ChartDirective[] {\n const out: ChartDirective[] = [];\n collect(children, ctx, out, 0);\n return out;\n}\n\nexport interface ChartMargin {\n top?: number;\n right?: number;\n bottom?: number;\n left?: number;\n}\n\n/**\n * The plot-wide half of faceting. The panels themselves come from a mark's `fx` / `fy` channels\n * (`<ChartBarY fx=\"region\" />`); per-scale options go on `ChartFacetX` / `ChartFacetY`.\n */\nexport interface ChartFacetOptions {\n /**\n * Space around each facet panel — the gutter *between* small multiples.\n *\n * Not where the panel titles go: those are drawn in the **plot's** top margin, so a `margin`\n * with a small `top` renders them into nothing and the panels come out anonymous. Leave ~26px.\n */\n facetMargin?: number | ChartMargin;\n /** Draw the grid across the facet panels. */\n facetGrid?: boolean;\n /** The shared label for the facet axes; `null` removes it. */\n facetLabel?: string | null;\n}\n\nexport interface ChartSpecOptions extends ChartFacetOptions {\n children: ReactNode;\n /** Measured from the container by `TokenizedPlot`; vgplot defaults to 640 without it. */\n width: number;\n height: number;\n margin?: number | ChartMargin;\n aspectRatio?: number;\n attributes?: readonly unknown[];\n}\n\nconst MARGIN_SIDES = { top: \"Top\", right: \"Right\", bottom: \"Bottom\", left: \"Left\" } as const;\n\nfunction marginDirectives(\n prefix: \"margin\" | \"facetMargin\",\n margin: number | ChartMargin | undefined,\n): ChartAttributeDirective[] {\n if (margin === undefined) return [];\n const sides: ChartMargin =\n typeof margin === \"number\" ? { top: margin, right: margin, bottom: margin, left: margin } : margin;\n return (Object.keys(MARGIN_SIDES) as (keyof ChartMargin)[])\n .filter((side) => sides[side] !== undefined)\n .map((side) => ({ kind: \"attribute\", name: `${prefix}${MARGIN_SIDES[side]}`, value: sides[side] }));\n}\n\n/**\n * The whole plot: frame attributes, the config's colour scale, the children, then the raw\n * escape hatch last so a consumer directive can override anything the layer decided.\n */\nexport function buildChartSpec(options: ChartSpecOptions, ctx: ChartSpecContext): ChartDirective[] {\n const directives: ChartDirective[] = [\n { kind: \"attribute\", name: \"width\", value: options.width },\n { kind: \"attribute\", name: \"height\", value: options.height },\n ...marginDirectives(\"margin\", options.margin),\n ...marginDirectives(\"facetMargin\", options.facetMargin),\n ];\n if (options.aspectRatio !== undefined) {\n directives.push({ kind: \"attribute\", name: \"aspectRatio\", value: options.aspectRatio });\n }\n if (options.facetGrid !== undefined) {\n directives.push({ kind: \"attribute\", name: \"facetGrid\", value: options.facetGrid });\n }\n if (options.facetLabel !== undefined) {\n directives.push({ kind: \"attribute\", name: \"facetLabel\", value: options.facetLabel });\n }\n const scale = chartColorScale(ctx.config);\n if (scale) {\n directives.push({ kind: \"attribute\", name: \"colorDomain\", value: scale.domain });\n directives.push({\n kind: \"attribute\",\n name: \"colorRange\",\n value: scale.range.map((c) => (isColorToken(c) ? ctx.resolveColor(c) : c)),\n });\n }\n directives.push(...compileChartSpec(options.children, ctx));\n for (const raw of options.attributes ?? []) directives.push({ kind: \"raw\", value: raw });\n return directives;\n}\n\n/** Marks whose primary channel is a band scale, which an interval brush cannot read. */\nconst BAND_MARKS: Record<string, \"x\" | \"y\"> = {\n barY: \"x\", waffleY: \"x\", cellX: \"x\",\n barX: \"y\", waffleX: \"y\", cellY: \"y\",\n};\n\nfunction component(name: string): string {\n return `<Chart${name[0]!.toUpperCase()}${name.slice(1)}>`;\n}\n\n/** A mark whose query carries a `GROUP BY` — any channel holding an aggregate expression. */\nfunction isAggregating(mark: ChartMarkDirective): boolean {\n // `isAggregateExpression` walks a SQL AST and answers 0 for anything that is not a node, so a\n // plain `y=\"region\"` costs one type check rather than a guard here.\n return Object.values(mark.options).some(\n (value) => isAggregateExpression(value as Parameters<typeof isAggregateExpression>[0]) !== 0,\n );\n}\n\n/** A cross-filtered selection never reports its own clause back to the client that published it. */\nfunction isCross(selection: Selection): boolean {\n return Boolean(selection.resolver?.cross);\n}\n\nexport interface ChartSpecWarningContext {\n /**\n * Selections shared by the whole `<MosaicProvider>` — anyone's clause can land in these, so they\n * are never safe as a `ChartHighlight` target on an aggregating mark.\n */\n readonly shared?: readonly unknown[];\n}\n\n/**\n * Combinations that fail at *runtime*, reported at build time.\n *\n * Both entries here are silent failures — the kind that costs an afternoon because nothing on\n * screen says anything is wrong.\n *\n * 1. An interval brush over a band scale throws `Unrecognized scale type: band` from Mosaic's\n * pre-aggregator on pointer-enter — and because that pre-aggregator is coordinator-scoped, the\n * blast radius is every other chart on the page, which go blank with no error of their own.\n * 2. A `ChartHighlight` pointed at a page-wide selection over an aggregating mark. The highlight\n * appends its predicate as an extra column on the mark's own `GROUP BY` query, so the first\n * clause naming a column this plot does not group by is a DuckDB binder error; the query dies\n * and the plot silently keeps its previous render. The default `by` is the root's own selection\n * and cannot hit this — only an explicit `by`/`as` naming a shared selection can.\n */\nexport function chartSpecWarnings(spec: ChartDirective[], context?: ChartSpecWarningContext): string[] {\n const warnings: string[] = [];\n const marks = spec.filter((d): d is ChartMarkDirective => d.kind === \"mark\");\n const shared = context?.shared ?? [];\n\n for (const d of spec) {\n if (d.kind !== \"interactor\") continue;\n\n if (d.interactor === \"highlight\") {\n const by = d.options.by as Selection | null | undefined;\n if (!by) continue;\n if (isCross(by)) {\n warnings.push(\n \"<ChartHighlight> reads a cross-filtered selection, which by definition hides a clause \" +\n \"from the client that published it — so the predicate comes back empty and nothing is \" +\n \"ever dimmed. Drop `by` to use the root's own selection, or point it at a plain union.\",\n );\n continue;\n }\n const aggregating = marks.find(isAggregating);\n if (shared.includes(by) && aggregating) {\n warnings.push(\n `<ChartHighlight by={…}> targets a selection shared by the whole <MosaicProvider>, and ` +\n `${component(aggregating.mark)} aggregates. The highlight appends its predicate as a ` +\n \"column on that GROUP BY query, so as soon as another chart publishes a clause over a \" +\n \"column this plot does not group by, DuckDB answers \\\"must appear in the GROUP BY \" +\n \"clause\\\", the query dies and this plot silently keeps its previous render. Drop `by` \" +\n \"— the root's own selection only ever names columns this plot groups by.\",\n );\n }\n continue;\n }\n\n const axis = d.interactor === \"intervalX\" ? \"x\" : d.interactor === \"intervalY\" ? \"y\" : null;\n if (!axis) continue;\n const clash = marks.find((m) => BAND_MARKS[m.mark] === axis);\n if (clash) {\n warnings.push(\n `${component(d.interactor)} brushes a band scale ` +\n `(${component(clash.mark)} makes ${axis} categorical). ` +\n \"Mosaic throws \\\"Unrecognized scale type: band\\\" on hover and blanks every other chart \" +\n `sharing the coordinator. Use <ChartToggle${axis.toUpperCase()}> for categories, or bin ${axis} first.`,\n );\n }\n }\n return warnings;\n}\n\n/**\n * A stable fingerprint of a compiled spec, for `TokenizedPlot`'s dependency list — the plot is\n * rebuilt (and its queries re-run) only when the grammar actually changed, not on every render.\n * SQL expression nodes (`count()`, `bin(x)`) stringify to their SQL; selections, params and\n * functions fall back to identity, which is stable as long as the caller does not rebuild them.\n */\nconst identities = new WeakMap<object, number>();\nlet nextIdentity = 0;\n\nfunction identityOf(value: object): number {\n let id = identities.get(value);\n if (id === undefined) {\n id = ++nextIdentity;\n identities.set(value, id);\n }\n return id;\n}\n\nfunction tag(value: unknown, depth: number): unknown {\n if (typeof value === \"function\") return `fn#${identityOf(value)}`;\n if (typeof value === \"symbol\") return `sym#${String(value.description)}`;\n if (value === null || typeof value !== \"object\") return value;\n if (depth > MAX_DEPTH) return `deep#${identityOf(value)}`;\n if (Array.isArray(value)) return value.map((v) => tag(v, depth + 1));\n const proto: unknown = Object.getPrototypeOf(value);\n if (proto === Object.prototype || proto === null) {\n return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, tag(v, depth + 1)]));\n }\n let text = \"[object]\";\n try {\n text = String(value);\n } catch {\n /* a toString that throws is no worse than no toString */\n }\n return text.startsWith(\"[object\") ? `obj#${identityOf(value)}` : text;\n}\n\nexport function chartSpecSignature(directives: readonly ChartDirective[]): string {\n return JSON.stringify(tag(directives, 0));\n}\n"],"names":["chartTableKey","table","asTableRef","chartDescriptor","displayName","compile","isChartDescriptor","type","MAX_DEPTH","collect","node","ctx","out","depth","child","isValidElement","Fragment","produced","compileChartSpec","children","MARGIN_SIDES","marginDirectives","prefix","margin","sides","side","buildChartSpec","options","directives","scale","chartColorScale","c","isColorToken","raw","BAND_MARKS","component","name","isAggregating","mark","value","isAggregateExpression","isCross","selection","_a","chartSpecWarnings","spec","context","warnings","marks","d","shared","by","aggregating","axis","clash","m","identities","nextIdentity","identityOf","id","tag","v","proto","k","text","chartSpecSignature"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { TableExpr } from '@kanzo-tech/mosaic';
1
2
  import { ExprValue } from '@uwdata/mosaic-sql';
2
3
  import { StatValueProps } from '../simples/stat.js';
3
4
  /**
@@ -7,8 +8,8 @@ import { StatValueProps } from '../simples/stat.js';
7
8
  * value it replaces, so the label, the delta and the link stay the host's.
8
9
  */
9
10
  export interface ChartStatProps extends Omit<StatValueProps, "children" | "loading"> {
10
- /** The relation. Defaults to the enclosing `ChartRoot`'s table. */
11
- table?: string;
11
+ /** The relation, as `ChartRoot` takes it. Defaults to the enclosing `ChartRoot`'s table. */
12
+ table?: TableExpr;
12
13
  /** The aggregate to show — `count()`, `avg("latency")`, any `mosaic-sql` expression. */
13
14
  value: ExprValue;
14
15
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"chart-stat.d.ts","sourceRoot":"","sources":["../../src/charts/chart-stat.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIpE;;;;;GAKG;AAEH,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,SAAS,CAAC;IAClF,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wFAAwF;IACxF,KAAK,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,+BA6B9C;yBA7Be,SAAS"}
1
+ {"version":3,"file":"chart-stat.d.ts","sourceRoot":"","sources":["../../src/charts/chart-stat.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAKpE;;;;;GAKG;AAEH,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,cAAc,EAAE,UAAU,GAAG,SAAS,CAAC;IAClF,4FAA4F;IAC5F,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wFAAwF;IACxF,KAAK,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,+BA6B9C;yBA7Be,SAAS"}
@@ -1,19 +1,20 @@
1
1
  "use client";
2
- import { jsx as n } from "react/jsx-runtime";
2
+ import { jsx as i } from "react/jsx-runtime";
3
3
  import { FormatNumber as p } from "@ark-ui/react/format";
4
4
  import { Query as c } from "@uwdata/mosaic-sql";
5
5
  import { StatValue as f } from "../simples/stat.js";
6
- import { useChartContextOptional as d } from "./chart-root.js";
7
- import { useChartQuery as h } from "./use-chart-query.js";
8
- function b(i) {
9
- const { table: l, value: e, format: m, ...s } = i, a = d(), t = l ?? (a == null ? void 0 : a.table), { row: r } = h({
6
+ import { useChartContextOptional as h } from "./chart-root.js";
7
+ import { chartTableKey as d } from "./chart-spec.js";
8
+ import { useChartQuery as b } from "./use-chart-query.js";
9
+ function C(n) {
10
+ const { table: l, value: e, format: m, ...s } = n, a = h(), t = l ?? (a == null ? void 0 : a.table), { row: r } = b({
10
11
  query: (u) => t ? c.from(t).select({ value: e }).where(u) : null,
11
- deps: [t, e]
12
+ deps: [d(t), e]
12
13
  });
13
14
  if (!t)
14
15
  throw new Error("ChartStat needs a `table`, or a <ChartRoot table> around it.");
15
16
  const o = Number((r == null ? void 0 : r.value) ?? 0);
16
- return /* @__PURE__ */ n(f, { loading: r === void 0, ...s, children: m ? m(o) : /* @__PURE__ */ n(
17
+ return /* @__PURE__ */ i(f, { loading: r === void 0, ...s, children: m ? m(o) : /* @__PURE__ */ i(
17
18
  p,
18
19
  {
19
20
  maximumFractionDigits: 1,
@@ -22,8 +23,8 @@ function b(i) {
22
23
  }
23
24
  ) });
24
25
  }
25
- b.displayName = "ChartStat";
26
+ C.displayName = "ChartStat";
26
27
  export {
27
- b as ChartStat
28
+ C as ChartStat
28
29
  };
29
30
  //# sourceMappingURL=chart-stat.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-stat.js","sources":["../../src/charts/chart-stat.tsx"],"sourcesContent":["\"use client\";\n\nimport { FormatNumber } from \"@ark-ui/react/format\";\nimport type { ExprValue } from \"@uwdata/mosaic-sql\";\nimport { Query } from \"@uwdata/mosaic-sql\";\nimport { StatValue, type StatValueProps } from \"../simples/stat.js\";\nimport { useChartContextOptional } from \"./chart-root.js\";\nimport { useChartQuery } from \"./use-chart-query.js\";\n\n/**\n * `StatValue` with the figure read from the relation, under the same crossfilter as the plots. The\n * connected half of the pair, which is the engine rule: the `Stat*` parts take a number and live in\n * the root barrel, this one queries for it and lives here. It sits inside a `StatRoot` like the\n * value it replaces, so the label, the delta and the link stay the host's.\n */\n\nexport interface ChartStatProps extends Omit<StatValueProps, \"children\" | \"loading\"> {\n /** The relation. Defaults to the enclosing `ChartRoot`'s table. */\n table?: string;\n /** The aggregate to show — `count()`, `avg(\"latency\")`, any `mosaic-sql` expression. */\n value: ExprValue;\n /**\n * Formats the number for display. By default a count under ten thousand reads in full and\n * anything larger compacts — `4,233`, `12.9K` — so a four-digit figure is never abbreviated\n * into ambiguity.\n */\n format?: (value: number) => string;\n}\n\nexport function ChartStat(props: ChartStatProps) {\n const { table, value, format, ...rest } = props;\n const chart = useChartContextOptional();\n const relation = table ?? chart?.table;\n\n const { row } = useChartQuery({\n query: (filter) =>\n relation ? Query.from(relation).select({ value }).where(filter) : null,\n deps: [relation, value],\n });\n\n if (!relation) {\n throw new Error(\"ChartStat needs a `table`, or a <ChartRoot table> around it.\");\n }\n\n const raw = Number(row?.value ?? 0);\n return (\n <StatValue loading={row === undefined} {...rest}>\n {format ? (\n format(raw)\n ) : (\n <FormatNumber\n maximumFractionDigits={1}\n notation={Math.abs(raw) >= 10_000 ? \"compact\" : \"standard\"}\n value={raw}\n />\n )}\n </StatValue>\n );\n}\n\n// The chart context is optional: a tile sits in a dashboard grid, outside any plot.\nChartStat.displayName = \"ChartStat\";\n"],"names":["ChartStat"],"mappings":";;;;;;;AA6BO;AACL;AAI8B;AAEwC;AAC9C;AAGxB;AACE;AAGF;AACA;AAKM;AAAC;AAAA;AACwB;AACyB;AACzC;AAAA;AAKjB;AAGAA;;;;"}
1
+ {"version":3,"file":"chart-stat.js","sources":["../../src/charts/chart-stat.tsx"],"sourcesContent":["\"use client\";\n\nimport type { TableExpr } from \"@kanzo-tech/mosaic\";\nimport { FormatNumber } from \"@ark-ui/react/format\";\nimport type { ExprValue } from \"@uwdata/mosaic-sql\";\nimport { Query } from \"@uwdata/mosaic-sql\";\nimport { StatValue, type StatValueProps } from \"../simples/stat.js\";\nimport { useChartContextOptional } from \"./chart-root.js\";\nimport { chartTableKey } from \"./chart-spec.js\";\nimport { useChartQuery } from \"./use-chart-query.js\";\n\n/**\n * `StatValue` with the figure read from the relation, under the same crossfilter as the plots. The\n * connected half of the pair, which is the engine rule: the `Stat*` parts take a number and live in\n * the root barrel, this one queries for it and lives here. It sits inside a `StatRoot` like the\n * value it replaces, so the label, the delta and the link stay the host's.\n */\n\nexport interface ChartStatProps extends Omit<StatValueProps, \"children\" | \"loading\"> {\n /** The relation, as `ChartRoot` takes it. Defaults to the enclosing `ChartRoot`'s table. */\n table?: TableExpr;\n /** The aggregate to show — `count()`, `avg(\"latency\")`, any `mosaic-sql` expression. */\n value: ExprValue;\n /**\n * Formats the number for display. By default a count under ten thousand reads in full and\n * anything larger compacts — `4,233`, `12.9K` — so a four-digit figure is never abbreviated\n * into ambiguity.\n */\n format?: (value: number) => string;\n}\n\nexport function ChartStat(props: ChartStatProps) {\n const { table, value, format, ...rest } = props;\n const chart = useChartContextOptional();\n const relation = table ?? chart?.table;\n\n const { row } = useChartQuery({\n query: (filter) =>\n relation ? Query.from(relation).select({ value }).where(filter) : null,\n deps: [chartTableKey(relation), value],\n });\n\n if (!relation) {\n throw new Error(\"ChartStat needs a `table`, or a <ChartRoot table> around it.\");\n }\n\n const raw = Number(row?.value ?? 0);\n return (\n <StatValue loading={row === undefined} {...rest}>\n {format ? (\n format(raw)\n ) : (\n <FormatNumber\n maximumFractionDigits={1}\n notation={Math.abs(raw) >= 10_000 ? \"compact\" : \"standard\"}\n value={raw}\n />\n )}\n </StatValue>\n );\n}\n\n// The chart context is optional: a tile sits in a dashboard grid, outside any plot.\nChartStat.displayName = \"ChartStat\";\n"],"names":["ChartStat"],"mappings":";;;;;;;;AA+BO;AACL;AAI8B;AAEwC;AAC/B;AAGvC;AACE;AAGF;AACA;AAKM;AAAC;AAAA;AACwB;AACyB;AACzC;AAAA;AAKjB;AAGAA;;;;"}
@@ -19,6 +19,13 @@ export interface LanguagePickerProps {
19
19
  * input — rather than a bordered control of its own.
20
20
  */
21
21
  inline?: boolean;
22
+ /**
23
+ * The control height, one of the shared sizes. Ignored with `inline`, which takes the height of
24
+ * the field it sits in.
25
+ *
26
+ * @default "md"
27
+ */
28
+ size?: "sm" | "md" | "lg";
22
29
  disabled?: boolean;
23
30
  readOnly?: boolean;
24
31
  invalid?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"language-picker.d.ts","sourceRoot":"","sources":["../../src/composites/language-picker.tsx"],"names":[],"mappings":"AAwEA,0EAA0E;AAC1E,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAQD,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,4FAA4F;IAC5F,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC,0BAA0B,CAAC,CAAC;CACpD;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,mBAAmB,gCAkGxD,CAAC"}
1
+ {"version":3,"file":"language-picker.d.ts","sourceRoot":"","sources":["../../src/composites/language-picker.tsx"],"names":[],"mappings":"AAwEA,0EAA0E;AAC1E,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAQD,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,4FAA4F;IAC5F,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC,0BAA0B,CAAC,CAAC;CACpD;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,mBAAmB,gCAoGxD,CAAC"}
@@ -1,11 +1,11 @@
1
1
  "use client";
2
2
  import { jsxs as p, jsx as s } from "react/jsx-runtime";
3
- import { createListCollection as M } from "@ark-ui/react/collection";
4
- import { useFilter as S } from "@ark-ui/react/locale";
5
- import { useState as T, useId as P, useMemo as b } from "react";
6
- import { tv as j } from "tailwind-variants";
7
- import { cn as A } from "../lib/cn.js";
8
- import { Combobox as E, ComboboxControl as F, ComboboxFieldInput as G, ComboboxInput as O, ComboboxContent as q, ComboboxEmpty as B, ComboboxItem as U } from "../simples/combobox.js";
3
+ import { createListCollection as S } from "@ark-ui/react/collection";
4
+ import { useFilter as T } from "@ark-ui/react/locale";
5
+ import { useState as P, useId as j, useMemo as b } from "react";
6
+ import { tv as A } from "tailwind-variants";
7
+ import { cn as E } from "../lib/cn.js";
8
+ import { Combobox as F, ComboboxControl as G, ComboboxFieldInput as O, ComboboxInput as q, ComboboxContent as z, ComboboxEmpty as B, ComboboxItem as U } from "../simples/combobox.js";
9
9
  const $ = [
10
10
  "en",
11
11
  "es",
@@ -56,7 +56,7 @@ const $ = [
56
56
  "sw",
57
57
  "af"
58
58
  ];
59
- function z(o) {
59
+ function D(o) {
60
60
  try {
61
61
  const t = o.split("-")[0] ?? o, r = new Intl.DisplayNames([o], { type: "language" }).of(t);
62
62
  return !r || r.toLowerCase() === t.toLowerCase() ? o : r.charAt(0).toLocaleUpperCase(o) + r.slice(1);
@@ -64,14 +64,14 @@ function z(o) {
64
64
  return o;
65
65
  }
66
66
  }
67
- function D(o) {
67
+ function H(o) {
68
68
  try {
69
69
  return Intl.getCanonicalLocales(o.trim())[0] ?? null;
70
70
  } catch {
71
71
  return null;
72
72
  }
73
73
  }
74
- const H = j({
74
+ const Q = A({
75
75
  variants: {
76
76
  // A slot inside another field's control — a trailing addon of a text input — is not a control of
77
77
  // its own, so it draws no box, no ring and no chevron of its own: the field around it does.
@@ -79,73 +79,75 @@ const H = j({
79
79
  true: "w-24 min-w-0 border-0 bg-transparent text-inherit outline-none [font:inherit]"
80
80
  }
81
81
  }
82
- }), Q = {
82
+ }), _ = {
83
83
  placeholder: "Search or type a tag…",
84
84
  filterPlaceholder: "Filter…",
85
85
  noMatches: "No matches"
86
- }, Z = (o) => {
86
+ }, ee = (o) => {
87
87
  const {
88
88
  value: t,
89
89
  onValueChange: r,
90
90
  languages: n,
91
91
  inline: c = !1,
92
- disabled: x,
93
- readOnly: v,
94
- invalid: I,
92
+ size: x,
93
+ disabled: v,
94
+ readOnly: I,
95
+ invalid: w,
95
96
  className: f,
96
- translations: w,
97
- "aria-label": L
98
- } = o, m = { ...Q, ...w }, l = !!(n != null && n.length), { contains: u } = S({ sensitivity: "base" }), [d, N] = T(""), V = P(), h = b(
99
- () => (n != null && n.length ? n : $).map((e) => ({ code: e, name: z(e) })),
97
+ translations: L,
98
+ "aria-label": N
99
+ } = o, m = { ..._, ...L }, l = !!(n != null && n.length), { contains: u } = T({ sensitivity: "base" }), [d, V] = P(""), k = j(), h = b(
100
+ () => (n != null && n.length ? n : $).map((e) => ({ code: e, name: D(e) })),
100
101
  [n]
101
102
  ), C = b(() => {
102
103
  const e = d.trim(), i = e ? h.filter((a) => u(a.code, e) || u(a.name, e)) : h;
103
- return M({
104
+ return S({
104
105
  items: i,
105
106
  itemToValue: (a) => a.code,
106
107
  itemToString: (a) => `${a.name} · ${a.code}`
107
108
  });
108
- }, [h, d, u]), k = b(() => t ? [t] : [], [t]), y = l ? m.filterPlaceholder : m.placeholder, g = () => {
109
- const e = l ? null : D(d);
109
+ }, [h, d, u]), M = b(() => t ? [t] : [], [t]), y = l ? m.filterPlaceholder : m.placeholder, g = () => {
110
+ const e = l ? null : H(d);
110
111
  e && e !== t && r(e);
111
112
  };
112
113
  return /* @__PURE__ */ p(
113
- E,
114
+ F,
114
115
  {
115
- "aria-label": L,
116
+ "aria-label": N,
116
117
  allowCustomValue: !l,
117
118
  collection: C,
118
- disabled: x,
119
- ids: c ? { input: V } : void 0,
120
- invalid: I,
121
- onInputValueChange: (e) => N(e.inputValue),
119
+ disabled: v,
120
+ ids: c ? { input: k } : void 0,
121
+ invalid: w,
122
+ onInputValueChange: (e) => V(e.inputValue),
122
123
  onValueChange: (e) => {
123
124
  const i = e.value[0];
124
125
  i && r(i);
125
126
  },
126
- readOnly: v,
127
- value: k,
127
+ readOnly: I,
128
+ value: M,
128
129
  children: [
129
130
  c ? (
130
131
  // `ComboboxControl` stays because the popover positions against it.
131
- /* @__PURE__ */ s(F, { children: /* @__PURE__ */ s(
132
- G,
132
+ /* @__PURE__ */ s(G, { children: /* @__PURE__ */ s(
133
+ O,
133
134
  {
134
- className: A(H({ inline: c }), f),
135
+ className: E(Q({ inline: c }), f),
135
136
  onBlur: g,
136
137
  placeholder: y
137
138
  }
138
139
  ) })
139
140
  ) : /* @__PURE__ */ s(
140
- O,
141
+ q,
141
142
  {
142
143
  className: f,
143
144
  onBlur: g,
144
145
  placeholder: y,
145
- showTrigger: l
146
+ showTrigger: l,
147
+ size: x
146
148
  }
147
149
  ),
148
- /* @__PURE__ */ p(q, { children: [
150
+ /* @__PURE__ */ p(z, { children: [
149
151
  /* @__PURE__ */ s(B, { children: m.noMatches }),
150
152
  C.items.map((e) => /* @__PURE__ */ p(U, { item: e, children: [
151
153
  e.name,
@@ -158,6 +160,6 @@ const H = j({
158
160
  );
159
161
  };
160
162
  export {
161
- Z as LanguagePicker
163
+ ee as LanguagePicker
162
164
  };
163
165
  //# sourceMappingURL=language-picker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"language-picker.js","sources":["../../src/composites/language-picker.tsx"],"sourcesContent":["\"use client\";\n\nimport { createListCollection } from \"@ark-ui/react/collection\";\nimport { useFilter } from \"@ark-ui/react/locale\";\nimport { useId, useMemo, useState } from \"react\";\nimport { tv } from \"tailwind-variants\";\nimport { cn } from \"../lib/cn\";\nimport {\n Combobox,\n ComboboxContent,\n ComboboxControl,\n ComboboxEmpty,\n ComboboxFieldInput,\n ComboboxInput,\n ComboboxItem,\n} from \"../simples/combobox\";\n\n/**\n * A broad default set of language subtags, offered when the host does not pin `languages`. The\n * search filters it, so its length is not a cost.\n */\nconst COMMON_LANGUAGES = [\n \"en\", \"es\", \"fr\", \"de\", \"it\", \"pt\", \"nl\", \"ca\", \"gl\", \"eu\", \"ast\", \"oc\",\n \"ga\", \"cy\", \"sv\", \"da\", \"nb\", \"nn\", \"fi\", \"is\", \"pl\", \"cs\", \"sk\", \"sl\",\n \"hr\", \"sr\", \"bg\", \"ro\", \"hu\", \"el\", \"tr\", \"ru\", \"uk\", \"ar\", \"he\", \"fa\",\n \"hi\", \"bn\", \"ur\", \"zh\", \"ja\", \"ko\", \"th\", \"vi\", \"id\", \"ms\", \"sw\", \"af\",\n] as const;\n\n/**\n * The language's name in its own language, `es` → \"Español\", so a reader recognises theirs\n * without knowing its code. Falls back to the tag when the runtime cannot name it, which is also\n * what `Intl.DisplayNames` reports by echoing the code back.\n */\nfunction endonym(tag: string): string {\n try {\n const base = tag.split(\"-\")[0] ?? tag;\n const name = new Intl.DisplayNames([tag], { type: \"language\" }).of(base);\n if (!name || name.toLowerCase() === base.toLowerCase()) return tag;\n return name.charAt(0).toLocaleUpperCase(tag) + name.slice(1);\n } catch {\n return tag;\n }\n}\n\n/**\n * The canonical spelling of a well-formed BCP 47 tag (`ES-mx` → `es-MX`), or `null` when the\n * string is not one. The runtime is the parser: a hand-written pattern accepts what the grammar\n * refuses and refuses what it accepts.\n */\nfunction canonicalTag(text: string): string | null {\n try {\n return Intl.getCanonicalLocales(text.trim())[0] ?? null;\n } catch {\n return null;\n }\n}\n\ninterface Language {\n code: string;\n name: string;\n}\n\nconst languagePickerInputVariants = tv({\n variants: {\n // A slot inside another field's control — a trailing addon of a text input — is not a control of\n // its own, so it draws no box, no ring and no chevron of its own: the field around it does.\n inline: {\n true: \"w-24 min-w-0 border-0 bg-transparent text-inherit outline-none [font:inherit]\",\n },\n },\n});\n\n/** The words this control draws, for a product that is not in English. */\nexport interface LanguagePickerTranslations {\n placeholder: string;\n filterPlaceholder: string;\n noMatches: string;\n}\n\nconst ENGLISH: LanguagePickerTranslations = {\n placeholder: \"Search or type a tag…\",\n filterPlaceholder: \"Filter…\",\n noMatches: \"No matches\",\n};\n\nexport interface LanguagePickerProps {\n /** A BCP 47 tag, or `\"\"` for none. */\n value: string;\n /** Called with the tag picked or typed, canonically spelled: `es-mx` arrives as `es-MX`. */\n onValueChange: (tag: string) => void;\n /**\n * The tags on offer. When given, the list is exactly these and a tag outside it cannot be\n * entered; when omitted, a broad default set is offered and any well-formed tag can be typed.\n */\n languages?: readonly string[];\n /**\n * Draw only the input, for a slot inside another field's control — the trailing addon of a text\n * input — rather than a bordered control of its own.\n */\n inline?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n invalid?: boolean;\n className?: string;\n \"aria-label\"?: string;\n translations?: Partial<LanguagePickerTranslations>;\n}\n\n/**\n * A searchable picker for BCP 47 language tags — the `lang` of a string, a page or a document.\n *\n * Each row shows the language's name in its own language beside its tag, \"Español · es\", and the\n * search matches either, so \"spa\", \"es\" and \"español\" all find it. With `languages` the list is a\n * closed set and an input that matches nothing reverts on blur; without it the list is a set of\n * suggestions, and a well-formed tag nobody listed stands.\n *\n * The list, the roving focus and the popover are `Combobox`'s; what this owns is the vocabulary —\n * the names, the default set and what counts as a tag.\n *\n * ARIA: a `combobox` with a `listbox` popup, as `Combobox` is. Give it an `aria-label` when there\n * is no `FieldLabel` around it.\n */\nexport const LanguagePicker = (props: LanguagePickerProps) => {\n const {\n value,\n onValueChange,\n languages,\n inline = false,\n disabled,\n readOnly,\n invalid,\n className,\n translations,\n \"aria-label\": ariaLabel,\n } = props;\n\n const t = { ...ENGLISH, ...translations };\n const constrained = !!languages?.length;\n const { contains } = useFilter({ sensitivity: \"base\" });\n const [query, setQuery] = useState(\"\");\n // Inside a `Field` the machine takes its input id from the field, which is right for the\n // field's own control and wrong for a second control in the same field: the text input has\n // already claimed it, and two elements would share it.\n const inputId = useId();\n\n const items = useMemo<Language[]>(\n () => (languages?.length ? languages : COMMON_LANGUAGES).map((code) => ({ code, name: endonym(code) })),\n [languages]\n );\n\n // Filtering is ours to own — the machine never mutates a collection. Both the tag and the name\n // match.\n const collection = useMemo(() => {\n const q = query.trim();\n const shown = q ? items.filter((i) => contains(i.code, q) || contains(i.name, q)) : items;\n return createListCollection({\n items: shown,\n itemToValue: (i) => i.code,\n itemToString: (i) => `${i.name} · ${i.code}`,\n });\n }, [items, query, contains]);\n\n // Memoised because the machine compares by identity: a fresh array per render reads as a value\n // change on every keystroke and resets the text being typed.\n const selected = useMemo(() => (value ? [value] : []), [value]);\n\n const placeholder = constrained ? t.filterPlaceholder : t.placeholder;\n\n // A typed tag is committed when the input is left, not per keystroke: \"es\" is a tag on the way to\n // \"es-MX\", and committing it there makes the machine swap the text for the name of the language\n // the user was still spelling. A pick has already been reported by `onValueChange`.\n const commitTyped = () => {\n const tag = constrained ? null : canonicalTag(query);\n if (tag && tag !== value) onValueChange(tag);\n };\n\n return (\n <Combobox\n aria-label={ariaLabel}\n // A tag the host did not list is only admissible when the host listed none.\n allowCustomValue={!constrained}\n collection={collection}\n disabled={disabled}\n ids={inline ? { input: inputId } : undefined}\n invalid={invalid}\n onInputValueChange={(details) => setQuery(details.inputValue)}\n onValueChange={(details) => {\n const picked = details.value[0];\n if (picked) onValueChange(picked);\n }}\n readOnly={readOnly}\n value={selected}\n >\n {inline ? (\n // `ComboboxControl` stays because the popover positions against it.\n <ComboboxControl>\n <ComboboxFieldInput\n className={cn(languagePickerInputVariants({ inline }), className)}\n onBlur={commitTyped}\n placeholder={placeholder}\n />\n </ComboboxControl>\n ) : (\n <ComboboxInput\n className={className}\n onBlur={commitTyped}\n placeholder={placeholder}\n showTrigger={constrained}\n />\n )}\n <ComboboxContent>\n <ComboboxEmpty>{t.noMatches}</ComboboxEmpty>\n {collection.items.map((item) => (\n <ComboboxItem item={item} key={item.code}>\n {item.name} · {item.code}\n </ComboboxItem>\n ))}\n </ComboboxContent>\n </Combobox>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAqBA;AAAyB;AACvB;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAO;AACnE;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAClE;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAClE;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAC9D;AAOA;AACE;AACE;AAEA;AAC2D;AAE3D;AAAO;AAEX;AAOA;AACE;AACE;AAAmD;AAEnD;AAAO;AAEX;AAOA;AAAuC;AAC3B;AAAA;AAAA;AAGA;AACA;AAAA;AAGZ;AAS4C;AAC7B;AACM;AAErB;AAwCE;AAAM;AACJ;AACA;AACA;AACS;AACT;AACA;AACA;AACA;AACA;AACc;AAYF;AAC0F;AAC5F;AAMV;AAEA;AAA4B;AACnB;AACe;AACoB;AAC3C;AAaD;AACA;AAA2C;AAG7C;AACE;AAAC;AAAA;AACa;AAEO;AACnB;AACA;AACmC;AACnC;AAC4D;AAE1D;AACA;AAAgC;AAClC;AACA;AACO;AAEN;AAAA;AAAA;AAGG;AAAC;AAAA;AACiE;AACxD;AACR;AAAA;AAEJ;AAEA;AAAC;AAAA;AACC;AACQ;AACR;AACa;AAAA;AAAA;AAIf;AAA4B;AAGvB;AAAK;AAAK;AAAS;AAEvB;AACH;AAAA;AAAA;AAGN;;;;"}
1
+ {"version":3,"file":"language-picker.js","sources":["../../src/composites/language-picker.tsx"],"sourcesContent":["\"use client\";\n\nimport { createListCollection } from \"@ark-ui/react/collection\";\nimport { useFilter } from \"@ark-ui/react/locale\";\nimport { useId, useMemo, useState } from \"react\";\nimport { tv } from \"tailwind-variants\";\nimport { cn } from \"../lib/cn\";\nimport {\n Combobox,\n ComboboxContent,\n ComboboxControl,\n ComboboxEmpty,\n ComboboxFieldInput,\n ComboboxInput,\n ComboboxItem,\n} from \"../simples/combobox\";\n\n/**\n * A broad default set of language subtags, offered when the host does not pin `languages`. The\n * search filters it, so its length is not a cost.\n */\nconst COMMON_LANGUAGES = [\n \"en\", \"es\", \"fr\", \"de\", \"it\", \"pt\", \"nl\", \"ca\", \"gl\", \"eu\", \"ast\", \"oc\",\n \"ga\", \"cy\", \"sv\", \"da\", \"nb\", \"nn\", \"fi\", \"is\", \"pl\", \"cs\", \"sk\", \"sl\",\n \"hr\", \"sr\", \"bg\", \"ro\", \"hu\", \"el\", \"tr\", \"ru\", \"uk\", \"ar\", \"he\", \"fa\",\n \"hi\", \"bn\", \"ur\", \"zh\", \"ja\", \"ko\", \"th\", \"vi\", \"id\", \"ms\", \"sw\", \"af\",\n] as const;\n\n/**\n * The language's name in its own language, `es` → \"Español\", so a reader recognises theirs\n * without knowing its code. Falls back to the tag when the runtime cannot name it, which is also\n * what `Intl.DisplayNames` reports by echoing the code back.\n */\nfunction endonym(tag: string): string {\n try {\n const base = tag.split(\"-\")[0] ?? tag;\n const name = new Intl.DisplayNames([tag], { type: \"language\" }).of(base);\n if (!name || name.toLowerCase() === base.toLowerCase()) return tag;\n return name.charAt(0).toLocaleUpperCase(tag) + name.slice(1);\n } catch {\n return tag;\n }\n}\n\n/**\n * The canonical spelling of a well-formed BCP 47 tag (`ES-mx` → `es-MX`), or `null` when the\n * string is not one. The runtime is the parser: a hand-written pattern accepts what the grammar\n * refuses and refuses what it accepts.\n */\nfunction canonicalTag(text: string): string | null {\n try {\n return Intl.getCanonicalLocales(text.trim())[0] ?? null;\n } catch {\n return null;\n }\n}\n\ninterface Language {\n code: string;\n name: string;\n}\n\nconst languagePickerInputVariants = tv({\n variants: {\n // A slot inside another field's control — a trailing addon of a text input — is not a control of\n // its own, so it draws no box, no ring and no chevron of its own: the field around it does.\n inline: {\n true: \"w-24 min-w-0 border-0 bg-transparent text-inherit outline-none [font:inherit]\",\n },\n },\n});\n\n/** The words this control draws, for a product that is not in English. */\nexport interface LanguagePickerTranslations {\n placeholder: string;\n filterPlaceholder: string;\n noMatches: string;\n}\n\nconst ENGLISH: LanguagePickerTranslations = {\n placeholder: \"Search or type a tag…\",\n filterPlaceholder: \"Filter…\",\n noMatches: \"No matches\",\n};\n\nexport interface LanguagePickerProps {\n /** A BCP 47 tag, or `\"\"` for none. */\n value: string;\n /** Called with the tag picked or typed, canonically spelled: `es-mx` arrives as `es-MX`. */\n onValueChange: (tag: string) => void;\n /**\n * The tags on offer. When given, the list is exactly these and a tag outside it cannot be\n * entered; when omitted, a broad default set is offered and any well-formed tag can be typed.\n */\n languages?: readonly string[];\n /**\n * Draw only the input, for a slot inside another field's control — the trailing addon of a text\n * input — rather than a bordered control of its own.\n */\n inline?: boolean;\n /**\n * The control height, one of the shared sizes. Ignored with `inline`, which takes the height of\n * the field it sits in.\n *\n * @default \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\";\n disabled?: boolean;\n readOnly?: boolean;\n invalid?: boolean;\n className?: string;\n \"aria-label\"?: string;\n translations?: Partial<LanguagePickerTranslations>;\n}\n\n/**\n * A searchable picker for BCP 47 language tags — the `lang` of a string, a page or a document.\n *\n * Each row shows the language's name in its own language beside its tag, \"Español · es\", and the\n * search matches either, so \"spa\", \"es\" and \"español\" all find it. With `languages` the list is a\n * closed set and an input that matches nothing reverts on blur; without it the list is a set of\n * suggestions, and a well-formed tag nobody listed stands.\n *\n * The list, the roving focus and the popover are `Combobox`'s; what this owns is the vocabulary —\n * the names, the default set and what counts as a tag.\n *\n * ARIA: a `combobox` with a `listbox` popup, as `Combobox` is. Give it an `aria-label` when there\n * is no `FieldLabel` around it.\n */\nexport const LanguagePicker = (props: LanguagePickerProps) => {\n const {\n value,\n onValueChange,\n languages,\n inline = false,\n size,\n disabled,\n readOnly,\n invalid,\n className,\n translations,\n \"aria-label\": ariaLabel,\n } = props;\n\n const t = { ...ENGLISH, ...translations };\n const constrained = !!languages?.length;\n const { contains } = useFilter({ sensitivity: \"base\" });\n const [query, setQuery] = useState(\"\");\n // Inside a `Field` the machine takes its input id from the field, which is right for the\n // field's own control and wrong for a second control in the same field: the text input has\n // already claimed it, and two elements would share it.\n const inputId = useId();\n\n const items = useMemo<Language[]>(\n () => (languages?.length ? languages : COMMON_LANGUAGES).map((code) => ({ code, name: endonym(code) })),\n [languages]\n );\n\n // Filtering is ours to own — the machine never mutates a collection. Both the tag and the name\n // match.\n const collection = useMemo(() => {\n const q = query.trim();\n const shown = q ? items.filter((i) => contains(i.code, q) || contains(i.name, q)) : items;\n return createListCollection({\n items: shown,\n itemToValue: (i) => i.code,\n itemToString: (i) => `${i.name} · ${i.code}`,\n });\n }, [items, query, contains]);\n\n // Memoised because the machine compares by identity: a fresh array per render reads as a value\n // change on every keystroke and resets the text being typed.\n const selected = useMemo(() => (value ? [value] : []), [value]);\n\n const placeholder = constrained ? t.filterPlaceholder : t.placeholder;\n\n // A typed tag is committed when the input is left, not per keystroke: \"es\" is a tag on the way to\n // \"es-MX\", and committing it there makes the machine swap the text for the name of the language\n // the user was still spelling. A pick has already been reported by `onValueChange`.\n const commitTyped = () => {\n const tag = constrained ? null : canonicalTag(query);\n if (tag && tag !== value) onValueChange(tag);\n };\n\n return (\n <Combobox\n aria-label={ariaLabel}\n // A tag the host did not list is only admissible when the host listed none.\n allowCustomValue={!constrained}\n collection={collection}\n disabled={disabled}\n ids={inline ? { input: inputId } : undefined}\n invalid={invalid}\n onInputValueChange={(details) => setQuery(details.inputValue)}\n onValueChange={(details) => {\n const picked = details.value[0];\n if (picked) onValueChange(picked);\n }}\n readOnly={readOnly}\n value={selected}\n >\n {inline ? (\n // `ComboboxControl` stays because the popover positions against it.\n <ComboboxControl>\n <ComboboxFieldInput\n className={cn(languagePickerInputVariants({ inline }), className)}\n onBlur={commitTyped}\n placeholder={placeholder}\n />\n </ComboboxControl>\n ) : (\n <ComboboxInput\n className={className}\n onBlur={commitTyped}\n placeholder={placeholder}\n showTrigger={constrained}\n size={size}\n />\n )}\n <ComboboxContent>\n <ComboboxEmpty>{t.noMatches}</ComboboxEmpty>\n {collection.items.map((item) => (\n <ComboboxItem item={item} key={item.code}>\n {item.name} · {item.code}\n </ComboboxItem>\n ))}\n </ComboboxContent>\n </Combobox>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAqBA;AAAyB;AACvB;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAO;AACnE;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAClE;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAClE;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAAM;AAC9D;AAOA;AACE;AACE;AAEA;AAC2D;AAE3D;AAAO;AAEX;AAOA;AACE;AACE;AAAmD;AAEnD;AAAO;AAEX;AAOA;AAAuC;AAC3B;AAAA;AAAA;AAGA;AACA;AAAA;AAGZ;AAS4C;AAC7B;AACM;AAErB;AA+CE;AAAM;AACJ;AACA;AACA;AACS;AACT;AACA;AACA;AACA;AACA;AACA;AACc;AAYF;AAC0F;AAC5F;AAMV;AAEA;AAA4B;AACnB;AACe;AACoB;AAC3C;AAaD;AACA;AAA2C;AAG7C;AACE;AAAC;AAAA;AACa;AAEO;AACnB;AACA;AACmC;AACnC;AAC4D;AAE1D;AACA;AAAgC;AAClC;AACA;AACO;AAEN;AAAA;AAAA;AAGG;AAAC;AAAA;AACiE;AACxD;AACR;AAAA;AAEJ;AAEA;AAAC;AAAA;AACC;AACQ;AACR;AACa;AACb;AAAA;AAAA;AAIF;AAA4B;AAGvB;AAAK;AAAK;AAAS;AAEvB;AACH;AAAA;AAAA;AAGN;;;;"}
package/dist/index.d.ts CHANGED
@@ -24,7 +24,7 @@ export type { DebouncedCommit } from './lib/use-debounced-commit.js';
24
24
  export { createListCollection, useListCollection, } from '@ark-ui/react/collection';
25
25
  export type { ListCollection, CollectionItem } from '@ark-ui/react/collection';
26
26
  export { useFilter } from '@ark-ui/react/locale';
27
- export { parseDate } from '@internationalized/date';
27
+ export { parseDate, parseDateTime } from '@internationalized/date';
28
28
  export type { DateValue } from '@internationalized/date';
29
29
  export * from './simples/accordion.js';
30
30
  export * from './simples/action-bar.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}