@dax-ui/detail-field 0.0.0-stage → 0.4.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/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # @dax-ui/detail-field
2
+
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 14ab1d4: New `@dax-ui/skeleton` (loading placeholders), `@dax-ui/chip` (status pills, tags, removable chips) and `@dax-ui/detail-field` (icon + label + value fields, section headings, grids), included in `@dax-ui/react`.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [14ab1d4]
12
+ - @dax-ui/skeleton@0.4.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Digital Auxilius
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,147 @@
1
- # Temporary Holding Version
1
+ # @dax-ui/detail-field
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Read-only details, the way a "view" modal or page shows a record: `DetailField` is a small
4
+ muted label with an icon and the value below it; `DetailSection` groups fields under a
5
+ colored title with a line running to the right; `DetailGrid` lays fields out in responsive
6
+ columns. Values can be anything (text, chips, links); empty values show a placeholder,
7
+ loading values a skeleton, and text values can be copied.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pnpm add @dax-ui/detail-field
13
+ ```
14
+
15
+ MUI and Emotion are included; the app only needs React 18 or 19.
16
+
17
+ One-time setup per app (skip if the app already uses dax-ui): install
18
+ [`@dax-ui/theme`](https://www.npmjs.com/package/@dax-ui/theme) and wrap the app in its `UIProvider`.
19
+
20
+ ```bash
21
+ pnpm add @dax-ui/theme
22
+ ```
23
+
24
+ Any icon component works; the examples use [`lucide-react`](https://lucide.dev).
25
+
26
+ ## Usage
27
+
28
+ ```tsx
29
+ import { DetailField, DetailGrid, DetailSection } from '@dax-ui/detail-field';
30
+ import { Chip } from '@dax-ui/chip';
31
+ import { CalendarDays, Clock, FileText, LayoutGrid, MapPin } from 'lucide-react';
32
+
33
+ <DetailSection title="General Information">
34
+ <DetailGrid>
35
+ <DetailField label="Site" value="PK-nineToFive" icon={<MapPin />} copyable />
36
+ <DetailField label="Title" value="qwrwq" icon={<FileText />} />
37
+ <DetailField label="Event Type" value="Meeting" icon={<LayoutGrid />} />
38
+ <DetailField label="Priority" value={<Chip label="Medium" color="success" dot />} />
39
+ </DetailGrid>
40
+ </DetailSection>
41
+
42
+ <DetailSection title="Schedule" action={<Button size="sm" variant="ghost">Edit</Button>}>
43
+ <DetailGrid>
44
+ <DetailField label="Date" value="Nov 1, 2026" icon={<CalendarDays />} span="full" />
45
+ <DetailField label="Start Time" value={start} icon={<Clock />} loading={isLoading} />
46
+ <DetailField label="End Time" value={end} icon={<Clock />} loading={isLoading} />
47
+ </DetailGrid>
48
+ </DetailSection>
49
+
50
+ // Empty, custom colors, side by side
51
+ <DetailField label="Department" value={null} emptyValue="Not set" />
52
+ <DetailField label="Owner" value="Amina" labelColor="#0f766e" iconColor="#0f766e" icon={<UserIcon />} />
53
+ <DetailField label="Created" value="Nov 2, 2026" orientation="inline" labelWidth={120} />
54
+ ```
55
+
56
+ Inside a `DetailGrid` (a `<dl>`), fields render as `<dt>`/`<dd>` pairs; elsewhere as plain
57
+ `<div>`s. `DetailSection` is a `<section>` named by its heading (`h3` by default, see
58
+ `headingLevel`).
59
+
60
+ ### Customizing
61
+
62
+ - Colors: `labelColor`, `valueColor`, `iconColor`, or `colors` (`label`, `value`, `icon`,
63
+ `empty`, `accent`) on a field; `titleColor`, `lineColor` or `colors` on a section. They're
64
+ CSS variables (`--dax-detail-field-<key>`, `--dax-detail-section-<key>`), so setting one on
65
+ an ancestor recolors every field inside it. Defaults follow light and dark mode
66
+ (`DEFAULT_DETAIL_FIELD_COLORS`, `DEFAULT_DETAIL_SECTION_COLORS` and their `_DARK_` twins).
67
+ - Sizes: `size` `sm`, `md` or `lg`; `orientation` `stacked` or `inline`.
68
+ - Layout: `span` (columns, or `'full'`), `maxLines`, `helperText`, `action`.
69
+ - Anything else: `sx` on every component, and `slotProps.label` / `.value` / `.icon` on a field.
70
+
71
+ ## Props
72
+
73
+ ### DetailField
74
+
75
+ <!-- props:start DetailField -->
76
+ | Prop | Type | Default | Description |
77
+ | --- | --- | --- | --- |
78
+ | `label` *(required)* | `ReactNode` | | What the value is, e.g. "Site". Shown small and muted above (or beside) the value. |
79
+ | `action` | `ReactNode` | | Shown at the end of the value row, e.g. an edit link or a small button. |
80
+ | `children` | `ReactNode` | | The value, when it reads better as children. `value` wins if both are set. |
81
+ | `className` | `string` | | Class name on the root element. |
82
+ | `colors` | `Partial<DetailFieldColors>` | | Overrides any of the field's colors. `labelColor`, `valueColor` and `iconColor` are shorthands that win over these. Unset keys keep the defaults (which follow light and dark mode). |
83
+ | `copyable` | `string \| boolean` | `false` | Adds a button that copies the value to the clipboard. `true` copies the value when it's text or a number; a string copies that string instead (e.g. a full ID behind a short label). |
84
+ | `copyLabel` | `string` | `'Copy <label>' (or 'Copy' when the label isn't text)` | Accessible name of the copy button. |
85
+ | `emptyValue` | `ReactNode` | `—` | Shown when the value is empty. |
86
+ | `helperText` | `ReactNode` | | Small muted text under the value, e.g. a hint or a timestamp. |
87
+ | `icon` | `ReactNode` | | Icon before the label, e.g. `<MapPinIcon />`. Decorative: hidden from screen readers. |
88
+ | `iconColor` | `string` | | Icon color. Shorthand for `colors.icon`. |
89
+ | `id` | `string` | | Id of the root element. |
90
+ | `labelColor` | `string` | | Label color, e.g. `'#0f766e'`. Shorthand for `colors.label`. |
91
+ | `labelWidth` | `string \| number` | `160` | Width of the label with `orientation="inline"`, in px or any CSS length. |
92
+ | `loading` | `boolean` | `false` | Shows a skeleton in place of the value while it loads, and marks the field `aria-busy`. |
93
+ | `loadingLines` | `number` | `1` | Number of skeleton lines while `loading`, for long values. |
94
+ | `maxLines` | `number` | | Cuts the value off after this many lines, ending in "…". |
95
+ | `onCopy` | `((text: string) => void)` | | Called with the copied text after a successful copy. |
96
+ | `orientation` | `"stacked" \| "inline"` | `stacked` | `stacked` puts the value under the label; `inline` puts them side by side, the label `labelWidth` wide. |
97
+ | `size` | `"sm" \| "md" \| "lg"` | `md` | Text sizes: `sm` (12px label, 14px value), `md` (14 / 16) or `lg` (15 / 19). |
98
+ | `slotProps` | `{ label?: DetailFieldSlotProps; value?: DetailFieldSlotProps; icon?: DetailFieldSlotProps \| undefined; } \| undefined` | `{}` | Extra props and `sx` for the parts: `label`, `value` and `icon`. |
99
+ | `span` | `number \| "full"` | `1` | Inside a `DetailGrid`: how many columns the field spans; `'full'` spans the whole row (e.g. a description). |
100
+ | `style` | `CSSProperties` | | Inline styles on the root element. |
101
+ | `sx` | `SxProps<Theme>` | | Style overrides on the root element. |
102
+ | `value` | `ReactNode` | | The value: text, a number, chips, a link, anything. Falls back to `children`; when both are empty (`null`, `undefined`, `''` or an empty array), `emptyValue` is shown. |
103
+ | `valueColor` | `string` | | Value color. Shorthand for `colors.value`. |
104
+ <!-- props:end -->
105
+
106
+ ### DetailSection
107
+
108
+ <!-- props:start DetailSection -->
109
+ | Prop | Type | Default | Description |
110
+ | --- | --- | --- | --- |
111
+ | `title` *(required)* | `ReactNode` | | Section title, e.g. "General Information". |
112
+ | `action` | `ReactNode` | | Shown at the right end of the title row, e.g. an "Edit" button. |
113
+ | `children` | `ReactNode` | | The section's content: usually a `DetailGrid` of fields. |
114
+ | `className` | `string` | | Class name on the root element. |
115
+ | `collapsed` | `boolean` | | Whether a `collapsible` section is collapsed. Pair with `onCollapsedChange` to control it. |
116
+ | `collapsible` | `boolean` | `false` | Makes the title a button that shows and hides the content. |
117
+ | `colors` | `Partial<DetailSectionColors>` | | Overrides any of the section's colors. Unset keys keep the defaults. |
118
+ | `defaultCollapsed` | `boolean` | `false` | Initial state of a `collapsible` section when `collapsed` isn't controlled. |
119
+ | `description` | `ReactNode` | | Muted text under the title. |
120
+ | `gap` | `string \| number` | `20` | Space between the title row and the content, in px or any CSS length. |
121
+ | `headingLevel` | `2 \| 3 \| 4 \| 5 \| 6` | `3` | Heading level of the title (`h2`…`h6`), to fit the page's outline. |
122
+ | `hideLine` | `boolean` | `false` | Hides the line extending to the right of the title. |
123
+ | `icon` | `ReactNode` | | Icon before the title. Decorative: hidden from screen readers. |
124
+ | `id` | `string` | | Id of the root element. |
125
+ | `lineColor` | `string` | | Color of the line next to the title. Shorthand for `colors.line`. |
126
+ | `onCollapsedChange` | `((collapsed: boolean) => void)` | | Called when the title of a `collapsible` section is clicked. |
127
+ | `style` | `CSSProperties` | | Inline styles on the root element. |
128
+ | `sx` | `SxProps<Theme>` | | Style overrides on the root element. |
129
+ | `titleColor` | `string` | | Title color. Shorthand for `colors.title`. |
130
+ <!-- props:end -->
131
+
132
+ ### DetailGrid
133
+
134
+ <!-- props:start DetailGrid -->
135
+ | Prop | Type | Default | Description |
136
+ | --- | --- | --- | --- |
137
+ | `children` | `ReactNode` | | `DetailField`s. |
138
+ | `className` | `string` | | Class name on the root element. |
139
+ | `columnGap` | `string \| number` | `32` | Space between columns, in px or any CSS length. |
140
+ | `columns` | `1 \| 2 \| 3 \| 4` | `2` | Most columns side by side. Columns drop one at a time as the grid gets narrower than `minColumnWidth` per column, down to a single column on small screens. |
141
+ | `gap` | `string \| number` | | Space between rows and columns, in px or any CSS length. Sets both `rowGap` and `columnGap`. |
142
+ | `id` | `string` | | Id of the root element. |
143
+ | `minColumnWidth` | `string \| number` | `200` | Narrowest a column may get before the grid drops a column, in px or any CSS length. |
144
+ | `rowGap` | `string \| number` | `24` | Space between rows, in px or any CSS length. |
145
+ | `style` | `CSSProperties` | | Inline styles on the root element. |
146
+ | `sx` | `SxProps<Theme>` | | Style overrides on the root element. |
147
+ <!-- props:end -->
package/lib/index.d.ts ADDED
@@ -0,0 +1,239 @@
1
+ import * as react from 'react';
2
+ import { CSSProperties, ReactNode, HTMLAttributes } from 'react';
3
+ import { SxProps, Theme } from '@mui/material/styles';
4
+
5
+ type DetailFieldSize = 'sm' | 'md' | 'lg';
6
+ type DetailFieldOrientation = 'stacked' | 'inline';
7
+ /** Every color a detail field uses. Any CSS color works. */
8
+ interface DetailFieldColors {
9
+ /** The label text. */
10
+ label: string;
11
+ /** The value text. */
12
+ value: string;
13
+ /** The icon before the label. */
14
+ icon: string;
15
+ /** `emptyValue` text. */
16
+ empty: string;
17
+ /** Copy button on hover and its focus ring. */
18
+ accent: string;
19
+ }
20
+ /** Every color a detail section uses. */
21
+ interface DetailSectionColors {
22
+ /** Section title. */
23
+ title: string;
24
+ /** The line extending to the right of the title. */
25
+ line: string;
26
+ /** Icon before the title. */
27
+ icon: string;
28
+ /** The `description` under the title. */
29
+ description: string;
30
+ }
31
+ /** Props for one part of a field: extra attributes, a class name and style overrides. */
32
+ interface DetailFieldSlotProps extends HTMLAttributes<HTMLElement> {
33
+ /** Style overrides for this part. */
34
+ sx?: SxProps<Theme>;
35
+ }
36
+ interface StyleProps {
37
+ /** Class name on the root element. */
38
+ className?: string;
39
+ /** Inline styles on the root element. */
40
+ style?: CSSProperties;
41
+ /** Style overrides on the root element. */
42
+ sx?: SxProps<Theme>;
43
+ /** Id of the root element. */
44
+ id?: string;
45
+ }
46
+ interface DetailFieldProps extends StyleProps {
47
+ /** What the value is, e.g. "Site". Shown small and muted above (or beside) the value. */
48
+ label: ReactNode;
49
+ /**
50
+ * The value: text, a number, chips, a link, anything. Falls back to `children`; when both
51
+ * are empty (`null`, `undefined`, `''` or an empty array), `emptyValue` is shown.
52
+ */
53
+ value?: ReactNode;
54
+ /** The value, when it reads better as children. `value` wins if both are set. */
55
+ children?: ReactNode;
56
+ /** Icon before the label, e.g. `<MapPinIcon />`. Decorative: hidden from screen readers. */
57
+ icon?: ReactNode;
58
+ /** Label color, e.g. `'#0f766e'`. Shorthand for `colors.label`. */
59
+ labelColor?: string;
60
+ /** Value color. Shorthand for `colors.value`. */
61
+ valueColor?: string;
62
+ /** Icon color. Shorthand for `colors.icon`. */
63
+ iconColor?: string;
64
+ /**
65
+ * Text sizes: `sm` (12px label, 14px value), `md` (14 / 16) or `lg` (15 / 19).
66
+ * @default 'md'
67
+ */
68
+ size?: DetailFieldSize;
69
+ /**
70
+ * `stacked` puts the value under the label; `inline` puts them side by side, the label
71
+ * `labelWidth` wide.
72
+ * @default 'stacked'
73
+ */
74
+ orientation?: DetailFieldOrientation;
75
+ /**
76
+ * Width of the label with `orientation="inline"`, in px or any CSS length.
77
+ * @default 160
78
+ */
79
+ labelWidth?: number | string;
80
+ /**
81
+ * Shown when the value is empty.
82
+ * @default '—'
83
+ */
84
+ emptyValue?: ReactNode;
85
+ /**
86
+ * Shows a skeleton in place of the value while it loads, and marks the field `aria-busy`.
87
+ * @default false
88
+ */
89
+ loading?: boolean;
90
+ /**
91
+ * Number of skeleton lines while `loading`, for long values.
92
+ * @default 1
93
+ */
94
+ loadingLines?: number;
95
+ /**
96
+ * Adds a button that copies the value to the clipboard. `true` copies the value when it's
97
+ * text or a number; a string copies that string instead (e.g. a full ID behind a short label).
98
+ * @default false
99
+ */
100
+ copyable?: boolean | string;
101
+ /**
102
+ * Accessible name of the copy button.
103
+ * @default 'Copy <label>' (or 'Copy' when the label isn't text)
104
+ */
105
+ copyLabel?: string;
106
+ /** Called with the copied text after a successful copy. */
107
+ onCopy?: (text: string) => void;
108
+ /** Small muted text under the value, e.g. a hint or a timestamp. */
109
+ helperText?: ReactNode;
110
+ /** Shown at the end of the value row, e.g. an edit link or a small button. */
111
+ action?: ReactNode;
112
+ /** Cuts the value off after this many lines, ending in "…". */
113
+ maxLines?: number;
114
+ /**
115
+ * Inside a `DetailGrid`: how many columns the field spans; `'full'` spans the whole row
116
+ * (e.g. a description).
117
+ * @default 1
118
+ */
119
+ span?: number | 'full';
120
+ /**
121
+ * Overrides any of the field's colors. `labelColor`, `valueColor` and `iconColor` are
122
+ * shorthands that win over these. Unset keys keep the defaults (which follow light and dark mode).
123
+ */
124
+ colors?: Partial<DetailFieldColors>;
125
+ /** Extra props and `sx` for the parts: `label`, `value` and `icon`. */
126
+ slotProps?: {
127
+ /** The label row (icon + label text). */
128
+ label?: DetailFieldSlotProps;
129
+ /** The value. */
130
+ value?: DetailFieldSlotProps;
131
+ /** The icon wrapper. */
132
+ icon?: DetailFieldSlotProps;
133
+ };
134
+ }
135
+ interface DetailSectionProps extends StyleProps {
136
+ /** Section title, e.g. "General Information". */
137
+ title: ReactNode;
138
+ /** The section's content: usually a `DetailGrid` of fields. */
139
+ children?: ReactNode;
140
+ /** Icon before the title. Decorative: hidden from screen readers. */
141
+ icon?: ReactNode;
142
+ /** Shown at the right end of the title row, e.g. an "Edit" button. */
143
+ action?: ReactNode;
144
+ /** Muted text under the title. */
145
+ description?: ReactNode;
146
+ /** Title color. Shorthand for `colors.title`. */
147
+ titleColor?: string;
148
+ /** Color of the line next to the title. Shorthand for `colors.line`. */
149
+ lineColor?: string;
150
+ /**
151
+ * Hides the line extending to the right of the title.
152
+ * @default false
153
+ */
154
+ hideLine?: boolean;
155
+ /**
156
+ * Heading level of the title (`h2`…`h6`), to fit the page's outline.
157
+ * @default 3
158
+ */
159
+ headingLevel?: 2 | 3 | 4 | 5 | 6;
160
+ /**
161
+ * Space between the title row and the content, in px or any CSS length.
162
+ * @default 20
163
+ */
164
+ gap?: number | string;
165
+ /**
166
+ * Makes the title a button that shows and hides the content.
167
+ * @default false
168
+ */
169
+ collapsible?: boolean;
170
+ /** Whether a `collapsible` section is collapsed. Pair with `onCollapsedChange` to control it. */
171
+ collapsed?: boolean;
172
+ /**
173
+ * Initial state of a `collapsible` section when `collapsed` isn't controlled.
174
+ * @default false
175
+ */
176
+ defaultCollapsed?: boolean;
177
+ /** Called when the title of a `collapsible` section is clicked. */
178
+ onCollapsedChange?: (collapsed: boolean) => void;
179
+ /** Overrides any of the section's colors. Unset keys keep the defaults. */
180
+ colors?: Partial<DetailSectionColors>;
181
+ }
182
+ type DetailGridColumns = 1 | 2 | 3 | 4;
183
+ interface DetailGridProps extends StyleProps {
184
+ /** `DetailField`s. */
185
+ children?: ReactNode;
186
+ /**
187
+ * Most columns side by side. Columns drop one at a time as the grid gets narrower than
188
+ * `minColumnWidth` per column, down to a single column on small screens.
189
+ * @default 2
190
+ */
191
+ columns?: DetailGridColumns;
192
+ /**
193
+ * Narrowest a column may get before the grid drops a column, in px or any CSS length.
194
+ * @default 200
195
+ */
196
+ minColumnWidth?: number | string;
197
+ /** Space between rows and columns, in px or any CSS length. Sets both `rowGap` and `columnGap`. */
198
+ gap?: number | string;
199
+ /**
200
+ * Space between rows, in px or any CSS length.
201
+ * @default 24
202
+ */
203
+ rowGap?: number | string;
204
+ /**
205
+ * Space between columns, in px or any CSS length.
206
+ * @default 32
207
+ */
208
+ columnGap?: number | string;
209
+ }
210
+
211
+ /**
212
+ * A read-only "label + value" pair: a small muted label with an icon, and the value below
213
+ * (or beside) it. The value can be anything; empty values show a placeholder, loading values
214
+ * a skeleton, and text values can be copied.
215
+ */
216
+ declare const DetailField: react.ForwardRefExoticComponent<DetailFieldProps & react.RefAttributes<HTMLDivElement>>;
217
+
218
+ /**
219
+ * A titled group of details: a colored heading with a line extending to the right
220
+ * ("General Information ———"), an optional action, and the content below. Can collapse.
221
+ */
222
+ declare const DetailSection: react.ForwardRefExoticComponent<DetailSectionProps & react.RefAttributes<HTMLElement>>;
223
+
224
+ /**
225
+ * Lays `DetailField`s out in up to four columns, dropping columns as space runs out down to
226
+ * one on small screens. Renders a description list (`<dl>`), so each field is a term and its value.
227
+ */
228
+ declare const DetailGrid: react.ForwardRefExoticComponent<DetailGridProps & react.RefAttributes<HTMLDListElement>>;
229
+
230
+ /** Default field colors in light mode; override any of them with the `colors` prop. */
231
+ declare const DEFAULT_DETAIL_FIELD_COLORS: DetailFieldColors;
232
+ /** Default field colors in dark mode. */
233
+ declare const DEFAULT_DETAIL_FIELD_DARK_COLORS: DetailFieldColors;
234
+ /** Default section colors in light mode. */
235
+ declare const DEFAULT_DETAIL_SECTION_COLORS: DetailSectionColors;
236
+ /** Default section colors in dark mode. */
237
+ declare const DEFAULT_DETAIL_SECTION_DARK_COLORS: DetailSectionColors;
238
+
239
+ export { DEFAULT_DETAIL_FIELD_COLORS, DEFAULT_DETAIL_FIELD_DARK_COLORS, DEFAULT_DETAIL_SECTION_COLORS, DEFAULT_DETAIL_SECTION_DARK_COLORS, DetailField, type DetailFieldColors, type DetailFieldOrientation, type DetailFieldProps, type DetailFieldSize, type DetailFieldSlotProps, DetailGrid, type DetailGridColumns, type DetailGridProps, DetailSection, type DetailSectionColors, type DetailSectionProps };
package/lib/index.js ADDED
@@ -0,0 +1,479 @@
1
+ "use client";
2
+
3
+ // src/DetailField.tsx
4
+ import { forwardRef, useContext } from "react";
5
+ import Box2 from "@mui/material/Box";
6
+ import { styled as styled2 } from "@mui/material/styles";
7
+ import { Skeleton } from "@dax-ui/skeleton";
8
+
9
+ // src/DetailField.constants.ts
10
+ import { createContext } from "react";
11
+
12
+ // src/colorVariables.ts
13
+ var varKey = (key) => key.endsWith("label") ? `${key}-color` : key;
14
+ function createColorVariables(prefix, light, dark) {
15
+ const keys = Object.keys(light);
16
+ const pick = (colors, infix) => Object.fromEntries(
17
+ Object.entries(colors).filter(([, value]) => value != null).map(([key, value]) => [`--dax-${prefix}-${infix}${varKey(key)}`, value])
18
+ );
19
+ return {
20
+ /** `cssVar.key` for use in styles. */
21
+ cssVar: Object.fromEntries(
22
+ keys.map((key) => [key, `var(--dax-${prefix}-${varKey(key)}, var(--dax-${prefix}-default-${varKey(key)}))`])
23
+ ),
24
+ /** Default colors for the current mode; spread into the root's styles. */
25
+ defaultColorStyles: (theme) => ({
26
+ ...pick(light, "default-"),
27
+ ...theme.applyStyles("dark", pick(dark, "default-"))
28
+ }),
29
+ /** The `colors` prop as inline CSS variables. */
30
+ colorVariables: (colors) => pick(colors ?? {}, "")
31
+ };
32
+ }
33
+
34
+ // src/DetailField.constants.ts
35
+ var DEFAULT_DETAIL_FIELD_COLORS = {
36
+ label: "#64748b",
37
+ value: "#1e293b",
38
+ icon: "#64748b",
39
+ empty: "#64748b",
40
+ accent: "#1f4d5a"
41
+ };
42
+ var DEFAULT_DETAIL_FIELD_DARK_COLORS = {
43
+ label: "#94a3b8",
44
+ value: "#f1f5f9",
45
+ icon: "#94a3b8",
46
+ empty: "#94a3b8",
47
+ accent: "#7fd1c7"
48
+ };
49
+ var DEFAULT_DETAIL_SECTION_COLORS = {
50
+ title: "#1f4d5a",
51
+ line: "#e2e8f0",
52
+ icon: "#1f4d5a",
53
+ description: "#64748b"
54
+ };
55
+ var DEFAULT_DETAIL_SECTION_DARK_COLORS = {
56
+ title: "#7fd1c7",
57
+ line: "#1e293b",
58
+ icon: "#7fd1c7",
59
+ description: "#94a3b8"
60
+ };
61
+ var fieldColors = createColorVariables(
62
+ "detail-field",
63
+ DEFAULT_DETAIL_FIELD_COLORS,
64
+ DEFAULT_DETAIL_FIELD_DARK_COLORS
65
+ );
66
+ var sectionColors = createColorVariables(
67
+ "detail-section",
68
+ DEFAULT_DETAIL_SECTION_COLORS,
69
+ DEFAULT_DETAIL_SECTION_DARK_COLORS
70
+ );
71
+ var FIELD_SIZES = {
72
+ sm: { label: 12, value: 14, icon: 14, gap: 4 },
73
+ md: { label: 14, value: 16, icon: 16, gap: 6 },
74
+ lg: { label: 15, value: 19, icon: 18, gap: 8 }
75
+ };
76
+ var toCss = (value) => typeof value === "number" ? `${value}px` : value;
77
+ var DetailGridContext = createContext(false);
78
+
79
+ // src/components/CopyButton.tsx
80
+ import { useEffect, useRef, useState } from "react";
81
+ import Box from "@mui/material/Box";
82
+ import { styled } from "@mui/material/styles";
83
+
84
+ // src/components/visuallyHidden.ts
85
+ var visuallyHidden = {
86
+ position: "absolute",
87
+ width: 1,
88
+ height: 1,
89
+ margin: -1,
90
+ padding: 0,
91
+ overflow: "hidden",
92
+ clip: "rect(0 0 0 0)",
93
+ whiteSpace: "nowrap",
94
+ border: 0
95
+ };
96
+
97
+ // src/components/CopyButton.tsx
98
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
99
+ var { cssVar } = fieldColors;
100
+ var Button = styled("button")({
101
+ all: "unset",
102
+ flexShrink: 0,
103
+ display: "inline-grid",
104
+ placeItems: "center",
105
+ width: 28,
106
+ height: 28,
107
+ borderRadius: 8,
108
+ cursor: "pointer",
109
+ color: cssVar.icon,
110
+ transition: "color 150ms, background-color 150ms",
111
+ "&:hover": { color: cssVar.accent, backgroundColor: "rgba(100, 116, 139, 0.12)" },
112
+ "&:focus-visible": { color: cssVar.accent, outline: `2px solid ${cssVar.accent}`, outlineOffset: 1 },
113
+ "& svg": { width: 16, height: 16 }
114
+ });
115
+ function CopyButton({ text, label, onCopy }) {
116
+ const [copied, setCopied] = useState(false);
117
+ const timer = useRef(void 0);
118
+ useEffect(() => () => clearTimeout(timer.current), []);
119
+ const copy = async () => {
120
+ try {
121
+ await navigator.clipboard.writeText(text);
122
+ } catch {
123
+ return;
124
+ }
125
+ setCopied(true);
126
+ onCopy?.(text);
127
+ clearTimeout(timer.current);
128
+ timer.current = setTimeout(() => setCopied(false), 2e3);
129
+ };
130
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
131
+ /* @__PURE__ */ jsx(Button, { type: "button", onClick: copy, "aria-label": label, title: copied ? "Copied" : label, children: copied ? /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M3.5 8.5l3 3 6-7", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) : /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: [
132
+ /* @__PURE__ */ jsx("rect", { x: "5.5", y: "5.5", width: "8", height: "8", rx: "1.8", stroke: "currentColor", strokeWidth: "1.4" }),
133
+ /* @__PURE__ */ jsx("path", { d: "M10.5 3.5v-.2A1.8 1.8 0 0 0 8.7 1.5H4.3a1.8 1.8 0 0 0-1.8 1.8v4.4a1.8 1.8 0 0 0 1.8 1.8h.2", stroke: "currentColor", strokeWidth: "1.4" })
134
+ ] }) }),
135
+ /* @__PURE__ */ jsx(Box, { component: "span", role: "status", sx: visuallyHidden, children: copied ? "Copied" : "" })
136
+ ] });
137
+ }
138
+
139
+ // src/DetailField.tsx
140
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
141
+ var { cssVar: cssVar2, defaultColorStyles, colorVariables } = fieldColors;
142
+ var Root = styled2("div", { shouldForwardProp: (p) => p !== "orientation" && p !== "size" })(({ theme, orientation, size }) => ({
143
+ ...defaultColorStyles(theme),
144
+ display: "flex",
145
+ flexDirection: orientation === "inline" ? "row" : "column",
146
+ alignItems: orientation === "inline" ? "baseline" : "stretch",
147
+ gap: orientation === "inline" ? 16 : FIELD_SIZES[size].gap,
148
+ minWidth: 0,
149
+ fontFamily: theme.typography.fontFamily,
150
+ "& > dt, & > dd": { margin: 0 }
151
+ }));
152
+ var isEmpty = (value) => value == null || value === "" || value === false || Array.isArray(value) && value.length === 0;
153
+ var textOf = (node) => typeof node === "string" || typeof node === "number" ? String(node) : void 0;
154
+ var mergeSx = (...items) => items.flatMap((item) => Array.isArray(item) ? item : [item]);
155
+ var DetailField = forwardRef(function DetailField2({
156
+ label,
157
+ value: valueProp,
158
+ children,
159
+ icon,
160
+ labelColor,
161
+ valueColor,
162
+ iconColor,
163
+ size = "md",
164
+ orientation = "stacked",
165
+ labelWidth = 160,
166
+ emptyValue = "\u2014",
167
+ loading = false,
168
+ loadingLines = 1,
169
+ copyable = false,
170
+ copyLabel,
171
+ onCopy,
172
+ helperText,
173
+ action,
174
+ maxLines,
175
+ span,
176
+ colors,
177
+ slotProps = {},
178
+ className,
179
+ style,
180
+ sx,
181
+ id
182
+ }, ref) {
183
+ const inList = useContext(DetailGridContext);
184
+ const sizes = FIELD_SIZES[size];
185
+ const value = valueProp !== void 0 ? valueProp : children;
186
+ const empty = isEmpty(value);
187
+ const copyText = typeof copyable === "string" ? copyable : copyable ? textOf(value) : void 0;
188
+ const showCopy = Boolean(copyText) && !empty && !loading;
189
+ const inline = orientation === "inline";
190
+ const isText = empty || textOf(value) !== void 0;
191
+ const { sx: labelSx, ...labelProps } = slotProps.label ?? {};
192
+ const { sx: valueSx, ...valueProps } = slotProps.value ?? {};
193
+ const { sx: iconSx, ...iconProps } = slotProps.icon ?? {};
194
+ return /* @__PURE__ */ jsxs2(
195
+ Root,
196
+ {
197
+ ref,
198
+ id,
199
+ orientation,
200
+ size,
201
+ className: ["DaxDetailField-root", className].filter(Boolean).join(" "),
202
+ style: {
203
+ ...colorVariables({
204
+ ...colors,
205
+ ...labelColor && { label: labelColor },
206
+ ...valueColor && { value: valueColor },
207
+ ...iconColor && { icon: iconColor }
208
+ }),
209
+ ...style
210
+ },
211
+ sx: mergeSx(
212
+ span != null && { gridColumn: span === "full" ? "1 / -1" : `span ${span}` },
213
+ sx
214
+ ),
215
+ children: [
216
+ /* @__PURE__ */ jsxs2(
217
+ Box2,
218
+ {
219
+ component: inList ? "dt" : "div",
220
+ className: "DaxDetailField-label",
221
+ ...labelProps,
222
+ sx: mergeSx(
223
+ {
224
+ display: "flex",
225
+ alignItems: "center",
226
+ gap: "8px",
227
+ minWidth: 0,
228
+ color: cssVar2.label,
229
+ fontSize: sizes.label,
230
+ fontWeight: 500,
231
+ lineHeight: 1.4,
232
+ ...inline && { flex: `0 0 ${toCss(labelWidth)}` }
233
+ },
234
+ labelSx
235
+ ),
236
+ children: [
237
+ icon && /* @__PURE__ */ jsx2(
238
+ Box2,
239
+ {
240
+ component: "span",
241
+ "aria-hidden": true,
242
+ className: "DaxDetailField-icon",
243
+ ...iconProps,
244
+ sx: mergeSx(
245
+ {
246
+ display: "inline-flex",
247
+ flexShrink: 0,
248
+ color: cssVar2.icon,
249
+ "& svg": { width: sizes.icon + 2, height: sizes.icon + 2 }
250
+ },
251
+ iconSx
252
+ ),
253
+ children: icon
254
+ }
255
+ ),
256
+ /* @__PURE__ */ jsx2("span", { children: label })
257
+ ]
258
+ }
259
+ ),
260
+ /* @__PURE__ */ jsxs2(
261
+ Box2,
262
+ {
263
+ component: inList ? "dd" : "div",
264
+ className: "DaxDetailField-value",
265
+ "aria-busy": loading || void 0,
266
+ ...valueProps,
267
+ sx: mergeSx(
268
+ {
269
+ // Browsers indent <dd> by default; values line up with the label's icon instead.
270
+ m: 0,
271
+ minWidth: 0,
272
+ flex: inline ? 1 : void 0,
273
+ color: empty && !loading ? cssVar2.empty : cssVar2.value,
274
+ fontSize: sizes.value,
275
+ fontWeight: 500,
276
+ lineHeight: 1.45,
277
+ overflowWrap: "anywhere"
278
+ },
279
+ valueSx
280
+ ),
281
+ children: [
282
+ loading ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
283
+ /* @__PURE__ */ jsx2(Skeleton, { lines: loadingLines, width: loadingLines > 1 ? "100%" : "60%", lastLineWidth: "60%" }),
284
+ /* @__PURE__ */ jsx2(Box2, { component: "span", sx: visuallyHidden, children: "Loading" })
285
+ ] }) : /* @__PURE__ */ jsxs2(Box2, { sx: { display: "flex", alignItems: "center", gap: "8px", minWidth: 0 }, children: [
286
+ /* @__PURE__ */ jsx2(
287
+ Box2,
288
+ {
289
+ className: "DaxDetailField-content",
290
+ sx: {
291
+ flex: "0 1 auto",
292
+ minWidth: 0,
293
+ ...isText ? maxLines && {
294
+ display: "-webkit-box",
295
+ WebkitLineClamp: maxLines,
296
+ WebkitBoxOrient: "vertical",
297
+ overflow: "hidden"
298
+ } : (
299
+ // Chips, links and other elements sit in a wrapping row.
300
+ { display: "flex", flexWrap: "wrap", alignItems: "center", gap: "8px" }
301
+ )
302
+ },
303
+ children: empty ? emptyValue : value
304
+ }
305
+ ),
306
+ showCopy && /* @__PURE__ */ jsx2(
307
+ CopyButton,
308
+ {
309
+ text: copyText,
310
+ label: copyLabel ?? (textOf(label) ? `Copy ${textOf(label)}` : "Copy"),
311
+ onCopy
312
+ }
313
+ ),
314
+ action && /* @__PURE__ */ jsx2(Box2, { sx: { ml: "auto", flexShrink: 0 }, children: action })
315
+ ] }),
316
+ helperText && /* @__PURE__ */ jsx2(
317
+ Box2,
318
+ {
319
+ className: "DaxDetailField-helper",
320
+ sx: { mt: "4px", color: cssVar2.label, fontSize: sizes.label - 1, fontWeight: 400, lineHeight: 1.4 },
321
+ children: helperText
322
+ }
323
+ )
324
+ ]
325
+ }
326
+ )
327
+ ]
328
+ }
329
+ );
330
+ });
331
+
332
+ // src/DetailSection.tsx
333
+ import { forwardRef as forwardRef2, useId, useState as useState2 } from "react";
334
+ import Box3 from "@mui/material/Box";
335
+ import Collapse from "@mui/material/Collapse";
336
+ import { styled as styled3 } from "@mui/material/styles";
337
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
338
+ var { cssVar: cssVar3, defaultColorStyles: defaultColorStyles2, colorVariables: colorVariables2 } = sectionColors;
339
+ var Root2 = styled3("section")(({ theme }) => ({
340
+ ...defaultColorStyles2(theme),
341
+ fontFamily: theme.typography.fontFamily,
342
+ minWidth: 0
343
+ }));
344
+ var Title = styled3("span")({
345
+ display: "inline-flex",
346
+ alignItems: "center",
347
+ gap: 8,
348
+ color: cssVar3.title,
349
+ fontSize: 16,
350
+ fontWeight: 600,
351
+ lineHeight: 1.4,
352
+ "& .DaxDetailSection-icon": { display: "inline-flex", color: cssVar3.icon, "& svg": { width: 18, height: 18 } }
353
+ });
354
+ var ToggleButton = styled3("button")({
355
+ all: "unset",
356
+ display: "inline-flex",
357
+ alignItems: "center",
358
+ gap: 8,
359
+ cursor: "pointer",
360
+ borderRadius: 6,
361
+ "&:focus-visible": { outline: `2px solid ${cssVar3.title}`, outlineOffset: 3 }
362
+ });
363
+ var DetailSection = forwardRef2(function DetailSection2({
364
+ title,
365
+ children,
366
+ icon,
367
+ action,
368
+ description,
369
+ titleColor,
370
+ lineColor,
371
+ hideLine = false,
372
+ headingLevel = 3,
373
+ gap = 20,
374
+ collapsible = false,
375
+ collapsed: collapsedProp,
376
+ defaultCollapsed = false,
377
+ onCollapsedChange,
378
+ colors,
379
+ className,
380
+ style,
381
+ sx,
382
+ id
383
+ }, ref) {
384
+ const titleId = useId();
385
+ const contentId = useId();
386
+ const [uncontrolled, setUncontrolled] = useState2(defaultCollapsed);
387
+ const collapsed = collapsible && (collapsedProp ?? uncontrolled);
388
+ const toggle = () => {
389
+ const next = !collapsed;
390
+ if (collapsedProp === void 0) setUncontrolled(next);
391
+ onCollapsedChange?.(next);
392
+ };
393
+ const titleContent = /* @__PURE__ */ jsxs3(Title, { children: [
394
+ icon && /* @__PURE__ */ jsx3("span", { className: "DaxDetailSection-icon", "aria-hidden": true, children: icon }),
395
+ /* @__PURE__ */ jsx3("span", { id: titleId, children: title }),
396
+ collapsible && /* @__PURE__ */ jsx3(
397
+ "svg",
398
+ {
399
+ viewBox: "0 0 16 16",
400
+ width: 16,
401
+ height: 16,
402
+ fill: "none",
403
+ "aria-hidden": true,
404
+ style: { transform: collapsed ? "rotate(-90deg)" : "none", transition: "transform 200ms" },
405
+ children: /* @__PURE__ */ jsx3("path", { d: "M4 6l4 4 4-4", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" })
406
+ }
407
+ )
408
+ ] });
409
+ const content = /* @__PURE__ */ jsx3(Box3, { id: contentId, className: "DaxDetailSection-content", sx: { pt: toCss(gap) }, children });
410
+ return /* @__PURE__ */ jsxs3(
411
+ Root2,
412
+ {
413
+ ref,
414
+ id,
415
+ "aria-labelledby": titleId,
416
+ className: ["DaxDetailSection-root", className].filter(Boolean).join(" "),
417
+ style: {
418
+ ...colorVariables2({
419
+ ...colors,
420
+ ...titleColor && { title: titleColor, icon: colors?.icon ?? titleColor },
421
+ ...lineColor && { line: lineColor }
422
+ }),
423
+ ...style
424
+ },
425
+ sx,
426
+ children: [
427
+ /* @__PURE__ */ jsxs3(Box3, { sx: { display: "flex", alignItems: "center", gap: "16px" }, children: [
428
+ /* @__PURE__ */ jsx3(Box3, { component: `h${headingLevel}`, sx: { m: 0, font: "inherit", flexShrink: 0, maxWidth: "100%" }, children: collapsible ? /* @__PURE__ */ jsx3(ToggleButton, { type: "button", "aria-expanded": !collapsed, "aria-controls": contentId, onClick: toggle, children: titleContent }) : titleContent }),
429
+ !hideLine && /* @__PURE__ */ jsx3(Box3, { "aria-hidden": true, sx: { flex: 1, height: "1px", backgroundColor: cssVar3.line } }),
430
+ hideLine && /* @__PURE__ */ jsx3(Box3, { sx: { flex: 1 } }),
431
+ action && /* @__PURE__ */ jsx3(Box3, { sx: { flexShrink: 0 }, children: action })
432
+ ] }),
433
+ description && /* @__PURE__ */ jsx3(Box3, { sx: { mt: "4px", color: cssVar3.description, fontSize: 14, lineHeight: 1.5 }, className: "DaxDetailSection-description", children: description }),
434
+ collapsible ? /* @__PURE__ */ jsx3(Collapse, { in: !collapsed, unmountOnExit: false, children: content }) : content
435
+ ]
436
+ }
437
+ );
438
+ });
439
+
440
+ // src/DetailGrid.tsx
441
+ import { forwardRef as forwardRef3 } from "react";
442
+ import Box4 from "@mui/material/Box";
443
+ import { jsx as jsx4 } from "react/jsx-runtime";
444
+ var DetailGrid = forwardRef3(function DetailGrid2({ children, columns = 2, minColumnWidth = 200, gap, rowGap = 24, columnGap = 32, className, style, sx, id }, ref) {
445
+ const colGap = toCss(gap ?? columnGap);
446
+ const minWidth = toCss(minColumnWidth);
447
+ const track = `minmax(max(min(${minWidth}, 100%), calc((100% - ${columns - 1} * ${colGap}) / ${columns})), 1fr)`;
448
+ return /* @__PURE__ */ jsx4(DetailGridContext.Provider, { value: true, children: /* @__PURE__ */ jsx4(
449
+ Box4,
450
+ {
451
+ ref,
452
+ component: "dl",
453
+ id,
454
+ className: ["DaxDetailGrid-root", className].filter(Boolean).join(" "),
455
+ style,
456
+ sx: [
457
+ {
458
+ m: 0,
459
+ display: "grid",
460
+ gridTemplateColumns: columns === 1 ? "minmax(0, 1fr)" : `repeat(auto-fill, ${track})`,
461
+ rowGap: toCss(gap ?? rowGap),
462
+ columnGap: colGap
463
+ },
464
+ ...Array.isArray(sx) ? sx : [sx]
465
+ ],
466
+ children
467
+ }
468
+ ) });
469
+ });
470
+ export {
471
+ DEFAULT_DETAIL_FIELD_COLORS,
472
+ DEFAULT_DETAIL_FIELD_DARK_COLORS,
473
+ DEFAULT_DETAIL_SECTION_COLORS,
474
+ DEFAULT_DETAIL_SECTION_DARK_COLORS,
475
+ DetailField,
476
+ DetailGrid,
477
+ DetailSection
478
+ };
479
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/DetailField.tsx","../src/DetailField.constants.ts","../src/colorVariables.ts","../src/components/CopyButton.tsx","../src/components/visuallyHidden.ts","../src/DetailSection.tsx","../src/DetailGrid.tsx"],"sourcesContent":["import { forwardRef, useContext, type ReactNode } from 'react';\nimport Box from '@mui/material/Box';\nimport { styled } from '@mui/material/styles';\nimport { Skeleton } from '@dax-ui/skeleton';\nimport { DetailGridContext, FIELD_SIZES, fieldColors, toCss } from './DetailField.constants';\nimport type { DetailFieldOrientation, DetailFieldProps, DetailFieldSize } from './DetailField.types';\nimport { CopyButton } from './components/CopyButton';\nimport { visuallyHidden } from './components/visuallyHidden';\n\nconst { cssVar, defaultColorStyles, colorVariables } = fieldColors;\n\nconst Root = styled('div', { shouldForwardProp: (p) => p !== 'orientation' && p !== 'size' })<{\n orientation: DetailFieldOrientation;\n size: DetailFieldSize;\n}>(({ theme, orientation, size }) => ({\n ...defaultColorStyles(theme),\n display: 'flex',\n flexDirection: orientation === 'inline' ? 'row' : 'column',\n alignItems: orientation === 'inline' ? 'baseline' : 'stretch',\n gap: orientation === 'inline' ? 16 : FIELD_SIZES[size].gap,\n minWidth: 0,\n fontFamily: theme.typography.fontFamily,\n '& > dt, & > dd': { margin: 0 },\n}));\n\nconst isEmpty = (value: ReactNode) =>\n value == null || value === '' || value === false || (Array.isArray(value) && value.length === 0);\n\nconst textOf = (node: ReactNode): string | undefined =>\n typeof node === 'string' || typeof node === 'number' ? String(node) : undefined;\n\nconst mergeSx = (...items: unknown[]) => items.flatMap((item) => (Array.isArray(item) ? item : [item]));\n\n/**\n * A read-only \"label + value\" pair: a small muted label with an icon, and the value below\n * (or beside) it. The value can be anything; empty values show a placeholder, loading values\n * a skeleton, and text values can be copied.\n */\nexport const DetailField = forwardRef<HTMLDivElement, DetailFieldProps>(function DetailField(\n {\n label,\n value: valueProp,\n children,\n icon,\n labelColor,\n valueColor,\n iconColor,\n size = 'md',\n orientation = 'stacked',\n labelWidth = 160,\n emptyValue = '—',\n loading = false,\n loadingLines = 1,\n copyable = false,\n copyLabel,\n onCopy,\n helperText,\n action,\n maxLines,\n span,\n colors,\n slotProps = {},\n className,\n style,\n sx,\n id,\n },\n ref,\n) {\n const inList = useContext(DetailGridContext);\n const sizes = FIELD_SIZES[size];\n const value = valueProp !== undefined ? valueProp : children;\n const empty = isEmpty(value);\n const copyText = typeof copyable === 'string' ? copyable : copyable ? textOf(value) : undefined;\n const showCopy = Boolean(copyText) && !empty && !loading;\n const inline = orientation === 'inline';\n const isText = empty || textOf(value) !== undefined;\n\n const { sx: labelSx, ...labelProps } = slotProps.label ?? {};\n const { sx: valueSx, ...valueProps } = slotProps.value ?? {};\n const { sx: iconSx, ...iconProps } = slotProps.icon ?? {};\n\n return (\n <Root\n ref={ref}\n id={id}\n orientation={orientation}\n size={size}\n className={['DaxDetailField-root', className].filter(Boolean).join(' ')}\n style={{\n ...colorVariables({\n ...colors,\n ...(labelColor && { label: labelColor }),\n ...(valueColor && { value: valueColor }),\n ...(iconColor && { icon: iconColor }),\n }),\n ...style,\n }}\n sx={mergeSx(\n span != null && { gridColumn: span === 'full' ? '1 / -1' : `span ${span}` },\n sx,\n )}\n >\n <Box\n component={inList ? 'dt' : 'div'}\n className=\"DaxDetailField-label\"\n {...labelProps}\n sx={mergeSx(\n {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n minWidth: 0,\n color: cssVar.label,\n fontSize: sizes.label,\n fontWeight: 500,\n lineHeight: 1.4,\n ...(inline && { flex: `0 0 ${toCss(labelWidth)}` }),\n },\n labelSx,\n )}\n >\n {icon && (\n <Box\n component=\"span\"\n aria-hidden\n className=\"DaxDetailField-icon\"\n {...iconProps}\n sx={mergeSx(\n {\n display: 'inline-flex',\n flexShrink: 0,\n color: cssVar.icon,\n '& svg': { width: sizes.icon + 2, height: sizes.icon + 2 },\n },\n iconSx,\n )}\n >\n {icon}\n </Box>\n )}\n <span>{label}</span>\n </Box>\n\n <Box\n component={inList ? 'dd' : 'div'}\n className=\"DaxDetailField-value\"\n aria-busy={loading || undefined}\n {...valueProps}\n sx={mergeSx(\n {\n // Browsers indent <dd> by default; values line up with the label's icon instead.\n m: 0,\n minWidth: 0,\n flex: inline ? 1 : undefined,\n color: empty && !loading ? cssVar.empty : cssVar.value,\n fontSize: sizes.value,\n fontWeight: 500,\n lineHeight: 1.45,\n overflowWrap: 'anywhere',\n },\n valueSx,\n )}\n >\n {loading ? (\n <>\n <Skeleton lines={loadingLines} width={loadingLines > 1 ? '100%' : '60%'} lastLineWidth=\"60%\" />\n <Box component=\"span\" sx={visuallyHidden}>\n Loading\n </Box>\n </>\n ) : (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: '8px', minWidth: 0 }}>\n <Box\n className=\"DaxDetailField-content\"\n sx={{\n flex: '0 1 auto',\n minWidth: 0,\n ...(isText\n ? maxLines && {\n display: '-webkit-box',\n WebkitLineClamp: maxLines,\n WebkitBoxOrient: 'vertical',\n overflow: 'hidden',\n }\n : // Chips, links and other elements sit in a wrapping row.\n { display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: '8px' }),\n }}\n >\n {empty ? emptyValue : value}\n </Box>\n {showCopy && (\n <CopyButton\n text={copyText!}\n label={copyLabel ?? (textOf(label) ? `Copy ${textOf(label)}` : 'Copy')}\n onCopy={onCopy}\n />\n )}\n {action && <Box sx={{ ml: 'auto', flexShrink: 0 }}>{action}</Box>}\n </Box>\n )}\n {helperText && (\n <Box\n className=\"DaxDetailField-helper\"\n sx={{ mt: '4px', color: cssVar.label, fontSize: sizes.label - 1, fontWeight: 400, lineHeight: 1.4 }}\n >\n {helperText}\n </Box>\n )}\n </Box>\n </Root>\n );\n});\n","import { createContext } from 'react';\nimport { createColorVariables } from './colorVariables';\nimport type { DetailFieldColors, DetailFieldSize, DetailSectionColors } from './DetailField.types';\n\n/** Default field colors in light mode; override any of them with the `colors` prop. */\nexport const DEFAULT_DETAIL_FIELD_COLORS: DetailFieldColors = {\n label: '#64748b',\n value: '#1e293b',\n icon: '#64748b',\n empty: '#64748b',\n accent: '#1f4d5a',\n};\n\n/** Default field colors in dark mode. */\nexport const DEFAULT_DETAIL_FIELD_DARK_COLORS: DetailFieldColors = {\n label: '#94a3b8',\n value: '#f1f5f9',\n icon: '#94a3b8',\n empty: '#94a3b8',\n accent: '#7fd1c7',\n};\n\n/** Default section colors in light mode. */\nexport const DEFAULT_DETAIL_SECTION_COLORS: DetailSectionColors = {\n title: '#1f4d5a',\n line: '#e2e8f0',\n icon: '#1f4d5a',\n description: '#64748b',\n};\n\n/** Default section colors in dark mode. */\nexport const DEFAULT_DETAIL_SECTION_DARK_COLORS: DetailSectionColors = {\n title: '#7fd1c7',\n line: '#1e293b',\n icon: '#7fd1c7',\n description: '#94a3b8',\n};\n\nexport const fieldColors = createColorVariables(\n 'detail-field',\n DEFAULT_DETAIL_FIELD_COLORS,\n DEFAULT_DETAIL_FIELD_DARK_COLORS,\n);\n\nexport const sectionColors = createColorVariables(\n 'detail-section',\n DEFAULT_DETAIL_SECTION_COLORS,\n DEFAULT_DETAIL_SECTION_DARK_COLORS,\n);\n\nexport const FIELD_SIZES: Record<DetailFieldSize, { label: number; value: number; icon: number; gap: number }> = {\n sm: { label: 12, value: 14, icon: 14, gap: 4 },\n md: { label: 14, value: 16, icon: 16, gap: 6 },\n lg: { label: 15, value: 19, icon: 18, gap: 8 },\n};\n\nexport const toCss = (value: number | string | undefined) => (typeof value === 'number' ? `${value}px` : value);\n\n/** Set by `DetailGrid` (a `<dl>`), so fields inside it render `<dt>`/`<dd>`. */\nexport const DetailGridContext = createContext(false);\n","import type { CSSObject, Theme } from '@mui/material/styles';\n\n/**\n * The color pattern shared by dax-ui components that follow light and dark mode.\n *\n * Parts read `var(--dax-<prefix>-<key>, var(--dax-<prefix>-default-<key>))`: the public\n * variable when anything sets it (the `colors` prop inline on the root, or any ancestor in\n * CSS), else a private default the root's class sets for the current color mode.\n */\n// Keys ending in \"label\" get a `-color` suffix (`--dax-detail-label-color`): Emotion reads any\n// `label:` in a style as its class-name label, which puts the color (with its `#`) into the\n// class name and makes the whole rule invalid.\nconst varKey = (key: string) => (key.endsWith('label') ? `${key}-color` : key);\n\nexport function createColorVariables<C extends object>(prefix: string, light: C, dark: C) {\n const keys = Object.keys(light) as Array<keyof C & string>;\n const pick = (colors: Partial<C>, infix: string) =>\n Object.fromEntries(\n Object.entries(colors)\n .filter(([, value]) => value != null)\n .map(([key, value]) => [`--dax-${prefix}-${infix}${varKey(key)}`, value]),\n ) as Record<string, string>;\n\n return {\n /** `cssVar.key` for use in styles. */\n cssVar: Object.fromEntries(\n keys.map((key) => [key, `var(--dax-${prefix}-${varKey(key)}, var(--dax-${prefix}-default-${varKey(key)}))`]),\n ) as Record<keyof C, string>,\n /** Default colors for the current mode; spread into the root's styles. */\n defaultColorStyles: (theme: Theme): CSSObject => ({\n ...pick(light, 'default-'),\n ...(theme.applyStyles('dark', pick(dark, 'default-')) as CSSObject),\n }),\n /** The `colors` prop as inline CSS variables. */\n colorVariables: (colors?: Partial<C>) => pick(colors ?? {}, ''),\n };\n}\n","import { useEffect, useRef, useState } from 'react';\nimport Box from '@mui/material/Box';\nimport { styled } from '@mui/material/styles';\nimport { fieldColors } from '../DetailField.constants';\nimport { visuallyHidden } from './visuallyHidden';\n\nconst { cssVar } = fieldColors;\n\nconst Button = styled('button')({\n all: 'unset',\n flexShrink: 0,\n display: 'inline-grid',\n placeItems: 'center',\n width: 28,\n height: 28,\n borderRadius: 8,\n cursor: 'pointer',\n color: cssVar.icon,\n transition: 'color 150ms, background-color 150ms',\n '&:hover': { color: cssVar.accent, backgroundColor: 'rgba(100, 116, 139, 0.12)' },\n '&:focus-visible': { color: cssVar.accent, outline: `2px solid ${cssVar.accent}`, outlineOffset: 1 },\n '& svg': { width: 16, height: 16 },\n});\n\ninterface CopyButtonProps {\n text: string;\n label: string;\n onCopy?: (text: string) => void;\n}\n\n/** Copies `text` to the clipboard and confirms with a check mark and a screen-reader message. */\nexport function CopyButton({ text, label, onCopy }: CopyButtonProps) {\n const [copied, setCopied] = useState(false);\n const timer = useRef<ReturnType<typeof setTimeout>>(undefined);\n useEffect(() => () => clearTimeout(timer.current), []);\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n return;\n }\n setCopied(true);\n onCopy?.(text);\n clearTimeout(timer.current);\n timer.current = setTimeout(() => setCopied(false), 2000);\n };\n\n return (\n <>\n <Button type=\"button\" onClick={copy} aria-label={label} title={copied ? 'Copied' : label}>\n {copied ? (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden>\n <path d=\"M3.5 8.5l3 3 6-7\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n ) : (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden>\n <rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8\" rx=\"1.8\" stroke=\"currentColor\" strokeWidth=\"1.4\" />\n <path d=\"M10.5 3.5v-.2A1.8 1.8 0 0 0 8.7 1.5H4.3a1.8 1.8 0 0 0-1.8 1.8v4.4a1.8 1.8 0 0 0 1.8 1.8h.2\" stroke=\"currentColor\" strokeWidth=\"1.4\" />\n </svg>\n )}\n </Button>\n <Box component=\"span\" role=\"status\" sx={visuallyHidden}>\n {copied ? 'Copied' : ''}\n </Box>\n </>\n );\n}\n","/** Hides content visually while keeping it available to screen readers. */\nexport const visuallyHidden = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n whiteSpace: 'nowrap',\n border: 0,\n} as const;\n","import { forwardRef, useId, useState } from 'react';\nimport Box from '@mui/material/Box';\nimport Collapse from '@mui/material/Collapse';\nimport { styled } from '@mui/material/styles';\nimport { sectionColors, toCss } from './DetailField.constants';\nimport type { DetailSectionProps } from './DetailField.types';\n\nconst { cssVar, defaultColorStyles, colorVariables } = sectionColors;\n\nconst Root = styled('section')(({ theme }) => ({\n ...defaultColorStyles(theme),\n fontFamily: theme.typography.fontFamily,\n minWidth: 0,\n}));\n\nconst Title = styled('span')({\n display: 'inline-flex',\n alignItems: 'center',\n gap: 8,\n color: cssVar.title,\n fontSize: 16,\n fontWeight: 600,\n lineHeight: 1.4,\n '& .DaxDetailSection-icon': { display: 'inline-flex', color: cssVar.icon, '& svg': { width: 18, height: 18 } },\n});\n\nconst ToggleButton = styled('button')({\n all: 'unset',\n display: 'inline-flex',\n alignItems: 'center',\n gap: 8,\n cursor: 'pointer',\n borderRadius: 6,\n '&:focus-visible': { outline: `2px solid ${cssVar.title}`, outlineOffset: 3 },\n});\n\n/**\n * A titled group of details: a colored heading with a line extending to the right\n * (\"General Information ———\"), an optional action, and the content below. Can collapse.\n */\nexport const DetailSection = forwardRef<HTMLElement, DetailSectionProps>(function DetailSection(\n {\n title,\n children,\n icon,\n action,\n description,\n titleColor,\n lineColor,\n hideLine = false,\n headingLevel = 3,\n gap = 20,\n collapsible = false,\n collapsed: collapsedProp,\n defaultCollapsed = false,\n onCollapsedChange,\n colors,\n className,\n style,\n sx,\n id,\n },\n ref,\n) {\n const titleId = useId();\n const contentId = useId();\n const [uncontrolled, setUncontrolled] = useState(defaultCollapsed);\n const collapsed = collapsible && (collapsedProp ?? uncontrolled);\n\n const toggle = () => {\n const next = !collapsed;\n if (collapsedProp === undefined) setUncontrolled(next);\n onCollapsedChange?.(next);\n };\n\n const titleContent = (\n <Title>\n {icon && (\n <span className=\"DaxDetailSection-icon\" aria-hidden>\n {icon}\n </span>\n )}\n <span id={titleId}>{title}</span>\n {collapsible && (\n <svg\n viewBox=\"0 0 16 16\"\n width={16}\n height={16}\n fill=\"none\"\n aria-hidden\n style={{ transform: collapsed ? 'rotate(-90deg)' : 'none', transition: 'transform 200ms' }}\n >\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </Title>\n );\n\n const content = (\n <Box id={contentId} className=\"DaxDetailSection-content\" sx={{ pt: toCss(gap) }}>\n {children}\n </Box>\n );\n\n return (\n <Root\n ref={ref}\n id={id}\n aria-labelledby={titleId}\n className={['DaxDetailSection-root', className].filter(Boolean).join(' ')}\n style={{\n ...colorVariables({\n ...colors,\n ...(titleColor && { title: titleColor, icon: colors?.icon ?? titleColor }),\n ...(lineColor && { line: lineColor }),\n }),\n ...style,\n }}\n sx={sx}\n >\n <Box sx={{ display: 'flex', alignItems: 'center', gap: '16px' }}>\n <Box component={`h${headingLevel}`} sx={{ m: 0, font: 'inherit', flexShrink: 0, maxWidth: '100%' }}>\n {collapsible ? (\n <ToggleButton type=\"button\" aria-expanded={!collapsed} aria-controls={contentId} onClick={toggle}>\n {titleContent}\n </ToggleButton>\n ) : (\n titleContent\n )}\n </Box>\n {!hideLine && <Box aria-hidden sx={{ flex: 1, height: '1px', backgroundColor: cssVar.line }} />}\n {hideLine && <Box sx={{ flex: 1 }} />}\n {action && <Box sx={{ flexShrink: 0 }}>{action}</Box>}\n </Box>\n {description && (\n <Box sx={{ mt: '4px', color: cssVar.description, fontSize: 14, lineHeight: 1.5 }} className=\"DaxDetailSection-description\">\n {description}\n </Box>\n )}\n {collapsible ? (\n <Collapse in={!collapsed} unmountOnExit={false}>\n {content}\n </Collapse>\n ) : (\n content\n )}\n </Root>\n );\n});\n","import { forwardRef } from 'react';\nimport Box from '@mui/material/Box';\nimport { DetailGridContext, toCss } from './DetailField.constants';\nimport type { DetailGridProps } from './DetailField.types';\n\n/**\n * Lays `DetailField`s out in up to four columns, dropping columns as space runs out down to\n * one on small screens. Renders a description list (`<dl>`), so each field is a term and its value.\n */\nexport const DetailGrid = forwardRef<HTMLDListElement, DetailGridProps>(function DetailGrid(\n { children, columns = 2, minColumnWidth = 200, gap, rowGap = 24, columnGap = 32, className, style, sx, id },\n ref,\n) {\n const colGap = toCss(gap ?? columnGap)!;\n const minWidth = toCss(minColumnWidth)!;\n // At most `columns` tracks, each at least `minColumnWidth` (or the full width, if that's less): narrower containers get fewer columns.\n const track = `minmax(max(min(${minWidth}, 100%), calc((100% - ${columns - 1} * ${colGap}) / ${columns})), 1fr)`;\n\n return (\n <DetailGridContext.Provider value>\n <Box\n ref={ref}\n component=\"dl\"\n id={id}\n className={['DaxDetailGrid-root', className].filter(Boolean).join(' ')}\n style={style}\n sx={[\n {\n m: 0,\n display: 'grid',\n gridTemplateColumns: columns === 1 ? 'minmax(0, 1fr)' : `repeat(auto-fill, ${track})`,\n rowGap: toCss(gap ?? rowGap),\n columnGap: colGap,\n },\n ...(Array.isArray(sx) ? sx : [sx]),\n ]}\n >\n {children}\n </Box>\n </DetailGridContext.Provider>\n );\n});\n"],"mappings":"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","names":["Box","styled","Fragment","jsx","jsxs","cssVar","styled","DetailField","Box","forwardRef","useState","Box","styled","jsx","jsxs","cssVar","defaultColorStyles","colorVariables","Root","styled","forwardRef","DetailSection","useState","Box","forwardRef","Box","jsx","forwardRef","DetailGrid","Box"]}
package/package.json CHANGED
@@ -1,6 +1,62 @@
1
1
  {
2
2
  "name": "@dax-ui/detail-field",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.4.0",
4
+ "description": "dax-ui DetailField: read-only label + value fields, titled sections and responsive grids for detail views",
5
+ "keywords": [
6
+ "dax-ui",
7
+ "react",
8
+ "design-system",
9
+ "mui",
10
+ "detail-field",
11
+ "description-list",
12
+ "details",
13
+ "read-only",
14
+ "field"
15
+ ],
16
+ "author": "Digital Auxilius",
17
+ "homepage": "https://github.com/FaaizHussain26/DAX-UI/tree/main/packages/detail-field#readme",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/FaaizHussain26/DAX-UI.git",
21
+ "directory": "packages/detail-field"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/FaaizHussain26/DAX-UI/issues"
25
+ },
26
+ "license": "MIT",
27
+ "type": "module",
28
+ "sideEffects": false,
29
+ "main": "lib/index.js",
30
+ "types": "lib/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./lib/index.d.ts",
34
+ "default": "./lib/index.js"
35
+ },
36
+ "./package.json": "./package.json"
37
+ },
38
+ "files": [
39
+ "lib",
40
+ "CHANGELOG.md"
41
+ ],
42
+ "dependencies": {
43
+ "@emotion/react": "^11.14.0",
44
+ "@emotion/styled": "^11.14.0",
45
+ "@mui/material": "^9.5.0",
46
+ "@dax-ui/skeleton": "^0.4.0"
47
+ },
48
+ "peerDependencies": {
49
+ "react": "^18.0.0 || ^19.0.0",
50
+ "react-dom": "^18.0.0 || ^19.0.0"
51
+ },
52
+ "devDependencies": {
53
+ "@dax-ui/builder": "^0.0.0",
54
+ "@dax-ui/chip": "^0.4.0"
55
+ },
56
+ "publishConfig": {
57
+ "access": "public"
58
+ },
59
+ "scripts": {
60
+ "build": "builder"
61
+ }
6
62
  }