@thesage/ui 0.0.14 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +96 -61
  2. package/dist/dates.d.mts +20 -0
  3. package/dist/dates.d.ts +20 -0
  4. package/dist/dates.js +230 -0
  5. package/dist/dates.js.map +1 -0
  6. package/dist/dates.mjs +193 -0
  7. package/dist/dates.mjs.map +1 -0
  8. package/dist/dnd.d.mts +126 -0
  9. package/dist/dnd.d.ts +126 -0
  10. package/dist/dnd.js +274 -0
  11. package/dist/dnd.js.map +1 -0
  12. package/dist/dnd.mjs +250 -0
  13. package/dist/dnd.mjs.map +1 -0
  14. package/dist/forms.d.mts +38 -0
  15. package/dist/forms.d.ts +38 -0
  16. package/dist/forms.js +198 -0
  17. package/dist/forms.js.map +1 -0
  18. package/dist/forms.mjs +159 -0
  19. package/dist/forms.mjs.map +1 -0
  20. package/dist/hooks.js +6 -5
  21. package/dist/hooks.js.map +1 -1
  22. package/dist/hooks.mjs +6 -5
  23. package/dist/hooks.mjs.map +1 -1
  24. package/dist/index.d.mts +484 -352
  25. package/dist/index.d.ts +484 -352
  26. package/dist/index.js +2674 -2092
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +2548 -1966
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/providers.js +6 -5
  31. package/dist/providers.js.map +1 -1
  32. package/dist/providers.mjs +6 -5
  33. package/dist/providers.mjs.map +1 -1
  34. package/dist/tables.d.mts +10 -0
  35. package/dist/tables.d.ts +10 -0
  36. package/dist/tables.js +248 -0
  37. package/dist/tables.js.map +1 -0
  38. package/dist/tables.mjs +218 -0
  39. package/dist/tables.mjs.map +1 -0
  40. package/dist/utils.js +2 -1
  41. package/dist/utils.js.map +1 -1
  42. package/dist/utils.mjs +2 -1
  43. package/dist/utils.mjs.map +1 -1
  44. package/dist/webgl.d.mts +104 -0
  45. package/dist/webgl.d.ts +104 -0
  46. package/dist/webgl.js +226 -0
  47. package/dist/webgl.js.map +1 -0
  48. package/dist/webgl.mjs +195 -0
  49. package/dist/webgl.mjs.map +1 -0
  50. package/package.json +145 -16
