@elabs-ai/components-ui 4.0.0 → 4.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.
- package/README.md +10 -8
- package/dist/chunk-JKPPTL63.js +48 -0
- package/dist/chunk-JKPPTL63.js.map +1 -0
- package/dist/form.d.ts +28 -0
- package/dist/form.js +123 -0
- package/dist/form.js.map +1 -0
- package/dist/index.d.ts +2485 -167
- package/dist/index.js +10716 -2706
- package/dist/index.js.map +1 -1
- package/package.json +21 -7
- package/src/_peer-deps.test.ts +59 -0
- package/src/blocks-comparison-table.stories.tsx +2 -2
- package/src/components/accordion/accordion.tsx +1 -1
- package/src/components/advanced-group/advanced-group.tsx +1 -1
- package/src/components/alert/alert.tsx +4 -1
- package/src/components/app-shell/app-shell.stories.tsx +44 -2
- package/src/components/app-shell/app-shell.tsx +35 -2
- package/src/components/app-sidebar/app-sidebar.stories.tsx +9 -1
- package/src/components/attribution-panel/attribution-panel.tsx +1 -1
- package/src/components/attribution-panel/attributions.generated.ts +81 -77
- package/src/components/badge/badge.stories.tsx +8 -0
- package/src/components/badge/badge.tsx +1 -1
- package/src/components/bento-grid/bento-grid.test.tsx +1 -1
- package/src/components/bento-grid/bento-grid.tsx +1 -1
- package/src/components/breadcrumb/breadcrumb.stories.tsx +38 -0
- package/src/components/breadcrumb/breadcrumb.test.tsx +24 -1
- package/src/components/breadcrumb/breadcrumb.tsx +7 -2
- package/src/components/button/button.stories.tsx +116 -8
- package/src/components/button/button.tsx +1 -1
- package/src/components/card/card.stories.tsx +11 -6
- package/src/components/card/card.tsx +1 -1
- package/src/components/change-review/change-review.stories.tsx +145 -1
- package/src/components/change-review/change-review.test.tsx +143 -0
- package/src/components/change-review/change-review.tsx +185 -4
- package/src/components/checkbox/checkbox.tsx +1 -1
- package/src/components/color-picker/color-picker.tsx +6 -5
- package/src/components/command/command.stories.tsx +16 -6
- package/src/components/command/command.test.tsx +73 -0
- package/src/components/command/command.tsx +30 -7
- package/src/components/command/index.ts +1 -0
- package/src/components/command-trigger/command-trigger.stories.tsx +39 -0
- package/src/components/command-trigger/command-trigger.test.tsx +18 -0
- package/src/components/command-trigger/command-trigger.tsx +70 -0
- package/src/components/command-trigger/index.ts +1 -0
- package/src/components/context-rail/context-rail.stories.tsx +285 -0
- package/src/components/context-rail/context-rail.test.tsx +263 -0
- package/src/components/context-rail/context-rail.tsx +678 -0
- package/src/components/context-rail/index.ts +1 -0
- package/src/components/copyable-value/copyable-value.tsx +1 -1
- package/src/components/dialog/dialog.tsx +2 -2
- package/src/components/dropdown-menu/dropdown-menu.stories.tsx +1 -1
- package/src/components/empty-state/empty-state.test.tsx +26 -0
- package/src/components/empty-state/empty-state.tsx +6 -1
- package/src/components/expand-dialog/expand-dialog.tsx +1 -2
- package/src/components/field/field-context.ts +59 -0
- package/src/components/field/field.stories.tsx +142 -0
- package/src/components/field/field.test.tsx +415 -0
- package/src/components/field/field.tsx +340 -0
- package/src/components/field/index.ts +9 -0
- package/src/components/field-row/field-row.stories.tsx +85 -1
- package/src/components/field-row/field-row.test.tsx +145 -0
- package/src/components/field-row/field-row.tsx +48 -6
- package/src/components/file-upload/file-upload.stories.tsx +16 -0
- package/src/components/file-upload/file-upload.test.tsx +7 -2
- package/src/components/file-upload/file-upload.tsx +15 -4
- package/src/components/form/form.tsx +5 -2
- package/src/components/icon-button/icon-button.test.tsx +1 -1
- package/src/components/icon-button/icon-button.tsx +2 -2
- package/src/components/input/input.stories.tsx +121 -0
- package/src/components/input/input.test.tsx +13 -0
- package/src/components/input/input.tsx +2 -2
- package/src/components/input-group/input-group.stories.tsx +74 -0
- package/src/components/input-group/input-group.tsx +13 -4
- package/src/components/input-otp/input-otp.tsx +5 -1
- package/src/components/keyboard-shortcuts/index.ts +6 -0
- package/src/components/keyboard-shortcuts/keyboard-shortcuts.stories.tsx +177 -0
- package/src/components/keyboard-shortcuts/keyboard-shortcuts.test.tsx +73 -0
- package/src/components/keyboard-shortcuts/keyboard-shortcuts.tsx +203 -0
- package/src/components/link-preview/link-preview.tsx +1 -1
- package/src/components/locale-provider/index.ts +6 -1
- package/src/components/locale-provider/locale-provider.stories.tsx +89 -1
- package/src/components/locale-provider/locale-provider.test.tsx +257 -1
- package/src/components/locale-provider/locale-provider.tsx +63 -8
- package/src/components/locale-provider/messages.ts +501 -2
- package/src/components/match-highlight/match-highlight.stories.tsx +1 -1
- package/src/components/mention-input/mention-input-mirror.stories.tsx +9 -1
- package/src/components/mention-input/mention-input.tsx +8 -38
- package/src/components/mention-input/mention-value.ts +8 -2
- package/src/components/metric-card/metric-card.stories.tsx +5 -3
- package/src/components/metric-card/metric-card.tsx +21 -2
- package/src/components/model-picker/model-picker.stories.tsx +63 -3
- package/src/components/model-picker/model-picker.test.tsx +63 -0
- package/src/components/model-picker/model-picker.tsx +62 -36
- package/src/components/nav-main/nav-main.tsx +1 -1
- package/src/components/nav-notifications/nav-notifications.stories.tsx +110 -0
- package/src/components/nav-notifications/nav-notifications.tsx +57 -5
- package/src/components/navigation-menu/navigation-menu.stories.tsx +22 -0
- package/src/components/navigation-menu/navigation-menu.test.tsx +174 -0
- package/src/components/navigation-menu/navigation-menu.tsx +189 -12
- package/src/components/page-shell/page-shell.stories.tsx +163 -0
- package/src/components/page-shell/page-shell.test.tsx +229 -0
- package/src/components/page-shell/page-shell.tsx +108 -25
- package/src/components/pagination/pagination.test.tsx +90 -0
- package/src/components/pagination/pagination.tsx +9 -5
- package/src/components/radio-group/radio-group.tsx +1 -1
- package/src/components/rating/rating.tsx +1 -1
- package/src/components/resizable/resizable.stories.tsx +114 -2
- package/src/components/resizable/resizable.tsx +1 -1
- package/src/components/revision-timeline/revision-timeline.stories.tsx +8 -1
- package/src/components/revision-timeline/revision-timeline.test.tsx +26 -0
- package/src/components/revision-timeline/revision-timeline.tsx +46 -3
- package/src/components/schema-form/from-json-schema.test.ts +390 -0
- package/src/components/schema-form/from-json-schema.ts +375 -0
- package/src/components/schema-form/index.ts +81 -0
- package/src/components/schema-form/schema-form-spec.ts +698 -0
- package/src/components/schema-form/schema-form.stories.tsx +566 -0
- package/src/components/schema-form/schema-form.test.tsx +900 -0
- package/src/components/schema-form/schema-form.tsx +1545 -0
- package/src/components/section-header/section-header.stories.tsx +37 -0
- package/src/components/section-header/section-header.tsx +12 -1
- package/src/components/select/select.tsx +6 -2
- package/src/components/sheet/sheet.tsx +1 -1
- package/src/components/side-dock/index.ts +1 -0
- package/src/components/side-dock/side-dock.stories.tsx +137 -0
- package/src/components/side-dock/side-dock.test.tsx +273 -0
- package/src/components/side-dock/side-dock.tsx +502 -0
- package/src/components/sidebar/index.ts +1 -0
- package/src/components/sidebar/sidebar-frame.test.tsx +162 -0
- package/src/components/sidebar/sidebar.stories.tsx +421 -1
- package/src/components/sidebar/sidebar.test.tsx +36 -1
- package/src/components/sidebar/sidebar.tsx +245 -33
- package/src/components/skip-link/index.ts +1 -0
- package/src/components/skip-link/skip-link.stories.tsx +106 -0
- package/src/components/skip-link/skip-link.test.tsx +20 -0
- package/src/components/skip-link/skip-link.tsx +34 -0
- package/src/components/slider/slider.tsx +1 -1
- package/src/components/split-panel/index.ts +6 -1
- package/src/components/split-panel/split-panel.stories.tsx +18 -2
- package/src/components/split-panel/split-panel.test.tsx +20 -0
- package/src/components/split-panel/split-panel.tsx +28 -8
- package/src/components/state-panel/state-panel.stories.tsx +52 -0
- package/src/components/state-panel/state-panel.test.tsx +125 -0
- package/src/components/state-panel/state-panel.tsx +96 -17
- package/src/components/status-badge/status-badge.stories.tsx +8 -0
- package/src/components/switch/switch.tsx +1 -1
- package/src/components/table/table.stories.tsx +62 -0
- package/src/components/table/table.test.tsx +142 -1
- package/src/components/table/table.tsx +60 -1
- package/src/components/tabs/tabs.tsx +8 -2
- package/src/components/tag-input/tag-input.tsx +3 -2
- package/src/components/team-switcher/team-switcher.tsx +34 -5
- package/src/components/textarea/textarea.tsx +1 -1
- package/src/components/theme-switcher/theme-switcher.tsx +6 -2
- package/src/components/theme-switcher/use-theme-transition.ts +2 -2
- package/src/components/timeline/timeline.stories.tsx +27 -0
- package/src/components/timeline/timeline.tsx +11 -1
- package/src/components/toggle/toggle.tsx +1 -1
- package/src/components/toolbar/toolbar.stories.tsx +10 -2
- package/src/components/tree/tree.stories.tsx +2 -2
- package/src/components/tree/tree.tsx +14 -9
- package/src/components/typography/prose.tsx +1 -1
- package/src/components/typography/typography.stories.tsx +228 -0
- package/src/components/view-toolbar/view-toolbar.stories.tsx +41 -1
- package/src/components/view-toolbar/view-toolbar.test.tsx +33 -0
- package/src/components/view-toolbar/view-toolbar.tsx +37 -4
- package/src/components/virtual-select/virtual-select.test.tsx +1 -1
- package/src/components/wizard/wizard.tsx +1 -1
- package/src/components/workspace-picker/index.ts +3 -0
- package/src/components/workspace-picker/workspace-picker-state.ts +50 -0
- package/src/components/workspace-picker/workspace-picker.stories.tsx +126 -0
- package/src/components/workspace-picker/workspace-picker.test.tsx +207 -0
- package/src/components/workspace-picker/workspace-picker.tsx +172 -0
- package/src/illustrations/empty-list-illustration.tsx +26 -0
- package/src/illustrations/error-illustration.tsx +60 -0
- package/src/illustrations/first-run-illustration.tsx +27 -0
- package/src/illustrations/illustration-base.tsx +108 -0
- package/src/illustrations/illustrations.stories.tsx +94 -0
- package/src/illustrations/illustrations.test.tsx +98 -0
- package/src/illustrations/index.ts +16 -0
- package/src/illustrations/no-access-illustration.tsx +45 -0
- package/src/illustrations/no-results-illustration.tsx +46 -0
- package/src/illustrations/offline-illustration.tsx +37 -0
- package/src/illustrations/success-illustration.tsx +40 -0
- package/src/index.ts +75 -2
- package/src/lib/agent-event-model.test.ts +12 -0
- package/src/lib/agent-event-model.ts +42 -0
- package/src/lib/approval-option.test.ts +17 -0
- package/src/lib/approval-option.ts +53 -0
- package/src/lib/check-result.ts +33 -0
- package/src/lib/diff-line.test.ts +36 -0
- package/src/lib/diff-line.ts +63 -0
- package/src/lib/diff-rows.test.ts +76 -0
- package/src/lib/diff-rows.ts +92 -0
- package/src/lib/format-duration.test.ts +22 -0
- package/src/lib/format-duration.ts +30 -0
- package/src/lib/has-renderable-content.test.ts +49 -0
- package/src/lib/has-renderable-content.ts +32 -0
- package/src/lib/operating-mode.test.ts +36 -0
- package/src/lib/operating-mode.ts +81 -0
- package/src/lib/optional-peer.ts +59 -0
- package/src/lib/session-launch.ts +37 -0
- package/src/lib/slash-command.test.ts +44 -0
- package/src/lib/slash-command.ts +45 -0
- package/src/lib/trigger-query.test.ts +94 -0
- package/src/lib/trigger-query.ts +88 -0
- package/src/lib/use-mobile.ts +12 -6
- package/src/motion.stories.tsx +6 -0
- package/src/templates-object-detail-hub.stories.tsx +2 -2
- package/src/templates-screen-states.stories.tsx +5 -5
- package/src/templates-settings.stories.tsx +1 -1
- package/src/blocks/sidebar-02/app-sidebar.tsx +0 -160
- package/src/blocks/sidebar-02/logo.tsx +0 -18
- package/src/blocks/sidebar-02/nav-main.tsx +0 -13
- package/src/blocks/sidebar-02/nav-notifications.tsx +0 -7
- package/src/blocks/sidebar-02/sidebar-02.stories.tsx +0 -23
- package/src/blocks/sidebar-02/team-switcher.tsx +0 -7
- package/src/blocks/sidebar-04/app-sidebar.tsx +0 -236
- package/src/blocks/sidebar-04/mail-context.tsx +0 -29
- package/src/blocks/sidebar-04/nav-user.tsx +0 -6
- package/src/blocks/sidebar-04/sidebar-04.stories.tsx +0 -150
- package/src/blocks/sidebar-05/app-sidebar.tsx +0 -375
- package/src/blocks/sidebar-05/sidebar-05.stories.tsx +0 -18
- package/src/blocks/sidebar-05/team-switcher.tsx +0 -6
package/README.md
CHANGED
|
@@ -6,15 +6,16 @@
|
|
|
6
6
|
> Foundation + app UI (Button, Card, Dialog, Tabs, AppShell, …).
|
|
7
7
|
|
|
8
8
|
Part of **brand-ui**, a source-owned, token-driven React component system.
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
Published to the **public npm registry** under the `@elabs-ai` scope — it
|
|
10
|
+
installs like any other npm dependency, with no registry configuration and
|
|
11
|
+
no token required. See `docs/CONSUMING.md`.
|
|
11
12
|
|
|
12
13
|
## Install
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add @elabs-ai/components-tokens @elabs-ai/components-ui
|
|
17
|
+
pnpm add @hookform/resolvers@"^3.9.1" # optional peer
|
|
18
|
+
pnpm add react-hook-form@"^7.54.2" # optional peer
|
|
18
19
|
```
|
|
19
20
|
|
|
20
21
|
## Set up styling (do not skip)
|
|
@@ -40,10 +41,11 @@ import { ThemeProvider } from "@elabs-ai/components-tokens";
|
|
|
40
41
|
## This package specifically
|
|
41
42
|
|
|
42
43
|
- The class-merge helper is at `.../lib/cn` — a pure, server-safe entry point.
|
|
44
|
+
- `react-hook-form` / `@hookform/resolvers` are **optional peers** — install them only if you use `Form` (import it from `.../form`, not the main barrel). `FieldRow` is the headless, react-hook-form-free field primitive and needs neither.
|
|
43
45
|
|
|
44
46
|
## What's in it
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
379 exported components — including `Accordion`, `AccordionContent`, `AccordionItem`, `AccordionTrigger`, `AdvancedGroup`.
|
|
47
49
|
|
|
48
50
|
Don't guess the API — ask the CLI:
|
|
49
51
|
|
|
@@ -73,6 +75,6 @@ prompt for migrating an existing project: `docs/CONSUMING.md`.
|
|
|
73
75
|
|
|
74
76
|
## License
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
MIT
|
|
77
79
|
|
|
78
80
|
<!-- brand-ui:gen:readme:end -->
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// src/lib/cn.ts
|
|
9
|
+
import { clsx } from "clsx";
|
|
10
|
+
import { extendTailwindMerge } from "tailwind-merge";
|
|
11
|
+
var TEXT_ROLES = ["display", "title", "subtitle", "body", "caption", "meta", "kpi", "code"];
|
|
12
|
+
var twMerge = extendTailwindMerge({
|
|
13
|
+
extend: {
|
|
14
|
+
classGroups: {
|
|
15
|
+
"font-size": [{ text: TEXT_ROLES }],
|
|
16
|
+
// `font-display` is the display-face seam (sibling of font-mono, #187).
|
|
17
|
+
"font-family": [{ font: ["display"] }]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
function cn(...inputs) {
|
|
22
|
+
return twMerge(clsx(inputs));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/components/label/label.tsx
|
|
26
|
+
import { forwardRef } from "react";
|
|
27
|
+
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
28
|
+
import { jsx } from "react/jsx-runtime";
|
|
29
|
+
var Label = forwardRef(function Label2({ className, ...props }, ref) {
|
|
30
|
+
return /* @__PURE__ */ jsx(
|
|
31
|
+
LabelPrimitive.Root,
|
|
32
|
+
{
|
|
33
|
+
ref,
|
|
34
|
+
className: cn(
|
|
35
|
+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
36
|
+
className
|
|
37
|
+
),
|
|
38
|
+
...props
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
__export,
|
|
45
|
+
cn,
|
|
46
|
+
Label
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=chunk-JKPPTL63.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/cn.ts","../src/components/label/label.tsx"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\n/**\n * The semantic type roles (`--text-<role>` tokens → `text-<role>` utilities, #187).\n * tailwind-merge doesn't know custom theme keys, so without registration it\n * classifies `text-title` as a text COLOR — and `cn(\"text-kpi\", \"text-foreground\")`\n * would silently drop the role. Registering the roles in the `font-size` class\n * group makes role-vs-role and role-vs-raw-size conflicts resolve correctly while\n * keeping role + color independent.\n */\nconst TEXT_ROLES = [\"display\", \"title\", \"subtitle\", \"body\", \"caption\", \"meta\", \"kpi\", \"code\"];\n\nconst twMerge = extendTailwindMerge({\n extend: {\n classGroups: {\n \"font-size\": [{ text: TEXT_ROLES }],\n // `font-display` is the display-face seam (sibling of font-mono, #187).\n \"font-family\": [{ font: [\"display\"] }],\n },\n },\n});\n\n/**\n * Merge class names with conflict resolution. `clsx` handles conditionals;\n * `tailwind-merge` ensures later Tailwind utilities win (e.g. `p-2 p-4` -> `p-4`).\n * Use this in every component that accepts a `className` prop.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from \"react\";\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { cn } from \"../../lib/cn\";\n\nexport const Label = forwardRef<\n ElementRef<typeof LabelPrimitive.Root>,\n ComponentPropsWithoutRef<typeof LabelPrimitive.Root>\n>(function Label({ className, ...props }, ref) {\n return (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(\n \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n className,\n )}\n {...props}\n />\n );\n});\n"],"mappings":";;;;;;;;AAAA,SAAS,YAA6B;AACtC,SAAS,2BAA2B;AAUpC,IAAM,aAAa,CAAC,WAAW,SAAS,YAAY,QAAQ,WAAW,QAAQ,OAAO,MAAM;AAE5F,IAAM,UAAU,oBAAoB;AAAA,EAClC,QAAQ;AAAA,IACN,aAAa;AAAA,MACX,aAAa,CAAC,EAAE,MAAM,WAAW,CAAC;AAAA;AAAA,MAElC,eAAe,CAAC,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;AAAA,IACvC;AAAA,EACF;AACF,CAAC;AAOM,SAAS,MAAM,QAA8B;AAClD,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;AC9BA,SAAS,kBAAkE;AAC3E,YAAY,oBAAoB;AAQ5B;AALG,IAAM,QAAQ,WAGnB,SAASA,OAAM,EAAE,WAAW,GAAG,MAAM,GAAG,KAAK;AAC7C,SACE;AAAA,IAAgB;AAAA,IAAf;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;","names":["Label"]}
|
package/dist/form.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as _radix_ui_react_slot from '@radix-ui/react-slot';
|
|
2
|
+
import * as _radix_ui_react_label from '@radix-ui/react-label';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { HTMLAttributes } from 'react';
|
|
5
|
+
import * as react_hook_form from 'react-hook-form';
|
|
6
|
+
import { FieldValues, FieldPath, ControllerProps } from 'react-hook-form';
|
|
7
|
+
|
|
8
|
+
declare const Form: <TFieldValues extends FieldValues, TContext = any, TTransformedValues = TFieldValues>({ children, watch, getValues, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, }: react_hook_form.FormProviderProps<TFieldValues, TContext, TTransformedValues>) => React.JSX.Element;
|
|
9
|
+
declare function FormField<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>(props: ControllerProps<TFieldValues, TName>): react.JSX.Element;
|
|
10
|
+
declare function useFormField(): {
|
|
11
|
+
invalid: boolean;
|
|
12
|
+
isDirty: boolean;
|
|
13
|
+
isTouched: boolean;
|
|
14
|
+
isValidating: boolean;
|
|
15
|
+
error?: react_hook_form.FieldError;
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
formItemId: string;
|
|
19
|
+
formDescriptionId: string;
|
|
20
|
+
formMessageId: string;
|
|
21
|
+
};
|
|
22
|
+
declare const FormItem: react.ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & react.RefAttributes<HTMLDivElement>>;
|
|
23
|
+
declare const FormLabel: react.ForwardRefExoticComponent<Omit<Omit<_radix_ui_react_label.LabelProps & react.RefAttributes<HTMLLabelElement>, "ref"> & react.RefAttributes<HTMLLabelElement>, "ref"> & react.RefAttributes<HTMLLabelElement>>;
|
|
24
|
+
declare const FormControl: react.ForwardRefExoticComponent<Omit<_radix_ui_react_slot.SlotProps & react.RefAttributes<HTMLElement>, "ref"> & react.RefAttributes<HTMLElement>>;
|
|
25
|
+
declare const FormDescription: react.ForwardRefExoticComponent<HTMLAttributes<HTMLParagraphElement> & react.RefAttributes<HTMLParagraphElement>>;
|
|
26
|
+
declare const FormMessage: react.ForwardRefExoticComponent<HTMLAttributes<HTMLParagraphElement> & react.RefAttributes<HTMLParagraphElement>>;
|
|
27
|
+
|
|
28
|
+
export { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField };
|
package/dist/form.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Label,
|
|
4
|
+
cn
|
|
5
|
+
} from "./chunk-JKPPTL63.js";
|
|
6
|
+
|
|
7
|
+
// src/components/form/form.tsx
|
|
8
|
+
import {
|
|
9
|
+
createContext,
|
|
10
|
+
forwardRef,
|
|
11
|
+
useContext,
|
|
12
|
+
useId
|
|
13
|
+
} from "react";
|
|
14
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
15
|
+
import {
|
|
16
|
+
Controller,
|
|
17
|
+
FormProvider,
|
|
18
|
+
useFormContext
|
|
19
|
+
} from "react-hook-form";
|
|
20
|
+
import { jsx } from "react/jsx-runtime";
|
|
21
|
+
var Form = FormProvider;
|
|
22
|
+
var FormFieldContext = createContext({});
|
|
23
|
+
function FormField(props) {
|
|
24
|
+
return /* @__PURE__ */ jsx(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx(Controller, { ...props }) });
|
|
25
|
+
}
|
|
26
|
+
var FormItemContext = createContext({});
|
|
27
|
+
function useFormField() {
|
|
28
|
+
const fieldContext = useContext(FormFieldContext);
|
|
29
|
+
const itemContext = useContext(FormItemContext);
|
|
30
|
+
const { getFieldState, formState } = useFormContext();
|
|
31
|
+
const fieldState = getFieldState(fieldContext.name, formState);
|
|
32
|
+
if (!fieldContext) throw new Error("useFormField should be used within <FormField>");
|
|
33
|
+
const { id } = itemContext;
|
|
34
|
+
return {
|
|
35
|
+
id,
|
|
36
|
+
name: fieldContext.name,
|
|
37
|
+
formItemId: `${id}-form-item`,
|
|
38
|
+
formDescriptionId: `${id}-form-item-description`,
|
|
39
|
+
formMessageId: `${id}-form-item-message`,
|
|
40
|
+
...fieldState
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
var FormItem = forwardRef(
|
|
44
|
+
function FormItem2({ className, ...props }, ref) {
|
|
45
|
+
const id = useId();
|
|
46
|
+
return /* @__PURE__ */ jsx(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx("div", { ref, className: cn("space-y-2", className), ...props }) });
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
var FormLabel = forwardRef(function FormLabel2({ className, ...props }, ref) {
|
|
50
|
+
const { error, formItemId } = useFormField();
|
|
51
|
+
return /* @__PURE__ */ jsx(
|
|
52
|
+
Label,
|
|
53
|
+
{
|
|
54
|
+
ref,
|
|
55
|
+
htmlFor: formItemId,
|
|
56
|
+
className: cn(
|
|
57
|
+
"transition-colors duration-fast ease-standard",
|
|
58
|
+
// #124: the label's own error-state text, not a mark — ink rung.
|
|
59
|
+
error && "text-destructive-text",
|
|
60
|
+
className
|
|
61
|
+
),
|
|
62
|
+
...props
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
var FormControl = forwardRef(function FormControl2(props, ref) {
|
|
67
|
+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
|
|
68
|
+
return /* @__PURE__ */ jsx(
|
|
69
|
+
Slot,
|
|
70
|
+
{
|
|
71
|
+
ref,
|
|
72
|
+
id: formItemId,
|
|
73
|
+
"aria-describedby": error ? `${formDescriptionId} ${formMessageId}` : formDescriptionId,
|
|
74
|
+
"aria-invalid": !!error,
|
|
75
|
+
...props
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
var FormDescription = forwardRef(function FormDescription2({ className, ...props }, ref) {
|
|
80
|
+
const { formDescriptionId } = useFormField();
|
|
81
|
+
return /* @__PURE__ */ jsx(
|
|
82
|
+
"p",
|
|
83
|
+
{
|
|
84
|
+
ref,
|
|
85
|
+
id: formDescriptionId,
|
|
86
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
87
|
+
...props
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
var FormMessage = forwardRef(
|
|
92
|
+
function FormMessage2({ className, children, ...props }, ref) {
|
|
93
|
+
const { error, formMessageId } = useFormField();
|
|
94
|
+
const body = error ? String(error?.message ?? "") : children;
|
|
95
|
+
if (!body) return null;
|
|
96
|
+
return /* @__PURE__ */ jsx(
|
|
97
|
+
"p",
|
|
98
|
+
{
|
|
99
|
+
ref,
|
|
100
|
+
id: formMessageId,
|
|
101
|
+
className: cn(
|
|
102
|
+
// #124: the error message body is running text — ink rung, not the
|
|
103
|
+
// 3:1 mark rung `text-destructive` guarantees.
|
|
104
|
+
"text-sm font-medium text-destructive-text animate-in fade-in slide-in-from-top-1 ease-entrance",
|
|
105
|
+
className
|
|
106
|
+
),
|
|
107
|
+
...props,
|
|
108
|
+
children: body
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
export {
|
|
114
|
+
Form,
|
|
115
|
+
FormControl,
|
|
116
|
+
FormDescription,
|
|
117
|
+
FormField,
|
|
118
|
+
FormItem,
|
|
119
|
+
FormLabel,
|
|
120
|
+
FormMessage,
|
|
121
|
+
useFormField
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=form.js.map
|
package/dist/form.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/form/form.tsx"],"sourcesContent":["import {\n createContext,\n forwardRef,\n useContext,\n useId,\n type ComponentPropsWithoutRef,\n type ElementRef,\n type HTMLAttributes,\n} from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport {\n Controller,\n FormProvider,\n useFormContext,\n type ControllerProps,\n type FieldPath,\n type FieldValues,\n} from \"react-hook-form\";\nimport { cn } from \"../../lib/cn\";\nimport { Label } from \"../label\";\n\nexport const Form = FormProvider;\n\ntype FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = { name: TName };\n\nconst FormFieldContext = createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\nexport function FormField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>(props: ControllerProps<TFieldValues, TName>) {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n}\n\nconst FormItemContext = createContext<{ id: string }>({} as { id: string });\n\nexport function useFormField() {\n const fieldContext = useContext(FormFieldContext);\n const itemContext = useContext(FormItemContext);\n const { getFieldState, formState } = useFormContext();\n const fieldState = getFieldState(fieldContext.name, formState);\n if (!fieldContext) throw new Error(\"useFormField should be used within <FormField>\");\n const { id } = itemContext;\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n };\n}\n\nexport const FormItem = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n function FormItem({ className, ...props }, ref) {\n const id = useId();\n return (\n <FormItemContext.Provider value={{ id }}>\n <div ref={ref} className={cn(\"space-y-2\", className)} {...props} />\n </FormItemContext.Provider>\n );\n },\n);\n\nexport const FormLabel = forwardRef<\n ElementRef<typeof Label>,\n ComponentPropsWithoutRef<typeof Label>\n>(function FormLabel({ className, ...props }, ref) {\n const { error, formItemId } = useFormField();\n return (\n <Label\n ref={ref}\n htmlFor={formItemId}\n className={cn(\n \"transition-colors duration-fast ease-standard\",\n // #124: the label's own error-state text, not a mark — ink rung.\n error && \"text-destructive-text\",\n className,\n )}\n {...props}\n />\n );\n});\n\nexport const FormControl = forwardRef<\n ElementRef<typeof Slot>,\n ComponentPropsWithoutRef<typeof Slot>\n>(function FormControl(props, ref) {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n return (\n <Slot\n ref={ref}\n id={formItemId}\n aria-describedby={error ? `${formDescriptionId} ${formMessageId}` : formDescriptionId}\n aria-invalid={!!error}\n {...props}\n />\n );\n});\n\nexport const FormDescription = forwardRef<\n HTMLParagraphElement,\n HTMLAttributes<HTMLParagraphElement>\n>(function FormDescription({ className, ...props }, ref) {\n const { formDescriptionId } = useFormField();\n return (\n <p\n ref={ref}\n id={formDescriptionId}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n );\n});\n\nexport const FormMessage = forwardRef<HTMLParagraphElement, HTMLAttributes<HTMLParagraphElement>>(\n function FormMessage({ className, children, ...props }, ref) {\n const { error, formMessageId } = useFormField();\n const body = error ? String(error?.message ?? \"\") : children;\n if (!body) return null;\n return (\n <p\n ref={ref}\n id={formMessageId}\n className={cn(\n // #124: the error message body is running text — ink rung, not the\n // 3:1 mark rung `text-destructive` guarantees.\n \"text-sm font-medium text-destructive-text animate-in fade-in slide-in-from-top-1 ease-entrance\",\n className,\n )}\n {...props}\n >\n {body}\n </p>\n );\n },\n);\n"],"mappings":";;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAmBD;AAfC,IAAM,OAAO;AAOpB,IAAM,mBAAmB,cAAqC,CAAC,CAA0B;AAElF,SAAS,UAGd,OAA6C;AAC7C,SACE,oBAAC,iBAAiB,UAAjB,EAA0B,OAAO,EAAE,MAAM,MAAM,KAAK,GACnD,8BAAC,cAAY,GAAG,OAAO,GACzB;AAEJ;AAEA,IAAM,kBAAkB,cAA8B,CAAC,CAAmB;AAEnE,SAAS,eAAe;AAC7B,QAAM,eAAe,WAAW,gBAAgB;AAChD,QAAM,cAAc,WAAW,eAAe;AAC9C,QAAM,EAAE,eAAe,UAAU,IAAI,eAAe;AACpD,QAAM,aAAa,cAAc,aAAa,MAAM,SAAS;AAC7D,MAAI,CAAC,aAAc,OAAM,IAAI,MAAM,gDAAgD;AACnF,QAAM,EAAE,GAAG,IAAI;AACf,SAAO;AAAA,IACL;AAAA,IACA,MAAM,aAAa;AAAA,IACnB,YAAY,GAAG,EAAE;AAAA,IACjB,mBAAmB,GAAG,EAAE;AAAA,IACxB,eAAe,GAAG,EAAE;AAAA,IACpB,GAAG;AAAA,EACL;AACF;AAEO,IAAM,WAAW;AAAA,EACtB,SAASA,UAAS,EAAE,WAAW,GAAG,MAAM,GAAG,KAAK;AAC9C,UAAM,KAAK,MAAM;AACjB,WACE,oBAAC,gBAAgB,UAAhB,EAAyB,OAAO,EAAE,GAAG,GACpC,8BAAC,SAAI,KAAU,WAAW,GAAG,aAAa,SAAS,GAAI,GAAG,OAAO,GACnE;AAAA,EAEJ;AACF;AAEO,IAAM,YAAY,WAGvB,SAASC,WAAU,EAAE,WAAW,GAAG,MAAM,GAAG,KAAK;AACjD,QAAM,EAAE,OAAO,WAAW,IAAI,aAAa;AAC3C,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,SAAS;AAAA,MACT,WAAW;AAAA,QACT;AAAA;AAAA,QAEA,SAAS;AAAA,QACT;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AAEM,IAAM,cAAc,WAGzB,SAASC,aAAY,OAAO,KAAK;AACjC,QAAM,EAAE,OAAO,YAAY,mBAAmB,cAAc,IAAI,aAAa;AAC7E,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,IAAI;AAAA,MACJ,oBAAkB,QAAQ,GAAG,iBAAiB,IAAI,aAAa,KAAK;AAAA,MACpE,gBAAc,CAAC,CAAC;AAAA,MACf,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AAEM,IAAM,kBAAkB,WAG7B,SAASC,iBAAgB,EAAE,WAAW,GAAG,MAAM,GAAG,KAAK;AACvD,QAAM,EAAE,kBAAkB,IAAI,aAAa;AAC3C,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,IAAI;AAAA,MACJ,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AAEM,IAAM,cAAc;AAAA,EACzB,SAASC,aAAY,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,KAAK;AAC3D,UAAM,EAAE,OAAO,cAAc,IAAI,aAAa;AAC9C,UAAM,OAAO,QAAQ,OAAO,OAAO,WAAW,EAAE,IAAI;AACpD,QAAI,CAAC,KAAM,QAAO;AAClB,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,IAAI;AAAA,QACJ,WAAW;AAAA;AAAA;AAAA,UAGT;AAAA,UACA;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;","names":["FormItem","FormLabel","FormControl","FormDescription","FormMessage"]}
|