@gridui/grid 2.2.1 → 2.3.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Grid foundation
2
2
 
3
- See the [usage handbook](../../docs/usage/README.md) and
3
+ See the [usage handbook](https://github.com/sudo-ui/GridUI-React-Monorepo/blob/main/docs/usage/README.md) and
4
4
  [Grid contract](docs/README.md) for practical usage.
5
5
 
6
6
  `@gridui/grid` owns Container, Grid, GridItem, Split, Stack, Row,
@@ -18,9 +18,13 @@ controls and tables inside those regions so their own borders remain intact.
18
18
  See [linear regions](docs/README.md#linear-regions) for the full contract.
19
19
 
20
20
  FrameSection and FrameFooter accept `tone="neutral" | "brand" | "warning" | "danger"`.
21
- Non-neutral tones scope background, foreground, muted text, borders, controls,
22
- and focus colors to that region. Theme owns the paired light/dark tokens;
23
- Grid owns their inherited application. Nested non-neutral tones establish their own palette; neutral inherits its surroundings.
21
+ Non-neutral tones reuse Theme's public `paletteClass` contract for background,
22
+ foreground, muted text, borders, controls, and focus colors. Theme owns both
23
+ palette values and their scoped semantic mapping; Grid owns region geometry.
24
+ Nested non-neutral tones establish their own palette; `tone="neutral"` continues
25
+ to inherit its surroundings. Use `paletteClass("neutral")` from `@gridui/theme`
26
+ on a native content surface for an explicit reset to registered application
27
+ neutral colors without adding a section or boundary.
24
28
 
25
29
  FrameSection owns its leading separator and inline frame edges. Use
26
30
  `boundary="none"` and `edges="none"` when an enclosing region owns them.
@@ -47,12 +51,17 @@ At a section seam, a non-neutral tone takes precedence over neutral; between
47
51
  two non-neutral tones, the lower section supplies the color. The lower section
48
52
  still draws the only separator. This works across React section groups without
49
53
  changing either region's content palette. Astro host elements require an
50
- [application-owned adapter](../../docs/usage/framework-adapters.md). The page filler uses
54
+ [application-owned adapter](https://github.com/sudo-ui/GridUI-React-Monorepo/blob/main/docs/usage/framework-adapters.md). The page filler uses
51
55
  the final section's tone for its leading line.
52
56
  Grid `frame="cells"` owns outer and cell edges; `frame="internal"` owns seams
53
57
  inside an existing frame. Use `fillLastRow` with direct GridItem children to
54
58
  fill incomplete rows at every breakpoint. Explicit gaps are disallowed in
55
- framed grids. Hover/focus outlines paint above neighboring seams and page lines.
59
+ framed grids. For wrapping lists with a container-driven track count, use
60
+ `columns="auto"` with `minItemWidth` and optional responsive gap. The minimum is
61
+ capped to available space. `Grid asChild` and `GridItem asChild` preserve native
62
+ ul/ol/li hosts without wrapper elements. Adaptive mode excludes frames and
63
+ `fillLastRow`; root `asChild` also excludes `fillLastRow`, preserving the fixed
64
+ planner's direct-item contract. Hover/focus outlines paint above neighboring seams and page lines.
56
65
  Table cell lines belong to Table; functional control borders belong to their Core families.
57
66
 
58
67
  See the [Grid contract](docs/README.md#grid-foundation) for geometry and API.
@@ -76,11 +85,11 @@ Unit tests mirror these owners under `test/unit/primitives/` and
76
85
  `test/unit/frame/`. Tests can combine public primitives to protect their
77
86
  collaboration. Keep ordinary presentation in the owner's CVA `style.ts`. Retain
78
87
  track resolution, seams, and decorative geometry in colocated CSS imported by
79
- the root stylesheet. See the [source conventions](../../docs/development/typescript-conventions.md#component-directories).
88
+ the root stylesheet. See the [source conventions](https://github.com/sudo-ui/GridUI-React-Monorepo/blob/main/docs/development/typescript-conventions.md#component-directories).
80
89
  Consumers use the package root and explicit stylesheet export; internal file
81
90
  paths are private.
82
91
 
83
- See [quarterly release history](.changeset/history/) for prepared release notes and consumption records.
92
+ See [quarterly release history](https://github.com/sudo-ui/GridUI-React-Monorepo/tree/main/packages-layout/grid/.changeset/history) for prepared release notes and consumption records.
84
93
 
85
94
  `DashboardFrame` supplies full-height workspace gutters and structural edges without
86
95
  creating a main landmark. See [dashboard frames](docs/README.md#dashboard-frames).
@@ -7,15 +7,31 @@
7
7
  import type { ElementProps } from "../shared/types";
8
8
  import type { GridColumns } from "./responsive";
9
9
  import { type Responsive, type Space } from "@gridui/style-utils/responsive";
10
- import { type FC } from "react";
11
- export type GridProps = ElementProps & {
12
- readonly columns?: Responsive<GridColumns>;
13
- readonly fillLastRow?: boolean;
14
- } & ({
10
+ import { type FC, type ReactElement } from "react";
11
+ type GridFrameOptions = {
15
12
  readonly frame?: "none";
16
13
  readonly gap?: Responsive<Space>;
17
14
  } | {
18
- readonly frame: "cells" | "internal";
15
+ readonly frame: "none" | "cells" | "internal";
19
16
  readonly gap?: never;
17
+ };
18
+ type GridLayoutOptions = ({
19
+ readonly columns?: Responsive<GridColumns>;
20
+ readonly minItemWidth?: never;
21
+ } & GridFrameOptions) | {
22
+ readonly columns: "auto";
23
+ readonly minItemWidth: Responsive<string | number>;
24
+ readonly frame?: "none";
25
+ readonly gap?: Responsive<Space>;
26
+ readonly fillLastRow?: false;
27
+ };
28
+ export type GridProps = ElementProps & GridLayoutOptions & ({
29
+ readonly asChild?: false;
30
+ readonly fillLastRow?: boolean;
31
+ } | {
32
+ readonly asChild: true;
33
+ readonly children: ReactElement;
34
+ readonly fillLastRow?: false;
20
35
  });
21
36
  export declare const Grid: FC<GridProps>;
37
+ export {};
@@ -7,4 +7,5 @@
7
7
  import type { GridColumns } from "./responsive";
8
8
  export declare const gridColumnCount: (columns: GridColumns) => number;
9
9
  export declare const gridTemplate: (columns: GridColumns) => string;
10
+ export declare const adaptiveGridTemplate: (minItemWidth: string | number) => string;
10
11
  export declare const fillGridRowSpans: (columns: number, spans: readonly number[]) => number[];
package/dist/index.js CHANGED
@@ -70,28 +70,28 @@ import { cva as cva2 } from "class-variance-authority";
70
70
  var dashboardFrameVariants = cva2("gridui-dashboard-frame", {
71
71
  variants: {
72
72
  startSize: {
73
- none: "[--gridui-dashboard-start:0px] [--gridui-dashboard-start-minimum:0px]",
74
- small: "[--gridui-dashboard-start:var(--gridui-space-8)]",
75
- medium: "[--gridui-dashboard-start:var(--gridui-space-16)]",
76
- large: "[--gridui-dashboard-start:var(--gridui-space-24)]"
73
+ none: "gridui-u-[--gridui-dashboard-start:0px] gridui-u-[--gridui-dashboard-start-minimum:0px]",
74
+ small: "gridui-u-[--gridui-dashboard-start:var(--gridui-space-8)]",
75
+ medium: "gridui-u-[--gridui-dashboard-start:var(--gridui-space-16)]",
76
+ large: "gridui-u-[--gridui-dashboard-start:var(--gridui-space-24)]"
77
77
  },
78
78
  endSize: {
79
- none: "[--gridui-dashboard-end:0px] [--gridui-dashboard-end-minimum:0px]",
80
- small: "[--gridui-dashboard-end:var(--gridui-space-8)]",
81
- medium: "[--gridui-dashboard-end:var(--gridui-space-16)]",
82
- large: "[--gridui-dashboard-end:var(--gridui-space-24)]"
79
+ none: "gridui-u-[--gridui-dashboard-end:0px] gridui-u-[--gridui-dashboard-end-minimum:0px]",
80
+ small: "gridui-u-[--gridui-dashboard-end:var(--gridui-space-8)]",
81
+ medium: "gridui-u-[--gridui-dashboard-end:var(--gridui-space-16)]",
82
+ large: "gridui-u-[--gridui-dashboard-end:var(--gridui-space-24)]"
83
83
  },
84
84
  compactStartSize: {
85
- none: "[--gridui-dashboard-compact-start:0px] [--gridui-dashboard-compact-start-minimum:0px]",
86
- small: "[--gridui-dashboard-compact-start:var(--gridui-space-8)]",
87
- medium: "[--gridui-dashboard-compact-start:var(--gridui-space-16)]",
88
- large: "[--gridui-dashboard-compact-start:var(--gridui-space-24)]"
85
+ none: "gridui-u-[--gridui-dashboard-compact-start:0px] gridui-u-[--gridui-dashboard-compact-start-minimum:0px]",
86
+ small: "gridui-u-[--gridui-dashboard-compact-start:var(--gridui-space-8)]",
87
+ medium: "gridui-u-[--gridui-dashboard-compact-start:var(--gridui-space-16)]",
88
+ large: "gridui-u-[--gridui-dashboard-compact-start:var(--gridui-space-24)]"
89
89
  },
90
90
  compactEndSize: {
91
- none: "[--gridui-dashboard-compact-end:0px] [--gridui-dashboard-compact-end-minimum:0px]",
92
- small: "[--gridui-dashboard-compact-end:var(--gridui-space-8)]",
93
- medium: "[--gridui-dashboard-compact-end:var(--gridui-space-16)]",
94
- large: "[--gridui-dashboard-compact-end:var(--gridui-space-24)]"
91
+ none: "gridui-u-[--gridui-dashboard-compact-end:0px] gridui-u-[--gridui-dashboard-compact-end-minimum:0px]",
92
+ small: "gridui-u-[--gridui-dashboard-compact-end:var(--gridui-space-8)]",
93
+ medium: "gridui-u-[--gridui-dashboard-compact-end:var(--gridui-space-16)]",
94
+ large: "gridui-u-[--gridui-dashboard-compact-end:var(--gridui-space-24)]"
95
95
  }
96
96
  },
97
97
  defaultVariants: {
@@ -205,30 +205,25 @@ var frameChromeStyles = cva4("gridui-frame-chrome");
205
205
 
206
206
  // src/shared/frame-style.ts
207
207
  import { cn as cn4 } from "@gridui/style-utils";
208
+ import { paletteClass } from "@gridui/theme";
208
209
  import { cva as cva5 } from "class-variance-authority";
209
- var frameToneStyles = cva5("", {
210
- variants: {
211
- tone: {
212
- neutral: "",
213
- brand: "gridui-frame-brand",
214
- warning: "gridui-frame-warning",
215
- danger: "gridui-frame-danger"
216
- }
217
- }
218
- });
210
+ var frameToneStyles = (options = {}) => {
211
+ const { tone = "neutral" } = options;
212
+ return tone === "neutral" ? "" : `gridui-frame-${tone} ${paletteClass(tone)}`;
213
+ };
219
214
  var frameContentStyles = cva5(cn4(
220
215
  "gridui-frame-content",
221
- "border-x border-solid border-border wrap-anywhere"
216
+ "gridui-u-border-x gridui-u-border-solid gridui-u-border-border gridui-u-wrap-anywhere"
222
217
  ));
223
218
 
224
219
  // src/frame-footer/style.ts
225
220
  import { cn as cn5 } from "@gridui/style-utils";
226
221
  import { cva as cva6 } from "class-variance-authority";
227
222
  var frameSignatureStyles = cva6(cn5(
228
- "gridui-frame-signature flex min-w-0 items-center justify-center gap-gridui-24 py-gridui-32 px-gridui-24 overflow-hidden border-t border-solid border-border bg-transparent",
229
- "[&>svg]:h-auto [&>svg]:opacity-30 [&>span]:font-display [&>span]:leading-none [&>span]:text-transparent"
223
+ "gridui-frame-signature gridui-u-flex gridui-u-min-w-0 gridui-u-items-center gridui-u-justify-center gridui-u-gap-gridui-24 gridui-u-py-gridui-32 gridui-u-px-gridui-24 gridui-u-overflow-hidden gridui-u-border-t gridui-u-border-solid gridui-u-border-border gridui-u-bg-transparent",
224
+ "gridui-u-[&>svg]:h-auto gridui-u-[&>svg]:opacity-30 gridui-u-[&>span]:font-display gridui-u-[&>span]:leading-none gridui-u-[&>span]:text-transparent"
230
225
  ));
231
- var frameSignatureCroppedStyles = cva6("gridui-frame-signature-cropped block pb-0 @container [&>span]:block [&>span]:text-center [&>span]:whitespace-nowrap");
226
+ var frameSignatureCroppedStyles = cva6("gridui-frame-signature-cropped gridui-u-block gridui-u-pb-0 gridui-u-@container gridui-u-[&>span]:block gridui-u-[&>span]:text-center gridui-u-[&>span]:whitespace-nowrap");
232
227
 
233
228
  // src/frame-footer/frame-footer.tsx
234
229
  import { cn as cn6 } from "@gridui/style-utils";
@@ -316,9 +311,9 @@ var FrameHeader = (props) => {
316
311
 
317
312
  // src/frame-rail/style.ts
318
313
  import { cva as cva7 } from "class-variance-authority";
319
- var frameRailStyles = cva7("gridui-frame-rail flex h-full box-border flex-col py-gridui-24 text-muted");
320
- var frameRailContentStyles = cva7("gridui-frame-rail-content relative z-(--gridui-z-interaction) min-w-0 type-eyebrow bg-inherit");
321
- var frameRailStickyBottomStyles = cva7("gridui-frame-rail-sticky-bottom justify-end [&>.gridui-frame-rail-content]:sticky");
314
+ var frameRailStyles = cva7("gridui-frame-rail gridui-u-flex gridui-u-h-full gridui-u-box-border gridui-u-flex-col gridui-u-py-gridui-24 gridui-u-text-muted");
315
+ var frameRailContentStyles = cva7("gridui-frame-rail-content gridui-u-relative gridui-u-z-(--gridui-z-interaction) gridui-u-min-w-0 gridui-u-type-eyebrow gridui-u-bg-inherit");
316
+ var frameRailStickyBottomStyles = cva7("gridui-frame-rail-sticky-bottom gridui-u-justify-end gridui-u-[&>.gridui-frame-rail-content]:sticky");
322
317
 
323
318
  // src/frame-rail/frame-rail.tsx
324
319
  import { cn as cn8 } from "@gridui/style-utils";
@@ -477,7 +472,7 @@ var FrameSection = (props) => {
477
472
  /* @__PURE__ */ jsxs5(
478
473
  "div",
479
474
  {
480
- className: cn12(frameContentStyles(), "gridui-frame-surface", edges === "none" && "border-x-0"),
475
+ className: cn12(frameContentStyles(), "gridui-frame-surface", edges === "none" && "gridui-u-border-x-0"),
481
476
  style: {
482
477
  ...spacingVariables("section-padding-inline", paddingInline),
483
478
  ...spacingVariables("section-padding-block", paddingBlock)
@@ -528,7 +523,7 @@ import { cn as cn14 } from "@gridui/style-utils";
528
523
  import { cva as cva8 } from "class-variance-authority";
529
524
  var gridItemStyles = cva8(cn14(
530
525
  "gridui-grid-item",
531
- "min-w-0 wrap-anywhere"
526
+ "gridui-u-min-w-0 gridui-u-wrap-anywhere"
532
527
  ));
533
528
 
534
529
  // src/grid-item/grid-item.tsx
@@ -577,15 +572,15 @@ import { cn as cn16 } from "@gridui/style-utils";
577
572
  import { cva as cva9 } from "class-variance-authority";
578
573
  var gridStyles = cva9(cn16(
579
574
  "gridui-grid",
580
- "grid min-w-0"
575
+ "gridui-u-grid gridui-u-min-w-0"
581
576
  ));
582
577
  var gridCellsStyles = cva9(cn16(
583
578
  "gridui-grid-cells",
584
- "border-t border-solid border-border border-l border-solid border-border"
579
+ "gridui-u-border-t gridui-u-border-solid gridui-u-border-border gridui-u-border-l gridui-u-border-solid gridui-u-border-border"
585
580
  ));
586
581
  var gridInternalStyles = cva9(cn16(
587
582
  "gridui-grid-internal",
588
- "bg-border"
583
+ "gridui-u-bg-border"
589
584
  ));
590
585
  var gridVariants = cva9(gridStyles(), {
591
586
  variants: {
@@ -610,6 +605,13 @@ var gridTemplate = (columns) => {
610
605
  return track === "1fr" ? "minmax(0, 1fr)" : track;
611
606
  }).join(" ");
612
607
  };
608
+ var adaptiveGridTemplate = (minItemWidth) => {
609
+ if (typeof minItemWidth === "number" && (!Number.isFinite(minItemWidth) || minItemWidth <= 0) || typeof minItemWidth === "string" && !minItemWidth.trim()) {
610
+ throw new RangeError("Adaptive Grid minItemWidth must be a positive number or a nonempty CSS length.");
611
+ }
612
+ const minimum = typeof minItemWidth === "number" ? `${minItemWidth}px` : minItemWidth;
613
+ return `repeat(auto-fit, minmax(min(100%, ${minimum}), 1fr))`;
614
+ };
613
615
  var fillGridRowSpans = (columns, spans) => {
614
616
  let occupied = 0;
615
617
  return spans.map((span, index) => {
@@ -636,11 +638,14 @@ var fillGridRowSpans = (columns, spans) => {
636
638
  // src/grid/grid.tsx
637
639
  import { cn as cn17 } from "@gridui/style-utils";
638
640
  import { resolveResponsive as resolveResponsive4, spaceValue as spaceValue5 } from "@gridui/style-utils/responsive";
639
- import { Children, cloneElement, isValidElement } from "react";
641
+ import { Slot as Slot4 } from "@radix-ui/react-slot";
642
+ import { Children, cloneElement, Fragment as Fragment2, isValidElement } from "react";
640
643
  import { jsx as jsx15 } from "react/jsx-runtime";
641
644
  var Grid = (props) => {
642
645
  const {
643
646
  columns = 1,
647
+ minItemWidth,
648
+ asChild = false,
644
649
  frame = "none",
645
650
  gap = 16,
646
651
  fillLastRow = false,
@@ -649,27 +654,56 @@ var Grid = (props) => {
649
654
  children,
650
655
  ...restProps
651
656
  } = props;
652
- const tracks = resolveResponsive4(columns);
653
- const count = {
654
- base: gridColumnCount(tracks.base),
655
- md: gridColumnCount(tracks.md),
656
- lg: gridColumnCount(tracks.lg)
657
- };
657
+ if (fillLastRow && (asChild || columns === "auto")) {
658
+ throw new TypeError("Grid fillLastRow requires fixed columns and direct GridItem children, without asChild.");
659
+ }
660
+ if (columns === "auto" && frame !== "none") {
661
+ throw new TypeError("Adaptive Grid does not support framed cells.");
662
+ }
663
+ if (asChild && (!isValidElement(children) || children.type === Fragment2)) {
664
+ throw new TypeError("Grid asChild requires one element that forwards props and refs to its root.");
665
+ }
666
+ let geometry;
667
+ let count = null;
668
+ if (columns === "auto") {
669
+ if (minItemWidth === void 0) {
670
+ throw new TypeError("Adaptive Grid requires minItemWidth.");
671
+ }
672
+ const minimum = resolveResponsive4(minItemWidth);
673
+ geometry = {
674
+ "--gridui-grid-template": adaptiveGridTemplate(minimum.base),
675
+ "--gridui-grid-template-md": adaptiveGridTemplate(minimum.md),
676
+ "--gridui-grid-template-lg": adaptiveGridTemplate(minimum.lg)
677
+ };
678
+ } else {
679
+ if (minItemWidth !== void 0) {
680
+ throw new TypeError("Grid minItemWidth requires columns=auto.");
681
+ }
682
+ const tracks = resolveResponsive4(columns);
683
+ count = {
684
+ base: gridColumnCount(tracks.base),
685
+ md: gridColumnCount(tracks.md),
686
+ lg: gridColumnCount(tracks.lg)
687
+ };
688
+ geometry = {
689
+ "--gridui-columns": count.base,
690
+ "--gridui-columns-md": count.md,
691
+ "--gridui-columns-lg": count.lg,
692
+ "--gridui-grid-template": gridTemplate(tracks.base),
693
+ "--gridui-grid-template-md": gridTemplate(tracks.md),
694
+ "--gridui-grid-template-lg": gridTemplate(tracks.lg)
695
+ };
696
+ }
658
697
  const spacing = resolveResponsive4(frame === "none" ? gap : 0);
659
698
  const layoutStyle = {
660
- "--gridui-columns": count.base,
661
- "--gridui-columns-md": count.md,
662
- "--gridui-columns-lg": count.lg,
663
- "--gridui-grid-template": gridTemplate(tracks.base),
664
- "--gridui-grid-template-md": gridTemplate(tracks.md),
665
- "--gridui-grid-template-lg": gridTemplate(tracks.lg),
699
+ ...geometry,
666
700
  "--gridui-gap": frame === "internal" ? "1px" : spaceValue5(spacing.base),
667
701
  "--gridui-gap-md": frame === "internal" ? "1px" : spaceValue5(spacing.md),
668
702
  "--gridui-gap-lg": frame === "internal" ? "1px" : spaceValue5(spacing.lg),
669
703
  ...style
670
704
  };
671
705
  let content = children;
672
- if (fillLastRow) {
706
+ if (fillLastRow && count) {
673
707
  const items = Children.toArray(children).map((child) => {
674
708
  if (!isValidElement(child) || child.type !== GridItem) {
675
709
  throw new TypeError("Grid fillLastRow requires direct GridItem children.");
@@ -702,8 +736,9 @@ var Grid = (props) => {
702
736
  });
703
737
  });
704
738
  }
739
+ const Component = asChild ? Slot4 : "div";
705
740
  return /* @__PURE__ */ jsx15(
706
- "div",
741
+ Component,
707
742
  {
708
743
  ...restProps,
709
744
  className: cn17(gridVariants({ frame }), className),
@@ -715,7 +750,7 @@ var Grid = (props) => {
715
750
 
716
751
  // src/page-frame/style.ts
717
752
  import { cva as cva10 } from "class-variance-authority";
718
- var pageFrameVariants = cva10("gridui-page-frame min-h-svh", {
753
+ var pageFrameVariants = cva10("gridui-page-frame gridui-u-min-h-svh", {
719
754
  variants: {
720
755
  width: {
721
756
  narrow: "gridui-container-narrow",
@@ -729,7 +764,7 @@ var pageFrameVariants = cva10("gridui-page-frame min-h-svh", {
729
764
  // src/page-frame/page-frame.tsx
730
765
  import { cn as cn18 } from "@gridui/style-utils";
731
766
  import { spacingVariables as spacingVariables2 } from "@gridui/style-utils/responsive";
732
- import { Fragment as Fragment2, jsx as jsx16, jsxs as jsxs6 } from "react/jsx-runtime";
767
+ import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs6 } from "react/jsx-runtime";
733
768
  var PageFrame = (props) => {
734
769
  const {
735
770
  width = "standard",
@@ -744,7 +779,7 @@ var PageFrame = (props) => {
744
779
  ...restProps
745
780
  } = props;
746
781
  const railOptions = railWidth === void 0 ? {} : { railWidth };
747
- const content = /* @__PURE__ */ jsxs6(Fragment2, { children: [
782
+ const content = /* @__PURE__ */ jsxs6(Fragment3, { children: [
748
783
  /* @__PURE__ */ jsx16(FrameSections, { children }),
749
784
  /* @__PURE__ */ jsx16(
750
785
  "div",
@@ -808,7 +843,7 @@ import { cn as cn19 } from "@gridui/style-utils";
808
843
  import { cva as cva11 } from "class-variance-authority";
809
844
  var rowStyles = cva11(cn19(
810
845
  "gridui-row",
811
- "min-w-0"
846
+ "gridui-u-min-w-0"
812
847
  ));
813
848
 
814
849
  // src/row/row.tsx
@@ -874,7 +909,7 @@ import { cn as cn22 } from "@gridui/style-utils";
874
909
  import { cva as cva12 } from "class-variance-authority";
875
910
  var stackStyles = cva12(cn22(
876
911
  "gridui-stack",
877
- "flex min-w-0 flex-col"
912
+ "gridui-u-flex gridui-u-min-w-0 gridui-u-flex-col"
878
913
  ));
879
914
 
880
915
  // src/stack/stack.tsx