@you-agent-factory/components 0.0.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.
Files changed (92) hide show
  1. package/README.md +223 -0
  2. package/docs/README.md +83 -0
  3. package/docs/button.md +119 -0
  4. package/docs/charts.md +325 -0
  5. package/docs/data-display-code-panel.md +120 -0
  6. package/docs/feedback-alert-panel.md +117 -0
  7. package/docs/feedback-skeleton.md +54 -0
  8. package/docs/forms-form-field.md +490 -0
  9. package/docs/forms-input-primitives.md +311 -0
  10. package/docs/forms-select-primitives.md +362 -0
  11. package/docs/graphs.md +250 -0
  12. package/docs/layout-display-primitives.md +211 -0
  13. package/docs/overlays.md +414 -0
  14. package/docs/table-data-table.md +331 -0
  15. package/docs/typography-roles.md +182 -0
  16. package/docs/widget-frame-recipes.md +273 -0
  17. package/package.json +161 -0
  18. package/src/category-paths.ts +20 -0
  19. package/src/charts/chart-state-panel.tsx +103 -0
  20. package/src/charts/chart.tsx +287 -0
  21. package/src/charts/index.ts +21 -0
  22. package/src/data-display/code-panel.tsx +67 -0
  23. package/src/data-display/data-table.tsx +180 -0
  24. package/src/data-display/description-list.tsx +24 -0
  25. package/src/data-display/index.ts +34 -0
  26. package/src/data-display/table-layout.ts +12 -0
  27. package/src/data-display/table.tsx +131 -0
  28. package/src/feedback/alert-panel-semantics.ts +75 -0
  29. package/src/feedback/alert-panel.tsx +187 -0
  30. package/src/feedback/index.ts +21 -0
  31. package/src/feedback/skeleton.tsx +16 -0
  32. package/src/forms/index.ts +73 -0
  33. package/src/forms/package-checkbox.tsx +50 -0
  34. package/src/forms/package-enum-select.tsx +185 -0
  35. package/src/forms/package-file-input.tsx +25 -0
  36. package/src/forms/package-form-field.tsx +202 -0
  37. package/src/forms/package-input.tsx +25 -0
  38. package/src/forms/package-native-select.tsx +25 -0
  39. package/src/forms/package-select.tsx +209 -0
  40. package/src/forms/package-textarea.tsx +35 -0
  41. package/src/forms/select-icons.tsx +35 -0
  42. package/src/graphs/graph-edge-path.ts +241 -0
  43. package/src/graphs/graph-edge.tsx +130 -0
  44. package/src/graphs/graph-interactive-example.tsx +187 -0
  45. package/src/graphs/graph-node-button.tsx +51 -0
  46. package/src/graphs/graph-node-handle-badge.tsx +108 -0
  47. package/src/graphs/graph-node-handle.ts +28 -0
  48. package/src/graphs/graph-node-shell.tsx +111 -0
  49. package/src/graphs/graph-node-state-indicator.tsx +47 -0
  50. package/src/graphs/graph-node-state.ts +111 -0
  51. package/src/graphs/graph-viewport-surface.tsx +27 -0
  52. package/src/graphs/index.ts +41 -0
  53. package/src/icons/index.ts +4 -0
  54. package/src/index.ts +209 -0
  55. package/src/layout/action-row.tsx +53 -0
  56. package/src/layout/index.ts +9 -0
  57. package/src/layout/surface-panel.tsx +91 -0
  58. package/src/navigation/index.ts +4 -0
  59. package/src/overlays/collapsible.tsx +22 -0
  60. package/src/overlays/dialog.tsx +148 -0
  61. package/src/overlays/index.ts +31 -0
  62. package/src/overlays/overlay-layout.ts +9 -0
  63. package/src/overlays/popover.tsx +29 -0
  64. package/src/overlays/scroll-area.tsx +78 -0
  65. package/src/primitives/button-link.tsx +22 -0
  66. package/src/primitives/button.tsx +258 -0
  67. package/src/primitives/icon-button-shell.tsx +49 -0
  68. package/src/primitives/index.ts +31 -0
  69. package/src/primitives/package-text.tsx +29 -0
  70. package/src/primitives/typography-roles.ts +12 -0
  71. package/src/primitives/typography.tsx +165 -0
  72. package/src/recipes/index.ts +61 -0
  73. package/src/recipes/widget-frame-content.tsx +114 -0
  74. package/src/recipes/widget-frame-disclosure.tsx +161 -0
  75. package/src/recipes/widget-frame-layout.ts +40 -0
  76. package/src/recipes/widget-frame-skeleton.tsx +16 -0
  77. package/src/recipes/widget-frame-states.tsx +99 -0
  78. package/src/recipes/widget-frame-typography.ts +19 -0
  79. package/src/recipes/widget-frame.tsx +84 -0
  80. package/src/styles/color-palette-presets.css +167 -0
  81. package/src/styles/color-role-tokens.css +163 -0
  82. package/src/styles/layout-role-tokens.css +27 -0
  83. package/src/styles/text-color-role-tokens.css +29 -0
  84. package/src/styles/typography-role-tokens.css +72 -0
  85. package/src/styles/typography-role-utilities.css +73 -0
  86. package/src/styles/typography-roles.css +53 -0
  87. package/src/styles.css +32 -0
  88. package/src/testing/index.ts +13 -0
  89. package/src/testing/render.tsx +16 -0
  90. package/src/tokens/index.ts +4 -0
  91. package/src/utilities/cn.ts +5 -0
  92. package/src/utilities/index.ts +6 -0
