@godxjp/ui 33.25.2 → 33.26.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.
package/agent/tokens.json CHANGED
@@ -13337,6 +13337,120 @@
13337
13337
  "tier": "component",
13338
13338
  "value": "initial"
13339
13339
  },
13340
+ {
13341
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13342
+ "name": "--flex-card-size-ratio",
13343
+ "tier": "component",
13344
+ "value": "1.4"
13345
+ },
13346
+ {
13347
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13348
+ "name": "--flex-card-width",
13349
+ "tier": "component",
13350
+ "value": "clamp(3.25rem, 6.6vw, 5.625rem)"
13351
+ },
13352
+ {
13353
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13354
+ "name": "--flex-compact-card-width",
13355
+ "tier": "component",
13356
+ "value": "clamp(1.875rem, 3.3vw, 2.8125rem)"
13357
+ },
13358
+ {
13359
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13360
+ "name": "--flex-orientation-duration",
13361
+ "tier": "component",
13362
+ "value": "180ms"
13363
+ },
13364
+ {
13365
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13366
+ "name": "--flex-felt-background",
13367
+ "tier": "component",
13368
+ "value": "initial"
13369
+ },
13370
+ {
13371
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13372
+ "name": "--flex-felt-foreground",
13373
+ "tier": "component",
13374
+ "value": "initial"
13375
+ },
13376
+ {
13377
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13378
+ "name": "--flex-felt-muted-foreground",
13379
+ "tier": "component",
13380
+ "value": "initial"
13381
+ },
13382
+ {
13383
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13384
+ "name": "--flex-felt-focus-color",
13385
+ "tier": "component",
13386
+ "value": "initial"
13387
+ },
13388
+ {
13389
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13390
+ "name": "--flex-felt-control-border-alpha",
13391
+ "tier": "component",
13392
+ "value": "0.65"
13393
+ },
13394
+ {
13395
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13396
+ "name": "--flex-felt-track-alpha",
13397
+ "tier": "component",
13398
+ "value": "0.8"
13399
+ },
13400
+ {
13401
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13402
+ "name": "--flex-felt-grain-width",
13403
+ "tier": "component",
13404
+ "value": "1px"
13405
+ },
13406
+ {
13407
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13408
+ "name": "--flex-felt-highlight-size",
13409
+ "tier": "component",
13410
+ "value": "72%"
13411
+ },
13412
+ {
13413
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13414
+ "name": "--flex-felt-grain-size",
13415
+ "tier": "component",
13416
+ "value": "3px"
13417
+ },
13418
+ {
13419
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13420
+ "name": "--flex-felt-grain-alpha",
13421
+ "tier": "component",
13422
+ "value": "0.025"
13423
+ },
13424
+ {
13425
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13426
+ "name": "--flex-felt-highlight-alpha",
13427
+ "tier": "component",
13428
+ "value": "0.045"
13429
+ },
13430
+ {
13431
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13432
+ "name": "--flex-etched-border-color",
13433
+ "tier": "component",
13434
+ "value": "initial"
13435
+ },
13436
+ {
13437
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13438
+ "name": "--flex-etched-border-alpha",
13439
+ "tier": "component",
13440
+ "value": "0.5"
13441
+ },
13442
+ {
13443
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13444
+ "name": "--flex-etched-border-size",
13445
+ "tier": "component",
13446
+ "value": "var(--stroke-hairline)"
13447
+ },
13448
+ {
13449
+ "description": "Lightweight row surfaces and hover actions; theme overrides remain scoped component knobs.",
13450
+ "name": "--flex-etched-radius",
13451
+ "tier": "component",
13452
+ "value": "initial"
13453
+ },
13340
13454
  {
13341
13455
  "description": "THE TWO CORNER INSETS gh#558 ASKED FOR BY NAME. Ant Design's are `marginXXL` (48px) from the bottom and `marginLG` (24px) from the inline end. Spelled here in this library's own stack/inline steps, which land on the same two numbers: --space-stack-xl = --space-10 = 40px, --space-6 = 24px. The block inset is the one a service actually has to move — a sticky action bar, a cookie strip, a mobile tab bar all live in that corner — and moving it is now retuning ONE custom property, not writing a media query at the call site (which is `no-arbitrary-spacing` and has no legal spelling).",
13342
13456
  "name": "--float-button-offset-block-end",
@@ -15701,6 +15815,90 @@
15701
15815
  "tier": "component",
15702
15816
  "value": "initial"
15703
15817
  },
