@you-agent-factory/components 0.0.0 → 0.0.2

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 (182) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +38 -7
  3. package/dist/category-paths.d.ts +3 -0
  4. package/dist/charts/chart-state-panel.d.ts +11 -0
  5. package/dist/charts/chart.d.ts +35 -0
  6. package/dist/charts/index.d.ts +5 -0
  7. package/dist/charts/index.js +287 -0
  8. package/dist/chunks/action-row.js +39 -0
  9. package/dist/chunks/alert-panel.js +182 -0
  10. package/dist/chunks/button.js +193 -0
  11. package/dist/chunks/cn.js +6 -0
  12. package/dist/chunks/factory-emulator-controls.js +123 -0
  13. package/dist/chunks/package-form-field.js +546 -0
  14. package/dist/chunks/scroll-area.js +261 -0
  15. package/dist/chunks/surface-panel.js +73 -0
  16. package/dist/chunks/table-layout.js +292 -0
  17. package/dist/chunks/typography-roles.js +26 -0
  18. package/dist/chunks/typography.js +129 -0
  19. package/dist/chunks/widget-frame.js +344 -0
  20. package/dist/data-display/code-panel.d.ts +12 -0
  21. package/dist/data-display/data-table.d.ts +27 -0
  22. package/dist/data-display/description-list.d.ts +4 -0
  23. package/{src/data-display/index.ts → dist/data-display/index.d.ts} +4 -26
  24. package/dist/data-display/index.js +20 -0
  25. package/dist/data-display/table-layout.d.ts +8 -0
  26. package/dist/data-display/table.d.ts +14 -0
  27. package/dist/factory-emulator/factory-emulator-controls.d.ts +23 -0
  28. package/dist/factory-emulator/index.d.ts +6 -0
  29. package/dist/factory-emulator/index.js +6 -0
  30. package/dist/feedback/alert-panel-semantics.d.ts +11 -0
  31. package/dist/feedback/alert-panel.d.ts +29 -0
  32. package/dist/feedback/index.d.ts +6 -0
  33. package/dist/feedback/index.js +10 -0
  34. package/dist/feedback/skeleton.d.ts +2 -0
  35. package/dist/forms/index.d.ts +19 -0
  36. package/dist/forms/index.js +37 -0
  37. package/dist/forms/package-checkbox.d.ts +3 -0
  38. package/dist/forms/package-enum-select.d.ts +42 -0
  39. package/dist/forms/package-file-input.d.ts +3 -0
  40. package/dist/forms/package-form-field.d.ts +49 -0
  41. package/dist/forms/package-input.d.ts +6 -0
  42. package/dist/forms/package-native-select.d.ts +3 -0
  43. package/dist/forms/package-select.d.ts +32 -0
  44. package/dist/forms/package-textarea.d.ts +10 -0
  45. package/dist/forms/select-icons.d.ts +3 -0
  46. package/dist/graphs/graph-edge-path.d.ts +18 -0
  47. package/dist/graphs/graph-edge.d.ts +15 -0
  48. package/dist/graphs/graph-node-button.d.ts +11 -0
  49. package/dist/graphs/graph-node-handle-badge.d.ts +5 -0
  50. package/dist/graphs/graph-node-handle.d.ts +18 -0
  51. package/dist/graphs/graph-node-shell.d.ts +13 -0
  52. package/dist/graphs/graph-node-state-indicator.d.ts +6 -0
  53. package/dist/graphs/graph-node-state.d.ts +23 -0
  54. package/dist/graphs/graph-viewport-surface.d.ts +5 -0
  55. package/dist/graphs/index.d.ts +13 -0
  56. package/dist/graphs/index.js +614 -0
  57. package/{src/icons/index.ts → dist/icons/index.d.ts} +1 -2
  58. package/dist/icons/index.js +4 -0
  59. package/dist/index.d.ts +26 -0
  60. package/dist/index.js +145 -0
  61. package/dist/layout/action-row.d.ts +8 -0
  62. package/{src/layout/index.ts → dist/layout/index.d.ts} +1 -3
  63. package/dist/layout/index.js +9 -0
  64. package/dist/layout/surface-panel.d.ts +15 -0
  65. package/{src/navigation/index.ts → dist/navigation/index.d.ts} +1 -2
  66. package/dist/navigation/index.js +4 -0
  67. package/dist/overlays/collapsible.d.ts +5 -0
  68. package/dist/overlays/dialog.d.ts +16 -0
  69. package/dist/overlays/index.d.ts +10 -0
  70. package/dist/overlays/index.js +27 -0
  71. package/dist/overlays/overlay-layout.d.ts +6 -0
  72. package/dist/overlays/popover.d.ts +6 -0
  73. package/dist/overlays/scroll-area.d.ts +9 -0
  74. package/dist/primitives/button-link.d.ts +5 -0
  75. package/dist/primitives/button.d.ts +9 -0
  76. package/dist/primitives/icon-button-shell.d.ts +10 -0
  77. package/{src/primitives/index.ts → dist/primitives/index.d.ts} +2 -19
  78. package/dist/primitives/index.js +49 -0
  79. package/dist/primitives/package-text.d.ts +6 -0
  80. package/dist/primitives/typography-roles.d.ts +12 -0
  81. package/dist/primitives/typography.d.ts +36 -0
  82. package/dist/recipes/index.d.ts +14 -0
  83. package/dist/recipes/index.js +32 -0
  84. package/dist/recipes/widget-frame-content.d.ts +24 -0
  85. package/dist/recipes/widget-frame-disclosure.d.ts +33 -0
  86. package/dist/recipes/widget-frame-layout.d.ts +12 -0
  87. package/dist/recipes/widget-frame-skeleton.d.ts +2 -0
  88. package/dist/recipes/widget-frame-states.d.ts +15 -0
  89. package/dist/recipes/widget-frame-typography.d.ts +10 -0
  90. package/dist/recipes/widget-frame.d.ts +12 -0
  91. package/{src → dist}/styles.css +36 -0
  92. package/dist/testing/index.d.ts +4 -0
  93. package/dist/testing/index.js +16 -0
  94. package/dist/testing/render.d.ts +5 -0
  95. package/{src/tokens/index.ts → dist/tokens/index.d.ts} +1 -2
  96. package/dist/tokens/index.js +4 -0
  97. package/dist/utilities/cn.d.ts +1 -0
  98. package/{src/utilities/index.ts → dist/utilities/index.d.ts} +1 -3
  99. package/dist/utilities/index.js +6 -0
  100. package/package.json +65 -64
  101. package/docs/README.md +0 -83
  102. package/docs/button.md +0 -119
  103. package/docs/charts.md +0 -325
  104. package/docs/data-display-code-panel.md +0 -120
  105. package/docs/feedback-alert-panel.md +0 -117
  106. package/docs/feedback-skeleton.md +0 -54
  107. package/docs/forms-form-field.md +0 -490
  108. package/docs/forms-input-primitives.md +0 -311
  109. package/docs/forms-select-primitives.md +0 -362
  110. package/docs/graphs.md +0 -250
  111. package/docs/layout-display-primitives.md +0 -211
  112. package/docs/overlays.md +0 -414
  113. package/docs/table-data-table.md +0 -331
  114. package/docs/typography-roles.md +0 -182
  115. package/docs/widget-frame-recipes.md +0 -273
  116. package/src/category-paths.ts +0 -20
  117. package/src/charts/chart-state-panel.tsx +0 -103
  118. package/src/charts/chart.tsx +0 -287
  119. package/src/charts/index.ts +0 -21
  120. package/src/data-display/code-panel.tsx +0 -67
  121. package/src/data-display/data-table.tsx +0 -180
  122. package/src/data-display/description-list.tsx +0 -24
  123. package/src/data-display/table-layout.ts +0 -12
  124. package/src/data-display/table.tsx +0 -131
  125. package/src/feedback/alert-panel-semantics.ts +0 -75
  126. package/src/feedback/alert-panel.tsx +0 -187
  127. package/src/feedback/index.ts +0 -21
  128. package/src/feedback/skeleton.tsx +0 -16
  129. package/src/forms/index.ts +0 -73
  130. package/src/forms/package-checkbox.tsx +0 -50
  131. package/src/forms/package-enum-select.tsx +0 -185
  132. package/src/forms/package-file-input.tsx +0 -25
  133. package/src/forms/package-form-field.tsx +0 -202
  134. package/src/forms/package-input.tsx +0 -25
  135. package/src/forms/package-native-select.tsx +0 -25
  136. package/src/forms/package-select.tsx +0 -209
  137. package/src/forms/package-textarea.tsx +0 -35
  138. package/src/forms/select-icons.tsx +0 -35
  139. package/src/graphs/graph-edge-path.ts +0 -241
  140. package/src/graphs/graph-edge.tsx +0 -130
  141. package/src/graphs/graph-interactive-example.tsx +0 -187
  142. package/src/graphs/graph-node-button.tsx +0 -51
  143. package/src/graphs/graph-node-handle-badge.tsx +0 -108
  144. package/src/graphs/graph-node-handle.ts +0 -28
  145. package/src/graphs/graph-node-shell.tsx +0 -111
  146. package/src/graphs/graph-node-state-indicator.tsx +0 -47
  147. package/src/graphs/graph-node-state.ts +0 -111
  148. package/src/graphs/graph-viewport-surface.tsx +0 -27
  149. package/src/graphs/index.ts +0 -41
  150. package/src/index.ts +0 -209
  151. package/src/layout/action-row.tsx +0 -53
  152. package/src/layout/surface-panel.tsx +0 -91
  153. package/src/overlays/collapsible.tsx +0 -22
  154. package/src/overlays/dialog.tsx +0 -148
  155. package/src/overlays/index.ts +0 -31
  156. package/src/overlays/overlay-layout.ts +0 -9
  157. package/src/overlays/popover.tsx +0 -29
  158. package/src/overlays/scroll-area.tsx +0 -78
  159. package/src/primitives/button-link.tsx +0 -22
  160. package/src/primitives/button.tsx +0 -258
  161. package/src/primitives/icon-button-shell.tsx +0 -49
  162. package/src/primitives/package-text.tsx +0 -29
  163. package/src/primitives/typography-roles.ts +0 -12
  164. package/src/primitives/typography.tsx +0 -165
  165. package/src/recipes/index.ts +0 -61
  166. package/src/recipes/widget-frame-content.tsx +0 -114
  167. package/src/recipes/widget-frame-disclosure.tsx +0 -161
  168. package/src/recipes/widget-frame-layout.ts +0 -40
  169. package/src/recipes/widget-frame-skeleton.tsx +0 -16
  170. package/src/recipes/widget-frame-states.tsx +0 -99
  171. package/src/recipes/widget-frame-typography.ts +0 -19
  172. package/src/recipes/widget-frame.tsx +0 -84
  173. package/src/testing/index.ts +0 -13
  174. package/src/testing/render.tsx +0 -16
  175. package/src/utilities/cn.ts +0 -5
  176. /package/{src → dist}/styles/color-palette-presets.css +0 -0
  177. /package/{src → dist}/styles/color-role-tokens.css +0 -0
  178. /package/{src → dist}/styles/layout-role-tokens.css +0 -0
  179. /package/{src → dist}/styles/text-color-role-tokens.css +0 -0
  180. /package/{src → dist}/styles/typography-role-tokens.css +0 -0
  181. /package/{src → dist}/styles/typography-role-utilities.css +0 -0
  182. /package/{src → dist}/styles/typography-roles.css +0 -0