package/dist/dnd.js ADDED
@@ -0,0 +1,274 @@
1
+ "use client";
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/dnd.ts
32
+ var dnd_exports = {};
33
+ __export(dnd_exports, {
34
+ DragDropHandle: () => DragDropHandle,
35
+ DragDropList: () => DragDropList,
36
+ DragDropTable: () => DragDropTable
37
+ });
38
+ module.exports = __toCommonJS(dnd_exports);
39
+
40
+ // src/components/forms/DragDrop.tsx
41
+ var import_react = __toESM(require("react"));
42
+ var import_core = require("@dnd-kit/core");
43
+ var import_sortable = require("@dnd-kit/sortable");
44
+ var import_utilities = require("@dnd-kit/utilities");
45
+ var import_lucide_react = require("lucide-react");
46
+
47
+ // src/lib/utils.ts
48
+ var import_clsx = require("clsx");
49
+ var import_tailwind_merge = require("tailwind-merge");
50
+ function cn(...inputs) {
51
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
52
+ }
53
+
54
+ // src/components/forms/DragDrop.tsx
55
+ var import_jsx_runtime = require("react/jsx-runtime");
56
+ var DragHandleContext = (0, import_react.createContext)(null);
57
+ function SortableItem({ id, children, withHandle, className }) {
58
+ const {
59
+ attributes,
60
+ listeners,
61
+ setNodeRef,
62
+ setActivatorNodeRef,
63
+ transform,
64
+ transition,
65
+ isDragging
66
+ } = (0, import_sortable.useSortable)({ id });
67
+ const style = {
68
+ transform: import_utilities.CSS.Transform.toString(transform),
69
+ transition,
70
+ opacity: isDragging ? 0.5 : 1
71
+ };
72
+ const itemProps = withHandle ? {} : { ...listeners, ...attributes };
73
+ const content = withHandle ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DragHandleContext.Provider, { value: { attributes, listeners, setActivatorNodeRef }, children }) : children;
74
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
75
+ "div",
76
+ {
77
+ ref: setNodeRef,
78
+ style,
79
+ className: cn(
80
+ "relative transition-opacity",
81
+ isDragging && "z-50",
82
+ className
83
+ ),
84
+ ...itemProps,
85
+ children: content
86
+ }
87
+ );
88
+ }
89
+ function DragDropHandle({ className, icon }) {
90
+ const context = (0, import_react.useContext)(DragHandleContext);
91
+ if (!context) {
92
+ console.warn("DragDropHandle must be used within a DragDropList with withHandle={true}");
93
+ return null;
94
+ }
95
+ const { attributes, listeners, setActivatorNodeRef } = context;
96
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
97
+ "div",
98
+ {
99
+ ref: setActivatorNodeRef,
100
+ ...attributes,
101
+ ...listeners,
102
+ className: cn(
103
+ "flex items-center justify-center cursor-grab active:cursor-grabbing",
104
+ "text-[var(--color-text-secondary)] hover:text-[var(--color-foreground)]",
105
+ "transition-colors",
106
+ className
107
+ ),
108
+ children: icon || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.GripVertical, { className: "w-4 h-4" })
109
+ }
110
+ );
111
+ }
112
+ function DragDropList({
113
+ items,
114
+ onReorder,
115
+ renderItem,
116
+ withHandle = false,
117
+ className,
118
+ itemClassName,
119
+ strategy = import_sortable.verticalListSortingStrategy
120
+ }) {
121
+ const [activeId, setActiveId] = import_react.default.useState(null);
122
+ const sensors = (0, import_core.useSensors)(
123
+ (0, import_core.useSensor)(import_core.PointerSensor, {
124
+ activationConstraint: {
125
+ distance: 5
126
+ // Prevents accidental drags on mobile
127
+ }
128
+ }),
129
+ (0, import_core.useSensor)(import_core.KeyboardSensor, {
130
+ coordinateGetter: import_sortable.sortableKeyboardCoordinates
131
+ })
132
+ );
133
+ const handleDragStart = (event) => {
134
+ setActiveId(event.active.id);
135
+ };
136
+ const handleDragEnd = (event) => {
137
+ const { active, over } = event;
138
+ if (over && active.id !== over.id) {
139
+ const oldIndex = items.findIndex((item) => item.id === active.id);
140
+ const newIndex = items.findIndex((item) => item.id === over.id);
141
+ onReorder((0, import_sortable.arrayMove)(items, oldIndex, newIndex));
142
+ }
143
+ setActiveId(null);
144
+ };
145
+ const activeItem = items.find((item) => item.id === activeId);
146
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
147
+ import_core.DndContext,
148
+ {
149
+ sensors,
150
+ collisionDetection: import_core.closestCenter,
151
+ onDragStart: handleDragStart,
152
+ onDragEnd: handleDragEnd,
153
+ children: [
154
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sortable.SortableContext, { items, strategy, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn(strategy === import_sortable.verticalListSortingStrategy && "space-y-2", className), children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
155
+ SortableItem,
156
+ {
157
+ id: item.id,
158
+ withHandle,
159
+ className: itemClassName,
160
+ children: renderItem(item, item.id === activeId)
161
+ },
162
+ item.id
163
+ )) }) }),
164
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.DragOverlay, { children: activeId && activeItem ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "opacity-80 shadow-lg", children: renderItem(activeItem, true) }) : null })
165
+ ]
166
+ }
167
+ );
168
+ }
169
+ function DragDropTable({
170
+ items,
171
+ onReorder,
172
+ columns,
173
+ className
174
+ }) {
175
+ const [activeId, setActiveId] = import_react.default.useState(null);
176
+ const sensors = (0, import_core.useSensors)(
177
+ (0, import_core.useSensor)(import_core.PointerSensor, {
178
+ activationConstraint: {
179
+ distance: 5
180
+ }
181
+ }),
182
+ (0, import_core.useSensor)(import_core.KeyboardSensor, {
183
+ coordinateGetter: import_sortable.sortableKeyboardCoordinates
184
+ })
185
+ );
186
+ const handleDragStart = (event) => {
187
+ setActiveId(event.active.id);
188
+ };
189
+ const handleDragEnd = (event) => {
190
+ const { active, over } = event;
191
+ if (over && active.id !== over.id) {
192
+ const oldIndex = items.findIndex((item) => item.id === active.id);
193
+ const newIndex = items.findIndex((item) => item.id === over.id);
194
+ onReorder((0, import_sortable.arrayMove)(items, oldIndex, newIndex));
195
+ }
196
+ setActiveId(null);
197
+ };
198
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
199
+ import_core.DndContext,
200
+ {
201
+ sensors,
202
+ collisionDetection: import_core.closestCenter,
203
+ onDragStart: handleDragStart,
204
+ onDragEnd: handleDragEnd,
205
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn("overflow-x-auto", className), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "w-full border-collapse", children: [
206
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: "border-b border-[var(--color-border)]", children: [
207
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: "w-12" }),
208
+ columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
209
+ "th",
210
+ {
211
+ className: "text-left p-3 text-sm font-medium text-[var(--color-text-secondary)]",
212
+ children: column.header
213
+ },
214
+ column.key
215
+ ))
216
+ ] }) }),
217
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_sortable.SortableContext, { items, strategy: import_sortable.verticalListSortingStrategy, children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
218
+ TableRow,
219
+ {
220
+ item,
221
+ columns,
222
+ isDragging: item.id === activeId
223
+ },
224
+ item.id
225
+ )) }) })
226
+ ] }) })
227
+ }
228
+ );
229
+ }
230
+ function TableRow({ item, columns, isDragging }) {
231
+ const {
232
+ attributes,
233
+ listeners,
234
+ setNodeRef,
235
+ transform,
236
+ transition
237
+ } = (0, import_sortable.useSortable)({ id: item.id });
238
+ const style = {
239
+ transform: import_utilities.CSS.Transform.toString(transform),
240
+ transition,
241
+ opacity: isDragging ? 0.5 : 1
242
+ };
243
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
244
+ "tr",
245
+ {
246
+ ref: setNodeRef,
247
+ style,
248
+ className: cn(
249
+ "border-b border-[var(--color-border)] hover:bg-[var(--color-hover)]",
250
+ "transition-colors",
251
+ isDragging && "bg-[var(--color-active)]"
252
+ ),
253
+ children: [
254
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "p-3", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
255
+ "div",
256
+ {
257
+ ...attributes,
258
+ ...listeners,
259
+ className: "cursor-grab active:cursor-grabbing text-[var(--color-text-secondary)] hover:text-[var(--color-foreground)] transition-colors",
260
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.GripVertical, { className: "w-4 h-4" })
261
+ }
262
+ ) }),
263
+ columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "p-3 text-sm", children: column.render ? column.render(item) : item[column.key] }, column.key))
264
+ ]
265
+ }
266
+ );
267
+ }
268
+ // Annotate the CommonJS export names for ESM import in node:
269
+ 0 && (module.exports = {
270
+ DragDropHandle,
271
+ DragDropList,
272
+ DragDropTable
273
+ });
274
+ //# sourceMappingURL=dnd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dnd.ts","../src/components/forms/DragDrop.tsx","../src/lib/utils.ts"],"sourcesContent":["export * from './components/forms/DragDrop';\n","'use client';\n\nimport React, { createContext, useContext } from 'react';\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n DragEndEvent,\n DragOverlay,\n DragStartEvent,\n} from '@dnd-kit/core';\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n rectSortingStrategy,\n SortingStrategy,\n} from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport { GripVertical } from 'lucide-react';\nimport { cn } from '../../lib/utils';\n\n/**\n * Item interface for drag and drop lists\n */\nexport interface DragDropItem {\n id: string;\n [key: string]: any;\n}\n\n/**\n * Context for sharing drag handle listeners\n */\ninterface DragHandleContextValue {\n attributes: any;\n listeners: any;\n setActivatorNodeRef?: (element: HTMLElement | null) => void;\n}\n\nconst DragHandleContext = createContext<DragHandleContextValue | null>(null);\n\n/**\n * Props for DragDropList component\n */\nexport interface DragDropListProps<T extends DragDropItem> {\n /**\n * Array of items to display\n */\n items: T[];\n /**\n * Callback fired when items are reordered\n */\n onReorder: (items: T[]) => void;\n /**\n * Render function for each item\n */\n renderItem: (item: T, isDragging: boolean) => React.ReactNode;\n /**\n * Enable drag handle mode (only drag from handle)\n * @default false\n */\n withHandle?: boolean;\n /**\n * Custom class name for the list container\n */\n className?: string;\n /**\n * Custom class name for list items\n */\n itemClassName?: string;\n /**\n * Sorting strategy for the drag & drop behavior\n * - verticalListSortingStrategy: For vertical lists (default)\n * - rectSortingStrategy: For grid layouts\n * @default verticalListSortingStrategy\n */\n strategy?: SortingStrategy;\n}\n\n/**\n * Props for sortable item\n */\ninterface SortableItemProps {\n id: string;\n children: React.ReactNode;\n withHandle?: boolean;\n className?: string;\n}\n\n/**\n * Internal sortable item component\n */\nfunction SortableItem({ id, children, withHandle, className }: SortableItemProps) {\n const {\n attributes,\n listeners,\n setNodeRef,\n setActivatorNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.5 : 1,\n };\n\n // If using handle, don't attach listeners to the item\n const itemProps = withHandle ? {} : { ...listeners, ...attributes };\n\n const content = withHandle ? (\n <DragHandleContext.Provider value={{ attributes, listeners, setActivatorNodeRef }}>\n {children}\n </DragHandleContext.Provider>\n ) : (\n children\n );\n\n return (\n <div\n ref={setNodeRef}\n style={style}\n className={cn(\n 'relative transition-opacity',\n isDragging && 'z-50',\n className\n )}\n {...itemProps}\n >\n {content}\n </div>\n );\n}\n\n/**\n * Drag handle component for manual drag control\n * Must be used within a DragDropList with withHandle={true}\n */\nexport interface DragDropHandleProps {\n /**\n * Custom class name\n */\n className?: string;\n /**\n * Handle icon\n */\n icon?: React.ReactNode;\n}\n\nexport function DragDropHandle({ className, icon }: DragDropHandleProps) {\n const context = useContext(DragHandleContext);\n\n if (!context) {\n console.warn('DragDropHandle must be used within a DragDropList with withHandle={true}');\n return null;\n }\n\n const { attributes, listeners, setActivatorNodeRef } = context;\n\n return (\n <div\n ref={setActivatorNodeRef}\n {...attributes}\n {...listeners}\n className={cn(\n 'flex items-center justify-center cursor-grab active:cursor-grabbing',\n 'text-[var(--color-text-secondary)] hover:text-[var(--color-foreground)]',\n 'transition-colors',\n className\n )}\n >\n {icon || <GripVertical className=\"w-4 h-4\" />}\n </div>\n );\n}\n\n/**\n * DragDropList - Sortable list component with drag and drop functionality\n *\n * @example\n * ```tsx\n * const [items, setItems] = useState([\n * { id: '1', name: 'Item 1' },\n * { id: '2', name: 'Item 2' },\n * ]);\n *\n * <DragDropList\n * items={items}\n * onReorder={setItems}\n * renderItem={(item) => (\n * <div className=\"p-4 bg-surface rounded\">{item.name}</div>\n * )}\n * />\n * ```\n */\nexport function DragDropList<T extends DragDropItem>({\n items,\n onReorder,\n renderItem,\n withHandle = false,\n className,\n itemClassName,\n strategy = verticalListSortingStrategy,\n}: DragDropListProps<T>) {\n const [activeId, setActiveId] = React.useState<string | null>(null);\n\n // Configure sensors for touch/mouse/keyboard support\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: {\n distance: 5, // Prevents accidental drags on mobile\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n const handleDragStart = (event: DragStartEvent) => {\n setActiveId(event.active.id as string);\n };\n\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const oldIndex = items.findIndex((item) => item.id === active.id);\n const newIndex = items.findIndex((item) => item.id === over.id);\n onReorder(arrayMove(items, oldIndex, newIndex));\n }\n\n setActiveId(null);\n };\n\n const activeItem = items.find((item) => item.id === activeId);\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n <SortableContext items={items} strategy={strategy}>\n <div className={cn(strategy === verticalListSortingStrategy && 'space-y-2', className)}>\n {items.map((item) => (\n <SortableItem\n key={item.id}\n id={item.id}\n withHandle={withHandle}\n className={itemClassName}\n >\n {renderItem(item, item.id === activeId)}\n </SortableItem>\n ))}\n </div>\n </SortableContext>\n\n <DragOverlay>\n {activeId && activeItem ? (\n <div className=\"opacity-80 shadow-lg\">\n {renderItem(activeItem, true)}\n </div>\n ) : null}\n </DragOverlay>\n </DndContext>\n );\n}\n\n/**\n * Props for DragDropTable component\n */\nexport interface DragDropTableProps<T extends DragDropItem> {\n /**\n * Array of items to display\n */\n items: T[];\n /**\n * Callback fired when items are reordered\n */\n onReorder: (items: T[]) => void;\n /**\n * Table columns configuration\n */\n columns: {\n key: string;\n header: string;\n render?: (item: T) => React.ReactNode;\n }[];\n /**\n * Custom class name for the table\n */\n className?: string;\n}\n\n/**\n * DragDropTable - Sortable table with draggable rows\n *\n * @example\n * ```tsx\n * <DragDropTable\n * items={data}\n * onReorder={setData}\n * columns={[\n * { key: 'name', header: 'Name' },\n * { key: 'email', header: 'Email' },\n * ]}\n * />\n * ```\n */\nexport function DragDropTable<T extends DragDropItem>({\n items,\n onReorder,\n columns,\n className,\n}: DragDropTableProps<T>) {\n const [activeId, setActiveId] = React.useState<string | null>(null);\n\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: {\n distance: 5,\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n const handleDragStart = (event: DragStartEvent) => {\n setActiveId(event.active.id as string);\n };\n\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const oldIndex = items.findIndex((item) => item.id === active.id);\n const newIndex = items.findIndex((item) => item.id === over.id);\n onReorder(arrayMove(items, oldIndex, newIndex));\n }\n\n setActiveId(null);\n };\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n <div className={cn('overflow-x-auto', className)}>\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className=\"border-b border-[var(--color-border)]\">\n <th className=\"w-12\"></th>\n {columns.map((column) => (\n <th\n key={column.key}\n className=\"text-left p-3 text-sm font-medium text-[var(--color-text-secondary)]\"\n >\n {column.header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n <SortableContext items={items} strategy={verticalListSortingStrategy}>\n {items.map((item) => (\n <TableRow\n key={item.id}\n item={item}\n columns={columns}\n isDragging={item.id === activeId}\n />\n ))}\n </SortableContext>\n </tbody>\n </table>\n </div>\n </DndContext>\n );\n}\n\ninterface TableRowProps<T extends DragDropItem> {\n item: T;\n columns: { key: string; header: string; render?: (item: T) => React.ReactNode }[];\n isDragging: boolean;\n}\n\nfunction TableRow<T extends DragDropItem>({ item, columns, isDragging }: TableRowProps<T>) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n } = useSortable({ id: item.id });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.5 : 1,\n };\n\n return (\n <tr\n ref={setNodeRef}\n style={style}\n className={cn(\n 'border-b border-[var(--color-border)] hover:bg-[var(--color-hover)]',\n 'transition-colors',\n isDragging && 'bg-[var(--color-active)]'\n )}\n >\n <td className=\"p-3\">\n <div\n {...attributes}\n {...listeners}\n className=\"cursor-grab active:cursor-grabbing text-[var(--color-text-secondary)] hover:text-[var(--color-foreground)] transition-colors\"\n >\n <GripVertical className=\"w-4 h-4\" />\n </div>\n </td>\n {columns.map((column) => (\n <td key={column.key} className=\"p-3 text-sm\">\n {column.render ? column.render(item) : (item as any)[column.key]}\n </td>\n ))}\n </tr>\n );\n}\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"],"mappings":"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","names":["React"]}
package/dist/dnd.mjs ADDED
@@ -0,0 +1,250 @@
1
+ "use client";
2
+
3
+ // src/components/forms/DragDrop.tsx
4
+ import React, { createContext, useContext } from "react";
5
+ import {
6
+ DndContext,
7
+ closestCenter,
8
+ KeyboardSensor,
9
+ PointerSensor,
10
+ useSensor,
11
+ useSensors,
12
+ DragOverlay
13
+ } from "@dnd-kit/core";
14
+ import {
15
+ arrayMove,
16
+ SortableContext,
17
+ sortableKeyboardCoordinates,
18
+ useSortable,
19
+ verticalListSortingStrategy
20
+ } from "@dnd-kit/sortable";
21
+ import { CSS } from "@dnd-kit/utilities";
22
+ import { GripVertical } from "lucide-react";
23
+
24
+ // src/lib/utils.ts
25
+ import { clsx } from "clsx";
26
+ import { twMerge } from "tailwind-merge";
27
+ function cn(...inputs) {
28
+ return twMerge(clsx(inputs));
29
+ }
30
+
31
+ // src/components/forms/DragDrop.tsx
32
+ import { jsx, jsxs } from "react/jsx-runtime";
33
+ var DragHandleContext = createContext(null);
34
+ function SortableItem({ id, children, withHandle, className }) {
35
+ const {
36
+ attributes,
37
+ listeners,
38
+ setNodeRef,
39
+ setActivatorNodeRef,
40
+ transform,
41
+ transition,
42
+ isDragging
43
+ } = useSortable({ id });
44
+ const style = {
45
+ transform: CSS.Transform.toString(transform),
46
+ transition,
47
+ opacity: isDragging ? 0.5 : 1
48
+ };
49
+ const itemProps = withHandle ? {} : { ...listeners, ...attributes };
50
+ const content = withHandle ? /* @__PURE__ */ jsx(DragHandleContext.Provider, { value: { attributes, listeners, setActivatorNodeRef }, children }) : children;
51
+ return /* @__PURE__ */ jsx(
52
+ "div",
53
+ {
54
+ ref: setNodeRef,
55
+ style,
56
+ className: cn(
57
+ "relative transition-opacity",
58
+ isDragging && "z-50",
59
+ className
60
+ ),
61
+ ...itemProps,
62
+ children: content
63
+ }
64
+ );
65
+ }
66
+ function DragDropHandle({ className, icon }) {
67
+ const context = useContext(DragHandleContext);
68
+ if (!context) {
69
+ console.warn("DragDropHandle must be used within a DragDropList with withHandle={true}");
70
+ return null;
71
+ }
72
+ const { attributes, listeners, setActivatorNodeRef } = context;
73
+ return /* @__PURE__ */ jsx(
74
+ "div",
75
+ {
76
+ ref: setActivatorNodeRef,
77
+ ...attributes,
78
+ ...listeners,
79
+ className: cn(
80
+ "flex items-center justify-center cursor-grab active:cursor-grabbing",
81
+ "text-[var(--color-text-secondary)] hover:text-[var(--color-foreground)]",
82
+ "transition-colors",
83
+ className
84
+ ),
85
+ children: icon || /* @__PURE__ */ jsx(GripVertical, { className: "w-4 h-4" })
86
+ }
87
+ );
88
+ }
89
+ function DragDropList({
90
+ items,
91
+ onReorder,
92
+ renderItem,
93
+ withHandle = false,
94
+ className,
95
+ itemClassName,
96
+ strategy = verticalListSortingStrategy
97
+ }) {
98
+ const [activeId, setActiveId] = React.useState(null);
99
+ const sensors = useSensors(
100
+ useSensor(PointerSensor, {
101
+ activationConstraint: {
102
+ distance: 5
103
+ // Prevents accidental drags on mobile
104
+ }
105
+ }),
106
+ useSensor(KeyboardSensor, {
107
+ coordinateGetter: sortableKeyboardCoordinates
108
+ })
109
+ );
110
+ const handleDragStart = (event) => {
111
+ setActiveId(event.active.id);
112
+ };
113
+ const handleDragEnd = (event) => {
114
+ const { active, over } = event;
115
+ if (over && active.id !== over.id) {
116
+ const oldIndex = items.findIndex((item) => item.id === active.id);
117
+ const newIndex = items.findIndex((item) => item.id === over.id);
118
+ onReorder(arrayMove(items, oldIndex, newIndex));
119
+ }
120
+ setActiveId(null);
121
+ };
122
+ const activeItem = items.find((item) => item.id === activeId);
123
+ return /* @__PURE__ */ jsxs(
124
+ DndContext,
125
+ {
126
+ sensors,
127
+ collisionDetection: closestCenter,
128
+ onDragStart: handleDragStart,
129
+ onDragEnd: handleDragEnd,
130
+ children: [
131
+ /* @__PURE__ */ jsx(SortableContext, { items, strategy, children: /* @__PURE__ */ jsx("div", { className: cn(strategy === verticalListSortingStrategy && "space-y-2", className), children: items.map((item) => /* @__PURE__ */ jsx(
132
+ SortableItem,
133
+ {
134
+ id: item.id,
135
+ withHandle,
136
+ className: itemClassName,
137
+ children: renderItem(item, item.id === activeId)
138
+ },
139
+ item.id
140
+ )) }) }),
141
+ /* @__PURE__ */ jsx(DragOverlay, { children: activeId && activeItem ? /* @__PURE__ */ jsx("div", { className: "opacity-80 shadow-lg", children: renderItem(activeItem, true) }) : null })
142
+ ]
143
+ }
144
+ );
145
+ }
146
+ function DragDropTable({
147
+ items,
148
+ onReorder,
149
+ columns,
150
+ className
151
+ }) {
152
+ const [activeId, setActiveId] = React.useState(null);
153
+ const sensors = useSensors(
154
+ useSensor(PointerSensor, {
155
+ activationConstraint: {
156
+ distance: 5
157
+ }
158
+ }),
159
+ useSensor(KeyboardSensor, {
160
+ coordinateGetter: sortableKeyboardCoordinates
161
+ })
162
+ );
163
+ const handleDragStart = (event) => {
164
+ setActiveId(event.active.id);
165
+ };
166
+ const handleDragEnd = (event) => {
167
+ const { active, over } = event;
168
+ if (over && active.id !== over.id) {
169
+ const oldIndex = items.findIndex((item) => item.id === active.id);
170
+ const newIndex = items.findIndex((item) => item.id === over.id);
171
+ onReorder(arrayMove(items, oldIndex, newIndex));
172
+ }
173
+ setActiveId(null);
174
+ };
175
+ return /* @__PURE__ */ jsx(
176
+ DndContext,
177
+ {
178
+ sensors,
179
+ collisionDetection: closestCenter,
180
+ onDragStart: handleDragStart,
181
+ onDragEnd: handleDragEnd,
182
+ children: /* @__PURE__ */ jsx("div", { className: cn("overflow-x-auto", className), children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse", children: [
183
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b border-[var(--color-border)]", children: [
184
+ /* @__PURE__ */ jsx("th", { className: "w-12" }),
185
+ columns.map((column) => /* @__PURE__ */ jsx(
186
+ "th",
187
+ {
188
+ className: "text-left p-3 text-sm font-medium text-[var(--color-text-secondary)]",
189
+ children: column.header
190
+ },
191
+ column.key
192
+ ))
193
+ ] }) }),
194
+ /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx(SortableContext, { items, strategy: verticalListSortingStrategy, children: items.map((item) => /* @__PURE__ */ jsx(
195
+ TableRow,
196
+ {
197
+ item,
198
+ columns,
199
+ isDragging: item.id === activeId
200
+ },
201
+ item.id
202
+ )) }) })
203
+ ] }) })
204
+ }
205
+ );
206
+ }
207
+ function TableRow({ item, columns, isDragging }) {
208
+ const {
209
+ attributes,
210
+ listeners,
211
+ setNodeRef,
212
+ transform,
213
+ transition
214
+ } = useSortable({ id: item.id });
215
+ const style = {
216
+ transform: CSS.Transform.toString(transform),
217
+ transition,
218
+ opacity: isDragging ? 0.5 : 1
219
+ };
220
+ return /* @__PURE__ */ jsxs(
221
+ "tr",
222
+ {
223
+ ref: setNodeRef,
224
+ style,
225
+ className: cn(
226
+ "border-b border-[var(--color-border)] hover:bg-[var(--color-hover)]",
227
+ "transition-colors",
228
+ isDragging && "bg-[var(--color-active)]"
229
+ ),
230
+ children: [
231
+ /* @__PURE__ */ jsx("td", { className: "p-3", children: /* @__PURE__ */ jsx(
232
+ "div",
233
+ {
234
+ ...attributes,
235
+ ...listeners,
236
+ className: "cursor-grab active:cursor-grabbing text-[var(--color-text-secondary)] hover:text-[var(--color-foreground)] transition-colors",
237
+ children: /* @__PURE__ */ jsx(GripVertical, { className: "w-4 h-4" })
238
+ }
239
+ ) }),
240
+ columns.map((column) => /* @__PURE__ */ jsx("td", { className: "p-3 text-sm", children: column.render ? column.render(item) : item[column.key] }, column.key))
241
+ ]
242
+ }
243
+ );
244
+ }
245
+ export {
246
+ DragDropHandle,
247
+ DragDropList,
248
+ DragDropTable
249
+ };
250
+ //# sourceMappingURL=dnd.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/forms/DragDrop.tsx","../src/lib/utils.ts"],"sourcesContent":["'use client';\n\nimport React, { createContext, useContext } from 'react';\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n DragEndEvent,\n DragOverlay,\n DragStartEvent,\n} from '@dnd-kit/core';\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n rectSortingStrategy,\n SortingStrategy,\n} from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport { GripVertical } from 'lucide-react';\nimport { cn } from '../../lib/utils';\n\n/**\n * Item interface for drag and drop lists\n */\nexport interface DragDropItem {\n id: string;\n [key: string]: any;\n}\n\n/**\n * Context for sharing drag handle listeners\n */\ninterface DragHandleContextValue {\n attributes: any;\n listeners: any;\n setActivatorNodeRef?: (element: HTMLElement | null) => void;\n}\n\nconst DragHandleContext = createContext<DragHandleContextValue | null>(null);\n\n/**\n * Props for DragDropList component\n */\nexport interface DragDropListProps<T extends DragDropItem> {\n /**\n * Array of items to display\n */\n items: T[];\n /**\n * Callback fired when items are reordered\n */\n onReorder: (items: T[]) => void;\n /**\n * Render function for each item\n */\n renderItem: (item: T, isDragging: boolean) => React.ReactNode;\n /**\n * Enable drag handle mode (only drag from handle)\n * @default false\n */\n withHandle?: boolean;\n /**\n * Custom class name for the list container\n */\n className?: string;\n /**\n * Custom class name for list items\n */\n itemClassName?: string;\n /**\n * Sorting strategy for the drag & drop behavior\n * - verticalListSortingStrategy: For vertical lists (default)\n * - rectSortingStrategy: For grid layouts\n * @default verticalListSortingStrategy\n */\n strategy?: SortingStrategy;\n}\n\n/**\n * Props for sortable item\n */\ninterface SortableItemProps {\n id: string;\n children: React.ReactNode;\n withHandle?: boolean;\n className?: string;\n}\n\n/**\n * Internal sortable item component\n */\nfunction SortableItem({ id, children, withHandle, className }: SortableItemProps) {\n const {\n attributes,\n listeners,\n setNodeRef,\n setActivatorNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.5 : 1,\n };\n\n // If using handle, don't attach listeners to the item\n const itemProps = withHandle ? {} : { ...listeners, ...attributes };\n\n const content = withHandle ? (\n <DragHandleContext.Provider value={{ attributes, listeners, setActivatorNodeRef }}>\n {children}\n </DragHandleContext.Provider>\n ) : (\n children\n );\n\n return (\n <div\n ref={setNodeRef}\n style={style}\n className={cn(\n 'relative transition-opacity',\n isDragging && 'z-50',\n className\n )}\n {...itemProps}\n >\n {content}\n </div>\n );\n}\n\n/**\n * Drag handle component for manual drag control\n * Must be used within a DragDropList with withHandle={true}\n */\nexport interface DragDropHandleProps {\n /**\n * Custom class name\n */\n className?: string;\n /**\n * Handle icon\n */\n icon?: React.ReactNode;\n}\n\nexport function DragDropHandle({ className, icon }: DragDropHandleProps) {\n const context = useContext(DragHandleContext);\n\n if (!context) {\n console.warn('DragDropHandle must be used within a DragDropList with withHandle={true}');\n return null;\n }\n\n const { attributes, listeners, setActivatorNodeRef } = context;\n\n return (\n <div\n ref={setActivatorNodeRef}\n {...attributes}\n {...listeners}\n className={cn(\n 'flex items-center justify-center cursor-grab active:cursor-grabbing',\n 'text-[var(--color-text-secondary)] hover:text-[var(--color-foreground)]',\n 'transition-colors',\n className\n )}\n >\n {icon || <GripVertical className=\"w-4 h-4\" />}\n </div>\n );\n}\n\n/**\n * DragDropList - Sortable list component with drag and drop functionality\n *\n * @example\n * ```tsx\n * const [items, setItems] = useState([\n * { id: '1', name: 'Item 1' },\n * { id: '2', name: 'Item 2' },\n * ]);\n *\n * <DragDropList\n * items={items}\n * onReorder={setItems}\n * renderItem={(item) => (\n * <div className=\"p-4 bg-surface rounded\">{item.name}</div>\n * )}\n * />\n * ```\n */\nexport function DragDropList<T extends DragDropItem>({\n items,\n onReorder,\n renderItem,\n withHandle = false,\n className,\n itemClassName,\n strategy = verticalListSortingStrategy,\n}: DragDropListProps<T>) {\n const [activeId, setActiveId] = React.useState<string | null>(null);\n\n // Configure sensors for touch/mouse/keyboard support\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: {\n distance: 5, // Prevents accidental drags on mobile\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n const handleDragStart = (event: DragStartEvent) => {\n setActiveId(event.active.id as string);\n };\n\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const oldIndex = items.findIndex((item) => item.id === active.id);\n const newIndex = items.findIndex((item) => item.id === over.id);\n onReorder(arrayMove(items, oldIndex, newIndex));\n }\n\n setActiveId(null);\n };\n\n const activeItem = items.find((item) => item.id === activeId);\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n <SortableContext items={items} strategy={strategy}>\n <div className={cn(strategy === verticalListSortingStrategy && 'space-y-2', className)}>\n {items.map((item) => (\n <SortableItem\n key={item.id}\n id={item.id}\n withHandle={withHandle}\n className={itemClassName}\n >\n {renderItem(item, item.id === activeId)}\n </SortableItem>\n ))}\n </div>\n </SortableContext>\n\n <DragOverlay>\n {activeId && activeItem ? (\n <div className=\"opacity-80 shadow-lg\">\n {renderItem(activeItem, true)}\n </div>\n ) : null}\n </DragOverlay>\n </DndContext>\n );\n}\n\n/**\n * Props for DragDropTable component\n */\nexport interface DragDropTableProps<T extends DragDropItem> {\n /**\n * Array of items to display\n */\n items: T[];\n /**\n * Callback fired when items are reordered\n */\n onReorder: (items: T[]) => void;\n /**\n * Table columns configuration\n */\n columns: {\n key: string;\n header: string;\n render?: (item: T) => React.ReactNode;\n }[];\n /**\n * Custom class name for the table\n */\n className?: string;\n}\n\n/**\n * DragDropTable - Sortable table with draggable rows\n *\n * @example\n * ```tsx\n * <DragDropTable\n * items={data}\n * onReorder={setData}\n * columns={[\n * { key: 'name', header: 'Name' },\n * { key: 'email', header: 'Email' },\n * ]}\n * />\n * ```\n */\nexport function DragDropTable<T extends DragDropItem>({\n items,\n onReorder,\n columns,\n className,\n}: DragDropTableProps<T>) {\n const [activeId, setActiveId] = React.useState<string | null>(null);\n\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: {\n distance: 5,\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n const handleDragStart = (event: DragStartEvent) => {\n setActiveId(event.active.id as string);\n };\n\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const oldIndex = items.findIndex((item) => item.id === active.id);\n const newIndex = items.findIndex((item) => item.id === over.id);\n onReorder(arrayMove(items, oldIndex, newIndex));\n }\n\n setActiveId(null);\n };\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n <div className={cn('overflow-x-auto', className)}>\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className=\"border-b border-[var(--color-border)]\">\n <th className=\"w-12\"></th>\n {columns.map((column) => (\n <th\n key={column.key}\n className=\"text-left p-3 text-sm font-medium text-[var(--color-text-secondary)]\"\n >\n {column.header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n <SortableContext items={items} strategy={verticalListSortingStrategy}>\n {items.map((item) => (\n <TableRow\n key={item.id}\n item={item}\n columns={columns}\n isDragging={item.id === activeId}\n />\n ))}\n </SortableContext>\n </tbody>\n </table>\n </div>\n </DndContext>\n );\n}\n\ninterface TableRowProps<T extends DragDropItem> {\n item: T;\n columns: { key: string; header: string; render?: (item: T) => React.ReactNode }[];\n isDragging: boolean;\n}\n\nfunction TableRow<T extends DragDropItem>({ item, columns, isDragging }: TableRowProps<T>) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n } = useSortable({ id: item.id });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.5 : 1,\n };\n\n return (\n <tr\n ref={setNodeRef}\n style={style}\n className={cn(\n 'border-b border-[var(--color-border)] hover:bg-[var(--color-hover)]',\n 'transition-colors',\n isDragging && 'bg-[var(--color-active)]'\n )}\n >\n <td className=\"p-3\">\n <div\n {...attributes}\n {...listeners}\n className=\"cursor-grab active:cursor-grabbing text-[var(--color-text-secondary)] hover:text-[var(--color-foreground)] transition-colors\"\n >\n <GripVertical className=\"w-4 h-4\" />\n </div>\n </td>\n {columns.map((column) => (\n <td key={column.key} className=\"p-3 text-sm\">\n {column.render ? column.render(item) : (item as any)[column.key]}\n </td>\n ))}\n </tr>\n );\n}\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,38 @@
1
+ import * as react_hook_form from 'react-hook-form';
2
+ import { FormProvider, FieldValues, FieldPath, ControllerProps } from 'react-hook-form';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+ import * as React from 'react';
5
+ import * as LabelPrimitive from '@radix-ui/react-label';
6
+ import { Slot } from '@radix-ui/react-slot';
7
+
8
+ declare const Form: typeof FormProvider;
9
+ declare const FormField: <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ ...props }: ControllerProps<TFieldValues, TName>) => react_jsx_runtime.JSX.Element;
10
+ declare const 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: ({ ref, className, ...props }: React.HTMLAttributes<HTMLDivElement> & {
23
+ ref?: React.Ref<HTMLDivElement>;
24
+ }) => react_jsx_runtime.JSX.Element;
25
+ declare const FormLabel: ({ ref, className, ...props }: React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & {
26
+ ref?: React.Ref<React.ElementRef<typeof LabelPrimitive.Root>>;
27
+ }) => react_jsx_runtime.JSX.Element;
28
+ declare const FormControl: ({ ref, ...props }: React.ComponentPropsWithoutRef<typeof Slot> & {
29
+ ref?: React.Ref<React.ElementRef<typeof Slot>>;
30
+ }) => react_jsx_runtime.JSX.Element;
31
+ declare const FormDescription: ({ ref, className, ...props }: React.HTMLAttributes<HTMLParagraphElement> & {
32
+ ref?: React.Ref<HTMLParagraphElement>;
33
+ }) => react_jsx_runtime.JSX.Element;
34
+ declare const FormMessage: ({ ref, className, children, ...props }: React.HTMLAttributes<HTMLParagraphElement> & {
35
+ ref?: React.Ref<HTMLParagraphElement>;
36
+ }) => react_jsx_runtime.JSX.Element | null;
37
+
38
+ export { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField };
@@ -0,0 +1,38 @@
1
+ import * as react_hook_form from 'react-hook-form';
2
+ import { FormProvider, FieldValues, FieldPath, ControllerProps } from 'react-hook-form';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+ import * as React from 'react';
5
+ import * as LabelPrimitive from '@radix-ui/react-label';
6
+ import { Slot } from '@radix-ui/react-slot';
7
+
8
+ declare const Form: typeof FormProvider;
9
+ declare const FormField: <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ ...props }: ControllerProps<TFieldValues, TName>) => react_jsx_runtime.JSX.Element;
10
+ declare const 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: ({ ref, className, ...props }: React.HTMLAttributes<HTMLDivElement> & {
23
+ ref?: React.Ref<HTMLDivElement>;
24
+ }) => react_jsx_runtime.JSX.Element;
25
+ declare const FormLabel: ({ ref, className, ...props }: React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & {
26
+ ref?: React.Ref<React.ElementRef<typeof LabelPrimitive.Root>>;
27
+ }) => react_jsx_runtime.JSX.Element;
28
+ declare const FormControl: ({ ref, ...props }: React.ComponentPropsWithoutRef<typeof Slot> & {
29
+ ref?: React.Ref<React.ElementRef<typeof Slot>>;
30
+ }) => react_jsx_runtime.JSX.Element;
31
+ declare const FormDescription: ({ ref, className, ...props }: React.HTMLAttributes<HTMLParagraphElement> & {
32
+ ref?: React.Ref<HTMLParagraphElement>;
33
+ }) => react_jsx_runtime.JSX.Element;
34
+ declare const FormMessage: ({ ref, className, children, ...props }: React.HTMLAttributes<HTMLParagraphElement> & {
35
+ ref?: React.Ref<HTMLParagraphElement>;
36
+ }) => react_jsx_runtime.JSX.Element | null;
37
+
38
+ export { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField };