@ciridae/ui 0.2.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 +31 -0
- package/dist/components/agentic/agent-card.d.ts +28 -0
- package/dist/components/agentic/agent-card.js +27 -0
- package/dist/components/agentic/agent-composer.d.ts +44 -0
- package/dist/components/agentic/agent-composer.js +104 -0
- package/dist/components/agentic/agent-context.d.ts +28 -0
- package/dist/components/agentic/agent-context.js +102 -0
- package/dist/components/agentic/agent-plan.d.ts +27 -0
- package/dist/components/agentic/agent-plan.js +43 -0
- package/dist/components/agentic/agent-queue.d.ts +46 -0
- package/dist/components/agentic/agent-queue.js +53 -0
- package/dist/components/agentic/agent-task.d.ts +16 -0
- package/dist/components/agentic/agent-task.js +20 -0
- package/dist/components/agentic/approval-request.d.ts +24 -0
- package/dist/components/agentic/approval-request.js +57 -0
- package/dist/components/agentic/artifact.d.ts +24 -0
- package/dist/components/agentic/artifact.js +72 -0
- package/dist/components/agentic/attachments.d.ts +124 -0
- package/dist/components/agentic/attachments.js +595 -0
- package/dist/components/agentic/audio-player.d.ts +16 -0
- package/dist/components/agentic/audio-player.js +21 -0
- package/dist/components/agentic/canvas.d.ts +10 -0
- package/dist/components/agentic/canvas.js +22 -0
- package/dist/components/agentic/clipboard.d.ts +2 -0
- package/dist/components/agentic/clipboard.js +12 -0
- package/dist/components/agentic/code-block.d.ts +43 -0
- package/dist/components/agentic/code-block.js +92 -0
- package/dist/components/agentic/commit.d.ts +57 -0
- package/dist/components/agentic/commit.js +85 -0
- package/dist/components/agentic/connection.d.ts +3 -0
- package/dist/components/agentic/connection.js +8 -0
- package/dist/components/agentic/controls.d.ts +6 -0
- package/dist/components/agentic/controls.js +7 -0
- package/dist/components/agentic/conversation.d.ts +25 -0
- package/dist/components/agentic/conversation.js +56 -0
- package/dist/components/agentic/edge.d.ts +8 -0
- package/dist/components/agentic/edge.js +65 -0
- package/dist/components/agentic/effort-selector.d.ts +43 -0
- package/dist/components/agentic/effort-selector.js +47 -0
- package/dist/components/agentic/environment-variables.d.ts +32 -0
- package/dist/components/agentic/environment-variables.js +66 -0
- package/dist/components/agentic/file-tree.d.ts +24 -0
- package/dist/components/agentic/file-tree.js +56 -0
- package/dist/components/agentic/image.d.ts +9 -0
- package/dist/components/agentic/image.js +11 -0
- package/dist/components/agentic/inline-citation.d.ts +40 -0
- package/dist/components/agentic/inline-citation.js +111 -0
- package/dist/components/agentic/jsx-preview.d.ts +19 -0
- package/dist/components/agentic/jsx-preview.js +34 -0
- package/dist/components/agentic/message-branch.d.ts +20 -0
- package/dist/components/agentic/message-branch.js +83 -0
- package/dist/components/agentic/message-response.css +265 -0
- package/dist/components/agentic/message-response.css.d.ts +2 -0
- package/dist/components/agentic/message.d.ts +27 -0
- package/dist/components/agentic/message.js +57 -0
- package/dist/components/agentic/mic-selector.d.ts +58 -0
- package/dist/components/agentic/mic-selector.js +173 -0
- package/dist/components/agentic/model-selector.d.ts +39 -0
- package/dist/components/agentic/model-selector.js +47 -0
- package/dist/components/agentic/node.d.ts +26 -0
- package/dist/components/agentic/node.js +29 -0
- package/dist/components/agentic/open-in-chat.d.ts +9 -0
- package/dist/components/agentic/open-in-chat.js +8 -0
- package/dist/components/agentic/package-info.d.ts +30 -0
- package/dist/components/agentic/package-info.js +44 -0
- package/dist/components/agentic/panel.d.ts +6 -0
- package/dist/components/agentic/panel.js +7 -0
- package/dist/components/agentic/persona.d.ts +16 -0
- package/dist/components/agentic/persona.js +116 -0
- package/dist/components/agentic/prompt-input-action-menu.d.ts +16 -0
- package/dist/components/agentic/prompt-input-action-menu.js +22 -0
- package/dist/components/agentic/prompt-input-command.d.ts +18 -0
- package/dist/components/agentic/prompt-input-command.js +25 -0
- package/dist/components/agentic/prompt-input-hover-card.d.ts +10 -0
- package/dist/components/agentic/prompt-input-hover-card.js +13 -0
- package/dist/components/agentic/prompt-input-select.d.ts +14 -0
- package/dist/components/agentic/prompt-input-select.js +19 -0
- package/dist/components/agentic/prompt-input-tabs.d.ts +17 -0
- package/dist/components/agentic/prompt-input-tabs.js +45 -0
- package/dist/components/agentic/prompt-input.d.ts +79 -0
- package/dist/components/agentic/prompt-input.js +206 -0
- package/dist/components/agentic/reasoning.d.ts +21 -0
- package/dist/components/agentic/reasoning.js +106 -0
- package/dist/components/agentic/run-checkpoint.d.ts +13 -0
- package/dist/components/agentic/run-checkpoint.js +19 -0
- package/dist/components/agentic/run-trace.d.ts +30 -0
- package/dist/components/agentic/run-trace.js +56 -0
- package/dist/components/agentic/sandbox.d.ts +24 -0
- package/dist/components/agentic/sandbox.js +33 -0
- package/dist/components/agentic/schema-display.d.ts +39 -0
- package/dist/components/agentic/schema-display.js +56 -0
- package/dist/components/agentic/shimmer.d.ts +11 -0
- package/dist/components/agentic/shimmer.js +16 -0
- package/dist/components/agentic/snippet.d.ts +18 -0
- package/dist/components/agentic/snippet.js +35 -0
- package/dist/components/agentic/sources.d.ts +16 -0
- package/dist/components/agentic/sources.js +17 -0
- package/dist/components/agentic/speech-input.d.ts +24 -0
- package/dist/components/agentic/speech-input.js +30 -0
- package/dist/components/agentic/stack-trace.d.ts +27 -0
- package/dist/components/agentic/stack-trace.js +76 -0
- package/dist/components/agentic/suggestion.d.ts +12 -0
- package/dist/components/agentic/suggestion.js +15 -0
- package/dist/components/agentic/terminal.d.ts +24 -0
- package/dist/components/agentic/terminal.js +47 -0
- package/dist/components/agentic/test-results.d.ts +51 -0
- package/dist/components/agentic/test-results.js +83 -0
- package/dist/components/agentic/theme.d.ts +5 -0
- package/dist/components/agentic/theme.js +31 -0
- package/dist/components/agentic/tool.d.ts +25 -0
- package/dist/components/agentic/tool.js +73 -0
- package/dist/components/agentic/toolbar.d.ts +6 -0
- package/dist/components/agentic/toolbar.js +7 -0
- package/dist/components/agentic/transcription.d.ts +20 -0
- package/dist/components/agentic/transcription.js +32 -0
- package/dist/components/agentic/types.d.ts +172 -0
- package/dist/components/agentic/types.js +1 -0
- package/dist/components/agentic/use-controllable-state.d.ts +6 -0
- package/dist/components/agentic/use-controllable-state.js +13 -0
- package/dist/components/agentic/voice-selector.d.ts +69 -0
- package/dist/components/agentic/voice-selector.js +122 -0
- package/dist/components/agentic/web-preview.d.ts +25 -0
- package/dist/components/agentic/web-preview.js +33 -0
- package/dist/components/ui/accordion.d.ts +7 -0
- package/dist/components/ui/accordion.js +17 -0
- package/dist/components/ui/alert-dialog.d.ts +22 -0
- package/dist/components/ui/alert-dialog.js +51 -0
- package/dist/components/ui/alert.d.ts +9 -0
- package/dist/components/ui/alert.js +24 -0
- package/dist/components/ui/aspect-ratio.d.ts +3 -0
- package/dist/components/ui/aspect-ratio.js +7 -0
- package/dist/components/ui/avatar.d.ts +11 -0
- package/dist/components/ui/avatar.js +22 -0
- package/dist/components/ui/badge-variants.d.ts +100 -0
- package/dist/components/ui/badge-variants.js +140 -0
- package/dist/components/ui/badge.d.ts +6 -0
- package/dist/components/ui/badge.js +9 -0
- package/dist/components/ui/breadcrumb.d.ts +11 -0
- package/dist/components/ui/breadcrumb.js +27 -0
- package/dist/components/ui/button-group-variants.d.ts +6 -0
- package/dist/components/ui/button-group-variants.js +13 -0
- package/dist/components/ui/button-group.d.ts +8 -0
- package/dist/components/ui/button-group.js +16 -0
- package/dist/components/ui/button-variants.d.ts +133 -0
- package/dist/components/ui/button-variants.js +170 -0
- package/dist/components/ui/button.d.ts +8 -0
- package/dist/components/ui/button.js +67 -0
- package/dist/components/ui/calendar.d.ts +9 -0
- package/dist/components/ui/calendar.js +99 -0
- package/dist/components/ui/card.d.ts +14 -0
- package/dist/components/ui/card.js +28 -0
- package/dist/components/ui/carousel.d.ts +19 -0
- package/dist/components/ui/carousel.js +104 -0
- package/dist/components/ui/chart-context.d.ts +33 -0
- package/dist/components/ui/chart-context.js +36 -0
- package/dist/components/ui/chart-panel.d.ts +11 -0
- package/dist/components/ui/chart-panel.js +6 -0
- package/dist/components/ui/chart-tooltip.d.ts +13 -0
- package/dist/components/ui/chart-tooltip.js +84 -0
- package/dist/components/ui/chart.d.ts +23 -0
- package/dist/components/ui/chart.js +52 -0
- package/dist/components/ui/checkbox.d.ts +4 -0
- package/dist/components/ui/checkbox.js +9 -0
- package/dist/components/ui/collapsible.d.ts +5 -0
- package/dist/components/ui/collapsible.js +12 -0
- package/dist/components/ui/combobox-anchor.d.ts +3 -0
- package/dist/components/ui/combobox-anchor.js +5 -0
- package/dist/components/ui/combobox.d.ts +23 -0
- package/dist/components/ui/combobox.js +54 -0
- package/dist/components/ui/command.d.ts +19 -0
- package/dist/components/ui/command.js +38 -0
- package/dist/components/ui/context-menu.d.ts +30 -0
- package/dist/components/ui/context-menu.js +63 -0
- package/dist/components/ui/data-table.d.ts +17 -0
- package/dist/components/ui/data-table.js +26 -0
- package/dist/components/ui/dialog.d.ts +22 -0
- package/dist/components/ui/dialog.js +48 -0
- package/dist/components/ui/direction-context.d.ts +3 -0
- package/dist/components/ui/direction-context.js +3 -0
- package/dist/components/ui/direction.d.ts +6 -0
- package/dist/components/ui/direction.js +7 -0
- package/dist/components/ui/drawer.d.ts +18 -0
- package/dist/components/ui/drawer.js +47 -0
- package/dist/components/ui/dropdown-menu.d.ts +30 -0
- package/dist/components/ui/dropdown-menu.js +63 -0
- package/dist/components/ui/empty.d.ts +11 -0
- package/dist/components/ui/empty.js +33 -0
- package/dist/components/ui/expandable-data-table.d.ts +24 -0
- package/dist/components/ui/expandable-data-table.js +62 -0
- package/dist/components/ui/field.d.ts +26 -0
- package/dist/components/ui/field.js +74 -0
- package/dist/components/ui/file-upload-field-parts.d.ts +21 -0
- package/dist/components/ui/file-upload-field-parts.js +55 -0
- package/dist/components/ui/file-upload-field.d.ts +15 -0
- package/dist/components/ui/file-upload-field.js +85 -0
- package/dist/components/ui/form-context.d.ts +23 -0
- package/dist/components/ui/form-context.js +35 -0
- package/dist/components/ui/form.d.ts +12 -0
- package/dist/components/ui/form.js +38 -0
- package/dist/components/ui/hover-card.d.ts +10 -0
- package/dist/components/ui/hover-card.js +22 -0
- package/dist/components/ui/input-group.d.ts +16 -0
- package/dist/components/ui/input-group.js +62 -0
- package/dist/components/ui/input-otp.d.ts +11 -0
- package/dist/components/ui/input-otp.js +21 -0
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/input.js +6 -0
- package/dist/components/ui/item.d.ts +23 -0
- package/dist/components/ui/item.js +66 -0
- package/dist/components/ui/kbd.d.ts +3 -0
- package/dist/components/ui/kbd.js +9 -0
- package/dist/components/ui/label.d.ts +4 -0
- package/dist/components/ui/label.js +7 -0
- package/dist/components/ui/loading-state.d.ts +27 -0
- package/dist/components/ui/loading-state.js +44 -0
- package/dist/components/ui/menubar.d.ts +30 -0
- package/dist/components/ui/menubar.js +63 -0
- package/dist/components/ui/metrics-strip.d.ts +7 -0
- package/dist/components/ui/metrics-strip.js +18 -0
- package/dist/components/ui/native-select.d.ts +7 -0
- package/dist/components/ui/native-select.js +13 -0
- package/dist/components/ui/navigation-menu-variants.d.ts +2 -0
- package/dist/components/ui/navigation-menu-variants.js +3 -0
- package/dist/components/ui/navigation-menu.d.ts +13 -0
- package/dist/components/ui/navigation-menu.js +30 -0
- package/dist/components/ui/page-header.d.ts +19 -0
- package/dist/components/ui/page-header.js +36 -0
- package/dist/components/ui/pagination.d.ts +13 -0
- package/dist/components/ui/pagination.js +29 -0
- package/dist/components/ui/popover.d.ts +14 -0
- package/dist/components/ui/popover.js +34 -0
- package/dist/components/ui/progress.d.ts +4 -0
- package/dist/components/ui/progress.js +8 -0
- package/dist/components/ui/property-list.d.ts +6 -0
- package/dist/components/ui/property-list.js +15 -0
- package/dist/components/ui/radio-group.d.ts +5 -0
- package/dist/components/ui/radio-group.js +11 -0
- package/dist/components/ui/registry-docs-api.d.ts +11 -0
- package/dist/components/ui/registry-docs-api.js +9 -0
- package/dist/components/ui/registry-docs-code.d.ts +19 -0
- package/dist/components/ui/registry-docs-code.js +78 -0
- package/dist/components/ui/registry-docs-showcase.d.ts +11 -0
- package/dist/components/ui/registry-docs-showcase.js +27 -0
- package/dist/components/ui/registry-docs.d.ts +27 -0
- package/dist/components/ui/registry-docs.js +32 -0
- package/dist/components/ui/resizable.d.ts +7 -0
- package/dist/components/ui/resizable.js +15 -0
- package/dist/components/ui/scroll-area.d.ts +7 -0
- package/dist/components/ui/scroll-area.js +10 -0
- package/dist/components/ui/select.d.ts +15 -0
- package/dist/components/ui/select.js +38 -0
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/separator.js +7 -0
- package/dist/components/ui/sheet.d.ts +21 -0
- package/dist/components/ui/sheet.js +62 -0
- package/dist/components/ui/sidebar/context.d.ts +21 -0
- package/dist/components/ui/sidebar/context.js +15 -0
- package/dist/components/ui/sidebar/group.d.ts +10 -0
- package/dist/components/ui/sidebar/group.js +18 -0
- package/dist/components/ui/sidebar/layout.d.ts +17 -0
- package/dist/components/ui/sidebar/layout.js +73 -0
- package/dist/components/ui/sidebar/menu.d.ts +30 -0
- package/dist/components/ui/sidebar/menu.js +64 -0
- package/dist/components/ui/sidebar/provider.d.ts +7 -0
- package/dist/components/ui/sidebar/provider.js +53 -0
- package/dist/components/ui/sidebar/rail.d.ts +3 -0
- package/dist/components/ui/sidebar/rail.js +12 -0
- package/dist/components/ui/sidebar/trigger.d.ts +4 -0
- package/dist/components/ui/sidebar/trigger.js +16 -0
- package/dist/components/ui/sidebar-account-menu-theme.d.ts +7 -0
- package/dist/components/ui/sidebar-account-menu-theme.js +32 -0
- package/dist/components/ui/sidebar-account-menu.d.ts +14 -0
- package/dist/components/ui/sidebar-account-menu.js +51 -0
- package/dist/components/ui/sidebar.d.ts +7 -0
- package/dist/components/ui/sidebar.js +7 -0
- package/dist/components/ui/skeleton.d.ts +2 -0
- package/dist/components/ui/skeleton.js +15 -0
- package/dist/components/ui/slider.d.ts +4 -0
- package/dist/components/ui/slider.js +9 -0
- package/dist/components/ui/sonner.d.ts +3 -0
- package/dist/components/ui/sonner.js +33 -0
- package/dist/components/ui/spinner.d.ts +2 -0
- package/dist/components/ui/spinner.js +16 -0
- package/dist/components/ui/switch.d.ts +6 -0
- package/dist/components/ui/switch.js +7 -0
- package/dist/components/ui/table.d.ts +10 -0
- package/dist/components/ui/table.js +28 -0
- package/dist/components/ui/tabs-variants.d.ts +6 -0
- package/dist/components/ui/tabs-variants.js +13 -0
- package/dist/components/ui/tabs.d.ts +8 -0
- package/dist/components/ui/tabs.js +17 -0
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/textarea.js +6 -0
- package/dist/components/ui/toggle-group.d.ts +9 -0
- package/dist/components/ui/toggle-group.js +24 -0
- package/dist/components/ui/toggle-variants.d.ts +7 -0
- package/dist/components/ui/toggle-variants.js +19 -0
- package/dist/components/ui/toggle.d.ts +5 -0
- package/dist/components/ui/toggle.js +9 -0
- package/dist/components/ui/tooltip.d.ts +11 -0
- package/dist/components/ui/tooltip.js +25 -0
- package/dist/components/ui/workflow-timeline.d.ts +20 -0
- package/dist/components/ui/workflow-timeline.js +92 -0
- package/dist/hooks/use-mobile.d.ts +1 -0
- package/dist/hooks/use-mobile.js +15 -0
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.js +8 -0
- package/dist/styled-system/css/conditions.mjs +36 -0
- package/dist/styled-system/css/css.mjs +45 -0
- package/dist/styled-system/css/cva.mjs +87 -0
- package/dist/styled-system/css/cx.mjs +15 -0
- package/dist/styled-system/css/index.mjs +4 -0
- package/dist/styled-system/css/sva.mjs +46 -0
- package/dist/styled-system/helpers.mjs +316 -0
- package/dist/styled-system/patterns/aspect-ratio.mjs +38 -0
- package/dist/styled-system/patterns/bleed.mjs +24 -0
- package/dist/styled-system/patterns/box.mjs +15 -0
- package/dist/styled-system/patterns/center.mjs +21 -0
- package/dist/styled-system/patterns/circle.mjs +25 -0
- package/dist/styled-system/patterns/container.mjs +21 -0
- package/dist/styled-system/patterns/cq.mjs +21 -0
- package/dist/styled-system/patterns/divider.mjs +25 -0
- package/dist/styled-system/patterns/flex.mjs +26 -0
- package/dist/styled-system/patterns/float.mjs +52 -0
- package/dist/styled-system/patterns/grid-item.mjs +25 -0
- package/dist/styled-system/patterns/grid.mjs +27 -0
- package/dist/styled-system/patterns/hstack.mjs +24 -0
- package/dist/styled-system/patterns/index.mjs +20 -0
- package/dist/styled-system/patterns/link-overlay.mjs +24 -0
- package/dist/styled-system/patterns/spacer.mjs +25 -0
- package/dist/styled-system/patterns/square.mjs +24 -0
- package/dist/styled-system/patterns/stack.mjs +24 -0
- package/dist/styled-system/patterns/visually-hidden.mjs +18 -0
- package/dist/styled-system/patterns/vstack.mjs +24 -0
- package/dist/styled-system/patterns/wrap.mjs +25 -0
- package/dist/styled-system/styles.css +1089 -0
- package/dist/styled-system/styles.css.d.ts +2 -0
- package/dist/styled-system/tokens/index.mjs +2304 -0
- package/package.json +688 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import { cn } from "@ciridae/ui/utils";
|
|
6
|
+
import { Label } from "@ciridae/ui/label";
|
|
7
|
+
import { Separator } from "@ciridae/ui/separator";
|
|
8
|
+
function FieldSet({ className, ...props }) {
|
|
9
|
+
return (_jsx("fieldset", { "data-slot": "field-set", className: cn("flex flex-col gap-[calc(var(--panel-gap)+0.5rem)]", "has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", className), ...props }));
|
|
10
|
+
}
|
|
11
|
+
function FieldLegend({ className, variant = "legend", ...props }) {
|
|
12
|
+
return (_jsx("legend", { "data-slot": "field-legend", "data-variant": variant, className: cn("mb-3 font-medium", "data-[variant=legend]:text-base", "data-[variant=label]:text-sm", className), ...props }));
|
|
13
|
+
}
|
|
14
|
+
function FieldGroup({ className, ...props }) {
|
|
15
|
+
return (_jsx("div", { "data-slot": "field-group", className: cn("group/field-group @container/field-group flex w-full flex-col gap-[calc(var(--panel-gap)+0.75rem)] data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-(--panel-gap)", className), ...props }));
|
|
16
|
+
}
|
|
17
|
+
const fieldVariants = cva("group/field flex w-full gap-3 data-[invalid=true]:text-destructive", {
|
|
18
|
+
variants: {
|
|
19
|
+
orientation: {
|
|
20
|
+
vertical: ["flex-col [&>*]:w-full [&>.sr-only]:w-auto"],
|
|
21
|
+
horizontal: [
|
|
22
|
+
"flex-row items-center",
|
|
23
|
+
"[&>[data-slot=field-label]]:flex-auto",
|
|
24
|
+
"has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
|
|
25
|
+
],
|
|
26
|
+
responsive: [
|
|
27
|
+
"flex-col @md/field-group:flex-row @md/field-group:items-center [&>*]:w-full @md/field-group:[&>*]:w-auto [&>.sr-only]:w-auto",
|
|
28
|
+
"@md/field-group:[&>[data-slot=field-label]]:flex-auto",
|
|
29
|
+
"@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
defaultVariants: {
|
|
34
|
+
orientation: "vertical",
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
function Field({ className, orientation = "vertical", ...props }) {
|
|
38
|
+
return (_jsx("div", { role: "group", "data-slot": "field", "data-orientation": orientation, className: cn(fieldVariants({ orientation }), className), ...props }));
|
|
39
|
+
}
|
|
40
|
+
function FieldContent({ className, ...props }) {
|
|
41
|
+
return (_jsx("div", { "data-slot": "field-content", className: cn("group/field-content flex flex-1 flex-col gap-1.5 leading-snug", className), ...props }));
|
|
42
|
+
}
|
|
43
|
+
function FieldLabel({ children, className, required, ...props }) {
|
|
44
|
+
return (_jsxs(Label, { "data-slot": "field-label", className: cn("group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50", "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-(--panel-padding)", "has-data-[state=checked]:border-primary has-data-[state=checked]:bg-primary/5 dark:has-data-[state=checked]:bg-primary/10", className), ...props, children: [children, required ? (_jsx("span", { "aria-hidden": "true", className: "text-destructive", children: "*" })) : null] }));
|
|
45
|
+
}
|
|
46
|
+
function FieldTitle({ className, ...props }) {
|
|
47
|
+
return (_jsx("div", { "data-slot": "field-label", className: cn("flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50", className), ...props }));
|
|
48
|
+
}
|
|
49
|
+
function FieldDescription({ className, ...props }) {
|
|
50
|
+
return (_jsx("p", { "data-slot": "field-description", className: cn("text-sm leading-normal font-normal text-muted-foreground group-has-[[data-orientation=horizontal]]/field:text-balance", "last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5", "[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary", className), ...props }));
|
|
51
|
+
}
|
|
52
|
+
function FieldSeparator({ children, className, ...props }) {
|
|
53
|
+
return (_jsxs("div", { "data-slot": "field-separator", "data-content": !!children, className: cn("relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2", className), ...props, children: [_jsx(Separator, { className: "absolute inset-0 top-1/2" }), children && (_jsx("span", { className: "relative mx-auto block w-fit bg-background px-2 text-muted-foreground", "data-slot": "field-separator-content", children: children }))] }));
|
|
54
|
+
}
|
|
55
|
+
function FieldError({ className, children, errors, ...props }) {
|
|
56
|
+
const content = useMemo(() => {
|
|
57
|
+
if (children) {
|
|
58
|
+
return children;
|
|
59
|
+
}
|
|
60
|
+
if (!errors?.length) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const uniqueErrors = [...new Map(errors.map((error) => [error?.message, error])).values()];
|
|
64
|
+
if (uniqueErrors?.length == 1) {
|
|
65
|
+
return uniqueErrors[0]?.message;
|
|
66
|
+
}
|
|
67
|
+
return (_jsx("ul", { className: "ml-4 flex list-disc flex-col gap-1", children: uniqueErrors.map((error, index) => error?.message && _jsx("li", { children: error.message }, index)) }));
|
|
68
|
+
}, [children, errors]);
|
|
69
|
+
if (!content) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return (_jsx("div", { role: "alert", "data-slot": "field-error", className: cn("text-sm font-normal text-destructive", className), ...props, children: content }));
|
|
73
|
+
}
|
|
74
|
+
export { Field, FieldLabel, FieldDescription, FieldError, FieldGroup, FieldLegend, FieldSeparator, FieldSet, FieldContent, FieldTitle, };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
type FileUploadControlProps = {
|
|
3
|
+
acceptedFileTypes: string | undefined;
|
|
4
|
+
disabled: boolean;
|
|
5
|
+
dragActive: boolean;
|
|
6
|
+
error: string | undefined;
|
|
7
|
+
files: File[];
|
|
8
|
+
inputId: string;
|
|
9
|
+
inputRef: React.RefObject<HTMLInputElement | null>;
|
|
10
|
+
maxAttachments: number;
|
|
11
|
+
onAddFiles: (files: FileList | File[]) => void;
|
|
12
|
+
onDragActiveChange: (active: boolean) => void;
|
|
13
|
+
};
|
|
14
|
+
declare function FileUploadCompactControl({ acceptedFileTypes, disabled, dragActive, error, files, inputId, inputRef, maxAttachments, onAddFiles, onDragActiveChange, }: FileUploadControlProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
declare function FileUploadDropZone({ acceptedFileTypes, disabled, dragActive, error, files, inputId, inputRef, maxAttachments, onAddFiles, onDragActiveChange, }: FileUploadControlProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
declare function FileUploadList({ disabled, files, onRemoveFile, }: {
|
|
17
|
+
disabled: boolean;
|
|
18
|
+
files: File[];
|
|
19
|
+
onRemoveFile: (index: number) => void;
|
|
20
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
21
|
+
export { FileUploadCompactControl, FileUploadDropZone, FileUploadList };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { FileIcon, PaperclipIcon, UploadCloudIcon, XIcon } from "lucide-react";
|
|
3
|
+
import { cn } from "@ciridae/ui/utils";
|
|
4
|
+
import { Button } from "@ciridae/ui/button";
|
|
5
|
+
import { Item, ItemActions, ItemContent, ItemDescription, ItemGroup, ItemMedia, ItemTitle, } from "@ciridae/ui/item";
|
|
6
|
+
function FileUploadCompactControl({ acceptedFileTypes, disabled, dragActive, error, files, inputId, inputRef, maxAttachments, onAddFiles, onDragActiveChange, }) {
|
|
7
|
+
const isAtLimit = files.length >= maxAttachments;
|
|
8
|
+
return (_jsxs("div", { "data-drag-active": dragActive, className: cn("flex items-center gap-3 rounded-md border bg-card px-3 py-2 transition-colors", "data-[drag-active=true]:border-ring data-[drag-active=true]:bg-muted/50", disabled && "cursor-not-allowed opacity-60"), onDragEnter: (event) => handleDragEnter(event, disabled, onDragActiveChange), onDragLeave: (event) => handleDragLeave(event, onDragActiveChange), onDragOver: (event) => event.preventDefault(), onDrop: (event) => handleDrop(event, { disabled, onAddFiles, onDragActiveChange }), children: [_jsx("input", { accept: acceptedFileTypes, "aria-describedby": error ? `${inputId}-error` : undefined, className: "sr-only", disabled: disabled || isAtLimit, id: inputId, multiple: true, onChange: (event) => handleFileInputChange(event, onAddFiles), ref: inputRef, type: "file" }), _jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [_jsx(PaperclipIcon, { className: "size-4 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "truncate text-sm font-medium", children: files.length > 0 ? `${files.length} attached` : "Attach files" }), _jsx("div", { className: "truncate text-xs text-muted-foreground", children: "Files stay in the browser until submit." })] })] }), _jsx(Button, { disabled: disabled || isAtLimit, onClick: () => inputRef.current?.click(), size: "sm", type: "button", variant: "outline", children: "Attach" })] }));
|
|
9
|
+
}
|
|
10
|
+
function FileUploadDropZone({ acceptedFileTypes, disabled, dragActive, error, files, inputId, inputRef, maxAttachments, onAddFiles, onDragActiveChange, }) {
|
|
11
|
+
const isAtLimit = files.length >= maxAttachments;
|
|
12
|
+
return (_jsxs("div", { "data-drag-active": dragActive, className: cn("grid gap-3 rounded-lg border border-dashed bg-card p-(--panel-padding) transition-colors", "data-[drag-active=true]:border-ring data-[drag-active=true]:bg-muted/50", disabled && "cursor-not-allowed opacity-60"), onDragEnter: (event) => handleDragEnter(event, disabled, onDragActiveChange), onDragLeave: (event) => handleDragLeave(event, onDragActiveChange), onDragOver: (event) => event.preventDefault(), onDrop: (event) => handleDrop(event, { disabled, onAddFiles, onDragActiveChange }), children: [_jsx(FileUploadDropZoneContent, { disabled: disabled, files: files, inputRef: inputRef, maxAttachments: maxAttachments }), _jsx("input", { accept: acceptedFileTypes, "aria-describedby": error ? `${inputId}-error` : undefined, className: "sr-only", disabled: disabled || isAtLimit, id: inputId, multiple: true, onChange: (event) => handleFileInputChange(event, onAddFiles), ref: inputRef, type: "file" })] }));
|
|
13
|
+
}
|
|
14
|
+
function FileUploadDropZoneContent({ disabled, files, inputRef, maxAttachments, }) {
|
|
15
|
+
const isAtLimit = files.length >= maxAttachments;
|
|
16
|
+
return (_jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "flex size-9 shrink-0 items-center justify-center rounded-md border bg-muted", children: _jsx(UploadCloudIcon, { className: "size-4 text-muted-foreground" }) }), _jsxs("div", { className: "grid flex-1 gap-1", children: [_jsx("div", { className: "text-sm font-medium", children: "Drop files here or browse" }), _jsx("div", { className: "text-sm text-muted-foreground", children: "Supports images, PDFs, spreadsheets, text files, and documents." })] }), _jsx(Button, { disabled: disabled || isAtLimit, onClick: () => inputRef.current?.click(), type: "button", variant: "outline", children: "Browse" })] }));
|
|
17
|
+
}
|
|
18
|
+
function FileUploadList({ disabled, files, onRemoveFile, }) {
|
|
19
|
+
if (files.length === 0)
|
|
20
|
+
return null;
|
|
21
|
+
return (_jsx(ItemGroup, { className: "gap-2", children: files.map((file, index) => (_jsxs(Item, { size: "sm", variant: "outline", children: [_jsx(ItemMedia, { variant: "icon", children: _jsx(FileIcon, { className: "size-4 text-muted-foreground" }) }), _jsxs(ItemContent, { children: [_jsx(ItemTitle, { className: "max-w-full break-all", children: file.name }), _jsx(ItemDescription, { className: "font-mono tabular-nums", children: formatFileSize(file.size) })] }), _jsx(ItemActions, { children: _jsx(Button, { "aria-label": `Remove ${file.name}`, disabled: disabled, onClick: () => onRemoveFile(index), size: "icon-sm", type: "button", variant: "ghost", children: _jsx(XIcon, {}) }) })] }, `${file.name}-${file.size}-${index}`))) }));
|
|
22
|
+
}
|
|
23
|
+
function handleDragEnter(event, disabled, onDragActiveChange) {
|
|
24
|
+
event.preventDefault();
|
|
25
|
+
if (!disabled)
|
|
26
|
+
onDragActiveChange(true);
|
|
27
|
+
}
|
|
28
|
+
function handleDragLeave(event, onDragActiveChange) {
|
|
29
|
+
event.preventDefault();
|
|
30
|
+
const nextTarget = event.relatedTarget;
|
|
31
|
+
if (nextTarget instanceof Node && event.currentTarget.contains(nextTarget))
|
|
32
|
+
return;
|
|
33
|
+
onDragActiveChange(false);
|
|
34
|
+
}
|
|
35
|
+
function handleDrop(event, options) {
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
options.onDragActiveChange(false);
|
|
38
|
+
if (options.disabled)
|
|
39
|
+
return;
|
|
40
|
+
if (event.dataTransfer.files.length > 0)
|
|
41
|
+
options.onAddFiles(event.dataTransfer.files);
|
|
42
|
+
}
|
|
43
|
+
function handleFileInputChange(event, onAddFiles) {
|
|
44
|
+
if (!event.target.files)
|
|
45
|
+
return;
|
|
46
|
+
if (event.target.files.length > 0)
|
|
47
|
+
onAddFiles(event.target.files);
|
|
48
|
+
event.currentTarget.value = "";
|
|
49
|
+
}
|
|
50
|
+
function formatFileSize(size) {
|
|
51
|
+
if (size < 1024 * 1024)
|
|
52
|
+
return `${Math.max(1, Math.round(size / 1024))} KB`;
|
|
53
|
+
return `${(size / 1024 / 1024).toFixed(1)} MB`;
|
|
54
|
+
}
|
|
55
|
+
export { FileUploadCompactControl, FileUploadDropZone, FileUploadList };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type FileUploadFieldProps = {
|
|
2
|
+
acceptedFileTypes?: string;
|
|
3
|
+
className?: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
files: File[];
|
|
7
|
+
label?: string;
|
|
8
|
+
maxAttachmentSizeMb?: number;
|
|
9
|
+
maxAttachments?: number;
|
|
10
|
+
onFilesChange: (files: File[]) => void;
|
|
11
|
+
showConstraints?: boolean;
|
|
12
|
+
variant?: "compact" | "dropzone";
|
|
13
|
+
};
|
|
14
|
+
declare function FileUploadField({ acceptedFileTypes, className, description, disabled, files, label, maxAttachmentSizeMb, maxAttachments, onFilesChange, showConstraints, variant, }: FileUploadFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export { FileUploadField, type FileUploadFieldProps };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { FileUploadCompactControl, FileUploadDropZone, FileUploadList, } from "./file-upload-field-parts";
|
|
4
|
+
import { Field, FieldContent, FieldDescription, FieldError, FieldLabel, } from "@ciridae/ui/field";
|
|
5
|
+
function FileUploadField({ acceptedFileTypes, className, description, disabled = false, files, label = "Attachments", maxAttachmentSizeMb = 10, maxAttachments = 4, onFilesChange, showConstraints = true, variant = "dropzone", }) {
|
|
6
|
+
const inputId = React.useId();
|
|
7
|
+
const uploadState = useFileUploadFieldState({
|
|
8
|
+
acceptedFileTypes,
|
|
9
|
+
files,
|
|
10
|
+
maxAttachmentSizeMb,
|
|
11
|
+
maxAttachments,
|
|
12
|
+
onFilesChange,
|
|
13
|
+
});
|
|
14
|
+
const fieldDescription = description ??
|
|
15
|
+
(variant === "compact"
|
|
16
|
+
? "Optional supporting files."
|
|
17
|
+
: "Attach screenshots, documents, or source files that help explain the request.");
|
|
18
|
+
return (_jsxs(Field, { className: className, "data-invalid": !!uploadState.error, children: [_jsxs(FieldContent, { children: [_jsx(FieldLabel, { htmlFor: inputId, children: label }), _jsx(FieldDescription, { children: getFieldDescription(fieldDescription, showConstraints, {
|
|
19
|
+
maxAttachmentSizeMb,
|
|
20
|
+
maxAttachments,
|
|
21
|
+
}) })] }), variant === "compact" ? (_jsx(FileUploadCompactControl, { acceptedFileTypes: acceptedFileTypes, disabled: disabled, dragActive: uploadState.dragActive, error: uploadState.error, files: files, inputId: inputId, inputRef: uploadState.inputRef, maxAttachments: maxAttachments, onAddFiles: uploadState.addFiles, onDragActiveChange: uploadState.setDragActive })) : (_jsx(FileUploadDropZone, { acceptedFileTypes: acceptedFileTypes, disabled: disabled, dragActive: uploadState.dragActive, error: uploadState.error, files: files, inputId: inputId, inputRef: uploadState.inputRef, maxAttachments: maxAttachments, onAddFiles: uploadState.addFiles, onDragActiveChange: uploadState.setDragActive })), _jsx(FileUploadList, { disabled: disabled, files: files, onRemoveFile: uploadState.removeFile }), uploadState.error ? (_jsx(FieldError, { id: `${inputId}-error`, children: uploadState.error })) : null] }));
|
|
22
|
+
}
|
|
23
|
+
function useFileUploadFieldState({ acceptedFileTypes, files, maxAttachmentSizeMb, maxAttachments, onFilesChange, }) {
|
|
24
|
+
const inputRef = React.useRef(null);
|
|
25
|
+
const [dragActive, setDragActive] = React.useState(false);
|
|
26
|
+
const [error, setError] = React.useState();
|
|
27
|
+
const addFiles = (incomingFiles) => {
|
|
28
|
+
const nextFiles = Array.from(incomingFiles);
|
|
29
|
+
const validationError = getFileUploadError({
|
|
30
|
+
acceptedFileTypes,
|
|
31
|
+
currentCount: files.length,
|
|
32
|
+
files: nextFiles,
|
|
33
|
+
maxAttachmentSizeMb: maxAttachmentSizeMb ?? 10,
|
|
34
|
+
maxAttachments: maxAttachments ?? 4,
|
|
35
|
+
});
|
|
36
|
+
setError(validationError);
|
|
37
|
+
if (validationError)
|
|
38
|
+
return;
|
|
39
|
+
onFilesChange([...files, ...nextFiles]);
|
|
40
|
+
if (inputRef.current)
|
|
41
|
+
inputRef.current.value = "";
|
|
42
|
+
};
|
|
43
|
+
const removeFile = (indexToRemove) => {
|
|
44
|
+
setError(undefined);
|
|
45
|
+
onFilesChange(files.filter((_, index) => index !== indexToRemove));
|
|
46
|
+
};
|
|
47
|
+
return { addFiles, dragActive, error, inputRef, removeFile, setDragActive };
|
|
48
|
+
}
|
|
49
|
+
function getFieldDescription(description, showConstraints, { maxAttachmentSizeMb, maxAttachments, }) {
|
|
50
|
+
if (!showConstraints)
|
|
51
|
+
return description;
|
|
52
|
+
return `${description} Up to ${maxAttachments} files, ${maxAttachmentSizeMb} MB each.`;
|
|
53
|
+
}
|
|
54
|
+
function getFileUploadError({ acceptedFileTypes, currentCount, files, maxAttachmentSizeMb, maxAttachments, }) {
|
|
55
|
+
if (currentCount + files.length > maxAttachments) {
|
|
56
|
+
return `Attach up to ${maxAttachments} files.`;
|
|
57
|
+
}
|
|
58
|
+
const oversizedFile = files.find((file) => file.size > maxAttachmentSizeMb * 1024 * 1024);
|
|
59
|
+
if (oversizedFile) {
|
|
60
|
+
return `${oversizedFile.name} is larger than ${maxAttachmentSizeMb} MB.`;
|
|
61
|
+
}
|
|
62
|
+
const unsupportedFile = files.find((file) => !isAcceptedFile(file, acceptedFileTypes));
|
|
63
|
+
if (unsupportedFile) {
|
|
64
|
+
return `${unsupportedFile.name} is not an accepted file type.`;
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
function isAcceptedFile(file, acceptedFileTypes) {
|
|
69
|
+
if (!acceptedFileTypes)
|
|
70
|
+
return true;
|
|
71
|
+
const rules = acceptedFileTypes
|
|
72
|
+
.split(",")
|
|
73
|
+
.map((rule) => rule.trim().toLowerCase())
|
|
74
|
+
.filter(Boolean);
|
|
75
|
+
const fileName = file.name.toLowerCase();
|
|
76
|
+
const fileType = file.type.toLowerCase();
|
|
77
|
+
return rules.some((rule) => {
|
|
78
|
+
if (rule.startsWith("."))
|
|
79
|
+
return fileName.endsWith(rule);
|
|
80
|
+
if (rule.endsWith("/*"))
|
|
81
|
+
return fileType.startsWith(rule.slice(0, -1));
|
|
82
|
+
return fileType === rule;
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
export { FileUploadField };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type FieldPath, type FieldValues } from "react-hook-form";
|
|
3
|
+
type FormFieldContextValue<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = {
|
|
4
|
+
name: TName;
|
|
5
|
+
};
|
|
6
|
+
type FormItemContextValue = {
|
|
7
|
+
id: string;
|
|
8
|
+
};
|
|
9
|
+
declare const FormFieldContext: React.Context<FormFieldContextValue<FieldValues, string> | null>;
|
|
10
|
+
declare const FormItemContext: React.Context<FormItemContextValue | null>;
|
|
11
|
+
declare const useFormField: () => {
|
|
12
|
+
invalid: boolean;
|
|
13
|
+
isDirty: boolean;
|
|
14
|
+
isTouched: boolean;
|
|
15
|
+
isValidating: boolean;
|
|
16
|
+
error?: import("react-hook-form").FieldError;
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
formItemId: string;
|
|
20
|
+
formDescriptionId: string;
|
|
21
|
+
formMessageId: string;
|
|
22
|
+
};
|
|
23
|
+
export { FormFieldContext, FormItemContext, useFormField };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { useFormContext, useFormState } from "react-hook-form";
|
|
3
|
+
const FormFieldContext = React.createContext(null);
|
|
4
|
+
const FormItemContext = React.createContext(null);
|
|
5
|
+
function useFormFieldContext() {
|
|
6
|
+
const context = React.useContext(FormFieldContext);
|
|
7
|
+
if (!context) {
|
|
8
|
+
throw new Error("useFormField should be used within <FormField>");
|
|
9
|
+
}
|
|
10
|
+
return context;
|
|
11
|
+
}
|
|
12
|
+
function useFormItemContext() {
|
|
13
|
+
const context = React.useContext(FormItemContext);
|
|
14
|
+
if (!context) {
|
|
15
|
+
throw new Error("useFormField should be used within <FormItem>");
|
|
16
|
+
}
|
|
17
|
+
return context;
|
|
18
|
+
}
|
|
19
|
+
const useFormField = () => {
|
|
20
|
+
const fieldContext = useFormFieldContext();
|
|
21
|
+
const itemContext = useFormItemContext();
|
|
22
|
+
const { getFieldState } = useFormContext();
|
|
23
|
+
const formState = useFormState({ name: fieldContext.name });
|
|
24
|
+
const fieldState = getFieldState(fieldContext.name, formState);
|
|
25
|
+
const { id } = itemContext;
|
|
26
|
+
return {
|
|
27
|
+
id,
|
|
28
|
+
name: fieldContext.name,
|
|
29
|
+
formItemId: `${id}-form-item`,
|
|
30
|
+
formDescriptionId: `${id}-form-item-description`,
|
|
31
|
+
formMessageId: `${id}-form-item-message`,
|
|
32
|
+
...fieldState,
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export { FormFieldContext, FormItemContext, useFormField };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { Label as LabelPrimitive } from "radix-ui";
|
|
3
|
+
import { Slot } from "radix-ui";
|
|
4
|
+
import { type ControllerProps, type FieldPath, type FieldValues } from "react-hook-form";
|
|
5
|
+
declare const Form: <TFieldValues extends FieldValues, TContext = any, TTransformedValues = TFieldValues>(props: import("react-hook-form").FormProviderProps<TFieldValues, TContext, TTransformedValues>) => React.JSX.Element;
|
|
6
|
+
declare const FormField: <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ ...props }: ControllerProps<TFieldValues, TName>) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
declare function FormItem({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
declare function FormLabel({ className, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
declare function FormControl({ ...props }: React.ComponentProps<typeof Slot.Root>): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
declare function FormDescription({ className, ...props }: React.ComponentProps<"p">): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
declare function FormMessage({ className, ...props }: React.ComponentProps<"p">): import("react/jsx-runtime").JSX.Element | null;
|
|
12
|
+
export { Form, FormItem, FormLabel, FormControl, FormDescription, FormMessage, FormField };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Slot } from "radix-ui";
|
|
4
|
+
import { Controller, FormProvider, } from "react-hook-form";
|
|
5
|
+
import { cn } from "@ciridae/ui/utils";
|
|
6
|
+
import { FormFieldContext, FormItemContext, useFormField } from "@ciridae/ui/form-context";
|
|
7
|
+
import { Label } from "@ciridae/ui/label";
|
|
8
|
+
const Form = FormProvider;
|
|
9
|
+
const FormField = ({ ...props }) => {
|
|
10
|
+
const contextValue = React.useMemo(() => ({ name: props.name }), [props.name]);
|
|
11
|
+
return (_jsx(FormFieldContext.Provider, { value: contextValue, children: _jsx(Controller, { ...props }) }));
|
|
12
|
+
};
|
|
13
|
+
function FormItem({ className, ...props }) {
|
|
14
|
+
const id = React.useId();
|
|
15
|
+
const contextValue = React.useMemo(() => ({ id }), [id]);
|
|
16
|
+
return (_jsx(FormItemContext.Provider, { value: contextValue, children: _jsx("div", { "data-slot": "form-item", className: cn("grid gap-2", className), ...props }) }));
|
|
17
|
+
}
|
|
18
|
+
function FormLabel({ className, ...props }) {
|
|
19
|
+
const { error, formItemId } = useFormField();
|
|
20
|
+
return (_jsx(Label, { "data-slot": "form-label", "data-error": !!error, className: cn("data-[error=true]:text-destructive", className), htmlFor: formItemId, ...props }));
|
|
21
|
+
}
|
|
22
|
+
function FormControl({ ...props }) {
|
|
23
|
+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
|
|
24
|
+
return (_jsx(Slot.Root, { "data-slot": "form-control", id: formItemId, "aria-describedby": !error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`, "aria-invalid": !!error, ...props }));
|
|
25
|
+
}
|
|
26
|
+
function FormDescription({ className, ...props }) {
|
|
27
|
+
const { formDescriptionId } = useFormField();
|
|
28
|
+
return (_jsx("p", { "data-slot": "form-description", id: formDescriptionId, className: cn("text-sm text-muted-foreground", className), ...props }));
|
|
29
|
+
}
|
|
30
|
+
function FormMessage({ className, ...props }) {
|
|
31
|
+
const { error, formMessageId } = useFormField();
|
|
32
|
+
const body = error ? String(error?.message ?? "") : props.children;
|
|
33
|
+
if (!body) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return (_jsx("p", { "data-slot": "form-message", id: formMessageId, className: cn("text-sm text-destructive", className), ...props, children: body }));
|
|
37
|
+
}
|
|
38
|
+
export { Form, FormItem, FormLabel, FormControl, FormDescription, FormMessage, FormField };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { HoverCard as HoverCardPrimitive } from "radix-ui";
|
|
3
|
+
declare function HoverCardPortalContainerProvider({ children, container, }: {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
container: HTMLElement | null;
|
|
6
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
declare function HoverCard({ ...props }: React.ComponentProps<typeof HoverCardPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
declare function HoverCardTrigger({ ...props }: React.ComponentProps<typeof HoverCardPrimitive.Trigger>): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
declare function HoverCardContent({ className, align, sideOffset, ...props }: React.ComponentProps<typeof HoverCardPrimitive.Content>): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export { HoverCard, HoverCardTrigger, HoverCardContent, HoverCardPortalContainerProvider };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { HoverCard as HoverCardPrimitive } from "radix-ui";
|
|
4
|
+
import { cn } from "@ciridae/ui/utils";
|
|
5
|
+
const HoverCardPortalContainerContext = React.createContext({
|
|
6
|
+
container: null,
|
|
7
|
+
});
|
|
8
|
+
function HoverCardPortalContainerProvider({ children, container, }) {
|
|
9
|
+
const value = React.useMemo(() => ({ container }), [container]);
|
|
10
|
+
return (_jsx(HoverCardPortalContainerContext.Provider, { value: value, children: children }));
|
|
11
|
+
}
|
|
12
|
+
function HoverCard({ ...props }) {
|
|
13
|
+
return _jsx(HoverCardPrimitive.Root, { "data-slot": "hover-card", ...props });
|
|
14
|
+
}
|
|
15
|
+
function HoverCardTrigger({ ...props }) {
|
|
16
|
+
return _jsx(HoverCardPrimitive.Trigger, { "data-slot": "hover-card-trigger", ...props });
|
|
17
|
+
}
|
|
18
|
+
function HoverCardContent({ className, align = "center", sideOffset = 4, ...props }) {
|
|
19
|
+
const { container } = React.useContext(HoverCardPortalContainerContext);
|
|
20
|
+
return (_jsx(HoverCardPrimitive.Portal, { container: container ?? undefined, "data-slot": "hover-card-portal", children: _jsx(HoverCardPrimitive.Content, { "data-slot": "hover-card-content", align: align, sideOffset: sideOffset, className: cn("z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border bg-popover p-(--panel-padding) text-popover-foreground shadow-md outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0", className), ...props }) }));
|
|
21
|
+
}
|
|
22
|
+
export { HoverCard, HoverCardTrigger, HoverCardContent, HoverCardPortalContainerProvider };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
import { Button } from "@ciridae/ui/button";
|
|
4
|
+
declare function InputGroup({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
declare const inputGroupAddonVariants: (props?: ({
|
|
6
|
+
align?: "inline-end" | "inline-start" | "block-end" | "block-start" | null | undefined;
|
|
7
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
8
|
+
declare function InputGroupAddon({ className, align, ...props }: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
declare const inputGroupButtonVariants: (props?: ({
|
|
10
|
+
size?: "sm" | "xs" | "icon-xs" | "icon-sm" | null | undefined;
|
|
11
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
12
|
+
declare function InputGroupButton({ className, type, variant, size, ...props }: Omit<React.ComponentProps<typeof Button>, "size"> & VariantProps<typeof inputGroupButtonVariants>): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
declare function InputGroupText({ className, ...props }: React.ComponentProps<"span">): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
declare function InputGroupInput({ className, ...props }: React.ComponentProps<"input">): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
declare function InputGroupTextarea({ className, ...props }: React.ComponentProps<"textarea">): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea, };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
import { cn } from "@ciridae/ui/utils";
|
|
4
|
+
import { Button } from "@ciridae/ui/button";
|
|
5
|
+
import { Input } from "@ciridae/ui/input";
|
|
6
|
+
import { Textarea } from "@ciridae/ui/textarea";
|
|
7
|
+
function InputGroup({ className, ...props }) {
|
|
8
|
+
return (_jsx("div", { "data-slot": "input-group", role: "group", className: cn("group/input-group relative flex w-full items-center rounded-md border border-input shadow-xs transition-[color,box-shadow] outline-none dark:bg-input/30", "h-(--control-height) min-w-0 has-[>textarea]:h-auto",
|
|
9
|
+
// Variants based on alignment.
|
|
10
|
+
"has-[>[data-align=inline-start]]:[&>input]:pl-2", "has-[>[data-align=inline-end]]:[&>input]:pr-2", "has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3", "has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
|
|
11
|
+
// Focus state.
|
|
12
|
+
"has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-[var(--focus-ring-width)] has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50",
|
|
13
|
+
// Error state.
|
|
14
|
+
"has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40", className), ...props }));
|
|
15
|
+
}
|
|
16
|
+
const inputGroupAddonVariants = cva("flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4", {
|
|
17
|
+
variants: {
|
|
18
|
+
align: {
|
|
19
|
+
"inline-start": "order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]",
|
|
20
|
+
"inline-end": "order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]",
|
|
21
|
+
"block-start": "order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-2.5 [.border-b]:pb-3",
|
|
22
|
+
"block-end": "order-last w-full justify-start px-3 pb-3 group-has-[>input]/input-group:pb-2.5 [.border-t]:pt-3",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: {
|
|
26
|
+
align: "inline-start",
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
function InputGroupAddon({ className, align = "inline-start", ...props }) {
|
|
30
|
+
return (_jsx("div", { role: "group", "data-slot": "input-group-addon", "data-align": align, className: cn(inputGroupAddonVariants({ align }), className), onClick: (e) => {
|
|
31
|
+
if (e.target instanceof HTMLElement && e.target.closest("button")) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
e.currentTarget.parentElement?.querySelector("input")?.focus();
|
|
35
|
+
}, ...props }));
|
|
36
|
+
}
|
|
37
|
+
const inputGroupButtonVariants = cva("flex items-center gap-2 text-sm shadow-none", {
|
|
38
|
+
variants: {
|
|
39
|
+
size: {
|
|
40
|
+
xs: "h-(--control-height-xs) gap-1 rounded-[calc(var(--radius)-5px)] px-2 has-[>svg]:px-2 [&>svg:not([class*='size-'])]:size-3.5",
|
|
41
|
+
sm: "h-(--control-height-sm) gap-1.5 rounded-md px-2.5 has-[>svg]:px-2.5",
|
|
42
|
+
"icon-xs": "size-(--control-height-xs) rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0",
|
|
43
|
+
"icon-sm": "size-(--control-height-sm) p-0 has-[>svg]:p-0",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
defaultVariants: {
|
|
47
|
+
size: "xs",
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
function InputGroupButton({ className, type = "button", variant = "ghost", size = "xs", ...props }) {
|
|
51
|
+
return (_jsx(Button, { type: type, "data-size": size, variant: variant, className: cn(inputGroupButtonVariants({ size }), className), ...props }));
|
|
52
|
+
}
|
|
53
|
+
function InputGroupText({ className, ...props }) {
|
|
54
|
+
return (_jsx("span", { className: cn("flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4", className), ...props }));
|
|
55
|
+
}
|
|
56
|
+
function InputGroupInput({ className, ...props }) {
|
|
57
|
+
return (_jsx(Input, { "data-slot": "input-group-control", className: cn("flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent", className), ...props }));
|
|
58
|
+
}
|
|
59
|
+
function InputGroupTextarea({ className, ...props }) {
|
|
60
|
+
return (_jsx(Textarea, { "data-slot": "input-group-control", className: cn("flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent", className), ...props }));
|
|
61
|
+
}
|
|
62
|
+
export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea, };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { OTPInput } from "input-otp";
|
|
3
|
+
declare function InputOTP({ className, containerClassName, ...props }: React.ComponentProps<typeof OTPInput> & {
|
|
4
|
+
containerClassName?: string;
|
|
5
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
declare function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
declare function InputOTPSlot({ index, className, ...props }: React.ComponentProps<"div"> & {
|
|
8
|
+
index: number;
|
|
9
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
declare function InputOTPSeparator({ ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { OTPInput, OTPInputContext } from "input-otp";
|
|
5
|
+
import { MinusIcon } from "lucide-react";
|
|
6
|
+
import { cn } from "@ciridae/ui/utils";
|
|
7
|
+
function InputOTP({ className, containerClassName, ...props }) {
|
|
8
|
+
return (_jsx(OTPInput, { "data-slot": "input-otp", containerClassName: cn("flex items-center gap-2 has-disabled:opacity-50", containerClassName), className: cn("disabled:cursor-not-allowed", className), ...props }));
|
|
9
|
+
}
|
|
10
|
+
function InputOTPGroup({ className, ...props }) {
|
|
11
|
+
return (_jsx("div", { "data-slot": "input-otp-group", className: cn("flex items-center", className), ...props }));
|
|
12
|
+
}
|
|
13
|
+
function InputOTPSlot({ index, className, ...props }) {
|
|
14
|
+
const inputOTPContext = React.useContext(OTPInputContext);
|
|
15
|
+
const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {};
|
|
16
|
+
return (_jsxs("div", { "data-slot": "input-otp-slot", "data-active": isActive, className: cn("relative flex h-9 w-9 items-center justify-center border-y border-r border-input text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md aria-invalid:border-destructive data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-[var(--focus-ring-width)] data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:border-destructive data-[active=true]:aria-invalid:ring-destructive/20 dark:bg-input/30 dark:data-[active=true]:aria-invalid:ring-destructive/40", className), ...props, children: [char, hasFakeCaret && (_jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: _jsx("div", { className: "h-4 w-px animate-caret-blink bg-foreground duration-1000" }) }))] }));
|
|
17
|
+
}
|
|
18
|
+
function InputOTPSeparator({ ...props }) {
|
|
19
|
+
return (_jsx("div", { "data-slot": "input-otp-separator", role: "separator", ...props, children: _jsx(MinusIcon, {}) }));
|
|
20
|
+
}
|
|
21
|
+
export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "@ciridae/ui/utils";
|
|
3
|
+
function Input({ className, type, ...props }) {
|
|
4
|
+
return (_jsx("input", { type: type, "data-slot": "input", className: cn("h-(--control-height) w-full min-w-0 rounded-md border border-input bg-transparent px-(--control-padding-x) py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-[calc(var(--control-height)-0.375rem)] file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30", "focus-visible:border-ring focus-visible:ring-[var(--focus-ring-width)] focus-visible:ring-ring/50", "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40", className), ...props }));
|
|
5
|
+
}
|
|
6
|
+
export { Input };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
import { Separator } from "@ciridae/ui/separator";
|
|
4
|
+
declare function ItemGroup({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
declare function ItemSeparator({ className, ...props }: React.ComponentProps<typeof Separator>): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
declare const itemVariants: (props?: ({
|
|
7
|
+
variant?: "default" | "muted" | "outline" | null | undefined;
|
|
8
|
+
size?: "sm" | "default" | null | undefined;
|
|
9
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
10
|
+
declare function Item({ className, variant, size, asChild, ...props }: React.ComponentProps<"div"> & VariantProps<typeof itemVariants> & {
|
|
11
|
+
asChild?: boolean;
|
|
12
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
declare const itemMediaVariants: (props?: ({
|
|
14
|
+
variant?: "image" | "default" | "icon" | null | undefined;
|
|
15
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
16
|
+
declare function ItemMedia({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof itemMediaVariants>): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
declare function ItemContent({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
declare function ItemTitle({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
declare function ItemDescription({ className, ...props }: React.ComponentProps<"p">): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
declare function ItemActions({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
declare function ItemHeader({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
declare function ItemFooter({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export { Item, ItemMedia, ItemContent, ItemActions, ItemGroup, ItemSeparator, ItemTitle, ItemDescription, ItemHeader, ItemFooter, };
|