@godxjp/ui 33.25.1 → 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.
@@ -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.1",
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 {};
@@ -171,9 +171,21 @@ export type FlexJustifyProp = "start" | "center" | "end" | "between" | "around"
171
171
  * Bringhurst's 45–75 character reading band, `wide` (72rem) is the MARKETING measure. Do not give
172
172
  * a reading column `wide` — that rule is `--page-measure-wide`'s own, and it travels with the word.
173
173
  */
174
- export type FlexMeasureProp = "narrow" | "medium" | "wide";
174
+ export type FlexMeasureProp = "narrow" | "medium" | "wide" | "card" | "card-compact";
175
175
  /** @see Flex */
176
176
  export type FlexProp = React.HTMLAttributes<HTMLElement> & {
177
+ /** React19 ref to the rendered element. */
178
+ ref?: React.Ref<HTMLElement>;
179
+ /** Fit the visual viewport below this element's measured top; observes resize and scroll. */
180
+ viewport?: boolean;
181
+ /** Equal flexible region: flex 1 1 0 with zero minimum block size. */
182
+ basis?: "equal";
183
+ /** Internal scrolling; scroll-x and scroll-y constrain the other axis. */
184
+ overflow?: "hidden" | "auto" | "scroll-x" | "scroll-y";
185
+ /** Declarative orientation; no implied domain action. */
186
+ rotate?: 0 | 90 | 180 | 270;
187
+ /** Animate orientation changes only. Reduced motion always settles immediately. */
188
+ animated?: boolean;
177
189
  /**
178
190
  * Render element — `div` (default) or `span` when the Flex sits in a PHRASING context and a
179
191
  * `<div>` would be invalid HTML: inside a `TabsTrigger`/`PopoverTrigger`/`Button` (all of which
@@ -203,7 +215,7 @@ export type FlexProp = React.HTMLAttributes<HTMLElement> & {
203
215
  */
204
216
  marker?: FlexMarkerProp;
205
217
  /** Lightweight surfaces for rows and notices; no Card elevation by default. */
206
- surface?: "muted" | "popover" | "warning";
218
+ surface?: "muted" | "popover" | "warning" | "felt" | "etched";
207
219
  /** Negative inline inset, using the same spacing scale as pad. */
208
220
  bleed?: GapProp;
209
221
  /** Floating row actions: show on parent hover, focus-within, and touch. */
@@ -909,6 +909,26 @@ export declare const COMPONENT_PROP_REGISTRY: {
909
909
  readonly group: "layout";
910
910
  readonly file: "components/layout.prop.ts";
911
911
  readonly vocabulary: readonly [{
912
+ readonly field: "viewport";
913
+ readonly local: true;
914
+ readonly reason: "Generic bounded composition and declarative orientation capability; inert when omitted.";
915
+ }, {
916
+ readonly field: "basis";
917
+ readonly local: true;
918
+ readonly reason: "Generic bounded composition and declarative orientation capability; inert when omitted.";
919
+ }, {
920
+ readonly field: "overflow";
921
+ readonly local: true;
922
+ readonly reason: "Generic bounded composition and declarative orientation capability; inert when omitted.";
923
+ }, {
924
+ readonly field: "rotate";
925
+ readonly local: true;
926
+ readonly reason: "Generic bounded composition and declarative orientation capability; inert when omitted.";
927
+ }, {
928
+ readonly field: "animated";
929
+ readonly local: true;
930
+ readonly reason: "Generic bounded composition and declarative orientation capability; inert when omitted.";
931
+ }, {
912
932
  readonly field: "as";
913
933
  readonly local: true;
914
934
  readonly reason: "Closed tag seam (div | span) so a Flex stays valid HTML inside a phrasing-only parent such as the <button> a TabsTrigger renders — same shape as ListRow's `as` (gh#354).";
@@ -3616,6 +3636,43 @@ export declare const COMPONENT_PROP_REGISTRY: {
3616
3636
  readonly reason: "Chart-specific point-marker toggle.";
3617
3637
  }];
3618
3638
  };
3639
+ readonly RadarChartProp: {
3640
+ readonly group: "data-display";
3641
+ readonly file: "components/charts.prop.ts";
3642
+ readonly vocabulary: readonly ["LabelProp", "DescriptionProp", "SizeProp", "EmptyMessageProp", "FooterProp", "ClassNameProp", "IdProp", {
3643
+ readonly field: "data";
3644
+ readonly local: true;
3645
+ readonly reason: "Complete same-unit polar profile rows.";
3646
+ }, {
3647
+ readonly field: "categoryKey";
3648
+ readonly local: true;
3649
+ readonly reason: "Accessor for translated axis labels.";
3650
+ }, {
3651
+ readonly field: "valueKey";
3652
+ readonly local: true;
3653
+ readonly reason: "Accessor for the quantitative axis value.";
3654
+ }, {
3655
+ readonly field: "valueMax";
3656
+ readonly local: true;
3657
+ readonly reason: "Required positive shared scale ceiling.";
3658
+ }, {
3659
+ readonly field: "valueTicks";
3660
+ readonly local: true;
3661
+ readonly reason: "Optional positive shared scale ticks.";
3662
+ }, {
3663
+ readonly field: "showCaption";
3664
+ readonly local: true;
3665
+ readonly reason: "Hide visible caption while preserving figure name.";
3666
+ }, {
3667
+ readonly field: "numberFormat";
3668
+ readonly local: true;
3669
+ readonly reason: "Intl options for exact profile values.";
3670
+ }, {
3671
+ readonly field: "ref";
3672
+ readonly local: true;
3673
+ readonly reason: "Forwarded figure reference.";
3674
+ }];
3675
+ };
3619
3676
  readonly BarChartProp: {
3620
3677
  readonly group: "data-display";
3621
3678
  readonly file: "components/charts.prop.ts";
@@ -912,6 +912,31 @@ const COMPONENT_PROP_REGISTRY = {
912
912
  group: "layout",
913
913
  file: "components/layout.prop.ts",
914
914
  vocabulary: [
915
+ {
916
+ field: "viewport",
917
+ local: true,
918
+ reason: "Generic bounded composition and declarative orientation capability; inert when omitted."
919
+ },
920
+ {
921
+ field: "basis",
922
+ local: true,
923
+ reason: "Generic bounded composition and declarative orientation capability; inert when omitted."
924
+ },
925
+ {
926
+ field: "overflow",
927
+ local: true,
928
+ reason: "Generic bounded composition and declarative orientation capability; inert when omitted."
929
+ },
930
+ {
931
+ field: "rotate",
932
+ local: true,
933
+ reason: "Generic bounded composition and declarative orientation capability; inert when omitted."
934
+ },
935
+ {
936
+ field: "animated",
937
+ local: true,
938
+ reason: "Generic bounded composition and declarative orientation capability; inert when omitted."
939
+ },
915
940
  {
916
941
  field: "as",
917
942
  local: true,
@@ -3809,6 +3834,31 @@ const COMPONENT_PROP_REGISTRY = {
3809
3834
  { field: "showDots", local: true, reason: "Chart-specific point-marker toggle." }
3810
3835
  ]
3811
3836
  },
3837
+ RadarChartProp: {
3838
+ group: "data-display",
3839
+ file: "components/charts.prop.ts",
3840
+ vocabulary: [
3841
+ "LabelProp",
3842
+ "DescriptionProp",
3843
+ "SizeProp",
3844
+ "EmptyMessageProp",
3845
+ "FooterProp",
3846
+ "ClassNameProp",
3847
+ "IdProp",
3848
+ { field: "data", local: true, reason: "Complete same-unit polar profile rows." },
3849
+ { field: "categoryKey", local: true, reason: "Accessor for translated axis labels." },
3850
+ { field: "valueKey", local: true, reason: "Accessor for the quantitative axis value." },
3851
+ { field: "valueMax", local: true, reason: "Required positive shared scale ceiling." },
3852
+ { field: "valueTicks", local: true, reason: "Optional positive shared scale ticks." },
3853
+ {
3854
+ field: "showCaption",
3855
+ local: true,
3856
+ reason: "Hide visible caption while preserving figure name."
3857
+ },
3858
+ { field: "numberFormat", local: true, reason: "Intl options for exact profile values." },
3859
+ { field: "ref", local: true, reason: "Forwarded figure reference." }
3860
+ ]
3861
+ },
3812
3862
  BarChartProp: {
3813
3863
  group: "data-display",
3814
3864
  file: "components/charts.prop.ts",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "33.25.1",
2
+ "version": "33.26.0",
3
3
  "generatedBy": "scripts/gen-style-layers.mjs — do not edit by hand; run `pnpm gen:style-layers`",
4
4
  "base": "base.css",
5
5
  "fonts": "fonts.css",
@@ -1094,6 +1094,12 @@
1094
1094
  "data-display-layout.css"
1095
1095
  ]
1096
1096
  },
1097
+ "RadarChart": {
1098
+ "layers": [
1099
+ "layout.css",
1100
+ "chart-layout.css"
1101
+ ]
1102
+ },
1097
1103
  "Radio": {
1098
1104
  "layers": [
1099
1105
  "control.css",
@@ -2515,12 +2515,30 @@
2515
2515
  inline-size: var(--affix-content-inline-size, auto);
2516
2516
  }
2517
2517
 
2518
- .ui-affix-content[data-affixed][data-clamped] {
2518
+ .ui-affix-content[data-affixed][data-clamped],
2519
+ .ui-affix[data-pin] > .ui-affix-content[data-clamped] {
2519
2520
  max-block-size: var(--affix-content-max-block-size, none);
2520
2521
  overflow-y: auto;
2521
2522
  overscroll-behavior: contain;
2522
2523
  }
2523
2524
 
2525
+ .ui-affix[data-pin="sticky-start"] {
2526
+ position: sticky;
2527
+ inset-block-start: var(--affix-inset-block-start);
2528
+ z-index: var(--sticky-z-index);
2529
+ }
2530
+
2531
+ .ui-affix[data-pin="sticky-end"] {
2532
+ position: sticky;
2533
+ inset-block-end: var(--affix-inset-block-end);
2534
+ z-index: var(--sticky-z-index);
2535
+ }
2536
+
2537
+ .ui-affix[data-pin] > .ui-affix-content[data-affixed] {
2538
+ position: static;
2539
+ inline-size: auto;
2540
+ }
2541
+
2524
2542
  .ui-affix-content[data-affixed][data-edge="block-start"] {
2525
2543
  inset-block-start: calc(var(--affix-target-inset, 0px) + var(--affix-inset-block-start));
2526
2544
  }
@@ -2560,5 +2578,158 @@
2560
2578
  grid-template-columns: var(--responsive-grid-panels-track-size);
2561
2579
  gap: var(--responsive-grid-panels-gap);
2562
2580
  }
2581
+ }
2582
+
2583
+ @layer components {
2584
+ .ui-flex[data-viewport] {
2585
+ block-size: var(--flex-viewport-available, 100dvh);
2586
+ min-block-size: 0;
2563
2587
 
2588
+ overflow: clip;
2589
+ overflow-clip-margin: var(--focus-ring-clip-margin);
2590
+ }
2591
+ .ui-flex[data-basis="equal"] {
2592
+ flex: 1 1 0;
2593
+ min-block-size: 0;
2594
+ min-inline-size: 0;
2595
+ }
2596
+ .ui-flex[data-overflow] {
2597
+ min-block-size: 0;
2598
+ min-inline-size: 0;
2599
+ }
2600
+ .ui-flex[data-overflow="hidden"] {
2601
+ overflow: clip;
2602
+ overflow-clip-margin: var(--focus-ring-clip-margin);
2603
+ }
2604
+ .ui-flex[data-overflow="auto"] {
2605
+ overflow: auto;
2606
+ }
2607
+ .ui-flex[data-overflow="scroll-x"] {
2608
+ overflow-x: auto;
2609
+ overflow-y: hidden;
2610
+ }
2611
+ .ui-flex[data-overflow="scroll-y"] {
2612
+ overflow-y: auto;
2613
+ overflow-x: hidden;
2614
+ }
2615
+ .ui-flex[data-measure="card"],
2616
+ .ui-flex[data-measure="card-compact"] {
2617
+ margin-inline: 0;
2618
+ flex: 0 0 auto;
2619
+ max-inline-size: none;
2620
+ }
2621
+ .ui-flex[data-measure="card"] {
2622
+ inline-size: calc(var(--flex-card-width) * var(--flex-card-size-ratio));
2623
+ block-size: calc(var(--flex-card-width) * var(--flex-card-size-ratio));
2624
+ align-items: center;
2625
+ justify-content: center;
2626
+ }
2627
+ .ui-flex[data-measure="card-compact"] {
2628
+ inline-size: calc(var(--flex-compact-card-width) * var(--flex-card-size-ratio));
2629
+ block-size: calc(var(--flex-compact-card-width) * var(--flex-card-size-ratio));
2630
+ align-items: center;
2631
+ justify-content: center;
2632
+ }
2633
+ .ui-flex[data-rotate="0"] {
2634
+ transform: rotate(0deg);
2635
+ }
2636
+ .ui-flex[data-rotate="90"] {
2637
+ transform: rotate(90deg);
2638
+ }
2639
+ .ui-flex[data-rotate="180"] {
2640
+ transform: rotate(180deg);
2641
+ }
2642
+ .ui-flex[data-rotate="270"] {
2643
+ transform: rotate(270deg);
2644
+ }
2645
+ .ui-flex[data-animated][data-rotate] {
2646
+ transition: transform var(--flex-orientation-duration) var(--ease-decelerate);
2647
+ }
2648
+ @media (prefers-reduced-motion: reduce) {
2649
+ .ui-flex[data-animated][data-rotate] {
2650
+ transition: none;
2651
+ }
2652
+ }
2653
+ }
2654
+
2655
+ @layer components {
2656
+ .ui-flex[data-measure="card"] > * {
2657
+ inline-size: var(--flex-card-width);
2658
+ max-inline-size: var(--flex-card-width);
2659
+ }
2660
+ .ui-flex[data-measure="card-compact"] > * {
2661
+ inline-size: var(--flex-compact-card-width);
2662
+ max-inline-size: var(--flex-compact-card-width);
2663
+ }
2664
+ .ui-flex[data-viewport] {
2665
+ padding-block-end: env(safe-area-inset-bottom, 0px);
2666
+ box-sizing: border-box;
2667
+ }
2668
+ }
2669
+
2670
+ @layer components {
2671
+ .ui-flex[data-surface="felt"] {
2672
+ --background: var(--flex-felt-background, var(--primary));
2673
+ --button-outline-foreground: hsl(var(--foreground));
2674
+ --button-outline-background: transparent;
2675
+ --button-outline-border-color: hsl(
2676
+ var(--flex-etched-border-color, var(--foreground)) / var(--flex-felt-control-border-alpha)
2677
+ );
2678
+ --button-link-foreground: hsl(var(--foreground));
2679
+ --control-surface-background: hsl(var(--background));
2680
+ --control-surface-border-color: hsl(
2681
+ var(--flex-etched-border-color, var(--foreground)) / var(--flex-felt-control-border-alpha)
2682
+ );
2683
+ --secondary: var(--background);
2684
+ --secondary-foreground: var(--foreground);
2685
+ --accent: var(--foreground);
2686
+ --accent-foreground: var(--background);
2687
+ --slider-track-background: hsl(
2688
+ var(--flex-etched-border-color, var(--foreground)) / var(--flex-felt-track-alpha)
2689
+ );
2690
+ --slider-range-background: hsl(var(--foreground));
2691
+
2692
+ --foreground: var(--flex-felt-foreground, var(--primary-foreground));
2693
+ --muted-foreground: var(--flex-felt-muted-foreground, var(--primary-foreground));
2694
+ --ring: var(--flex-felt-focus-color, var(--primary-foreground));
2695
+ color: hsl(var(--foreground));
2696
+ background-color: hsl(var(--flex-felt-background, var(--primary)));
2697
+ background-image:
2698
+ radial-gradient(
2699
+ ellipse at center,
2700
+ hsl(var(--foreground) / var(--flex-felt-highlight-alpha)),
2701
+ transparent var(--flex-felt-highlight-size)
2702
+ ),
2703
+ repeating-linear-gradient(
2704
+ 0deg,
2705
+ hsl(var(--foreground) / var(--flex-felt-grain-alpha)) 0,
2706
+ transparent var(--flex-felt-grain-width),
2707
+ transparent var(--flex-felt-grain-size)
2708
+ ),
2709
+ repeating-linear-gradient(
2710
+ 90deg,
2711
+ hsl(var(--foreground) / var(--flex-felt-grain-alpha)) 0,
2712
+ transparent var(--flex-felt-grain-width),
2713
+ transparent var(--flex-felt-grain-size)
2714
+ );
2715
+ }
2716
+ .ui-flex[data-surface="etched"] {
2717
+ border: var(--flex-etched-border-size) solid
2718
+ hsl(var(--flex-etched-border-color, var(--foreground)) / var(--flex-etched-border-alpha));
2719
+ border-radius: var(--flex-etched-radius, var(--radius-md));
2720
+ background: transparent;
2721
+ box-sizing: border-box;
2722
+ }
2723
+ }
2724
+
2725
+ @layer components {
2726
+ .ui-flex[data-surface="felt"] .ui-button--default {
2727
+ --primary-foreground: var(--background);
2728
+ --primary-hover: var(--foreground);
2729
+ --button-default-background: hsl(var(--foreground));
2730
+ }
2731
+ .ui-flex[data-surface="felt"] .ui-slider-thumb {
2732
+ background: hsl(var(--foreground));
2733
+ border-color: hsl(var(--flex-etched-border-color, var(--foreground)));
2734
+ }
2564
2735
  }