@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.
- package/README.md +223 -0
- package/docs/README.md +83 -0
- package/docs/button.md +119 -0
- package/docs/charts.md +325 -0
- package/docs/data-display-code-panel.md +120 -0
- package/docs/feedback-alert-panel.md +117 -0
- package/docs/feedback-skeleton.md +54 -0
- package/docs/forms-form-field.md +490 -0
- package/docs/forms-input-primitives.md +311 -0
- package/docs/forms-select-primitives.md +362 -0
- package/docs/graphs.md +250 -0
- package/docs/layout-display-primitives.md +211 -0
- package/docs/overlays.md +414 -0
- package/docs/table-data-table.md +331 -0
- package/docs/typography-roles.md +182 -0
- package/docs/widget-frame-recipes.md +273 -0
- package/package.json +161 -0
- package/src/category-paths.ts +20 -0
- package/src/charts/chart-state-panel.tsx +103 -0
- package/src/charts/chart.tsx +287 -0
- package/src/charts/index.ts +21 -0
- package/src/data-display/code-panel.tsx +67 -0
- package/src/data-display/data-table.tsx +180 -0
- package/src/data-display/description-list.tsx +24 -0
- package/src/data-display/index.ts +34 -0
- package/src/data-display/table-layout.ts +12 -0
- package/src/data-display/table.tsx +131 -0
- package/src/feedback/alert-panel-semantics.ts +75 -0
- package/src/feedback/alert-panel.tsx +187 -0
- package/src/feedback/index.ts +21 -0
- package/src/feedback/skeleton.tsx +16 -0
- package/src/forms/index.ts +73 -0
- package/src/forms/package-checkbox.tsx +50 -0
- package/src/forms/package-enum-select.tsx +185 -0
- package/src/forms/package-file-input.tsx +25 -0
- package/src/forms/package-form-field.tsx +202 -0
- package/src/forms/package-input.tsx +25 -0
- package/src/forms/package-native-select.tsx +25 -0
- package/src/forms/package-select.tsx +209 -0
- package/src/forms/package-textarea.tsx +35 -0
- package/src/forms/select-icons.tsx +35 -0
- package/src/graphs/graph-edge-path.ts +241 -0
- package/src/graphs/graph-edge.tsx +130 -0
- package/src/graphs/graph-interactive-example.tsx +187 -0
- package/src/graphs/graph-node-button.tsx +51 -0
- package/src/graphs/graph-node-handle-badge.tsx +108 -0
- package/src/graphs/graph-node-handle.ts +28 -0
- package/src/graphs/graph-node-shell.tsx +111 -0
- package/src/graphs/graph-node-state-indicator.tsx +47 -0
- package/src/graphs/graph-node-state.ts +111 -0
- package/src/graphs/graph-viewport-surface.tsx +27 -0
- package/src/graphs/index.ts +41 -0
- package/src/icons/index.ts +4 -0
- package/src/index.ts +209 -0
- package/src/layout/action-row.tsx +53 -0
- package/src/layout/index.ts +9 -0
- package/src/layout/surface-panel.tsx +91 -0
- package/src/navigation/index.ts +4 -0
- package/src/overlays/collapsible.tsx +22 -0
- package/src/overlays/dialog.tsx +148 -0
- package/src/overlays/index.ts +31 -0
- package/src/overlays/overlay-layout.ts +9 -0
- package/src/overlays/popover.tsx +29 -0
- package/src/overlays/scroll-area.tsx +78 -0
- package/src/primitives/button-link.tsx +22 -0
- package/src/primitives/button.tsx +258 -0
- package/src/primitives/icon-button-shell.tsx +49 -0
- package/src/primitives/index.ts +31 -0
- package/src/primitives/package-text.tsx +29 -0
- package/src/primitives/typography-roles.ts +12 -0
- package/src/primitives/typography.tsx +165 -0
- package/src/recipes/index.ts +61 -0
- package/src/recipes/widget-frame-content.tsx +114 -0
- package/src/recipes/widget-frame-disclosure.tsx +161 -0
- package/src/recipes/widget-frame-layout.ts +40 -0
- package/src/recipes/widget-frame-skeleton.tsx +16 -0
- package/src/recipes/widget-frame-states.tsx +99 -0
- package/src/recipes/widget-frame-typography.ts +19 -0
- package/src/recipes/widget-frame.tsx +84 -0
- package/src/styles/color-palette-presets.css +167 -0
- package/src/styles/color-role-tokens.css +163 -0
- package/src/styles/layout-role-tokens.css +27 -0
- package/src/styles/text-color-role-tokens.css +29 -0
- package/src/styles/typography-role-tokens.css +72 -0
- package/src/styles/typography-role-utilities.css +73 -0
- package/src/styles/typography-roles.css +53 -0
- package/src/styles.css +32 -0
- package/src/testing/index.ts +13 -0
- package/src/testing/render.tsx +16 -0
- package/src/tokens/index.ts +4 -0
- package/src/utilities/cn.ts +5 -0
- package/src/utilities/index.ts +6 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
2
|
+
import {
|
|
3
|
+
type ButtonHTMLAttributes,
|
|
4
|
+
Children,
|
|
5
|
+
cloneElement,
|
|
6
|
+
forwardRef,
|
|
7
|
+
isValidElement,
|
|
8
|
+
type KeyboardEvent,
|
|
9
|
+
type MouseEvent,
|
|
10
|
+
type ReactNode,
|
|
11
|
+
type Ref,
|
|
12
|
+
} from "react";
|
|
13
|
+
|
|
14
|
+
import { cn } from "../utilities/cn";
|
|
15
|
+
|
|
16
|
+
const BUTTON_LOADING_CONTENT_CLASS = "inline-flex items-center justify-center gap-2";
|
|
17
|
+
const BUTTON_LOADING_HIDDEN_CONTENT_CLASS = "opacity-0";
|
|
18
|
+
const BUTTON_LOADING_OVERLAY_CLASS =
|
|
19
|
+
"pointer-events-none absolute inset-0 inline-flex items-center justify-center";
|
|
20
|
+
|
|
21
|
+
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
22
|
+
asChild?: boolean;
|
|
23
|
+
loading?: boolean;
|
|
24
|
+
tone?:
|
|
25
|
+
| "default"
|
|
26
|
+
| "destructive"
|
|
27
|
+
| "outline"
|
|
28
|
+
| "secondary"
|
|
29
|
+
| "ghost"
|
|
30
|
+
| "warning";
|
|
31
|
+
size?: "default" | "icon" | "iconPill" | "lg" | "pill" | "sm";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const BUTTON_BASE_CLASS =
|
|
35
|
+
"inline-flex min-h-11 items-center justify-center gap-2 rounded-xl border font-semibold outline-none transition-colors focus-visible:ring-2 focus-visible:ring-af-focus-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:border-outline disabled:bg-surface-container-low disabled:text-on-surface-disabled";
|
|
36
|
+
const BUTTON_TONE_CLASS: Record<NonNullable<ButtonProps["tone"]>, string> = {
|
|
37
|
+
default:
|
|
38
|
+
"border-primary bg-primary text-on-primary hover:border-on-primary-container hover:bg-on-primary-container",
|
|
39
|
+
destructive:
|
|
40
|
+
"border-error bg-error text-on-error hover:border-af-danger-hover hover:bg-af-danger-hover",
|
|
41
|
+
ghost:
|
|
42
|
+
"border-transparent bg-transparent text-on-surface-variant hover:bg-af-overlay hover:text-on-surface",
|
|
43
|
+
outline:
|
|
44
|
+
"border-outline bg-surface-container-high text-on-surface hover:border-outline-variant hover:bg-af-overlay",
|
|
45
|
+
secondary:
|
|
46
|
+
"border-outline-variant bg-surface-container-low text-primary hover:border-primary hover:bg-af-overlay",
|
|
47
|
+
warning:
|
|
48
|
+
"border-af-warning-border bg-warning-container text-on-warning-container hover:border-af-warning-border hover:bg-warning-container hover:text-on-warning-container",
|
|
49
|
+
};
|
|
50
|
+
const BUTTON_SIZE_CLASS: Record<NonNullable<ButtonProps["size"]>, string> = {
|
|
51
|
+
default: "px-4 py-2.5 text-sm",
|
|
52
|
+
icon: "h-11 w-11 px-0 py-0",
|
|
53
|
+
iconPill: "h-10 min-h-10 w-10 rounded-full px-0 py-0",
|
|
54
|
+
lg: "px-5 py-3 text-base",
|
|
55
|
+
pill: "min-h-9 rounded-full px-3 py-2 text-xs",
|
|
56
|
+
sm: "min-h-9 rounded-lg px-3 py-2 text-xs",
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const buttonVariants = ({
|
|
60
|
+
className,
|
|
61
|
+
size = "default",
|
|
62
|
+
tone = "default",
|
|
63
|
+
}: Pick<ButtonProps, "className" | "size" | "tone">) =>
|
|
64
|
+
cn(
|
|
65
|
+
BUTTON_BASE_CLASS,
|
|
66
|
+
BUTTON_TONE_CLASS[tone],
|
|
67
|
+
BUTTON_SIZE_CLASS[size],
|
|
68
|
+
className,
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
function ButtonLoadingSpinner() {
|
|
72
|
+
return (
|
|
73
|
+
<svg
|
|
74
|
+
aria-hidden="true"
|
|
75
|
+
className="size-4 animate-spin"
|
|
76
|
+
fill="none"
|
|
77
|
+
focusable="false"
|
|
78
|
+
viewBox="0 0 16 16"
|
|
79
|
+
>
|
|
80
|
+
<circle
|
|
81
|
+
className="text-on-surface-disabled"
|
|
82
|
+
cx="8"
|
|
83
|
+
cy="8"
|
|
84
|
+
r="6"
|
|
85
|
+
stroke="currentColor"
|
|
86
|
+
strokeWidth="1.5"
|
|
87
|
+
/>
|
|
88
|
+
<path
|
|
89
|
+
d="M8 2a6 6 0 0 1 6 6"
|
|
90
|
+
stroke="currentColor"
|
|
91
|
+
strokeLinecap="round"
|
|
92
|
+
strokeWidth="1.5"
|
|
93
|
+
/>
|
|
94
|
+
</svg>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function renderButtonContent(
|
|
99
|
+
children: ReactNode,
|
|
100
|
+
loading: boolean,
|
|
101
|
+
): ReactNode {
|
|
102
|
+
if (!loading) {
|
|
103
|
+
return children;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<>
|
|
108
|
+
<span
|
|
109
|
+
className={cn(
|
|
110
|
+
BUTTON_LOADING_CONTENT_CLASS,
|
|
111
|
+
BUTTON_LOADING_HIDDEN_CONTENT_CLASS,
|
|
112
|
+
)}
|
|
113
|
+
>
|
|
114
|
+
{children}
|
|
115
|
+
</span>
|
|
116
|
+
<span aria-hidden="true" className={BUTTON_LOADING_OVERLAY_CLASS}>
|
|
117
|
+
<ButtonLoadingSpinner />
|
|
118
|
+
</span>
|
|
119
|
+
</>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function suppressSlottedActivation(event: KeyboardEvent | MouseEvent): void {
|
|
124
|
+
event.preventDefault();
|
|
125
|
+
const nativeEvent = event.nativeEvent;
|
|
126
|
+
if (typeof nativeEvent.stopImmediatePropagation === "function") {
|
|
127
|
+
nativeEvent.stopImmediatePropagation();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
event.stopPropagation();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function shouldSuppressSlottedKeyboardActivation(
|
|
134
|
+
event: KeyboardEvent,
|
|
135
|
+
): boolean {
|
|
136
|
+
return event.key === "Enter" || event.key === " ";
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
type SlottedChildProps = {
|
|
140
|
+
"aria-busy"?: boolean | "true" | "false";
|
|
141
|
+
"aria-disabled"?: boolean | "true" | "false";
|
|
142
|
+
className?: string;
|
|
143
|
+
href?: string;
|
|
144
|
+
onClick?: (event: MouseEvent<HTMLElement>) => void;
|
|
145
|
+
onKeyDown?: (event: KeyboardEvent<HTMLElement>) => void;
|
|
146
|
+
ref?: Ref<HTMLElement>;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
function mergeRefs<T>(...refs: Array<Ref<T> | undefined>): Ref<T> {
|
|
150
|
+
return (value) => {
|
|
151
|
+
for (const ref of refs) {
|
|
152
|
+
if (typeof ref === "function") {
|
|
153
|
+
ref(value);
|
|
154
|
+
} else if (ref && typeof ref === "object") {
|
|
155
|
+
ref.current = value;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function renderBlockedAsChildButton(
|
|
162
|
+
{
|
|
163
|
+
children,
|
|
164
|
+
className,
|
|
165
|
+
loading,
|
|
166
|
+
props,
|
|
167
|
+
ref,
|
|
168
|
+
size,
|
|
169
|
+
tone,
|
|
170
|
+
}: {
|
|
171
|
+
children: ReactNode;
|
|
172
|
+
className?: string;
|
|
173
|
+
loading: boolean;
|
|
174
|
+
props: Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children">;
|
|
175
|
+
ref: Ref<HTMLButtonElement>;
|
|
176
|
+
size: NonNullable<ButtonProps["size"]>;
|
|
177
|
+
tone: NonNullable<ButtonProps["tone"]>;
|
|
178
|
+
},
|
|
179
|
+
) {
|
|
180
|
+
const child = Children.only(children);
|
|
181
|
+
if (!isValidElement<SlottedChildProps>(child)) {
|
|
182
|
+
throw new Error("Button with asChild requires a single React element child.");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return cloneElement(child, {
|
|
186
|
+
...props,
|
|
187
|
+
"aria-busy": loading || undefined,
|
|
188
|
+
"aria-disabled": true,
|
|
189
|
+
className: buttonVariants({
|
|
190
|
+
className: cn("pointer-events-none", className, child.props.className),
|
|
191
|
+
size,
|
|
192
|
+
tone,
|
|
193
|
+
}),
|
|
194
|
+
href: undefined,
|
|
195
|
+
onClick: suppressSlottedActivation,
|
|
196
|
+
onKeyDown: (event: KeyboardEvent<HTMLElement>) => {
|
|
197
|
+
if (shouldSuppressSlottedKeyboardActivation(event)) {
|
|
198
|
+
suppressSlottedActivation(event);
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
ref: mergeRefs(ref, child.props.ref),
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
206
|
+
function Button(
|
|
207
|
+
{
|
|
208
|
+
asChild = false,
|
|
209
|
+
children,
|
|
210
|
+
className,
|
|
211
|
+
disabled,
|
|
212
|
+
loading = false,
|
|
213
|
+
onClick,
|
|
214
|
+
onKeyDown,
|
|
215
|
+
size = "default",
|
|
216
|
+
tone = "default",
|
|
217
|
+
type = "button",
|
|
218
|
+
...props
|
|
219
|
+
},
|
|
220
|
+
ref,
|
|
221
|
+
) {
|
|
222
|
+
const isInteractionBlocked = disabled || loading;
|
|
223
|
+
const showLoadingOverlay = loading && !asChild;
|
|
224
|
+
|
|
225
|
+
if (asChild && isInteractionBlocked) {
|
|
226
|
+
return renderBlockedAsChildButton({
|
|
227
|
+
children,
|
|
228
|
+
className,
|
|
229
|
+
loading,
|
|
230
|
+
props,
|
|
231
|
+
ref,
|
|
232
|
+
size,
|
|
233
|
+
tone,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const Component = asChild ? Slot : "button";
|
|
238
|
+
|
|
239
|
+
return (
|
|
240
|
+
<Component
|
|
241
|
+
aria-busy={loading || undefined}
|
|
242
|
+
className={buttonVariants({
|
|
243
|
+
className: cn(showLoadingOverlay && "relative", className),
|
|
244
|
+
size,
|
|
245
|
+
tone,
|
|
246
|
+
})}
|
|
247
|
+
disabled={asChild ? undefined : isInteractionBlocked}
|
|
248
|
+
onClick={onClick}
|
|
249
|
+
onKeyDown={onKeyDown}
|
|
250
|
+
ref={ref}
|
|
251
|
+
{...(!asChild ? { type } : undefined)}
|
|
252
|
+
{...props}
|
|
253
|
+
>
|
|
254
|
+
{renderButtonContent(children, showLoadingOverlay)}
|
|
255
|
+
</Component>
|
|
256
|
+
);
|
|
257
|
+
},
|
|
258
|
+
);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../utilities/cn";
|
|
4
|
+
import { Button, type ButtonProps } from "./button";
|
|
5
|
+
|
|
6
|
+
const ICON_BUTTON_SHELL_BASE_CLASS = "relative shrink-0";
|
|
7
|
+
const ICON_BUTTON_SHELL_SIZE_CLASS = "h-10 w-10 rounded-lg";
|
|
8
|
+
const ICON_BUTTON_SHELL_TONE_CLASS = {
|
|
9
|
+
dangerGhost:
|
|
10
|
+
"text-on-surface-subtle hover:border-af-danger-border hover:bg-error-container hover:text-on-error-container",
|
|
11
|
+
} as const;
|
|
12
|
+
|
|
13
|
+
type IconButtonShellTone =
|
|
14
|
+
| ButtonProps["tone"]
|
|
15
|
+
| keyof typeof ICON_BUTTON_SHELL_TONE_CLASS;
|
|
16
|
+
|
|
17
|
+
export interface IconButtonShellProps
|
|
18
|
+
extends Omit<ButtonProps, "size" | "tone"> {
|
|
19
|
+
tone?: IconButtonShellTone;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const IconButtonShell = forwardRef<
|
|
23
|
+
HTMLButtonElement,
|
|
24
|
+
IconButtonShellProps
|
|
25
|
+
>(function IconButtonShell(
|
|
26
|
+
{ className, tone = "outline", ...props },
|
|
27
|
+
ref,
|
|
28
|
+
) {
|
|
29
|
+
const buttonTone = tone === "dangerGhost" ? "ghost" : tone;
|
|
30
|
+
const toneClassName =
|
|
31
|
+
tone === "dangerGhost"
|
|
32
|
+
? ICON_BUTTON_SHELL_TONE_CLASS.dangerGhost
|
|
33
|
+
: undefined;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Button
|
|
37
|
+
className={cn(
|
|
38
|
+
ICON_BUTTON_SHELL_BASE_CLASS,
|
|
39
|
+
ICON_BUTTON_SHELL_SIZE_CLASS,
|
|
40
|
+
toneClassName,
|
|
41
|
+
className,
|
|
42
|
+
)}
|
|
43
|
+
ref={ref}
|
|
44
|
+
size="icon"
|
|
45
|
+
tone={buttonTone}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Stable category path for `@you-agent-factory/components/primitives`. */
|
|
2
|
+
export const COMPONENTS_CATEGORY = "primitives" as const;
|
|
3
|
+
|
|
4
|
+
export type ComponentsCategory = typeof COMPONENTS_CATEGORY;
|
|
5
|
+
|
|
6
|
+
export { Button, buttonVariants } from "./button";
|
|
7
|
+
export type { ButtonProps } from "./button";
|
|
8
|
+
export { ButtonLink } from "./button-link";
|
|
9
|
+
export type { ButtonLinkProps } from "./button-link";
|
|
10
|
+
export { IconButtonShell } from "./icon-button-shell";
|
|
11
|
+
export type { IconButtonShellProps } from "./icon-button-shell";
|
|
12
|
+
export { PackageText } from "./package-text";
|
|
13
|
+
export type { PackageTextProps, PackageTextVariant } from "./package-text";
|
|
14
|
+
|
|
15
|
+
export { Code, Heading, Label, Text } from "./typography";
|
|
16
|
+
export type { CodeProps, HeadingProps, LabelProps, TextProps, TextVariant } from "./typography";
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
BODY_CODE_CLASS,
|
|
20
|
+
BODY_TEXT_CLASS,
|
|
21
|
+
CAPTION_TEXT_CLASS,
|
|
22
|
+
DENSE_BODY_TEXT_CLASS,
|
|
23
|
+
MUTED_TEXT_CLASS,
|
|
24
|
+
PAGE_HEADING_CLASS,
|
|
25
|
+
SECTION_HEADING_CLASS,
|
|
26
|
+
SUPPORTING_CODE_CLASS,
|
|
27
|
+
SUPPORTING_LABEL_CLASS,
|
|
28
|
+
SUPPORTING_TEXT_CLASS,
|
|
29
|
+
TEXT_TRUNCATE_CLASS,
|
|
30
|
+
TEXT_WRAP_CLASS,
|
|
31
|
+
} from "./typography-roles";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../utilities/cn";
|
|
4
|
+
|
|
5
|
+
export type PackageTextVariant = "body" | "title";
|
|
6
|
+
|
|
7
|
+
export type PackageTextProps = ComponentPropsWithoutRef<"p"> & {
|
|
8
|
+
variant?: PackageTextVariant;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function PackageText({
|
|
12
|
+
children,
|
|
13
|
+
className,
|
|
14
|
+
variant = "body",
|
|
15
|
+
...props
|
|
16
|
+
}: PackageTextProps) {
|
|
17
|
+
return (
|
|
18
|
+
<p
|
|
19
|
+
className={cn(
|
|
20
|
+
variant === "title" ? "text-title-large" : "text-body-medium",
|
|
21
|
+
"text-on-surface",
|
|
22
|
+
className,
|
|
23
|
+
)}
|
|
24
|
+
{...props}
|
|
25
|
+
>
|
|
26
|
+
{children}
|
|
27
|
+
</p>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const PAGE_HEADING_CLASS = "af-page-heading";
|
|
2
|
+
export const SECTION_HEADING_CLASS = "af-section-heading";
|
|
3
|
+
export const BODY_TEXT_CLASS = "af-body-text";
|
|
4
|
+
export const SUPPORTING_TEXT_CLASS = "af-supporting-text";
|
|
5
|
+
export const MUTED_TEXT_CLASS = "af-muted-text";
|
|
6
|
+
export const CAPTION_TEXT_CLASS = "af-caption-text";
|
|
7
|
+
export const DENSE_BODY_TEXT_CLASS = "af-dense-body-text";
|
|
8
|
+
export const SUPPORTING_LABEL_CLASS = "af-supporting-label";
|
|
9
|
+
export const BODY_CODE_CLASS = "af-body-code";
|
|
10
|
+
export const SUPPORTING_CODE_CLASS = "af-supporting-code";
|
|
11
|
+
export const TEXT_TRUNCATE_CLASS = "af-text-truncate";
|
|
12
|
+
export const TEXT_WRAP_CLASS = "af-text-wrap";
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ElementType,
|
|
3
|
+
forwardRef,
|
|
4
|
+
type HTMLAttributes,
|
|
5
|
+
type ReactNode,
|
|
6
|
+
} from "react";
|
|
7
|
+
|
|
8
|
+
import { cn } from "../utilities/cn";
|
|
9
|
+
import {
|
|
10
|
+
BODY_CODE_CLASS,
|
|
11
|
+
BODY_TEXT_CLASS,
|
|
12
|
+
CAPTION_TEXT_CLASS,
|
|
13
|
+
DENSE_BODY_TEXT_CLASS,
|
|
14
|
+
MUTED_TEXT_CLASS,
|
|
15
|
+
PAGE_HEADING_CLASS,
|
|
16
|
+
SECTION_HEADING_CLASS,
|
|
17
|
+
SUPPORTING_CODE_CLASS,
|
|
18
|
+
SUPPORTING_LABEL_CLASS,
|
|
19
|
+
SUPPORTING_TEXT_CLASS,
|
|
20
|
+
TEXT_TRUNCATE_CLASS,
|
|
21
|
+
TEXT_WRAP_CLASS,
|
|
22
|
+
} from "./typography-roles";
|
|
23
|
+
|
|
24
|
+
type TypographyElementProps = HTMLAttributes<HTMLElement> & {
|
|
25
|
+
as?: ElementType;
|
|
26
|
+
children?: ReactNode;
|
|
27
|
+
dateTime?: string;
|
|
28
|
+
htmlFor?: string;
|
|
29
|
+
type?: "button" | "reset" | "submit";
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
type TypographyOverflowProps = {
|
|
33
|
+
truncate?: boolean;
|
|
34
|
+
wrap?: boolean;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function typographyOverflowClass({
|
|
38
|
+
truncate,
|
|
39
|
+
wrap,
|
|
40
|
+
}: TypographyOverflowProps): string | undefined {
|
|
41
|
+
if (truncate) {
|
|
42
|
+
return TEXT_TRUNCATE_CLASS;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (wrap) {
|
|
46
|
+
return TEXT_WRAP_CLASS;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const TEXT_VARIANT_CLASS = {
|
|
53
|
+
body: BODY_TEXT_CLASS,
|
|
54
|
+
supporting: SUPPORTING_TEXT_CLASS,
|
|
55
|
+
muted: MUTED_TEXT_CLASS,
|
|
56
|
+
caption: CAPTION_TEXT_CLASS,
|
|
57
|
+
dense: DENSE_BODY_TEXT_CLASS,
|
|
58
|
+
} as const;
|
|
59
|
+
|
|
60
|
+
export type TextVariant = keyof typeof TEXT_VARIANT_CLASS;
|
|
61
|
+
|
|
62
|
+
export interface TextProps
|
|
63
|
+
extends TypographyElementProps,
|
|
64
|
+
TypographyOverflowProps {
|
|
65
|
+
variant?: TextVariant;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const Text = forwardRef<HTMLElement, TextProps>(function Text(
|
|
69
|
+
{
|
|
70
|
+
as: Component = "p",
|
|
71
|
+
children,
|
|
72
|
+
className,
|
|
73
|
+
truncate,
|
|
74
|
+
variant = "body",
|
|
75
|
+
wrap,
|
|
76
|
+
...props
|
|
77
|
+
},
|
|
78
|
+
ref,
|
|
79
|
+
) {
|
|
80
|
+
return (
|
|
81
|
+
<Component
|
|
82
|
+
className={cn(
|
|
83
|
+
TEXT_VARIANT_CLASS[variant],
|
|
84
|
+
typographyOverflowClass({ truncate, wrap }),
|
|
85
|
+
className,
|
|
86
|
+
)}
|
|
87
|
+
ref={ref}
|
|
88
|
+
{...props}
|
|
89
|
+
>
|
|
90
|
+
{children}
|
|
91
|
+
</Component>
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
export interface HeadingProps
|
|
96
|
+
extends TypographyElementProps,
|
|
97
|
+
TypographyOverflowProps {
|
|
98
|
+
level?: "page" | "section";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const Heading = forwardRef<HTMLElement, HeadingProps>(function Heading(
|
|
102
|
+
{ as, children, className, level = "section", truncate, wrap, ...props },
|
|
103
|
+
ref,
|
|
104
|
+
) {
|
|
105
|
+
const Component = as ?? (level === "page" ? "h1" : "h3");
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<Component
|
|
109
|
+
className={cn(
|
|
110
|
+
level === "page" ? PAGE_HEADING_CLASS : SECTION_HEADING_CLASS,
|
|
111
|
+
typographyOverflowClass({ truncate, wrap }),
|
|
112
|
+
className,
|
|
113
|
+
)}
|
|
114
|
+
ref={ref}
|
|
115
|
+
{...props}
|
|
116
|
+
>
|
|
117
|
+
{children}
|
|
118
|
+
</Component>
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
export interface LabelProps
|
|
123
|
+
extends TypographyElementProps,
|
|
124
|
+
TypographyOverflowProps {}
|
|
125
|
+
|
|
126
|
+
export const Label = forwardRef<HTMLElement, LabelProps>(function Label(
|
|
127
|
+
{ as: Component = "span", children, className, truncate, wrap, ...props },
|
|
128
|
+
ref,
|
|
129
|
+
) {
|
|
130
|
+
return (
|
|
131
|
+
<Component
|
|
132
|
+
className={cn(
|
|
133
|
+
SUPPORTING_LABEL_CLASS,
|
|
134
|
+
typographyOverflowClass({ truncate, wrap }),
|
|
135
|
+
className,
|
|
136
|
+
)}
|
|
137
|
+
ref={ref}
|
|
138
|
+
{...props}
|
|
139
|
+
>
|
|
140
|
+
{children}
|
|
141
|
+
</Component>
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
export interface CodeProps extends TypographyElementProps {
|
|
146
|
+
size?: "body" | "supporting";
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export const Code = forwardRef<HTMLElement, CodeProps>(function Code(
|
|
150
|
+
{ as: Component = "code", children, className, size = "body", ...props },
|
|
151
|
+
ref,
|
|
152
|
+
) {
|
|
153
|
+
return (
|
|
154
|
+
<Component
|
|
155
|
+
className={cn(
|
|
156
|
+
size === "body" ? BODY_CODE_CLASS : SUPPORTING_CODE_CLASS,
|
|
157
|
+
className,
|
|
158
|
+
)}
|
|
159
|
+
ref={ref}
|
|
160
|
+
{...props}
|
|
161
|
+
>
|
|
162
|
+
{children}
|
|
163
|
+
</Component>
|
|
164
|
+
);
|
|
165
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/** Stable category path for `@you-agent-factory/components/recipes`. */
|
|
2
|
+
export const COMPONENTS_CATEGORY = "recipes" as const;
|
|
3
|
+
|
|
4
|
+
export type ComponentsCategory = typeof COMPONENTS_CATEGORY;
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
WidgetFrameDisclosure,
|
|
8
|
+
WidgetFrameDisclosureIcon,
|
|
9
|
+
WidgetFrameDisclosurePanel,
|
|
10
|
+
WidgetFrameDisclosureTrigger,
|
|
11
|
+
} from "./widget-frame-disclosure";
|
|
12
|
+
export type {
|
|
13
|
+
WidgetFrameDisclosureIconProps,
|
|
14
|
+
WidgetFrameDisclosurePanelProps,
|
|
15
|
+
WidgetFrameDisclosureProps,
|
|
16
|
+
WidgetFrameDisclosureTriggerProps,
|
|
17
|
+
} from "./widget-frame-disclosure";
|
|
18
|
+
export {
|
|
19
|
+
WidgetDetailCopy,
|
|
20
|
+
WidgetEmptyState,
|
|
21
|
+
WidgetEmptyStateText,
|
|
22
|
+
WidgetEmptyStateTitle,
|
|
23
|
+
WidgetSubtitle,
|
|
24
|
+
} from "./widget-frame-content";
|
|
25
|
+
export type {
|
|
26
|
+
WidgetDetailCopyProps,
|
|
27
|
+
WidgetEmptyStateProps,
|
|
28
|
+
WidgetEmptyStateTextProps,
|
|
29
|
+
WidgetEmptyStateTitleProps,
|
|
30
|
+
WidgetSubtitleProps,
|
|
31
|
+
} from "./widget-frame-content";
|
|
32
|
+
export { WidgetFrameSkeleton } from "./widget-frame-skeleton";
|
|
33
|
+
export {
|
|
34
|
+
WidgetErrorState,
|
|
35
|
+
WidgetLoadingState,
|
|
36
|
+
WidgetSuccessState,
|
|
37
|
+
} from "./widget-frame-states";
|
|
38
|
+
export type {
|
|
39
|
+
WidgetErrorStateProps,
|
|
40
|
+
WidgetLoadingStateProps,
|
|
41
|
+
WidgetSuccessStateProps,
|
|
42
|
+
} from "./widget-frame-states";
|
|
43
|
+
export {
|
|
44
|
+
WIDGET_FRAME_MIN_WIDTH_CLASS,
|
|
45
|
+
WIDGET_FRAME_OVERFLOW_TOLERANCE_PX,
|
|
46
|
+
WIDGET_FRAME_RESPONSIVE_SHELL_CLASS,
|
|
47
|
+
WIDGET_FRAME_STORY_SHELL_DATA_ATTR,
|
|
48
|
+
WIDGET_FRAME_WIDE_BODY_CLASS,
|
|
49
|
+
widgetFrameDetailCardClass,
|
|
50
|
+
widgetFrameHasNoHorizontalOverflow,
|
|
51
|
+
widgetFrameStoryShellStyle,
|
|
52
|
+
} from "./widget-frame-layout";
|
|
53
|
+
export { WidgetFrame } from "./widget-frame";
|
|
54
|
+
export type { WidgetFrameProps } from "./widget-frame";
|
|
55
|
+
export {
|
|
56
|
+
WIDGET_FRAME_BODY_TEXT_CLASS,
|
|
57
|
+
WIDGET_FRAME_SECTION_HEADING_CLASS,
|
|
58
|
+
WIDGET_FRAME_SUBTITLE_CLASS,
|
|
59
|
+
WIDGET_FRAME_SUPPORTING_LABEL_CLASS,
|
|
60
|
+
WIDGET_FRAME_SUPPORTING_LABELS_CLASS,
|
|
61
|
+
} from "./widget-frame-typography";
|