@godxjp/ui 16.2.1 → 16.3.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/dist/components/data-display/descriptions.d.ts +5 -1
- package/dist/components/data-display/descriptions.js +31 -8
- package/dist/components/data-display/table.js +9 -1
- package/dist/props/registry.d.ts +5 -0
- package/dist/props/registry.js +5 -0
- package/dist/props/vocabulary/interaction.prop.d.ts +3 -0
- package/dist/styles/card-layout.css +1 -1
- package/dist/tokens/base.css +1 -0
- package/dist/tokens/components/card.css +12 -5
- package/dist/tokens/components/descriptions.css +9 -0
- package/package.json +1 -1
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import type { DescriptionsLayoutProp } from "../../props/vocabulary/interaction.prop";
|
|
3
|
+
export type { DescriptionsLayoutProp };
|
|
2
4
|
export interface DescriptionsProps {
|
|
3
5
|
columns?: 1 | 2 | 3;
|
|
6
|
+
/** Label placement within each item. Default `vertical` (label over value). */
|
|
7
|
+
layout?: DescriptionsLayoutProp;
|
|
4
8
|
className?: string;
|
|
5
9
|
children: React.ReactNode;
|
|
6
10
|
}
|
|
7
|
-
export declare function Descriptions({ columns, className, children }: DescriptionsProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export declare function Descriptions({ columns, layout, className, children, }: DescriptionsProps): import("react/jsx-runtime").JSX.Element;
|
|
8
12
|
export declare namespace Descriptions {
|
|
9
13
|
var Item: ({ label, mono, span, className, children, }: DescriptionsItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
14
|
}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
2
3
|
import { cn } from "../../lib/utils";
|
|
3
|
-
|
|
4
|
+
const DescriptionsLayoutContext = React.createContext("vertical");
|
|
5
|
+
function Descriptions({
|
|
6
|
+
columns = 2,
|
|
7
|
+
layout = "vertical",
|
|
8
|
+
className,
|
|
9
|
+
children
|
|
10
|
+
}) {
|
|
4
11
|
const colsClass = columns === 1 ? "grid-cols-1" : columns === 3 ? "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3" : "grid-cols-1 sm:grid-cols-2";
|
|
5
|
-
return /* @__PURE__ */ jsx("dl", { className: cn("grid gap-x-6 gap-y-3", colsClass, className), children });
|
|
12
|
+
return /* @__PURE__ */ jsx(DescriptionsLayoutContext.Provider, { value: layout, children: /* @__PURE__ */ jsx("dl", { className: cn("grid gap-x-6 gap-y-3", colsClass, className), children }) });
|
|
6
13
|
}
|
|
7
14
|
Descriptions.Item = function DescriptionsItem({
|
|
8
15
|
label,
|
|
@@ -11,13 +18,29 @@ Descriptions.Item = function DescriptionsItem({
|
|
|
11
18
|
className,
|
|
12
19
|
children
|
|
13
20
|
}) {
|
|
21
|
+
const layout = React.useContext(DescriptionsLayoutContext);
|
|
14
22
|
const spanClass = span === 2 ? "sm:col-span-2" : span === 3 ? "sm:col-span-2 lg:col-span-3" : "";
|
|
15
|
-
return (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
return /* @__PURE__ */ jsxs(
|
|
24
|
+
"div",
|
|
25
|
+
{
|
|
26
|
+
className: cn(
|
|
27
|
+
layout === "horizontal" ? (
|
|
28
|
+
// Label beside value — a token-aligned label column so the values line up. The
|
|
29
|
+
// `--descriptions-label-width` knob aligns labels (rule #44/#45).
|
|
30
|
+
"grid grid-cols-[var(--descriptions-label-width)_minmax(0,1fr)] items-baseline gap-x-3"
|
|
31
|
+
) : (
|
|
32
|
+
// Vertical (default): label over value. The shared --field-label-gap matches
|
|
33
|
+
// FormField / Form so the label→value gap is consistent everywhere.
|
|
34
|
+
"grid gap-[var(--field-label-gap)]"
|
|
35
|
+
),
|
|
36
|
+
spanClass,
|
|
37
|
+
className
|
|
38
|
+
),
|
|
39
|
+
children: [
|
|
40
|
+
/* @__PURE__ */ jsx("dt", { className: "text-muted-foreground text-xs", children: label }),
|
|
41
|
+
/* @__PURE__ */ jsx("dd", { className: cn("text-sm break-all", mono && "font-mono"), children })
|
|
42
|
+
]
|
|
43
|
+
}
|
|
21
44
|
);
|
|
22
45
|
};
|
|
23
46
|
export {
|
|
@@ -3,7 +3,15 @@ import * as React from "react";
|
|
|
3
3
|
import { tableHeadHeightClass } from "../../lib/control-styles";
|
|
4
4
|
import { cn } from "../../lib/utils";
|
|
5
5
|
const Table = React.forwardRef(
|
|
6
|
-
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx(
|
|
6
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx(
|
|
7
|
+
"table",
|
|
8
|
+
{
|
|
9
|
+
ref,
|
|
10
|
+
"data-slot": "table",
|
|
11
|
+
className: cn("w-full caption-bottom text-sm", className),
|
|
12
|
+
...props
|
|
13
|
+
}
|
|
14
|
+
) })
|
|
7
15
|
);
|
|
8
16
|
Table.displayName = "Table";
|
|
9
17
|
const TableHeader = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
|
package/dist/props/registry.d.ts
CHANGED
|
@@ -249,6 +249,11 @@ export declare const VOCABULARY_REGISTRY: {
|
|
|
249
249
|
readonly category: "interaction";
|
|
250
250
|
readonly description: "Form label layout: vertical | horizontal | inline";
|
|
251
251
|
};
|
|
252
|
+
readonly DescriptionsLayoutProp: {
|
|
253
|
+
readonly file: "vocabulary/interaction.prop.ts";
|
|
254
|
+
readonly category: "interaction";
|
|
255
|
+
readonly description: "Descriptions label layout: vertical (over) | horizontal (beside)";
|
|
256
|
+
};
|
|
252
257
|
readonly BreakpointProp: {
|
|
253
258
|
readonly file: "vocabulary/interaction.prop.ts";
|
|
254
259
|
readonly category: "interaction";
|
package/dist/props/registry.js
CHANGED
|
@@ -248,6 +248,11 @@ const VOCABULARY_REGISTRY = {
|
|
|
248
248
|
category: "interaction",
|
|
249
249
|
description: "Form label layout: vertical | horizontal | inline"
|
|
250
250
|
},
|
|
251
|
+
DescriptionsLayoutProp: {
|
|
252
|
+
file: "vocabulary/interaction.prop.ts",
|
|
253
|
+
category: "interaction",
|
|
254
|
+
description: "Descriptions label layout: vertical (over) | horizontal (beside)"
|
|
255
|
+
},
|
|
251
256
|
BreakpointProp: {
|
|
252
257
|
file: "vocabulary/interaction.prop.ts",
|
|
253
258
|
category: "interaction",
|
|
@@ -26,6 +26,9 @@ export type SizeProp = "xs" | "sm" | "md" | "lg";
|
|
|
26
26
|
export type ButtonSizeProp = SizeProp | "default" | "icon" | "icon-xs" | "icon-sm" | "icon-lg";
|
|
27
27
|
/** Form layout — label position relative to its control (Ant-style). */
|
|
28
28
|
export type FormLayoutProp = "vertical" | "horizontal" | "inline";
|
|
29
|
+
/** Descriptions layout — label over value (`vertical`) or beside it (`horizontal`); the
|
|
30
|
+
* `FormLayoutProp` subset that a metadata grid supports (no `inline`). */
|
|
31
|
+
export type DescriptionsLayoutProp = Extract<FormLayoutProp, "vertical" | "horizontal">;
|
|
29
32
|
/** Responsive breakpoint name (mobile-first); used by `collapseBelow` etc. */
|
|
30
33
|
export type BreakpointProp = "sm" | "md" | "lg" | "xl";
|
|
31
34
|
/** Dialog confirm button emphasis. */
|
|
@@ -285,7 +285,7 @@
|
|
|
285
285
|
/* A non-banded header before a FLUSH full-bleed table supplies its OWN bottom gap: the table's
|
|
286
286
|
* content padding is zeroed above, so without this the title/subtitle butt against the header
|
|
287
287
|
* row. Match the header's top inset so the header block reads balanced top↕bottom. */
|
|
288
|
-
[data-slot="card"]:has([data-slot="card-content"][data-flush] table)
|
|
288
|
+
[data-slot="card"]:has([data-slot="card-content"][data-flush] [data-slot="table"])
|
|
289
289
|
[data-slot="card-header"]:not([data-banded]) {
|
|
290
290
|
padding-bottom: var(--card-space-body-y);
|
|
291
291
|
}
|
package/dist/tokens/base.css
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
@import "./components/control.css";
|
|
10
10
|
@import "./components/form.css";
|
|
11
11
|
@import "./components/card.css";
|
|
12
|
+
@import "./components/descriptions.css";
|
|
12
13
|
@import "./components/table.css";
|
|
13
14
|
@import "./components/feedback.css";
|
|
14
15
|
@import "./components/badge.css";
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
/* Card component tokens: card chrome derives from semantic layout tokens. */
|
|
2
2
|
|
|
3
3
|
:root {
|
|
4
|
+
/* Horizontal inset of every slot (header / content / footer) + the resting top/bottom
|
|
5
|
+
* shell padding. This is the column the title, body and footer all align to. */
|
|
4
6
|
--card-space-inset: var(--space-section-active);
|
|
7
|
+
/* Vertical padding of a BANDED header band (top = bottom). Drives --card-space-divided-y. */
|
|
5
8
|
--card-space-header-y: var(--space-stack-sm);
|
|
9
|
+
/* Gap between the header and the body, and the body's own top padding — the breathing
|
|
10
|
+
* room under a title before content begins. */
|
|
6
11
|
--card-space-body-y: var(--space-section-active);
|
|
12
|
+
/* Vertical padding of a SEPARATED footer band (top = bottom). Drives --card-space-divided-y. */
|
|
7
13
|
--card-space-footer-y: var(--space-stack-sm);
|
|
8
|
-
/* DIVIDED-section vertical padding (rule #44/#45). A header/footer that carries a
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
14
|
+
/* DIVIDED-section vertical padding (rule #44/#45). A header/footer that carries a divider
|
|
15
|
+
* border (banded header, separated footer) reads as its own band, so it pads SYMMETRICALLY
|
|
16
|
+
* top+bottom — distinct from a plain header that flows into the body (top inset, no bottom).
|
|
17
|
+
* One themeable knob keeps the header- and footer-band rhythm in sync; a service theme tunes
|
|
18
|
+
* the band density here instead of forking per-slot CSS. */
|
|
13
19
|
--card-space-divided-y: var(--card-space-header-y);
|
|
20
|
+
/* Vertical gap between stacked items WITHIN a slot (e.g. title ↕ description in the header). */
|
|
14
21
|
--card-space-gap: var(--space-stack-xs);
|
|
15
22
|
--card-title-font-size: var(--font-size-base);
|
|
16
23
|
--card-title-line-height: var(--line-height-tight);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/* Descriptions component tokens. */
|
|
2
|
+
|
|
3
|
+
:root {
|
|
4
|
+
/* Width of the label column when <Descriptions layout="horizontal">. Labels align to this
|
|
5
|
+
* shared column so the values line up (the horizontal-detail look, mirroring <Form layout>).
|
|
6
|
+
* A rem value gives a fixed aligned column; set `max-content` to size each label to its text.
|
|
7
|
+
* (rule #44/#45 — a service theme tunes it here instead of forking CSS.) */
|
|
8
|
+
--descriptions-label-width: 8rem;
|
|
9
|
+
}
|