15818
+ {
15819
+ "description": "RadarChart tokens. Radii and font sizes use intrinsic SVG coordinates; colors resolve in the local theme scope.",
15820
+ "name": "--radar-chart-label-inset",
15821
+ "tier": "component",
15822
+ "value": "8px"
15823
+ },
15824
+ {
15825
+ "description": "Unitless scale of the normalized polar geometry.",
15826
+ "name": "--radar-chart-plot-radius",
15827
+ "tier": "component",
15828
+ "value": "96"
15829
+ },
15830
+ {
15831
+ "description": "scale-exempt: polar distance in viewBox user units, not a corner radius",
15832
+ "name": "--radar-chart-label-radius",
15833
+ "tier": "component",
15834
+ "value": "124px"
15835
+ },
15836
+ {
15837
+ "description": "RadarChart tokens. Radii and font sizes use intrinsic SVG coordinates; colors resolve in the local theme scope.",
15838
+ "name": "--radar-chart-grid-alpha",
15839
+ "tier": "component",
15840
+ "value": "0.16"
15841
+ },
15842
+ {
15843
+ "description": "RadarChart tokens. Radii and font sizes use intrinsic SVG coordinates; colors resolve in the local theme scope.",
15844
+ "name": "--radar-chart-boundary-alpha",
15845
+ "tier": "component",
15846
+ "value": "0.32"
15847
+ },
15848
+ {
15849
+ "description": "RadarChart tokens. Radii and font sizes use intrinsic SVG coordinates; colors resolve in the local theme scope.",
15850
+ "name": "--radar-chart-axis-alpha",
15851
+ "tier": "component",
15852
+ "value": "0.2"
15853
+ },
15854
+ {
15855
+ "description": "scale-exempt: viewBox user units, scaled with the SVG, not CSS type",
15856
+ "name": "--radar-chart-label-font-size",
15857
+ "tier": "component",
15858
+ "value": "16px"
15859
+ },
15860
+ {
15861
+ "description": "Unitless second-line leading, multiplied by the resolved label font size.",
15862
+ "name": "--radar-chart-label-line-height",
15863
+ "tier": "component",
15864
+ "value": "1.25"
15865
+ },
15866
+ {
15867
+ "description": "RadarChart tokens. Radii and font sizes use intrinsic SVG coordinates; colors resolve in the local theme scope.",
15868
+ "name": "--radar-chart-tick-offset",
15869
+ "tier": "component",
15870
+ "value": "6px"
15871
+ },
15872
+ {
15873
+ "description": "scale-exempt: viewBox user units, scaled with the SVG, not CSS type",
15874
+ "name": "--radar-chart-tick-font-size",
15875
+ "tier": "component",
15876
+ "value": "10px"
15877
+ },
15878
+ {
15879
+ "description": "scale-exempt: SVG circle r in viewBox user units, not a corner radius",
15880
+ "name": "--radar-chart-point-radius",
15881
+ "tier": "component",
15882
+ "value": "3px"
15883
+ },
15884
+ {
15885
+ "description": "HSL channels; default muted-foreground resolves at the chart.",
15886
+ "name": "--radar-chart-grid-color",
15887
+ "tier": "component",
15888
+ "value": "initial"
15889
+ },
15890
+ {
15891
+ "description": "HSL channels; default foreground resolves at the chart.",
15892
+ "name": "--radar-chart-label-color",
15893
+ "tier": "component",
15894
+ "value": "initial"
15895
+ },
15896
+ {
15897
+ "description": "RadarChart tokens. Radii and font sizes use intrinsic SVG coordinates; colors resolve in the local theme scope.",
15898
+ "name": "--radar-chart-grid-stroke-width",
15899
+ "tier": "component",
15900
+ "value": "1px"
15901
+ },
15704
15902
  {
15705
15903
  "description": "Separator layout thickness; focus paint must not reserve extra space.",
15706
15904
  "name": "--resizable-handle-size",
@@ -18,3 +18,5 @@ export { PieChart } from "./pie-chart.js";
18
18
  export type { PieChartProp, PieChartProps } from "./pie-chart.js";
19
19
  export type { ChartSeriesProp, ChartDatum, ChartDatumSelect } from "../../props/components/charts.prop.js";
20
20
  export { CHART_COLORS } from "./chart-frame.js";
21
+ export { RadarChart } from "./radar-chart.js";
22
+ export type { RadarChartProp, RadarChartProps } from "./radar-chart.js";
@@ -5,6 +5,7 @@ import { HeatmapChart } from "./heatmap-chart.js";
5
5
  import { AreaChart } from "./area-chart.js";
6
6
  import { PieChart } from "./pie-chart.js";
7
7
  import { CHART_COLORS } from "./chart-frame.js";
8
+ import { RadarChart } from "./radar-chart.js";
8
9
  export {
9
10
  AreaChart,
10
11
  BarChart,
@@ -12,5 +13,6 @@ export {
12
13
  CompactBarTrend,
13
14
  HeatmapChart,
14
15
  LineChart,
15
- PieChart
16
+ PieChart,
17
+ RadarChart
16
18
  };
@@ -0,0 +1,5 @@
1
+ import * as React from "react";
2
+ import type { RadarChartProp } from "../../props/components/charts.prop.js";
3
+ export type { RadarChartProp, RadarChartProp as RadarChartProps, } from "../../props/components/charts.prop.js";
4
+ /** Shared-scale profile. SVG geometry is intrinsic, never consumer CSS or inferred scores. */
5
+ export declare function RadarChart({ data, categoryKey, valueKey, valueMax, valueTicks, label, showCaption, description, size, numberFormat, emptyMessage, footer, className, id, ref, }: RadarChartProp): React.JSX.Element;
@@ -0,0 +1,273 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { EmptyState } from "../data-display/empty-state.js";
5
+ import { useTranslation } from "../../i18n/use-translation.js";
6
+ import { ChartFrame, chartColor, chartHeight, useChartNumberFormat } from "./chart-frame.js";
7
+ function wrapLabel(text, locale, width, measure) {
8
+ const words = new Intl.Segmenter(locale, { granularity: "word" });
9
+ const graphemes = new Intl.Segmenter(locale, { granularity: "grapheme" });
10
+ const lines = [];
11
+ let line = "";
12
+ for (const { segment } of words.segment(text)) {
13
+ if (measure(line + segment) <= width) {
14
+ line += segment;
15
+ continue;
16
+ }
17
+ if (line.trim()) {
18
+ lines.push(line.trim());
19
+ line = "";
20
+ }
21
+ for (const { segment: char } of graphemes.segment(segment.trimStart())) {
22
+ if (line && measure(line + char) > width) {
23
+ lines.push(line);
24
+ line = "";
25
+ }
26
+ line += char;
27
+ }
28
+ }
29
+ if (line.trim()) lines.push(line.trim());
30
+ if (lines.length <= 2) return lines;
31
+ const last = Array.from(graphemes.segment(lines[1]), (part) => part.segment);
32
+ while (last.length && measure(last.join("") + "\u2026") > width) last.pop();
33
+ return [lines[0], last.join("") + "\u2026"];
34
+ }
35
+ function RadarChart({
36
+ data,
37
+ categoryKey,
38
+ valueKey,
39
+ valueMax,
40
+ valueTicks,
41
+ label,
42
+ showCaption = true,
43
+ description,
44
+ size = "md",
45
+ numberFormat,
46
+ emptyMessage,
47
+ footer,
48
+ className,
49
+ id,
50
+ ref
51
+ }) {
52
+ const { t, locale } = useTranslation();
53
+ const fmt = useChartNumberFormat(numberFormat ?? { maximumSignificantDigits: 21 });
54
+ const uid = React.useId();
55
+ const svgRef = React.useRef(null);
56
+ const [measuredLabels, setMeasuredLabels] = React.useState([]);
57
+ React.useEffect(() => {
58
+ const svg = svgRef.current;
59
+ if (!svg || typeof svg.getBBox !== "function") return;
60
+ let disposed = false;
61
+ const context = document.createElement("canvas").getContext("2d");
62
+ if (!context) return;
63
+ const update = () => {
64
+ if (disposed) return;
65
+ const lines = Array.from(
66
+ svg.querySelectorAll('[data-slot="radar-label"]'),
67
+ (node, index) => {
68
+ const style = getComputedStyle(node);
69
+ context.font = `${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;
70
+ const transform = new DOMMatrix(style.transform);
71
+ const inset = parseFloat(style.getPropertyValue("--radar-chart-label-inset")) || 0;
72
+ const width = Math.abs(transform.e) > 1 ? 240 - Math.abs(transform.e) - inset : 480 - inset * 2;
73
+ return {
74
+ lines: wrapLabel(
75
+ String(data[index][categoryKey] ?? ""),
76
+ locale,
77
+ Math.max(1, width),
78
+ (text) => context.measureText(text).width
79
+ ),
80
+ lineHeight: parseFloat(style.getPropertyValue("--radar-chart-label-line-height")) || 1.25
81
+ };
82
+ }
83
+ );
84
+ setMeasuredLabels(
85
+ (previous) => JSON.stringify(previous) === JSON.stringify(lines) ? previous : lines
86
+ );
87
+ };
88
+ update();
89
+ const resize = new ResizeObserver(update);
90
+ resize.observe(svg);
91
+ const theme = new MutationObserver(update);
92
+ for (let node = svg; node; node = node.parentElement) {
93
+ theme.observe(node, {
94
+ attributes: true,
95
+ attributeFilter: ["class", "style", "data-theme", "data-tenant"]
96
+ });
97
+ }
98
+ void document.fonts?.ready.then(update);
99
+ return () => {
100
+ disposed = true;
101
+ resize.disconnect();
102
+ theme.disconnect();
103
+ };
104
+ }, [data, categoryKey, locale, size, valueMax]);
105
+ const valid = data.length >= 3 && data.length <= 6 && Number.isFinite(valueMax) && valueMax > 0 && data.every(
106
+ (d) => typeof d[valueKey] === "number" && Number.isFinite(d[valueKey]) && Number(d[valueKey]) >= 0 && Number(d[valueKey]) <= valueMax
107
+ );
108
+ const point = (index, fraction, radius = 1) => {
109
+ const angle = -Math.PI / 2 + index * Math.PI * 2 / data.length;
110
+ return [Math.cos(angle) * radius * fraction, Math.sin(angle) * radius * fraction];
111
+ };
112
+ const polygon = (fraction) => data.map((_, i) => point(i, fraction).join(",")).join(" ");
113
+ const rows = data.map(
114
+ (d) => `${String(d[categoryKey] ?? "")}: ${fmt.format(Number(d[valueKey]))}`
115
+ );
116
+ const summary = t("chart.summaryRadar", {
117
+ maximum: fmt.format(valueMax),
118
+ points: fmt.format(data.length)
119
+ });
120
+ const ticks = valueTicks?.filter((v) => Number.isFinite(v) && v > 0 && v <= valueMax).map((v) => v / valueMax) ?? [0.25, 0.5, 0.75, 1];
121
+ const stroke = "hsl(var(--radar-chart-grid-color, var(--muted-foreground)))";
122
+ return /* @__PURE__ */ jsx(
123
+ ChartFrame,
124
+ {
125
+ ref,
126
+ label,
127
+ showCaption,
128
+ description,
129
+ summaryRows: rows,
130
+ imgSummary: summary,
131
+ hasData: valid,
132
+ size,
133
+ footer,
134
+ className,
135
+ id,
136
+ children: valid ? /* @__PURE__ */ jsxs(
137
+ "svg",
138
+ {
139
+ ref: svgRef,
140
+ width: "100%",
141
+ style: { maxHeight: chartHeight(size), display: "block" },
142
+ viewBox: "0 0 480 320",
143
+ "aria-hidden": "true",
144
+ "data-slot": "radar-plot",
145
+ children: [
146
+ /* @__PURE__ */ jsx("title", { id: `${uid}-radar-title`, children: typeof label === "string" ? label : summary }),
147
+ /* @__PURE__ */ jsx("desc", { children: rows.join("; ") }),
148
+ /* @__PURE__ */ jsxs("g", { transform: "translate(240 160)", children: [
149
+ ticks.map((f) => /* @__PURE__ */ jsx(
150
+ "polygon",
151
+ {
152
+ points: polygon(f),
153
+ fill: "none",
154
+ style: { transform: "scale(var(--radar-chart-plot-radius))" },
155
+ vectorEffect: "non-scaling-stroke",
156
+ strokeWidth: "var(--radar-chart-grid-stroke-width)",
157
+ stroke,
158
+ opacity: f === 1 ? "var(--radar-chart-boundary-alpha)" : "var(--radar-chart-grid-alpha)"
159
+ },
160
+ f
161
+ )),
162
+ data.map((_, i) => {
163
+ const [x, y] = point(i, 1);
164
+ return /* @__PURE__ */ jsx(
165
+ "line",
166
+ {
167
+ strokeWidth: "var(--radar-chart-grid-stroke-width)",
168
+ x1: 0,
169
+ y1: 0,
170
+ x2: x,
171
+ y2: y,
172
+ stroke,
173
+ opacity: "var(--radar-chart-axis-alpha)",
174
+ vectorEffect: "non-scaling-stroke",
175
+ style: { transform: "scale(var(--radar-chart-plot-radius))" }
176
+ },
177
+ i
178
+ );
179
+ }),
180
+ ticks.map((f) => /* @__PURE__ */ jsx(
181
+ "text",
182
+ {
183
+ "data-slot": "radar-tick",
184
+ style: {
185
+ transform: `translate(calc(-1 * var(--radar-chart-tick-offset)), calc(-${f} * var(--radar-chart-plot-radius) * 1px))`
186
+ },
187
+ textAnchor: "end",
188
+ fill: stroke,
189
+ fontSize: "var(--radar-chart-tick-font-size)",
190
+ children: fmt.format(valueMax * f)
191
+ },
192
+ f
193
+ )),
194
+ /* @__PURE__ */ jsx(
195
+ "polygon",
196
+ {
197
+ "data-slot": "radar-area",
198
+ style: { transform: "scale(var(--radar-chart-plot-radius))" },
199
+ vectorEffect: "non-scaling-stroke",
200
+ points: data.map((d, i) => point(i, Number(d[valueKey]) / valueMax).join(",")).join(" "),
201
+ fill: chartColor(0),
202
+ fillOpacity: "var(--chart-area-fill-alpha)",
203
+ stroke: chartColor(0),
204
+ strokeWidth: "var(--chart-series-stroke-width)",
205
+ strokeLinejoin: "round"
206
+ }
207
+ ),
208
+ data.map((d, i) => {
209
+ const [x, y] = point(i, Number(d[valueKey]) / valueMax);
210
+ const [lx, ly] = point(i, 1);
211
+ const fullLabel = String(d[categoryKey] ?? "");
212
+ const shown = measuredLabels[i]?.lines ?? wrapLabel(
213
+ fullLabel,
214
+ locale,
215
+ Math.abs(lx) > 0.1 ? 104 : 400,
216
+ (text) => Array.from(text).reduce(
217
+ (width, char) => width + (char.codePointAt(0) > 255 ? 16 : 9),
218
+ 0
219
+ )
220
+ );
221
+ return /* @__PURE__ */ jsxs("g", { children: [
222
+ /* @__PURE__ */ jsx(
223
+ "circle",
224
+ {
225
+ r: "var(--radar-chart-point-radius)",
226
+ style: {
227
+ transform: `translate(calc(${x} * var(--radar-chart-plot-radius) * 1px), calc(${y} * var(--radar-chart-plot-radius) * 1px))`
228
+ },
229
+ fill: chartColor(0)
230
+ }
231
+ ),
232
+ /* @__PURE__ */ jsxs(
233
+ "text",
234
+ {
235
+ "data-slot": "radar-label",
236
+ style: {
237
+ transform: `translate(calc(${lx} * var(--radar-chart-label-radius)), calc(${ly} * var(--radar-chart-label-radius)))`
238
+ },
239
+ textAnchor: lx > 0.1 ? "start" : lx < -0.1 ? "end" : "middle",
240
+ dominantBaseline: "middle",
241
+ fill: "hsl(var(--radar-chart-label-color, var(--foreground)))",
242
+ fontSize: "var(--radar-chart-label-font-size)",
243
+ fontFamily: "inherit",
244
+ children: [
245
+ /* @__PURE__ */ jsxs("title", { children: [
246
+ fullLabel,
247
+ ": ",
248
+ fmt.format(Number(d[valueKey]))
249
+ ] }),
250
+ shown.map((line, index) => /* @__PURE__ */ jsx(
251
+ "tspan",
252
+ {
253
+ x: 0,
254
+ dy: index ? `${measuredLabels[i]?.lineHeight ?? 1.25}em` : 0,
255
+ children: line
256
+ },
257
+ index
258
+ ))
259
+ ]
260
+ }
261
+ )
262
+ ] }, i);
263
+ })
264
+ ] })
265
+ ]
266
+ }
267
+ ) : /* @__PURE__ */ jsx(EmptyState, { title: emptyMessage ?? t("chart.empty") })
268
+ }
269
+ );
270
+ }
271
+ export {
272
+ RadarChart
273
+ };
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { Children } from "react";
3
+ import { Children, useEffect, useRef } from "react";
4
4
  import { mergeAriaIds } from "../../lib/field-a11y.js";
5
5
  import { cn } from "../../lib/utils.js";
6
6
  import { flexGapClass, padStyle, padStepToken } from "../../lib/variants.js";
@@ -18,6 +18,12 @@ function Flex(props) {
18
18
  }
19
19
  function LayoutFlex({
20
20
  as: Element = "div",
21
+ viewport,
22
+ ref: forwardedRef,
23
+ basis,
24
+ overflow,
25
+ rotate,
26
+ animated,
21
27
  direction = "row",
22
28
  marker,
23
29
  grow,
@@ -47,6 +53,31 @@ function LayoutFlex({
47
53
  children,
48
54
  ...props
49
55
  }) {
56
+ const viewportRef = useRef(null);
57
+ useEffect(() => {
58
+ const node = viewportRef.current;
59
+ if (!viewport || !node) return;
60
+ const update = () => {
61
+ const visual = window.visualViewport;
62
+ const bottom = visual ? visual.height + visual.offsetTop : window.innerHeight;
63
+ const available = Math.max(0, bottom - Math.max(0, node.getBoundingClientRect().top));
64
+ node.style.setProperty("--flex-viewport-available", `${available}px`);
65
+ };
66
+ update();
67
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(update);
68
+ observer?.observe(document.documentElement);
69
+ window.addEventListener("resize", update);
70
+ window.addEventListener("scroll", update, true);
71
+ window.visualViewport?.addEventListener("resize", update);
72
+ window.visualViewport?.addEventListener("scroll", update);
73
+ return () => {
74
+ observer?.disconnect();
75
+ window.removeEventListener("resize", update);
76
+ window.removeEventListener("scroll", update, true);
77
+ window.visualViewport?.removeEventListener("resize", update);
78
+ window.visualViewport?.removeEventListener("scroll", update);
79
+ };
80
+ }, [viewport, Element]);
50
81
  let domProps = props;
51
82
  if (props.role === void 0 && !HAS_IMPLICIT_ROLE.has(typeof Element === "string" ? Element : "") && (props["aria-label"] !== void 0 || props["aria-labelledby"] !== void 0)) {
52
83
  const {
@@ -75,6 +106,16 @@ function LayoutFlex({
75
106
  return /* @__PURE__ */ jsxs(
76
107
  Element,
77
108
  {
109
+ ref: (node) => {
110
+ viewportRef.current = node;
111
+ if (typeof forwardedRef === "function") forwardedRef(node);
112
+ else if (forwardedRef) forwardedRef.current = node;
113
+ },
114
+ "data-viewport": viewport ? "" : void 0,
115
+ "data-basis": basis,
116
+ "data-overflow": overflow,
117
+ "data-rotate": rotate,
118
+ "data-animated": animated ? "" : void 0,
78
119
  "data-direction": responsive ? "responsive" : direction,
79
120
  "data-grow": grow ? "" : void 0,
80
121
  "data-shrink": shrink === false ? "false" : void 0,
@@ -112,6 +153,11 @@ function LayoutFlex({
112
153
  );
113
154
  }
114
155
  function AttachedFlex({
156
+ viewport: _viewport,
157
+ basis: _basis,
158
+ overflow: _overflow,
159
+ rotate: _rotate,
160
+ animated: _animated,
115
161
  as: _as,
116
162
  direction,
117
163
  marker: _marker,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
3
- "version": "33.25.2",
3
+ "version": "33.26.0",
4
4
  "targetSize": {
5
5
  "standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
6
6
  "min": 24,
@@ -805,6 +805,7 @@
805
805
  "chart": {
806
806
  "datumLabel": "{label}, {series}: {value}",
807
807
  "empty": "No data to display",
808
+ "summaryRadar": "Profile with {points} axes on a common scale from 0 to {maximum}",
808
809
  "summaryCartesian": "Chart with {series} series across {points} data points",
809
810
  "summaryPie": "Pie chart with {slices} slices",
810
811
  "summaryTrend": "Bar trend with {points} data points",
@@ -779,6 +779,7 @@
779
779
  "chart": {
780
780
  "datumLabel": "{label}, {series}: {value}",
781
781
  "empty": "データがありません",
782
+ "summaryRadar": "{points}軸のプロファイル(共通尺度:0〜{maximum})",
782
783
  "summaryCartesian": "{series}系列・{points}データ点のグラフ",
783
784
  "summaryPie": "{slices}区分の円グラフ",
784
785
  "summaryTrend": "{points}データ点の推移棒グラフ",
@@ -780,6 +780,7 @@
780
780
  "chart": {
781
781
  "datumLabel": "{label}, {series}: {value}",
782
782
  "empty": "Không có dữ liệu",
783
+ "summaryRadar": "Hồ sơ {points} trục trên thang chung từ 0 đến {maximum}",
783
784
  "summaryCartesian": "Biểu đồ gồm {series} chuỗi trên {points} điểm dữ liệu",
784
785
  "summaryPie": "Biểu đồ tròn gồm {slices} phần",
785
786
  "summaryTrend": "Biểu đồ cột xu hướng gồm {points} điểm dữ liệu",
@@ -252,4 +252,23 @@ export type PieChartProp = {
252
252
  className?: ClassNameProp;
253
253
  id?: IdProp;
254
254
  };
255
+ /** Single quantitative profile on a shared zero-based scale; incomplete data is never zero-filled. */
256
+ export type RadarChartProp = {
257
+ data: ChartDatum[];
258
+ categoryKey: string;
259
+ valueKey: string;
260
+ /** Required common ceiling, strictly positive; values outside [0,valueMax] are invalid. */
261
+ valueMax: number;
262
+ valueTicks?: number[];
263
+ label: LabelProp;
264
+ showCaption?: boolean;
265
+ description?: DescriptionProp;
266
+ size?: SizeProp;
267
+ numberFormat?: Intl.NumberFormatOptions;
268
+ emptyMessage?: EmptyMessageProp;
269
+ footer?: FooterProp;
270
+ className?: ClassNameProp;
271
+ id?: IdProp;
272
+ ref?: React.Ref<HTMLElement>;
273
+ };
255
274
  export {};