@godxjp/ui 0.2.0 → 2.1.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.
@@ -0,0 +1,266 @@
1
+ import { ClassValue } from 'clsx';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+ import * as react from 'react';
4
+ import { ComponentProps, ReactNode, TextareaHTMLAttributes, HTMLAttributes } from 'react';
5
+ import * as LabelPrimitive from '@radix-ui/react-label';
6
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
7
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
8
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
9
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
10
+ import { DayPickerProps } from 'react-day-picker';
11
+
12
+ declare function cn(...inputs: ClassValue[]): string;
13
+
14
+ /**
15
+ * Badge — status pill with a colored dot + label.
16
+ *
17
+ * Renders the canonical `.badge` class from `@godxjp/ui/tokens` so the
18
+ * visual layer is mastered in CSS (not Tailwind utilities). All six
19
+ * variants map onto a semantic role from the brand bible:
20
+ *
21
+ * - `success` — 若竹 task completed, healthy
22
+ * - `warning` — 山吹 needs attention, not yet broken
23
+ * - `info` — 群青 neutral state callout
24
+ * - `error` — 茜 failed / blocked
25
+ * - `attention`— 朱 pending, awaiting input
26
+ * - `neutral` — grey default chrome
27
+ * - `outline` — empty hairline only (rare)
28
+ *
29
+ * @example
30
+ * <Badge variant="success" dot>Healthy</Badge>
31
+ * <Badge variant="error">Failed</Badge>
32
+ */
33
+ type BadgeVariant = "success" | "warning" | "info" | "error" | "attention" | "neutral" | "outline";
34
+ interface BadgeProps extends ComponentProps<"span"> {
35
+ variant?: BadgeVariant;
36
+ /** When true renders a colored dot before the label. */
37
+ dot?: boolean;
38
+ children?: ReactNode;
39
+ }
40
+ declare function Badge({ variant, dot, className, children, ...rest }: BadgeProps): react_jsx_runtime.JSX.Element;
41
+
42
+ /**
43
+ * Button — canonical action atom.
44
+ *
45
+ * Maps onto the `.btn` family in tokens.css:
46
+ *
47
+ * primary — filled, brand color, default action
48
+ * secondary — bordered, foreground text, neutral surface
49
+ * ghost — transparent, foreground text, hover surface
50
+ * danger — destructive, --destructive bg
51
+ *
52
+ * Sizes mirror density tokens:
53
+ * sm — 28 px height (compact action bar)
54
+ * md — 32 px height (default)
55
+ * lg — 36 px height (page hero CTA)
56
+ *
57
+ * Supports `asChild` (Radix Slot pattern) so the button styles can wrap
58
+ * a Link or any other element without nesting:
59
+ *
60
+ * @example
61
+ * <Button variant="primary">Save</Button>
62
+ * <Button asChild variant="ghost"><a href="/docs">Docs</a></Button>
63
+ */
64
+ type ButtonVariant = "primary" | "secondary" | "ghost" | "danger";
65
+ type ButtonSize = "sm" | "md" | "lg";
66
+ interface ButtonProps extends ComponentProps<"button"> {
67
+ variant?: ButtonVariant;
68
+ size?: ButtonSize;
69
+ asChild?: boolean;
70
+ children?: ReactNode;
71
+ }
72
+ declare function Button({ variant, size, asChild, className, type, children, ...rest }: ButtonProps): react_jsx_runtime.JSX.Element;
73
+
74
+ /**
75
+ * Card — surface container for grouped content.
76
+ *
77
+ * The atom hierarchy mirrors the `.card`/`.card-header`/`.card-title`
78
+ * classes in tokens.css. Compose as:
79
+ *
80
+ * <Card>
81
+ * <CardHeader>
82
+ * <CardTitle>Pull requests</CardTitle>
83
+ * <CardSubtitle>Open / merged this week</CardSubtitle>
84
+ * </CardHeader>
85
+ * <CardContent>...</CardContent>
86
+ * </Card>
87
+ */
88
+ declare function Card({ className, ...rest }: ComponentProps<"div">): react_jsx_runtime.JSX.Element;
89
+ declare function CardHeader({ className, ...rest }: ComponentProps<"div">): react_jsx_runtime.JSX.Element;
90
+ declare function CardTitle({ className, ...rest }: ComponentProps<"h3">): react_jsx_runtime.JSX.Element;
91
+ interface CardSubtitleProps extends ComponentProps<"p"> {
92
+ children?: ReactNode;
93
+ }
94
+ declare function CardSubtitle({ className, ...rest }: CardSubtitleProps): react_jsx_runtime.JSX.Element;
95
+ declare function CardContent({ className, ...rest }: ComponentProps<"div">): react_jsx_runtime.JSX.Element;
96
+
97
+ /**
98
+ * Input — text input atom. Maps to `.input` in tokens.css.
99
+ *
100
+ * Forward-ref so consumers can wire `react-hook-form` / focus
101
+ * management without escaping the design tokens.
102
+ */
103
+ interface InputProps extends ComponentProps<"input"> {
104
+ }
105
+ declare const Input: react.ForwardRefExoticComponent<Omit<InputProps, "ref"> & react.RefAttributes<HTMLInputElement>>;
106
+ /** Textarea — uses `.input` for shape, leaves height auto. */
107
+ interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
108
+ }
109
+ declare const Textarea: react.ForwardRefExoticComponent<TextareaProps & react.RefAttributes<HTMLTextAreaElement>>;
110
+
111
+ /**
112
+ * Label — form-field label. Wraps Radix Label so `htmlFor` /
113
+ * click-to-focus works out of the box. Maps to `.label` in tokens.css.
114
+ *
115
+ * Pair with <Input /> + an optional `.help` paragraph:
116
+ *
117
+ * <Label htmlFor="name">Display name</Label>
118
+ * <Input id="name" />
119
+ * <p className="help">Visible to teammates.</p>
120
+ */
121
+ declare const Label: react.ForwardRefExoticComponent<Omit<LabelPrimitive.LabelProps & react.RefAttributes<HTMLLabelElement>, "ref"> & react.RefAttributes<HTMLLabelElement>>;
122
+
123
+ /**
124
+ * Tabs — Radix-backed tab strip styled with the canonical `.tabs` /
125
+ * `.tab` CSS from tokens.css. Keyboard navigation + ARIA come from
126
+ * Radix; the visual contract stays in the design tokens.
127
+ *
128
+ * @example
129
+ * <Tabs defaultValue="open">
130
+ * <TabsList>
131
+ * <TabsTrigger value="open">Open</TabsTrigger>
132
+ * <TabsTrigger value="closed">Closed</TabsTrigger>
133
+ * </TabsList>
134
+ * <TabsContent value="open">...</TabsContent>
135
+ * <TabsContent value="closed">...</TabsContent>
136
+ * </Tabs>
137
+ */
138
+ declare const Tabs: react.ForwardRefExoticComponent<TabsPrimitive.TabsProps & react.RefAttributes<HTMLDivElement>>;
139
+ declare const TabsList: react.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsListProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
140
+ declare const TabsTrigger: react.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsTriggerProps & react.RefAttributes<HTMLButtonElement>, "ref"> & react.RefAttributes<HTMLButtonElement>>;
141
+ declare const TabsContent: react.ForwardRefExoticComponent<TabsPrimitive.TabsContentProps & react.RefAttributes<HTMLDivElement>>;
142
+
143
+ /**
144
+ * Avatar — round chip with initials or an image. Maps to `.avatar`
145
+ * + `.avatar.brand` in tokens.css.
146
+ *
147
+ * @example
148
+ * <Avatar>PT</Avatar>
149
+ * <Avatar variant="brand">G</Avatar>
150
+ */
151
+ interface AvatarProps extends ComponentProps<"span"> {
152
+ variant?: "default" | "brand";
153
+ /** Optional image url; falls back to children (initials) when missing. */
154
+ src?: string;
155
+ alt?: string;
156
+ }
157
+ declare function Avatar({ variant, src, alt, className, children, ...rest }: AvatarProps): react_jsx_runtime.JSX.Element;
158
+
159
+ /**
160
+ * Separator — horizontal / vertical divider. Wraps Radix Separator for
161
+ * ARIA + decorative semantics. Maps to `.divider` styling in tokens.css
162
+ * (1px border, theme-aware color).
163
+ */
164
+ declare const Separator: react.ForwardRefExoticComponent<Omit<SeparatorPrimitive.SeparatorProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
165
+
166
+ /**
167
+ * Popover — Radix-backed floating panel anchored to a trigger element.
168
+ * Styled with the canonical `.popover-content` class from tokens.css
169
+ * so the visual contract stays in the design tokens.
170
+ *
171
+ * @example
172
+ * <Popover>
173
+ * <PopoverTrigger asChild>
174
+ * <Button variant="ghost">Open</Button>
175
+ * </PopoverTrigger>
176
+ * <PopoverContent>…body…</PopoverContent>
177
+ * </Popover>
178
+ */
179
+ declare const Popover: react.FC<PopoverPrimitive.PopoverProps>;
180
+ declare const PopoverTrigger: react.ForwardRefExoticComponent<PopoverPrimitive.PopoverTriggerProps & react.RefAttributes<HTMLButtonElement>>;
181
+ declare const PopoverAnchor: react.ForwardRefExoticComponent<PopoverPrimitive.PopoverAnchorProps & react.RefAttributes<HTMLDivElement>>;
182
+ declare const PopoverContent: react.ForwardRefExoticComponent<Omit<PopoverPrimitive.PopoverContentProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
183
+
184
+ /**
185
+ * DropdownMenu — Radix-backed action menu opened from a trigger
186
+ * (kebab, caret, button…). Styled via canonical `.dropdown-menu-*`
187
+ * classes from tokens.css.
188
+ *
189
+ * Items support `variant="destructive"` for dangerous actions and
190
+ * `inset` for left-padding alignment when icons aren't on every row.
191
+ *
192
+ * @example
193
+ * <DropdownMenu>
194
+ * <DropdownMenuTrigger asChild>
195
+ * <Button variant="ghost"><MoreVertical /></Button>
196
+ * </DropdownMenuTrigger>
197
+ * <DropdownMenuContent align="end">
198
+ * <DropdownMenuItem onSelect={onEdit}>Edit</DropdownMenuItem>
199
+ * <DropdownMenuSeparator />
200
+ * <DropdownMenuItem variant="destructive" onSelect={onDelete}>
201
+ * Delete
202
+ * </DropdownMenuItem>
203
+ * </DropdownMenuContent>
204
+ * </DropdownMenu>
205
+ */
206
+ declare const DropdownMenu: react.FC<DropdownMenuPrimitive.DropdownMenuProps>;
207
+ declare const DropdownMenuTrigger: react.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuTriggerProps & react.RefAttributes<HTMLButtonElement>>;
208
+ declare const DropdownMenuGroup: react.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuGroupProps & react.RefAttributes<HTMLDivElement>>;
209
+ declare const DropdownMenuPortal: react.FC<DropdownMenuPrimitive.DropdownMenuPortalProps>;
210
+ declare const DropdownMenuSub: react.FC<DropdownMenuPrimitive.DropdownMenuSubProps>;
211
+ declare const DropdownMenuRadioGroup: react.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuRadioGroupProps & react.RefAttributes<HTMLDivElement>>;
212
+ declare const DropdownMenuContent: react.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuContentProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
213
+ declare const DropdownMenuItem: react.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuItemProps & react.RefAttributes<HTMLDivElement>, "ref"> & {
214
+ inset?: boolean;
215
+ variant?: "default" | "destructive";
216
+ } & react.RefAttributes<HTMLDivElement>>;
217
+ declare const DropdownMenuSeparator: react.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuSeparatorProps & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
218
+ declare const DropdownMenuLabel: react.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuLabelProps & react.RefAttributes<HTMLDivElement>, "ref"> & {
219
+ inset?: boolean;
220
+ } & react.RefAttributes<HTMLDivElement>>;
221
+ declare function DropdownMenuShortcut({ className, ...rest }: HTMLAttributes<HTMLSpanElement>): react_jsx_runtime.JSX.Element;
222
+
223
+ /**
224
+ * Calendar — react-day-picker grid themed with brand tokens via the
225
+ * canonical `.calendar` class from tokens.css. Caller controls
226
+ * mode/selected/onSelect through DayPicker's standard props.
227
+ *
228
+ * Locale + week-start are inherited from i18next / browser by default;
229
+ * pass DayPickerProps explicitly to override (e.g. `weekStartsOn={1}`
230
+ * for Monday-first).
231
+ *
232
+ * @example
233
+ * const [date, setDate] = useState<Date>()
234
+ * <Calendar mode="single" selected={date} onSelect={setDate} />
235
+ */
236
+ declare function Calendar({ className, showOutsideDays, ...rest }: DayPickerProps): react_jsx_runtime.JSX.Element;
237
+
238
+ interface TimeInputProps {
239
+ /** Current time value in `"HH:mm"` (24-hour) format. */
240
+ value?: string;
241
+ /** Fired on blur with the validated `"HH:mm"` string. */
242
+ onChange?: (time: string) => void;
243
+ /** Additional class name applied to the input element. */
244
+ className?: string;
245
+ /** Disable input + propagate aria-disabled. */
246
+ disabled?: boolean;
247
+ /** Optional placeholder (defaults to "HH:mm"). */
248
+ placeholder?: string;
249
+ /** Optional id used for label association. */
250
+ id?: string;
251
+ /** Optional name used in form submissions. */
252
+ name?: string;
253
+ }
254
+ /**
255
+ * TimeInput — narrow text input for HH:mm (24-hour) values.
256
+ * Mirrors the public `@godxjp/ui@0.2.0` API so call sites don't change
257
+ * when upgrading to v2. Visual contract lives in the `.time-input`
258
+ * class in tokens.css.
259
+ *
260
+ * Validation: emits `onChange` with the normalized string on blur if
261
+ * it parses, otherwise leaves the value untouched and surfaces
262
+ * `aria-invalid` so the consumer can style the error state.
263
+ */
264
+ declare const TimeInput: react.ForwardRefExoticComponent<TimeInputProps & react.RefAttributes<HTMLInputElement>>;
265
+
266
+ export { Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Calendar, Card, CardContent, CardHeader, CardSubtitle, type CardSubtitleProps, CardTitle, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuTrigger, Input, type InputProps, Label, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Separator, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, type TextareaProps, TimeInput, type TimeInputProps, cn };
@@ -0,0 +1,252 @@
1
+ import { clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+ import { Slot } from '@radix-ui/react-slot';
5
+ import { forwardRef, useState, useEffect } from 'react';
6
+ import * as LabelPrimitive from '@radix-ui/react-label';
7
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
8
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
9
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
10
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
11
+ import { DayPicker } from 'react-day-picker';
12
+ import 'react-day-picker/dist/style.css';
13
+
14
+ function cn(...inputs) {
15
+ return twMerge(clsx(inputs));
16
+ }
17
+ function Badge({
18
+ variant = "neutral",
19
+ dot = false,
20
+ className,
21
+ children,
22
+ ...rest
23
+ }) {
24
+ return /* @__PURE__ */ jsxs("span", { className: cn("badge", `badge-${variant}`, className), ...rest, children: [
25
+ dot && /* @__PURE__ */ jsx("span", { className: "dot", "aria-hidden": true }),
26
+ children
27
+ ] });
28
+ }
29
+ function Button({
30
+ variant = "primary",
31
+ size = "md",
32
+ asChild = false,
33
+ className,
34
+ type = "button",
35
+ children,
36
+ ...rest
37
+ }) {
38
+ const Component = asChild ? Slot : "button";
39
+ return /* @__PURE__ */ jsx(
40
+ Component,
41
+ {
42
+ type: asChild ? void 0 : type,
43
+ className: cn(
44
+ "btn",
45
+ `btn-${variant}`,
46
+ size === "sm" && "btn-sm",
47
+ size === "lg" && "btn-lg",
48
+ className
49
+ ),
50
+ ...rest,
51
+ children
52
+ }
53
+ );
54
+ }
55
+ function Card({ className, ...rest }) {
56
+ return /* @__PURE__ */ jsx("div", { className: cn("card", className), ...rest });
57
+ }
58
+ function CardHeader({ className, ...rest }) {
59
+ return /* @__PURE__ */ jsx("div", { className: cn("card-header", className), ...rest });
60
+ }
61
+ function CardTitle({ className, ...rest }) {
62
+ return /* @__PURE__ */ jsx("h3", { className: cn("card-title", className), ...rest });
63
+ }
64
+ function CardSubtitle({ className, ...rest }) {
65
+ return /* @__PURE__ */ jsx("p", { className: cn("card-subtitle", className), ...rest });
66
+ }
67
+ function CardContent({ className, ...rest }) {
68
+ return /* @__PURE__ */ jsx("div", { className, ...rest });
69
+ }
70
+ var Input = forwardRef(function Input2({ className, type = "text", ...rest }, ref) {
71
+ return /* @__PURE__ */ jsx("input", { ref, type, className: cn("input", className), ...rest });
72
+ });
73
+ var Textarea = forwardRef(function Textarea2({ className, ...rest }, ref) {
74
+ return /* @__PURE__ */ jsx("textarea", { ref, className: cn("input", className), ...rest });
75
+ });
76
+ var Label = forwardRef(function Label2({ className, ...rest }, ref) {
77
+ return /* @__PURE__ */ jsx(LabelPrimitive.Root, { ref, className: cn("label", className), ...rest });
78
+ });
79
+ var Tabs = TabsPrimitive.Root;
80
+ var TabsList = forwardRef(function TabsList2({ className, ...rest }, ref) {
81
+ return /* @__PURE__ */ jsx(TabsPrimitive.List, { ref, className: cn("tabs", className), ...rest });
82
+ });
83
+ var TabsTrigger = forwardRef(function TabsTrigger2({ className, ...rest }, ref) {
84
+ return /* @__PURE__ */ jsx(
85
+ TabsPrimitive.Trigger,
86
+ {
87
+ ref,
88
+ className: cn("tab", className),
89
+ ...rest,
90
+ "data-active": void 0
91
+ }
92
+ );
93
+ });
94
+ var TabsContent = TabsPrimitive.Content;
95
+ function Avatar({
96
+ variant = "default",
97
+ src,
98
+ alt,
99
+ className,
100
+ children,
101
+ ...rest
102
+ }) {
103
+ return /* @__PURE__ */ jsx("span", { className: cn("avatar", variant === "brand" && "brand", className), ...rest, children: src ? /* @__PURE__ */ jsx("img", { src, alt: alt ?? "", style: { width: "100%", height: "100%", borderRadius: "inherit", objectFit: "cover" } }) : children });
104
+ }
105
+ var Separator = forwardRef(function Separator2({ className, orientation = "horizontal", decorative = true, ...rest }, ref) {
106
+ return /* @__PURE__ */ jsx(
107
+ SeparatorPrimitive.Root,
108
+ {
109
+ ref,
110
+ orientation,
111
+ decorative,
112
+ className: cn(
113
+ orientation === "horizontal" ? "divider" : "",
114
+ className
115
+ ),
116
+ style: orientation === "vertical" ? { width: 1, height: "100%", background: "var(--border)", border: 0 } : void 0,
117
+ ...rest
118
+ }
119
+ );
120
+ });
121
+ var Popover = PopoverPrimitive.Root;
122
+ var PopoverTrigger = PopoverPrimitive.Trigger;
123
+ var PopoverAnchor = PopoverPrimitive.Anchor;
124
+ var PopoverContent = forwardRef(function PopoverContent2({ className, align = "center", sideOffset = 6, ...rest }, ref) {
125
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
126
+ PopoverPrimitive.Content,
127
+ {
128
+ ref,
129
+ align,
130
+ sideOffset,
131
+ className: cn("popover-content", className),
132
+ ...rest
133
+ }
134
+ ) });
135
+ });
136
+ var DropdownMenu = DropdownMenuPrimitive.Root;
137
+ var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
138
+ var DropdownMenuGroup = DropdownMenuPrimitive.Group;
139
+ var DropdownMenuPortal = DropdownMenuPrimitive.Portal;
140
+ var DropdownMenuSub = DropdownMenuPrimitive.Sub;
141
+ var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
142
+ var DropdownMenuContent = forwardRef(function DropdownMenuContent2({ className, sideOffset = 6, ...rest }, ref) {
143
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
144
+ DropdownMenuPrimitive.Content,
145
+ {
146
+ ref,
147
+ sideOffset,
148
+ className: cn("dropdown-menu-content", className),
149
+ ...rest
150
+ }
151
+ ) });
152
+ });
153
+ var DropdownMenuItem = forwardRef(function DropdownMenuItem2({ className, inset, variant = "default", ...rest }, ref) {
154
+ return /* @__PURE__ */ jsx(
155
+ DropdownMenuPrimitive.Item,
156
+ {
157
+ ref,
158
+ className: cn("dropdown-menu-item", className),
159
+ "data-variant": variant === "destructive" ? "destructive" : void 0,
160
+ "data-inset": inset ? "true" : void 0,
161
+ ...rest
162
+ }
163
+ );
164
+ });
165
+ var DropdownMenuSeparator = forwardRef(function DropdownMenuSeparator2({ className, ...rest }, ref) {
166
+ return /* @__PURE__ */ jsx(
167
+ DropdownMenuPrimitive.Separator,
168
+ {
169
+ ref,
170
+ className: cn("dropdown-menu-separator", className),
171
+ ...rest
172
+ }
173
+ );
174
+ });
175
+ var DropdownMenuLabel = forwardRef(function DropdownMenuLabel2({ className, inset, ...rest }, ref) {
176
+ return /* @__PURE__ */ jsx(
177
+ DropdownMenuPrimitive.Label,
178
+ {
179
+ ref,
180
+ className: cn("dropdown-menu-label", className),
181
+ "data-inset": inset ? "true" : void 0,
182
+ ...rest
183
+ }
184
+ );
185
+ });
186
+ function DropdownMenuShortcut({
187
+ className,
188
+ ...rest
189
+ }) {
190
+ return /* @__PURE__ */ jsx("span", { className: cn("dropdown-menu-shortcut", className), ...rest });
191
+ }
192
+ function Calendar({ className, showOutsideDays = true, ...rest }) {
193
+ return /* @__PURE__ */ jsx(
194
+ DayPicker,
195
+ {
196
+ showOutsideDays,
197
+ className: cn("calendar", className),
198
+ ...rest
199
+ }
200
+ );
201
+ }
202
+ var TIME_PATTERN = /^([01]\d|2[0-3]):[0-5]\d$/;
203
+ function normalize(raw) {
204
+ const cleaned = raw.trim();
205
+ if (!cleaned) return "";
206
+ if (TIME_PATTERN.test(cleaned)) return cleaned;
207
+ const digits = cleaned.replace(/[^0-9]/g, "");
208
+ if (digits.length === 3 || digits.length === 4) {
209
+ const hh = digits.slice(0, digits.length - 2).padStart(2, "0");
210
+ const mm = digits.slice(-2);
211
+ const candidate = `${hh}:${mm}`;
212
+ if (TIME_PATTERN.test(candidate)) return candidate;
213
+ }
214
+ return raw;
215
+ }
216
+ var TimeInput = forwardRef(
217
+ function TimeInput2({ value, onChange, className, disabled, placeholder = "HH:mm", id, name }, ref) {
218
+ const [draft, setDraft] = useState(value ?? "");
219
+ useEffect(() => {
220
+ setDraft(value ?? "");
221
+ }, [value]);
222
+ const invalid = draft !== "" && !TIME_PATTERN.test(draft);
223
+ return /* @__PURE__ */ jsx(
224
+ "input",
225
+ {
226
+ ref,
227
+ type: "text",
228
+ inputMode: "numeric",
229
+ autoComplete: "off",
230
+ spellCheck: false,
231
+ maxLength: 5,
232
+ id,
233
+ name,
234
+ disabled,
235
+ placeholder,
236
+ value: draft,
237
+ "aria-invalid": invalid || void 0,
238
+ className: cn("time-input", className),
239
+ onChange: (e) => setDraft(e.target.value),
240
+ onBlur: (e) => {
241
+ const next = normalize(e.target.value);
242
+ setDraft(next);
243
+ if (TIME_PATTERN.test(next) && next !== value) onChange?.(next);
244
+ }
245
+ }
246
+ );
247
+ }
248
+ );
249
+
250
+ export { Avatar, Badge, Button, Calendar, Card, CardContent, CardHeader, CardSubtitle, CardTitle, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuTrigger, Input, Label, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Separator, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, TimeInput, cn };
251
+ //# sourceMappingURL=primitives.js.map
252
+ //# sourceMappingURL=primitives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/primitives/cn.ts","../../src/components/primitives/Badge.tsx","../../src/components/primitives/Button.tsx","../../src/components/primitives/Card.tsx","../../src/components/primitives/Input.tsx","../../src/components/primitives/Label.tsx","../../src/components/primitives/Tabs.tsx","../../src/components/primitives/Avatar.tsx","../../src/components/primitives/Separator.tsx","../../src/components/primitives/Popover.tsx","../../src/components/primitives/DropdownMenu.tsx","../../src/components/primitives/Calendar.tsx","../../src/components/primitives/TimeInput.tsx"],"names":["jsx","Input","Textarea","forwardRef","Label","TabsList","TabsTrigger","Separator","PopoverContent","DropdownMenuContent","DropdownMenuItem","DropdownMenuSeparator","DropdownMenuLabel","TimeInput"],"mappings":"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","file":"primitives.js","sourcesContent":["// cn — class-name merger. Standard shadcn utility: clsx merges values\n// and tailwind-merge resolves Tailwind class conflicts (e.g. last\n// `bg-*` wins). Every primitive in this package and every consumer\n// service imports cn from this single location to keep the dedupe\n// rules consistent.\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import type { ComponentProps, ReactNode } from \"react\"\nimport { cn } from \"./cn\"\n\n/**\n * Badge — status pill with a colored dot + label.\n *\n * Renders the canonical `.badge` class from `@godxjp/ui/tokens` so the\n * visual layer is mastered in CSS (not Tailwind utilities). All six\n * variants map onto a semantic role from the brand bible:\n *\n * - `success` — 若竹 task completed, healthy\n * - `warning` — 山吹 needs attention, not yet broken\n * - `info` — 群青 neutral state callout\n * - `error` — 茜 failed / blocked\n * - `attention`— 朱 pending, awaiting input\n * - `neutral` — grey default chrome\n * - `outline` — empty hairline only (rare)\n *\n * @example\n * <Badge variant=\"success\" dot>Healthy</Badge>\n * <Badge variant=\"error\">Failed</Badge>\n */\nexport type BadgeVariant =\n | \"success\"\n | \"warning\"\n | \"info\"\n | \"error\"\n | \"attention\"\n | \"neutral\"\n | \"outline\"\n\nexport interface BadgeProps extends ComponentProps<\"span\"> {\n variant?: BadgeVariant\n /** When true renders a colored dot before the label. */\n dot?: boolean\n children?: ReactNode\n}\n\nexport function Badge({\n variant = \"neutral\",\n dot = false,\n className,\n children,\n ...rest\n}: BadgeProps) {\n return (\n <span className={cn(\"badge\", `badge-${variant}`, className)} {...rest}>\n {dot && <span className=\"dot\" aria-hidden />}\n {children}\n </span>\n )\n}\n","import { Slot } from \"@radix-ui/react-slot\"\nimport type { ComponentProps, ReactNode } from \"react\"\nimport { cn } from \"./cn\"\n\n/**\n * Button — canonical action atom.\n *\n * Maps onto the `.btn` family in tokens.css:\n *\n * primary — filled, brand color, default action\n * secondary — bordered, foreground text, neutral surface\n * ghost — transparent, foreground text, hover surface\n * danger — destructive, --destructive bg\n *\n * Sizes mirror density tokens:\n * sm — 28 px height (compact action bar)\n * md — 32 px height (default)\n * lg — 36 px height (page hero CTA)\n *\n * Supports `asChild` (Radix Slot pattern) so the button styles can wrap\n * a Link or any other element without nesting:\n *\n * @example\n * <Button variant=\"primary\">Save</Button>\n * <Button asChild variant=\"ghost\"><a href=\"/docs\">Docs</a></Button>\n */\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"ghost\" | \"danger\"\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\"\n\nexport interface ButtonProps extends ComponentProps<\"button\"> {\n variant?: ButtonVariant\n size?: ButtonSize\n asChild?: boolean\n children?: ReactNode\n}\n\nexport function Button({\n variant = \"primary\",\n size = \"md\",\n asChild = false,\n className,\n type = \"button\",\n children,\n ...rest\n}: ButtonProps) {\n const Component = asChild ? Slot : \"button\"\n return (\n <Component\n type={asChild ? undefined : type}\n className={cn(\n \"btn\",\n `btn-${variant}`,\n size === \"sm\" && \"btn-sm\",\n size === \"lg\" && \"btn-lg\",\n className,\n )}\n {...rest}\n >\n {children}\n </Component>\n )\n}\n","import type { ComponentProps, ReactNode } from \"react\"\nimport { cn } from \"./cn\"\n\n/**\n * Card — surface container for grouped content.\n *\n * The atom hierarchy mirrors the `.card`/`.card-header`/`.card-title`\n * classes in tokens.css. Compose as:\n *\n * <Card>\n * <CardHeader>\n * <CardTitle>Pull requests</CardTitle>\n * <CardSubtitle>Open / merged this week</CardSubtitle>\n * </CardHeader>\n * <CardContent>...</CardContent>\n * </Card>\n */\nexport function Card({ className, ...rest }: ComponentProps<\"div\">) {\n return <div className={cn(\"card\", className)} {...rest} />\n}\n\nexport function CardHeader({ className, ...rest }: ComponentProps<\"div\">) {\n return <div className={cn(\"card-header\", className)} {...rest} />\n}\n\nexport function CardTitle({ className, ...rest }: ComponentProps<\"h3\">) {\n return <h3 className={cn(\"card-title\", className)} {...rest} />\n}\n\nexport interface CardSubtitleProps extends ComponentProps<\"p\"> {\n children?: ReactNode\n}\n\nexport function CardSubtitle({ className, ...rest }: CardSubtitleProps) {\n return <p className={cn(\"card-subtitle\", className)} {...rest} />\n}\n\nexport function CardContent({ className, ...rest }: ComponentProps<\"div\">) {\n return <div className={className} {...rest} />\n}\n","import { forwardRef, type ComponentProps, type TextareaHTMLAttributes } from \"react\"\nimport { cn } from \"./cn\"\n\n/**\n * Input — text input atom. Maps to `.input` in tokens.css.\n *\n * Forward-ref so consumers can wire `react-hook-form` / focus\n * management without escaping the design tokens.\n */\nexport interface InputProps extends ComponentProps<\"input\"> {}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n { className, type = \"text\", ...rest },\n ref,\n) {\n return <input ref={ref} type={type} className={cn(\"input\", className)} {...rest} />\n})\n\n/** Textarea — uses `.input` for shape, leaves height auto. */\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {}\n\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea(\n { className, ...rest },\n ref,\n) {\n return <textarea ref={ref} className={cn(\"input\", className)} {...rest} />\n})\n","import * as LabelPrimitive from \"@radix-ui/react-label\"\nimport { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from \"react\"\nimport { cn } from \"./cn\"\n\n/**\n * Label — form-field label. Wraps Radix Label so `htmlFor` /\n * click-to-focus works out of the box. Maps to `.label` in tokens.css.\n *\n * Pair with <Input /> + an optional `.help` paragraph:\n *\n * <Label htmlFor=\"name\">Display name</Label>\n * <Input id=\"name\" />\n * <p className=\"help\">Visible to teammates.</p>\n */\nexport const Label = forwardRef<\n ElementRef<typeof LabelPrimitive.Root>,\n ComponentPropsWithoutRef<typeof LabelPrimitive.Root>\n>(function Label({ className, ...rest }, ref) {\n return <LabelPrimitive.Root ref={ref} className={cn(\"label\", className)} {...rest} />\n})\n","import * as TabsPrimitive from \"@radix-ui/react-tabs\"\nimport { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from \"react\"\nimport { cn } from \"./cn\"\n\n/**\n * Tabs — Radix-backed tab strip styled with the canonical `.tabs` /\n * `.tab` CSS from tokens.css. Keyboard navigation + ARIA come from\n * Radix; the visual contract stays in the design tokens.\n *\n * @example\n * <Tabs defaultValue=\"open\">\n * <TabsList>\n * <TabsTrigger value=\"open\">Open</TabsTrigger>\n * <TabsTrigger value=\"closed\">Closed</TabsTrigger>\n * </TabsList>\n * <TabsContent value=\"open\">...</TabsContent>\n * <TabsContent value=\"closed\">...</TabsContent>\n * </Tabs>\n */\nexport const Tabs = TabsPrimitive.Root\n\nexport const TabsList = forwardRef<\n ElementRef<typeof TabsPrimitive.List>,\n ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(function TabsList({ className, ...rest }, ref) {\n return <TabsPrimitive.List ref={ref} className={cn(\"tabs\", className)} {...rest} />\n})\n\nexport const TabsTrigger = forwardRef<\n ElementRef<typeof TabsPrimitive.Trigger>,\n ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(function TabsTrigger({ className, ...rest }, ref) {\n // Radix sets `data-state=\"active\"` on the active trigger — map it to\n // the `data-active` attribute the .tab CSS expects.\n return (\n <TabsPrimitive.Trigger\n ref={ref}\n className={cn(\"tab\", className)}\n {...rest}\n data-active={undefined}\n />\n )\n})\n\nexport const TabsContent = TabsPrimitive.Content\n","import type { ComponentProps } from \"react\"\nimport { cn } from \"./cn\"\n\n/**\n * Avatar — round chip with initials or an image. Maps to `.avatar`\n * + `.avatar.brand` in tokens.css.\n *\n * @example\n * <Avatar>PT</Avatar>\n * <Avatar variant=\"brand\">G</Avatar>\n */\nexport interface AvatarProps extends ComponentProps<\"span\"> {\n variant?: \"default\" | \"brand\"\n /** Optional image url; falls back to children (initials) when missing. */\n src?: string\n alt?: string\n}\n\nexport function Avatar({\n variant = \"default\",\n src,\n alt,\n className,\n children,\n ...rest\n}: AvatarProps) {\n return (\n <span className={cn(\"avatar\", variant === \"brand\" && \"brand\", className)} {...rest}>\n {src ? <img src={src} alt={alt ?? \"\"} style={{ width: \"100%\", height: \"100%\", borderRadius: \"inherit\", objectFit: \"cover\" }} /> : children}\n </span>\n )\n}\n","import * as SeparatorPrimitive from \"@radix-ui/react-separator\"\nimport { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from \"react\"\nimport { cn } from \"./cn\"\n\n/**\n * Separator — horizontal / vertical divider. Wraps Radix Separator for\n * ARIA + decorative semantics. Maps to `.divider` styling in tokens.css\n * (1px border, theme-aware color).\n */\nexport const Separator = forwardRef<\n ElementRef<typeof SeparatorPrimitive.Root>,\n ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\n>(function Separator({ className, orientation = \"horizontal\", decorative = true, ...rest }, ref) {\n return (\n <SeparatorPrimitive.Root\n ref={ref}\n orientation={orientation}\n decorative={decorative}\n className={cn(\n orientation === \"horizontal\" ? \"divider\" : \"\",\n className,\n )}\n style={\n orientation === \"vertical\"\n ? { width: 1, height: \"100%\", background: \"var(--border)\", border: 0 }\n : undefined\n }\n {...rest}\n />\n )\n})\n","import * as PopoverPrimitive from \"@radix-ui/react-popover\"\nimport { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from \"react\"\nimport { cn } from \"./cn\"\n\n/**\n * Popover — Radix-backed floating panel anchored to a trigger element.\n * Styled with the canonical `.popover-content` class from tokens.css\n * so the visual contract stays in the design tokens.\n *\n * @example\n * <Popover>\n * <PopoverTrigger asChild>\n * <Button variant=\"ghost\">Open</Button>\n * </PopoverTrigger>\n * <PopoverContent>…body…</PopoverContent>\n * </Popover>\n */\nexport const Popover = PopoverPrimitive.Root\nexport const PopoverTrigger = PopoverPrimitive.Trigger\nexport const PopoverAnchor = PopoverPrimitive.Anchor\n\nexport const PopoverContent = forwardRef<\n ElementRef<typeof PopoverPrimitive.Content>,\n ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(function PopoverContent(\n { className, align = \"center\", sideOffset = 6, ...rest },\n ref,\n) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\"popover-content\", className)}\n {...rest}\n />\n </PopoverPrimitive.Portal>\n )\n})\n","import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\"\nimport { forwardRef, type ComponentPropsWithoutRef, type ElementRef, type HTMLAttributes } from \"react\"\nimport { cn } from \"./cn\"\n\n/**\n * DropdownMenu — Radix-backed action menu opened from a trigger\n * (kebab, caret, button…). Styled via canonical `.dropdown-menu-*`\n * classes from tokens.css.\n *\n * Items support `variant=\"destructive\"` for dangerous actions and\n * `inset` for left-padding alignment when icons aren't on every row.\n *\n * @example\n * <DropdownMenu>\n * <DropdownMenuTrigger asChild>\n * <Button variant=\"ghost\"><MoreVertical /></Button>\n * </DropdownMenuTrigger>\n * <DropdownMenuContent align=\"end\">\n * <DropdownMenuItem onSelect={onEdit}>Edit</DropdownMenuItem>\n * <DropdownMenuSeparator />\n * <DropdownMenuItem variant=\"destructive\" onSelect={onDelete}>\n * Delete\n * </DropdownMenuItem>\n * </DropdownMenuContent>\n * </DropdownMenu>\n */\nexport const DropdownMenu = DropdownMenuPrimitive.Root\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger\nexport const DropdownMenuGroup = DropdownMenuPrimitive.Group\nexport const DropdownMenuPortal = DropdownMenuPrimitive.Portal\nexport const DropdownMenuSub = DropdownMenuPrimitive.Sub\nexport const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup\n\nexport const DropdownMenuContent = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Content>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(function DropdownMenuContent({ className, sideOffset = 6, ...rest }, ref) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"dropdown-menu-content\", className)}\n {...rest}\n />\n </DropdownMenuPrimitive.Portal>\n )\n})\n\ntype DropdownItemProps = ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}\n\nexport const DropdownMenuItem = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Item>,\n DropdownItemProps\n>(function DropdownMenuItem({ className, inset, variant = \"default\", ...rest }, ref) {\n return (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\"dropdown-menu-item\", className)}\n data-variant={variant === \"destructive\" ? \"destructive\" : undefined}\n data-inset={inset ? \"true\" : undefined}\n {...rest}\n />\n )\n})\n\nexport const DropdownMenuSeparator = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Separator>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(function DropdownMenuSeparator({ className, ...rest }, ref) {\n return (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"dropdown-menu-separator\", className)}\n {...rest}\n />\n )\n})\n\nexport const DropdownMenuLabel = forwardRef<\n ElementRef<typeof DropdownMenuPrimitive.Label>,\n ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & { inset?: boolean }\n>(function DropdownMenuLabel({ className, inset, ...rest }, ref) {\n return (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\"dropdown-menu-label\", className)}\n data-inset={inset ? \"true\" : undefined}\n {...rest}\n />\n )\n})\n\nexport function DropdownMenuShortcut({\n className,\n ...rest\n}: HTMLAttributes<HTMLSpanElement>) {\n return <span className={cn(\"dropdown-menu-shortcut\", className)} {...rest} />\n}\n","import { DayPicker, type DayPickerProps } from \"react-day-picker\"\nimport \"react-day-picker/dist/style.css\"\nimport { cn } from \"./cn\"\n\n/**\n * Calendar — react-day-picker grid themed with brand tokens via the\n * canonical `.calendar` class from tokens.css. Caller controls\n * mode/selected/onSelect through DayPicker's standard props.\n *\n * Locale + week-start are inherited from i18next / browser by default;\n * pass DayPickerProps explicitly to override (e.g. `weekStartsOn={1}`\n * for Monday-first).\n *\n * @example\n * const [date, setDate] = useState<Date>()\n * <Calendar mode=\"single\" selected={date} onSelect={setDate} />\n */\nexport function Calendar({ className, showOutsideDays = true, ...rest }: DayPickerProps) {\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\"calendar\", className)}\n {...rest}\n />\n )\n}\n","import { forwardRef, useEffect, useState, type ChangeEvent, type FocusEvent } from \"react\"\nimport { cn } from \"./cn\"\n\nexport interface TimeInputProps {\n /** Current time value in `\"HH:mm\"` (24-hour) format. */\n value?: string\n /** Fired on blur with the validated `\"HH:mm\"` string. */\n onChange?: (time: string) => void\n /** Additional class name applied to the input element. */\n className?: string\n /** Disable input + propagate aria-disabled. */\n disabled?: boolean\n /** Optional placeholder (defaults to \"HH:mm\"). */\n placeholder?: string\n /** Optional id used for label association. */\n id?: string\n /** Optional name used in form submissions. */\n name?: string\n}\n\nconst TIME_PATTERN = /^([01]\\d|2[0-3]):[0-5]\\d$/\n\nfunction normalize(raw: string): string {\n // Strip whitespace + non-digits-or-colon. Accept either \"HH:mm\" or\n // \"HHmm\" / \"H:mm\" / \"Hmm\" and coerce into canonical \"HH:mm\". Returns\n // the original string when it can't be parsed — the caller decides\n // whether to surface aria-invalid.\n const cleaned = raw.trim()\n if (!cleaned) return \"\"\n if (TIME_PATTERN.test(cleaned)) return cleaned\n const digits = cleaned.replace(/[^0-9]/g, \"\")\n if (digits.length === 3 || digits.length === 4) {\n const hh = digits.slice(0, digits.length - 2).padStart(2, \"0\")\n const mm = digits.slice(-2)\n const candidate = `${hh}:${mm}`\n if (TIME_PATTERN.test(candidate)) return candidate\n }\n return raw\n}\n\n/**\n * TimeInput — narrow text input for HH:mm (24-hour) values.\n * Mirrors the public `@godxjp/ui@0.2.0` API so call sites don't change\n * when upgrading to v2. Visual contract lives in the `.time-input`\n * class in tokens.css.\n *\n * Validation: emits `onChange` with the normalized string on blur if\n * it parses, otherwise leaves the value untouched and surfaces\n * `aria-invalid` so the consumer can style the error state.\n */\nexport const TimeInput = forwardRef<HTMLInputElement, TimeInputProps>(\n function TimeInput(\n { value, onChange, className, disabled, placeholder = \"HH:mm\", id, name },\n ref,\n ) {\n const [draft, setDraft] = useState(value ?? \"\")\n\n useEffect(() => {\n setDraft(value ?? \"\")\n }, [value])\n\n const invalid = draft !== \"\" && !TIME_PATTERN.test(draft)\n\n return (\n <input\n ref={ref}\n type=\"text\"\n inputMode=\"numeric\"\n autoComplete=\"off\"\n spellCheck={false}\n maxLength={5}\n id={id}\n name={name}\n disabled={disabled}\n placeholder={placeholder}\n value={draft}\n aria-invalid={invalid || undefined}\n className={cn(\"time-input\", className)}\n onChange={(e: ChangeEvent<HTMLInputElement>) => setDraft(e.target.value)}\n onBlur={(e: FocusEvent<HTMLInputElement>) => {\n const next = normalize(e.target.value)\n setDraft(next)\n if (TIME_PATTERN.test(next) && next !== value) onChange?.(next)\n }}\n />\n )\n },\n)\n"]}
@@ -0,0 +1,51 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ForgeProduct, ForgeProject } from '../data.js';
3
+
4
+ interface DashboardScreenProps {
5
+ product: ForgeProduct;
6
+ }
7
+ declare function DashboardScreen({ product }: DashboardScreenProps): react_jsx_runtime.JSX.Element;
8
+
9
+ interface ProjectsListScreenProps {
10
+ product: ForgeProduct;
11
+ onSelect: (project: ForgeProject) => void;
12
+ }
13
+ declare function ProjectsListScreen({ product, onSelect }: ProjectsListScreenProps): react_jsx_runtime.JSX.Element;
14
+
15
+ interface PlansScreenProps {
16
+ onOpenPlan: (id: string) => void;
17
+ }
18
+ declare function PlansScreen({ onOpenPlan }: PlansScreenProps): react_jsx_runtime.JSX.Element;
19
+
20
+ interface IssuesScreenProps {
21
+ onOpenIssue: (id: string) => void;
22
+ }
23
+ declare function IssuesScreen({ onOpenIssue }: IssuesScreenProps): react_jsx_runtime.JSX.Element;
24
+
25
+ interface WikiScreenProps {
26
+ toc?: Array<{
27
+ id: string;
28
+ label: string;
29
+ }>;
30
+ children?: React.ReactNode;
31
+ meta?: React.ReactNode;
32
+ }
33
+ declare function WikiScreen({ toc, children, meta }: WikiScreenProps): react_jsx_runtime.JSX.Element;
34
+
35
+ declare function IdeasScreen(): react_jsx_runtime.JSX.Element;
36
+
37
+ interface PlanDetailScreenProps {
38
+ planId: string;
39
+ onBack: () => void;
40
+ onOpenIssue: (id: string) => void;
41
+ }
42
+ declare function PlanDetailScreen({ planId, onBack, onOpenIssue }: PlanDetailScreenProps): react_jsx_runtime.JSX.Element;
43
+
44
+ interface IssueDetailScreenProps {
45
+ issueId: string;
46
+ onBack: () => void;
47
+ onOpenPlan: (id: string) => void;
48
+ }
49
+ declare function IssueDetailScreen({ issueId, onBack, onOpenPlan }: IssueDetailScreenProps): react_jsx_runtime.JSX.Element;
50
+
51
+ export { DashboardScreen, type DashboardScreenProps, IdeasScreen, IssueDetailScreen, type IssueDetailScreenProps, IssuesScreen, type IssuesScreenProps, PlanDetailScreen, type PlanDetailScreenProps, PlansScreen, type PlansScreenProps, ProjectsListScreen, type ProjectsListScreenProps, WikiScreen, type WikiScreenProps };