@@ -0,0 +1,287 @@
1
+ import type {
2
+ CSSProperties,
3
+ HTMLAttributes,
4
+ MouseEvent as ReactMouseEvent,
5
+ ReactNode,
6
+ } from "react";
7
+ import { createContext, useContext } from "react";
8
+ import {
9
+ Legend as RechartsLegend,
10
+ Tooltip as RechartsTooltip,
11
+ ResponsiveContainer,
12
+ type TooltipContentProps,
13
+ } from "recharts";
14
+ import type {
15
+ LegendPayload,
16
+ Props as RechartsLegendContentProps,
17
+ } from "recharts/types/component/DefaultLegendContent";
18
+ import type {
19
+ NameType,
20
+ ValueType,
21
+ } from "recharts/types/component/DefaultTooltipContent";
22
+
23
+ import { cn } from "../utilities/cn";
24
+
25
+ export interface ChartConfigEntry {
26
+ color: string;
27
+ label: string;
28
+ }
29
+
30
+ export type ChartConfig = Record<string, ChartConfigEntry>;
31
+
32
+ const ChartContext = createContext<ChartConfig | null>(null);
33
+
34
+ export type ChartPresentation = "embedded" | "standalone";
35
+
36
+ // tailwind-exception: intrinsic-sizing
37
+ const CHART_CONTAINER_STANDALONE_CLASS =
38
+ "relative h-[18rem] rounded-2xl border border-outline bg-surface-container-low p-4 text-on-surface";
39
+ // tailwind-exception: intrinsic-sizing
40
+ const CHART_CONTAINER_EMBEDDED_CLASS =
41
+ "relative flex h-full min-h-0 min-w-0 w-full flex-1 flex-col text-on-surface";
42
+ const DEFAULT_CHART_INITIAL_DIMENSION = { height: 288, width: 640 } as const;
43
+
44
+ const CHART_LEGEND_BUTTON_CLASS =
45
+ "inline-flex min-h-0 items-center justify-center rounded-md border border-transparent bg-transparent px-0 py-1 text-left text-xs font-normal text-on-surface-variant focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-af-focus";
46
+
47
+ function chartContainerClassName(
48
+ presentation: ChartPresentation,
49
+ className?: string,
50
+ ): string {
51
+ return cn(
52
+ presentation === "embedded"
53
+ ? CHART_CONTAINER_EMBEDDED_CLASS
54
+ : CHART_CONTAINER_STANDALONE_CLASS,
55
+ className,
56
+ );
57
+ }
58
+
59
+ function useChartConfig() {
60
+ const context = useContext(ChartContext);
61
+
62
+ if (context === null) {
63
+ throw new Error("Chart components must be rendered inside ChartContainer.");
64
+ }
65
+
66
+ return context;
67
+ }
68
+
69
+ export function ChartContainer({
70
+ children,
71
+ className,
72
+ config,
73
+ footer,
74
+ interactionAttributes,
75
+ overlay,
76
+ presentation = "standalone",
77
+ rootAttributes,
78
+ style,
79
+ title,
80
+ }: {
81
+ children: ReactNode;
82
+ className?: string;
83
+ config: ChartConfig;
84
+ footer?: ReactNode;
85
+ interactionAttributes?: HTMLAttributes<HTMLDivElement>;
86
+ overlay?: ReactNode;
87
+ presentation?: ChartPresentation;
88
+ rootAttributes?: Record<string, string>;
89
+ style?: CSSProperties;
90
+ title: string;
91
+ }) {
92
+ const chartSurface = (
93
+ <ResponsiveContainer
94
+ height="100%"
95
+ initialDimension={DEFAULT_CHART_INITIAL_DIMENSION}
96
+ minHeight={0}
97
+ minWidth={0}
98
+ width="100%"
99
+ >
100
+ {children}
101
+ </ResponsiveContainer>
102
+ );
103
+
104
+ return (
105
+ <ChartContext.Provider value={config}>
106
+ <div
107
+ aria-label={title}
108
+ className={chartContainerClassName(presentation, className)}
109
+ data-chart-container=""
110
+ data-chart-presentation={presentation}
111
+ role="img"
112
+ {...interactionAttributes}
113
+ {...rootAttributes}
114
+ style={
115
+ {
116
+ ...Object.fromEntries(
117
+ Object.entries(config).map(([key, value]) => [
118
+ `--color-${key}`,
119
+ value.color,
120
+ ]),
121
+ ),
122
+ ...style,
123
+ } as CSSProperties
124
+ }
125
+ >
126
+ {overlay ? (
127
+ <div className="pointer-events-none absolute inset-0">{overlay}</div>
128
+ ) : null}
129
+ {footer ? (
130
+ <div className="flex min-h-0 flex-1 basis-0 flex-col">
131
+ <div className="h-full min-h-0 flex-1 basis-0">{chartSurface}</div>
132
+ {footer}
133
+ </div>
134
+ ) : (
135
+ chartSurface
136
+ )}
137
+ </div>
138
+ </ChartContext.Provider>
139
+ );
140
+ }
141
+
142
+ export const ChartTooltip = RechartsTooltip;
143
+ export const ChartLegend = RechartsLegend;
144
+
145
+ export function ChartTooltipContent({
146
+ active,
147
+ className,
148
+ label,
149
+ payload,
150
+ }: TooltipContentProps<ValueType, NameType> & { className?: string }) {
151
+ const config = useChartConfig();
152
+
153
+ if (!active || !payload?.length) {
154
+ return null;
155
+ }
156
+
157
+ return (
158
+ <div
159
+ className={cn(
160
+ "grid min-w-40 gap-2 rounded-xl border border-outline bg-surface-container-high px-3 py-2 text-sm shadow-af-card",
161
+ className,
162
+ )}
163
+ >
164
+ <p className="m-0 font-semibold text-on-surface">{String(label)}</p>
165
+ <div className="grid gap-1">
166
+ {payload.map((entry) => {
167
+ const key = entry.dataKey?.toString() ?? "";
168
+ const item = config[key];
169
+
170
+ return (
171
+ <div
172
+ className="flex items-center justify-between gap-3 text-on-surface-variant"
173
+ key={key}
174
+ >
175
+ <div className="flex items-center gap-2">
176
+ <span
177
+ className="h-2.5 w-2.5 rounded-full"
178
+ style={{
179
+ backgroundColor:
180
+ item?.color ?? entry.color ?? "currentColor",
181
+ }}
182
+ />
183
+ <span>{item?.label ?? key}</span>
184
+ </div>
185
+ <span className="font-medium text-on-surface">{entry.value}</span>
186
+ </div>
187
+ );
188
+ })}
189
+ </div>
190
+ </div>
191
+ );
192
+ }
193
+
194
+ export function ChartLegendContent({
195
+ className,
196
+ getToggleLabel,
197
+ hiddenSeries = new Set<string>(),
198
+ itemClassName,
199
+ onToggleSeries,
200
+ payload,
201
+ swatchClassName,
202
+ }: RechartsLegendContentProps & {
203
+ className?: string;
204
+ getToggleLabel?: (label: string, hidden: boolean) => string;
205
+ hiddenSeries?: ReadonlySet<string>;
206
+ itemClassName?: string;
207
+ onToggleSeries?: (key: string) => void;
208
+ swatchClassName?: string;
209
+ }) {
210
+ const config = useChartConfig();
211
+
212
+ if (!payload?.length) {
213
+ return null;
214
+ }
215
+
216
+ const stopChartInteraction = (event: ReactMouseEvent<HTMLButtonElement>) => {
217
+ event.stopPropagation();
218
+ };
219
+
220
+ return (
221
+ <div
222
+ className={cn(
223
+ "flex flex-wrap items-center gap-4 pt-3 text-xs text-on-surface-variant",
224
+ className,
225
+ )}
226
+ >
227
+ {payload.map((entry: LegendPayload) => {
228
+ const key = entry.dataKey?.toString() ?? "";
229
+ const item = config[key];
230
+ const label = item?.label ?? key;
231
+ const hidden = hiddenSeries.has(key);
232
+ const content = (
233
+ <>
234
+ <span
235
+ aria-hidden="true"
236
+ className={cn(
237
+ "rounded-full",
238
+ swatchClassName ?? "h-2.5 w-2.5",
239
+ hidden ? "border border-outline bg-surface-container-low" : "",
240
+ )}
241
+ style={{
242
+ backgroundColor: hidden
243
+ ? undefined
244
+ : (item?.color ?? entry.color ?? "currentColor"),
245
+ }}
246
+ />
247
+ <span>{label}</span>
248
+ </>
249
+ );
250
+
251
+ if (!onToggleSeries) {
252
+ return (
253
+ <div
254
+ className={cn("flex items-center gap-2", itemClassName)}
255
+ key={key}
256
+ >
257
+ {content}
258
+ </div>
259
+ );
260
+ }
261
+
262
+ return (
263
+ <button
264
+ aria-label={getToggleLabel?.(label, hidden) ?? label}
265
+ aria-pressed={!hidden}
266
+ className={cn(
267
+ CHART_LEGEND_BUTTON_CLASS,
268
+ hidden ? "text-on-surface-disabled" : "",
269
+ itemClassName,
270
+ )}
271
+ data-chart-legend-series={key}
272
+ data-chart-legend-series-hidden={hidden ? "true" : "false"}
273
+ key={key}
274
+ onClick={(event) => {
275
+ event.stopPropagation();
276
+ onToggleSeries(key);
277
+ }}
278
+ onMouseDown={stopChartInteraction}
279
+ type="button"
280
+ >
281
+ {content}
282
+ </button>
283
+ );
284
+ })}
285
+ </div>
286
+ );
287
+ }
@@ -0,0 +1,21 @@
1
+ /** Stable category path for `@you-agent-factory/components/charts`. */
2
+ export const COMPONENTS_CATEGORY = "charts" as const;
3
+
4
+ export type ComponentsCategory = typeof COMPONENTS_CATEGORY;
5
+
6
+ export {
7
+ ChartContainer,
8
+ ChartLegend,
9
+ ChartLegendContent,
10
+ ChartTooltip,
11
+ ChartTooltipContent,
12
+ type ChartConfig,
13
+ type ChartConfigEntry,
14
+ type ChartPresentation,
15
+ } from "./chart";
16
+
17
+ export {
18
+ ChartStatePanel,
19
+ type ChartStatePanelProps,
20
+ type ChartStateStatus,
21
+ } from "./chart-state-panel";
@@ -0,0 +1,67 @@
1
+ import { forwardRef, type HTMLAttributes } from "react";
2
+
3
+ import { cn } from "../utilities/cn";
4
+
5
+ type CodePanelPadding = "compact" | "default";
6
+ type CodePanelSurface = "high" | "low";
7
+ type CodePanelMaxHeight = "none" | "sm" | "md" | "lg";
8
+
9
+ export interface CodePanelProps extends HTMLAttributes<HTMLPreElement> {
10
+ maxHeight?: CodePanelMaxHeight;
11
+ padding?: CodePanelPadding;
12
+ surface?: CodePanelSurface;
13
+ }
14
+
15
+ const CODE_PANEL_PADDING_CLASS: Record<CodePanelPadding, string> = {
16
+ compact: "p-2",
17
+ default: "p-3",
18
+ };
19
+ const CODE_PANEL_SURFACE_CLASS: Record<CodePanelSurface, string> = {
20
+ high: "bg-surface-container-high",
21
+ low: "bg-surface-container-low",
22
+ };
23
+ const CODE_PANEL_MAX_HEIGHT_CLASS: Record<CodePanelMaxHeight, string> = {
24
+ none: "",
25
+ sm: "max-h-48 overflow-y-auto",
26
+ md: "max-h-72 overflow-y-auto",
27
+ lg: "max-h-96 overflow-y-auto",
28
+ };
29
+
30
+ const CODE_PANEL_BODY_CODE_CLASS = "font-mono text-code-medium text-code";
31
+
32
+ const CODE_PANEL_CONTAINMENT_CLASS =
33
+ "m-0 min-w-0 w-full max-w-full overflow-x-auto whitespace-pre-wrap rounded-lg border border-outline [overflow-wrap:anywhere] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary";
34
+
35
+ export function codePanelVariants({
36
+ className,
37
+ maxHeight = "none",
38
+ padding = "compact",
39
+ surface = "high",
40
+ }: Pick<CodePanelProps, "className" | "maxHeight" | "padding" | "surface">) {
41
+ return cn(
42
+ CODE_PANEL_CONTAINMENT_CLASS,
43
+ CODE_PANEL_PADDING_CLASS[padding],
44
+ CODE_PANEL_SURFACE_CLASS[surface],
45
+ CODE_PANEL_MAX_HEIGHT_CLASS[maxHeight],
46
+ CODE_PANEL_BODY_CODE_CLASS,
47
+ className,
48
+ );
49
+ }
50
+
51
+ export const CodePanel = forwardRef<HTMLPreElement, CodePanelProps>(
52
+ function CodePanel(
53
+ { className, maxHeight = "none", padding, surface, tabIndex, ...props },
54
+ ref,
55
+ ) {
56
+ const isScrollable = maxHeight !== "none";
57
+
58
+ return (
59
+ <pre
60
+ className={codePanelVariants({ className, maxHeight, padding, surface })}
61
+ ref={ref}
62
+ tabIndex={tabIndex ?? (isScrollable ? 0 : undefined)}
63
+ {...props}
64
+ />
65
+ );
66
+ },
67
+ );
@@ -0,0 +1,180 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+
3
+ import { cn } from "../utilities/cn";
4
+ import {
5
+ Table,
6
+ type TableSize,
7
+ TableBody,
8
+ TableCaption,
9
+ TableCell,
10
+ TableHead,
11
+ TableHeader,
12
+ TableRow,
13
+ } from "./table";
14
+
15
+ export type DataTableState = "empty" | "error" | "loading" | "success";
16
+
17
+ export interface DataTableColumn<Row> {
18
+ cell: (row: Row) => ReactNode;
19
+ header: ReactNode;
20
+ id: string;
21
+ cellClassName?: string;
22
+ headerClassName?: string;
23
+ }
24
+
25
+ export interface DataTableProps<Row> {
26
+ columns: DataTableColumn<Row>[];
27
+ data: Row[];
28
+ getRowKey: (row: Row) => string;
29
+ ariaLabel?: string;
30
+ caption?: ReactNode;
31
+ containerClassName?: string;
32
+ containerProps?: HTMLAttributes<HTMLDivElement>;
33
+ emptyMessage?: ReactNode;
34
+ errorMessage?: ReactNode;
35
+ loadingMessage?: ReactNode;
36
+ rowClassName?: (row: Row) => string | undefined;
37
+ size?: TableSize;
38
+ state?: DataTableState;
39
+ tableClassName?: string;
40
+ }
41
+
42
+ function DataTablePlaceholderBar({ className }: { className?: string }) {
43
+ return (
44
+ <div
45
+ aria-hidden="true"
46
+ className={cn("animate-pulse rounded-xl bg-af-overlay", className)}
47
+ />
48
+ );
49
+ }
50
+
51
+ function DataTableStatusRow({
52
+ children,
53
+ colSpan,
54
+ role,
55
+ ariaBusy,
56
+ ariaLive,
57
+ cellClassName,
58
+ }: {
59
+ children: ReactNode;
60
+ colSpan: number;
61
+ role: "alert" | "status";
62
+ ariaBusy?: boolean;
63
+ ariaLive?: "assertive" | "polite";
64
+ cellClassName?: string;
65
+ }) {
66
+ return (
67
+ <TableRow>
68
+ <TableCell className={cellClassName} colSpan={colSpan}>
69
+ <div
70
+ aria-busy={ariaBusy || undefined}
71
+ aria-live={ariaLive}
72
+ role={role}
73
+ >
74
+ {children}
75
+ </div>
76
+ </TableCell>
77
+ </TableRow>
78
+ );
79
+ }
80
+
81
+ export function DataTable<Row>({
82
+ columns,
83
+ data,
84
+ getRowKey,
85
+ ariaLabel,
86
+ caption,
87
+ containerClassName,
88
+ containerProps,
89
+ emptyMessage,
90
+ errorMessage,
91
+ loadingMessage,
92
+ rowClassName,
93
+ size,
94
+ state = "success",
95
+ tableClassName,
96
+ }: DataTableProps<Row>) {
97
+ const renderBody = () => {
98
+ if (state === "loading") {
99
+ return (
100
+ <DataTableStatusRow
101
+ ariaBusy
102
+ ariaLive="polite"
103
+ colSpan={columns.length}
104
+ role="status"
105
+ >
106
+ <div className="grid gap-3 py-1">
107
+ {loadingMessage}
108
+ <div aria-hidden="true" className="grid gap-2">
109
+ <DataTablePlaceholderBar className="h-4 w-full max-w-48" />
110
+ <DataTablePlaceholderBar className="h-8 w-full" />
111
+ <DataTablePlaceholderBar className="h-4 w-full max-w-48" />
112
+ </div>
113
+ </div>
114
+ </DataTableStatusRow>
115
+ );
116
+ }
117
+
118
+ if (state === "error") {
119
+ return (
120
+ <DataTableStatusRow
121
+ ariaLive="assertive"
122
+ cellClassName="text-af-text-subtle"
123
+ colSpan={columns.length}
124
+ role="alert"
125
+ >
126
+ {errorMessage}
127
+ </DataTableStatusRow>
128
+ );
129
+ }
130
+
131
+ if (state === "empty" || (state === "success" && data.length === 0)) {
132
+ return (
133
+ <DataTableStatusRow
134
+ ariaLive="polite"
135
+ cellClassName="text-af-text-subtle"
136
+ colSpan={columns.length}
137
+ role="status"
138
+ >
139
+ {emptyMessage}
140
+ </DataTableStatusRow>
141
+ );
142
+ }
143
+
144
+ return data.map((row) => (
145
+ <TableRow className={rowClassName?.(row)} key={getRowKey(row)}>
146
+ {columns.map((column) => (
147
+ <TableCell className={column.cellClassName} key={column.id}>
148
+ {column.cell(row)}
149
+ </TableCell>
150
+ ))}
151
+ </TableRow>
152
+ ));
153
+ };
154
+
155
+ return (
156
+ <Table
157
+ aria-label={ariaLabel}
158
+ className={tableClassName}
159
+ containerClassName={containerClassName}
160
+ containerProps={containerProps}
161
+ size={size}
162
+ >
163
+ {caption ? <TableCaption>{caption}</TableCaption> : null}
164
+ <TableHeader>
165
+ <TableRow>
166
+ {columns.map((column) => (
167
+ <TableHead
168
+ className={column.headerClassName}
169
+ key={column.id}
170
+ scope="col"
171
+ >
172
+ {column.header}
173
+ </TableHead>
174
+ ))}
175
+ </TableRow>
176
+ </TableHeader>
177
+ <TableBody>{renderBody()}</TableBody>
178
+ </Table>
179
+ );
180
+ }
@@ -0,0 +1,24 @@
1
+ import { forwardRef, type HTMLAttributes } from "react";
2
+
3
+ import { BODY_TEXT_CLASS } from "../primitives/typography-roles";
4
+ import { cn } from "../utilities/cn";
5
+
6
+ export interface DescriptionListProps
7
+ extends HTMLAttributes<HTMLDListElement> {}
8
+
9
+ export const DescriptionList = forwardRef<
10
+ HTMLDListElement,
11
+ DescriptionListProps
12
+ >(function DescriptionList({ className, ...props }, ref) {
13
+ return (
14
+ <dl
15
+ className={cn(
16
+ "m-0 grid min-w-0 gap-1.5 [&_dd]:m-0 [&_dd]:min-w-0 [&_div]:grid [&_div]:min-w-0 [&_div]:gap-2",
17
+ BODY_TEXT_CLASS,
18
+ className,
19
+ )}
20
+ ref={ref}
21
+ {...props}
22
+ />
23
+ );
24
+ });
@@ -0,0 +1,34 @@
1
+ /** Stable category path for `@you-agent-factory/components/data-display`. */
2
+ export const COMPONENTS_CATEGORY = "data-display" as const;
3
+
4
+ export type ComponentsCategory = typeof COMPONENTS_CATEGORY;
5
+
6
+ export { CodePanel, codePanelVariants } from "./code-panel";
7
+ export type { CodePanelProps } from "./code-panel";
8
+ export { DescriptionList } from "./description-list";
9
+ export type { DescriptionListProps } from "./description-list";
10
+
11
+ export { DataTable } from "./data-table";
12
+ export type {
13
+ DataTableColumn,
14
+ DataTableProps,
15
+ DataTableState,
16
+ } from "./data-table";
17
+
18
+ export {
19
+ Table,
20
+ TableBody,
21
+ TableCaption,
22
+ TableCell,
23
+ TableHead,
24
+ TableHeader,
25
+ TableRow,
26
+ } from "./table";
27
+ export type { TableProps, TableSize } from "./table";
28
+
29
+ export {
30
+ tableCellTruncateClassName,
31
+ tableCellWrapClassName,
32
+ tableMinWidthWideClassName,
33
+ tableNarrowContainerClassName,
34
+ } from "./table-layout";
@@ -0,0 +1,12 @@
1
+ /** Wrap long cell content without forcing page-level horizontal overflow. */
2
+ export const tableCellWrapClassName = "min-w-0 [overflow-wrap:anywhere]";
3
+
4
+ /** Truncate overflowing cell content with ellipsis. */
5
+ export const tableCellTruncateClassName =
6
+ "block min-w-0 max-w-full truncate whitespace-nowrap";
7
+
8
+ /** Minimum table width for wide datasets; pair with a narrow scroll container. */
9
+ export const tableMinWidthWideClassName = "min-w-2xl";
10
+
11
+ /** Scroll container classes for narrow viewport table containment. */
12
+ export const tableNarrowContainerClassName = "min-w-0 overscroll-x-contain";