@@ -1,273 +0,0 @@
1
- # Widget frame and layout recipes
2
-
3
- Domain-free widget frame shells and layout recipes for dashboard-like panels.
4
- Use these components when you need framed content regions with consistent
5
- typography, state treatments, disclosure controls, and responsive layout helpers
6
- without importing dashboard features, bento grids, API clients, or app state.
7
-
8
- ## Required setup
9
-
10
- Import package styles once in your host application before rendering recipes:
11
-
12
- ```css
13
- @import "@you-agent-factory/components/styles.css";
14
- ```
15
-
16
- Recipes depend on package role tokens (`--color-surface`, `--shadow-af-card`,
17
- typography roles) and Tailwind utility classes compiled from those tokens. They
18
- do not require dashboard `styles.css`, dashboard providers, generated OpenAPI
19
- types, React Query, Zustand, or app localization context.
20
-
21
- ## Import paths
22
-
23
- Prefer the recipes category entrypoint for tree-shaking and explicit category
24
- boundaries:
25
-
26
- ```ts
27
- import {
28
- WidgetFrame,
29
- WidgetSubtitle,
30
- WidgetDetailCopy,
31
- WidgetEmptyState,
32
- WidgetEmptyStateTitle,
33
- WidgetEmptyStateText,
34
- WidgetLoadingState,
35
- WidgetErrorState,
36
- WidgetSuccessState,
37
- WidgetFrameDisclosure,
38
- WidgetFrameDisclosureTrigger,
39
- WidgetFrameDisclosurePanel,
40
- widgetFrameDetailCardClass,
41
- } from "@you-agent-factory/components/recipes";
42
- ```
43
-
44
- The same exports are also available from the package root:
45
-
46
- ```ts
47
- import { WidgetFrame } from "@you-agent-factory/components";
48
- ```
49
-
50
- ## Host ownership
51
-
52
- The package owns presentation markup, layout classes, and accessibility
53
- semantics for frame shells. Host applications own everything domain-specific:
54
-
55
- | Concern | Owner |
56
- | --- | --- |
57
- | User-visible copy (titles, messages, labels) | Host |
58
- | Data fetching, caching, and error mapping | Host |
59
- | Domain models (factory, work, session, provider) | Host |
60
- | Collapsed/expanded boolean state | Host |
61
- | Header and body action callbacks | Host |
62
- | Bento grid composition, drag/resize, widget selection | Dashboard feature code |
63
- | Durable cross-route or persisted UI state | Host |
64
-
65
- Pass copy and state into recipe components as props and children. Do not expect
66
- recipes to read from your routers, stores, or API layers.
67
-
68
- ## Composition overview
69
-
70
- A typical framed panel stacks:
71
-
72
- 1. `WidgetFrame` — card shell with title, optional `headerAction`, and scrollable body.
73
- 2. Content primitives — `WidgetSubtitle`, `WidgetDetailCopy`, or arbitrary host children.
74
- 3. State shells — `WidgetLoadingState`, `WidgetErrorState`, `WidgetSuccessState`, or `WidgetEmptyState`.
75
- 4. Optional disclosure — `WidgetFrameDisclosure` + controlled trigger/panel pair.
76
-
77
- ```tsx
78
- import { useState } from "react";
79
- import {
80
- WidgetDetailCopy,
81
- WidgetEmptyStateText,
82
- WidgetEmptyStateTitle,
83
- WidgetFrame,
84
- WidgetFrameDisclosure,
85
- WidgetFrameDisclosurePanel,
86
- WidgetFrameDisclosureTrigger,
87
- WidgetLoadingState,
88
- WidgetSubtitle,
89
- } from "@you-agent-factory/components/recipes";
90
-
91
- export function ExamplePanel({
92
- loading,
93
- title,
94
- }: {
95
- loading: boolean;
96
- title: string;
97
- }) {
98
- const [expanded, setExpanded] = useState(false);
99
- const panelID = "example-panel-details";
100
-
101
- return (
102
- <WidgetFrame
103
- headerAction={
104
- <button type="button" onClick={() => undefined}>
105
- Refresh
106
- </button>
107
- }
108
- title={title}
109
- >
110
- <WidgetSubtitle>42 host-provided items</WidgetSubtitle>
111
- {loading ? (
112
- <WidgetLoadingState>
113
- <WidgetEmptyStateTitle>Loading content</WidgetEmptyStateTitle>
114
- <WidgetEmptyStateText>Host-provided loading message.</WidgetEmptyStateText>
115
- </WidgetLoadingState>
116
- ) : (
117
- <WidgetDetailCopy>Host-provided detail copy.</WidgetDetailCopy>
118
- )}
119
- <WidgetFrameDisclosure>
120
- <WidgetFrameDisclosureTrigger
121
- controlsID={panelID}
122
- expanded={expanded}
123
- onExpandedChange={setExpanded}
124
- >
125
- {expanded ? "Collapse details" : "Expand details"}
126
- </WidgetFrameDisclosureTrigger>
127
- <WidgetFrameDisclosurePanel expanded={expanded} id={panelID}>
128
- <WidgetDetailCopy>Host-provided disclosure content.</WidgetDetailCopy>
129
- </WidgetFrameDisclosurePanel>
130
- </WidgetFrameDisclosure>
131
- </WidgetFrame>
132
- );
133
- }
134
- ```
135
-
136
- ## Key props and layout helpers
137
-
138
- ### `WidgetFrame`
139
-
140
- | Prop | Purpose |
141
- | --- | --- |
142
- | `title` | Required accessible name (`aria-label` on the frame article). |
143
- | `children` | Host content region inside the body grid. |
144
- | `headerAction` | Optional header tools slot (buttons, menus). A spacer preserves header height when omitted. |
145
- | `wide` | Applies minimum body height for wide dashboard columns. |
146
- | `bodyScroll` | Enables scrollable body (`overflow-auto`). Defaults to `true`. |
147
- | `className` / `bodyClassName` | Host layout overrides. Apply `widgetFrameDetailCardClass` via `className` when rendering description lists. |
148
-
149
- Layout constants exported for host composition:
150
-
151
- - `widgetFrameDetailCardClass` — description-list spacing inside framed detail cards.
152
- - `WIDGET_FRAME_MIN_WIDTH_CLASS` — `min-w-0` shrink guard for grid parents.
153
- - `WIDGET_FRAME_WIDE_BODY_CLASS` — minimum body height for wide layouts.
154
- - `WIDGET_FRAME_RESPONSIVE_SHELL_CLASS` — full-width responsive shell helper.
155
-
156
- ### State shells
157
-
158
- | Component | Semantics | Host provides |
159
- | --- | --- | --- |
160
- | `WidgetLoadingState` | `role="status"`, `aria-busy="true"` | Loading copy via children; optional `placeholder` or `showDefaultPlaceholder={false}`. |
161
- | `WidgetErrorState` | `role="alert"` | Error title and message via children. |
162
- | `WidgetSuccessState` | `role="status"` | Success title and message via children. |
163
- | `WidgetEmptyState` | Neutral dashed panel | Empty title/text via `WidgetEmptyStateTitle` / `WidgetEmptyStateText` or arbitrary children. |
164
-
165
- State shells never invent domain-specific text. All user-visible strings come from
166
- the host.
167
-
168
- ### Disclosure (collapsed / expanded)
169
-
170
- Use controlled state from the host:
171
-
172
- - `WidgetFrameDisclosureTrigger` requires `controlsID`, `expanded`, and optional `onExpandedChange`.
173
- - `WidgetFrameDisclosurePanel` requires matching `id` and `expanded`.
174
- - Triggers expose `aria-expanded`, `aria-controls`, keyboard focus rings, and `type="button"`.
175
- - Panels use the `hidden` attribute when collapsed.
176
-
177
- Icon-only triggers must pass `aria-label`. Labeled triggers use visible button text.
178
-
179
- ### Responsive layout helpers
180
-
181
- For Storybook demos and host layout tests:
182
-
183
- - `widgetFrameStoryShellStyle(maxWidth)` — bounded shell wrapper style object.
184
- - `widgetFrameHasNoHorizontalOverflow(element)` — pure helper for overflow checks.
185
- - `WIDGET_FRAME_STORY_SHELL_DATA_ATTR` — `data-widget-frame-story-shell` marker for test shells.
186
-
187
- ## Accessibility expectations
188
-
189
- - Frame title renders as a level-3 heading inside a landmark `article` labeled with the same title text.
190
- - Loading, error, and success regions use appropriate live-region roles; do not nest conflicting roles.
191
- - Disclosure triggers are keyboard operable buttons with visible `focus-visible` outlines.
192
- - Header actions supplied by the host must include accessible names (`aria-label` or visible text).
193
- - Host copy inside alerts and status regions should use heading + body structure for screen-reader scanability.
194
-
195
- ## Storybook visual reference
196
-
197
- Package Storybook lives under `Recipes/WidgetFrame`. Stories use package imports
198
- and package token decorators only — no dashboard providers.
199
-
200
- | Story | Storybook id | Demonstrates |
201
- | --- | --- | --- |
202
- | Success content | `recipes-widgetframe--success-content` | Default framed content |
203
- | Empty state | `recipes-widgetframe--empty-state` | Host-provided empty copy |
204
- | Loading state | `recipes-widgetframe--loading-state` | `WidgetLoadingState` + placeholder |
205
- | Error state | `recipes-widgetframe--error-state` | `WidgetErrorState` alert treatment |
206
- | Success state | `recipes-widgetframe--success-state` | `WidgetSuccessState` treatment |
207
- | Collapsed disclosure | `recipes-widgetframe--collapsed-disclosure` | Controlled collapse + expand interaction |
208
- | Expanded disclosure | `recipes-widgetframe--expanded-disclosure` | Expanded panel visibility |
209
- | Responsive compact | `recipes-widgetframe--responsive-compact` | 360px bounded shell |
210
- | Responsive medium | `recipes-widgetframe--responsive-medium` | 768px bounded shell |
211
- | Responsive wide | `recipes-widgetframe--responsive-wide` | 1280px bounded shell |
212
-
213
- Run package Storybook locally:
214
-
215
- ```bash
216
- cd ui/packages/components
217
- bun run storybook
218
- ```
219
-
220
- Browser verification for documented stories:
221
-
222
- ```bash
223
- cd ui/packages/components
224
- bun run verify:widget-frame-docs
225
- ```
226
-
227
- Responsive overflow checks (compact + wide at mobile and desktop viewports):
228
-
229
- ```bash
230
- cd ui/packages/components
231
- bun run verify:widget-frame-responsive
232
- ```
233
-
234
- ## Allowed dependencies
235
-
236
- Recipe source may import:
237
-
238
- - Package utilities (`cn` from `@you-agent-factory/components/utilities`)
239
- - Package token CSS via the host `styles.css` import
240
- - React and `react-dom` peer dependencies
241
-
242
- Recipe source must **not** import:
243
-
244
- - Dashboard feature modules, routes, or bento grid (`react-grid-layout`)
245
- - Generated OpenAPI clients or dashboard API adapters
246
- - React Query, Zustand, Monaco, Sonner, or dashboard i18n/session providers
247
- - Factory/work/session/provider domain types
248
-
249
- `check:package-boundary` enforces these rules in CI.
250
-
251
- ## Source-copy guidance
252
-
253
- Teams may copy recipe files into a host repository to customize markup while
254
- keeping the same token foundation:
255
-
256
- 1. Import `@you-agent-factory/components/styles.css` in the host app.
257
- 2. Copy only the recipe files you need from `src/recipes/`.
258
- 3. Keep copied code on the package side of your boundary — do not pull dashboard
259
- modules into copied recipe files.
260
- 4. Retain host ownership of copy, data fetching, disclosure state, and action handlers.
261
-
262
- **No source-copy CLI or generator ships with this package.** Copy-and-adapt
263
- workflows are manual and maintained by the host application.
264
-
265
- ## Dashboard integration note
266
-
267
- The dashboard keeps bento composition (`AgentBentoCard`, grid layout, widget
268
- picker) in feature code. Dashboard widgets import recipe content primitives from
269
- `@you-agent-factory/components/recipes` while `DashboardWidgetFrame` remains a
270
- dashboard-owned wrapper that applies bento-specific chrome.
271
-
272
- When adopting recipes outside the dashboard, compose `WidgetFrame` directly and
273
- supply your own header actions, state, and slot content.
@@ -1,20 +0,0 @@
1
- /** Planned deep import paths for `@you-agent-factory/components` category entrypoints. */
2
- export const COMPONENT_CATEGORY_EXPORT_PATHS = [
3
- "primitives",
4
- "forms",
5
- "layout",
6
- "feedback",
7
- "data-display",
8
- "navigation",
9
- "overlays",
10
- "charts",
11
- "graphs",
12
- "recipes",
13
- "icons",
14
- "utilities",
15
- "testing",
16
- "tokens",
17
- ] as const;
18
-
19
- export type ComponentCategoryExportPath =
20
- (typeof COMPONENT_CATEGORY_EXPORT_PATHS)[number];
@@ -1,103 +0,0 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
2
-
3
- import { cn } from "../utilities/cn";
4
-
5
- import type { ChartPresentation } from "./chart";
6
-
7
- export type ChartStateStatus = "empty" | "error" | "loading" | "success";
8
-
9
- export interface ChartStatePanelProps extends HTMLAttributes<HTMLDivElement> {
10
- action?: ReactNode;
11
- description: string;
12
- presentation?: ChartPresentation;
13
- status: ChartStateStatus;
14
- title: string;
15
- }
16
-
17
- // tailwind-exception: intrinsic-sizing
18
- const CHART_STATE_PANEL_CLASS =
19
- "flex h-full min-h-[14rem] min-w-0 w-full flex-1 flex-col justify-center";
20
- // tailwind-exception: intrinsic-sizing
21
- const CHART_STATE_PANEL_EMBEDDED_CLASS =
22
- "grid min-h-[14rem] min-w-0 w-full flex-1 flex-col items-start justify-center gap-1.5 p-0 [&_h3]:m-0";
23
- const CHART_STATE_PANEL_STANDALONE_SHELL_CLASS =
24
- "grid min-h-60 items-start gap-1.5 rounded-2xl border border-dashed border-outline-variant bg-surface-container-low p-5 [&_h3]:m-0";
25
- const CHART_STATE_PANEL_TITLE_CLASS =
26
- "m-0 text-title-medium font-semibold text-on-surface";
27
- const CHART_STATE_PANEL_DESCRIPTION_CLASS = "m-0 text-body-medium text-on-surface-variant";
28
- const CHART_STATE_PANEL_SKELETON_CLASS = "animate-pulse rounded-xl bg-af-overlay";
29
-
30
- function chartStateRole(status: ChartStateStatus): "alert" | "status" {
31
- return status === "error" ? "alert" : "status";
32
- }
33
-
34
- function chartStateLive(status: ChartStateStatus): "assertive" | "polite" {
35
- return status === "error" ? "assertive" : "polite";
36
- }
37
-
38
- export function ChartStatePanel({
39
- action,
40
- className,
41
- description,
42
- presentation = "standalone",
43
- status,
44
- title,
45
- ...props
46
- }: ChartStatePanelProps) {
47
- const embedded = presentation === "embedded";
48
- const role = chartStateRole(status);
49
- const ariaLive = chartStateLive(status);
50
- const loading = status === "loading";
51
-
52
- const content = (
53
- <>
54
- {loading ? (
55
- <div aria-hidden="true" className="grid w-full gap-3">
56
- <div className={cn(CHART_STATE_PANEL_SKELETON_CLASS, "h-4 w-32")} />
57
- <div className={cn(CHART_STATE_PANEL_SKELETON_CLASS, "h-28 w-full")} />
58
- </div>
59
- ) : null}
60
- <h3 className={CHART_STATE_PANEL_TITLE_CLASS}>{title}</h3>
61
- <p className={CHART_STATE_PANEL_DESCRIPTION_CLASS}>{description}</p>
62
- {action ? <div className="mt-2">{action}</div> : null}
63
- </>
64
- );
65
-
66
- if (!embedded) {
67
- return (
68
- <div
69
- aria-busy={loading || undefined}
70
- aria-live={ariaLive}
71
- className={cn(
72
- CHART_STATE_PANEL_STANDALONE_SHELL_CLASS,
73
- CHART_STATE_PANEL_CLASS,
74
- className,
75
- )}
76
- data-chart-presentation={presentation}
77
- data-chart-state={status}
78
- role={role}
79
- {...props}
80
- >
81
- {content}
82
- </div>
83
- );
84
- }
85
-
86
- return (
87
- <div
88
- aria-busy={loading || undefined}
89
- aria-live={ariaLive}
90
- className={cn(
91
- CHART_STATE_PANEL_EMBEDDED_CLASS,
92
- CHART_STATE_PANEL_CLASS,
93
- className,
94
- )}
95
- data-chart-presentation={presentation}
96
- data-chart-state={status}
97
- role={role}
98
- {...props}
99
- >
100
- {content}
101
- </div>
102
- );
103
- }
@@ -1,287 +0,0 @@
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
- }
@@ -1,21 +0,0 @@
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";