shadcn-data-views 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.
package/dist/index.js ADDED
@@ -0,0 +1,1897 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
+ var __getProtoOf = Object.getPrototypeOf;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
+ var __spreadValues = (a, b) => {
14
+ for (var prop in b || (b = {}))
15
+ if (__hasOwnProp.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ if (__getOwnPropSymbols)
18
+ for (var prop of __getOwnPropSymbols(b)) {
19
+ if (__propIsEnum.call(b, prop))
20
+ __defNormalProp(a, prop, b[prop]);
21
+ }
22
+ return a;
23
+ };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __objRest = (source, exclude) => {
26
+ var target = {};
27
+ for (var prop in source)
28
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
29
+ target[prop] = source[prop];
30
+ if (source != null && __getOwnPropSymbols)
31
+ for (var prop of __getOwnPropSymbols(source)) {
32
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
33
+ target[prop] = source[prop];
34
+ }
35
+ return target;
36
+ };
37
+ var __export = (target, all) => {
38
+ for (var name in all)
39
+ __defProp(target, name, { get: all[name], enumerable: true });
40
+ };
41
+ var __copyProps = (to, from, except, desc) => {
42
+ if (from && typeof from === "object" || typeof from === "function") {
43
+ for (let key of __getOwnPropNames(from))
44
+ if (!__hasOwnProp.call(to, key) && key !== except)
45
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
46
+ }
47
+ return to;
48
+ };
49
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
50
+ // If the importer is in node compatibility mode or this is not an ESM
51
+ // file that has been converted to a CommonJS file using a Babel-
52
+ // compatible transform (i.e. "__esModule" has not been set), then set
53
+ // "default" to the CommonJS "module.exports" for node compatibility.
54
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
55
+ mod
56
+ ));
57
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
58
+
59
+ // src/index.ts
60
+ var index_exports = {};
61
+ __export(index_exports, {
62
+ DataViews: () => DataViews,
63
+ getDateField: () => getDateField,
64
+ getPrimaryField: () => getPrimaryField,
65
+ getSelectField: () => getSelectField,
66
+ tableSchema: () => tableSchema
67
+ });
68
+ module.exports = __toCommonJS(index_exports);
69
+
70
+ // src/components/DataViews.tsx
71
+ var import_react5 = require("react");
72
+
73
+ // src/lib/schema.ts
74
+ var tableSchema = {
75
+ id: "tasks",
76
+ name: "Tasks",
77
+ icon: "\u{1F4CB}",
78
+ fields: [
79
+ { id: "title", name: "Title", type: "text", isPrimary: true },
80
+ { id: "description", name: "Description", type: "text" },
81
+ {
82
+ id: "status",
83
+ name: "Status",
84
+ type: "select",
85
+ options: [
86
+ { id: "todo", name: "To Do", color: "gray" },
87
+ { id: "in_progress", name: "In Progress", color: "blue" },
88
+ { id: "review", name: "Review", color: "yellow" },
89
+ { id: "done", name: "Done", color: "green" }
90
+ ]
91
+ },
92
+ {
93
+ id: "priority",
94
+ name: "Priority",
95
+ type: "select",
96
+ options: [
97
+ { id: "low", name: "Low", color: "gray" },
98
+ { id: "medium", name: "Medium", color: "yellow" },
99
+ { id: "high", name: "High", color: "red" }
100
+ ]
101
+ },
102
+ { id: "dueDate", name: "Due Date", type: "date" },
103
+ { id: "completed", name: "Completed", type: "checkbox" }
104
+ ]
105
+ };
106
+ function getSelectField(schema) {
107
+ return schema.fields.find((f) => f.type === "select");
108
+ }
109
+ function getDateField(schema) {
110
+ return schema.fields.find((f) => f.type === "date");
111
+ }
112
+ function getPrimaryField(schema) {
113
+ return schema.fields.find((f) => f.isPrimary) || schema.fields[0];
114
+ }
115
+
116
+ // src/components/ui/tabs.tsx
117
+ var React = __toESM(require("react"));
118
+ var TabsPrimitive = __toESM(require("@radix-ui/react-tabs"));
119
+
120
+ // src/lib/utils.ts
121
+ var import_clsx = require("clsx");
122
+ var import_tailwind_merge = require("tailwind-merge");
123
+ function cn(...inputs) {
124
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
125
+ }
126
+
127
+ // src/components/ui/tabs.tsx
128
+ var import_jsx_runtime = require("react/jsx-runtime");
129
+ var Tabs = TabsPrimitive.Root;
130
+ var TabsList = React.forwardRef((_a, ref) => {
131
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
132
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
133
+ TabsPrimitive.List,
134
+ __spreadValues({
135
+ ref,
136
+ className: cn(
137
+ "inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
138
+ className
139
+ )
140
+ }, props)
141
+ );
142
+ });
143
+ TabsList.displayName = TabsPrimitive.List.displayName;
144
+ var TabsTrigger = React.forwardRef((_a, ref) => {
145
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
146
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
147
+ TabsPrimitive.Trigger,
148
+ __spreadValues({
149
+ ref,
150
+ className: cn(
151
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
152
+ className
153
+ )
154
+ }, props)
155
+ );
156
+ });
157
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
158
+ var TabsContent = React.forwardRef((_a, ref) => {
159
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
160
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
161
+ TabsPrimitive.Content,
162
+ __spreadValues({
163
+ ref,
164
+ className: cn(
165
+ "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
166
+ className
167
+ )
168
+ }, props)
169
+ );
170
+ });
171
+ TabsContent.displayName = TabsPrimitive.Content.displayName;
172
+
173
+ // src/components/DataViews.tsx
174
+ var import_lucide_react11 = require("lucide-react");
175
+
176
+ // src/components/views/GridView.tsx
177
+ var import_lucide_react2 = require("lucide-react");
178
+
179
+ // src/components/ui/button.tsx
180
+ var React2 = __toESM(require("react"));
181
+ var import_react_slot = require("@radix-ui/react-slot");
182
+ var import_class_variance_authority = require("class-variance-authority");
183
+ var import_jsx_runtime2 = require("react/jsx-runtime");
184
+ var buttonVariants = (0, import_class_variance_authority.cva)(
185
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
186
+ {
187
+ variants: {
188
+ variant: {
189
+ default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
190
+ destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
191
+ outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
192
+ secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
193
+ ghost: "hover:bg-accent hover:text-accent-foreground",
194
+ link: "text-primary underline-offset-4 hover:underline"
195
+ },
196
+ size: {
197
+ default: "h-9 px-4 py-2",
198
+ sm: "h-8 rounded-md px-3 text-xs",
199
+ lg: "h-10 rounded-md px-8",
200
+ icon: "h-9 w-9"
201
+ }
202
+ },
203
+ defaultVariants: {
204
+ variant: "default",
205
+ size: "default"
206
+ }
207
+ }
208
+ );
209
+ var Button = React2.forwardRef(
210
+ (_a, ref) => {
211
+ var _b = _a, { className, variant, size, asChild = false } = _b, props = __objRest(_b, ["className", "variant", "size", "asChild"]);
212
+ const Comp = asChild ? import_react_slot.Slot : "button";
213
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
214
+ Comp,
215
+ __spreadValues({
216
+ className: cn(buttonVariants({ variant, size, className })),
217
+ ref
218
+ }, props)
219
+ );
220
+ }
221
+ );
222
+ Button.displayName = "Button";
223
+
224
+ // src/components/ui/table.tsx
225
+ var React3 = __toESM(require("react"));
226
+ var import_jsx_runtime3 = require("react/jsx-runtime");
227
+ var Table = React3.forwardRef((_a, ref) => {
228
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
229
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
230
+ "table",
231
+ __spreadValues({
232
+ ref,
233
+ className: cn("w-full caption-bottom text-sm", className)
234
+ }, props)
235
+ ) });
236
+ });
237
+ Table.displayName = "Table";
238
+ var TableHeader = React3.forwardRef((_a, ref) => {
239
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
240
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("thead", __spreadValues({ ref, className: cn("[&_tr]:border-b", className) }, props));
241
+ });
242
+ TableHeader.displayName = "TableHeader";
243
+ var TableBody = React3.forwardRef((_a, ref) => {
244
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
245
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
246
+ "tbody",
247
+ __spreadValues({
248
+ ref,
249
+ className: cn("[&_tr:last-child]:border-0", className)
250
+ }, props)
251
+ );
252
+ });
253
+ TableBody.displayName = "TableBody";
254
+ var TableFooter = React3.forwardRef((_a, ref) => {
255
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
256
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
257
+ "tfoot",
258
+ __spreadValues({
259
+ ref,
260
+ className: cn(
261
+ "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
262
+ className
263
+ )
264
+ }, props)
265
+ );
266
+ });
267
+ TableFooter.displayName = "TableFooter";
268
+ var TableRow = React3.forwardRef((_a, ref) => {
269
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
270
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
271
+ "tr",
272
+ __spreadValues({
273
+ ref,
274
+ className: cn(
275
+ "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
276
+ className
277
+ )
278
+ }, props)
279
+ );
280
+ });
281
+ TableRow.displayName = "TableRow";
282
+ var TableHead = React3.forwardRef((_a, ref) => {
283
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
284
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
285
+ "th",
286
+ __spreadValues({
287
+ ref,
288
+ className: cn(
289
+ "h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
290
+ className
291
+ )
292
+ }, props)
293
+ );
294
+ });
295
+ TableHead.displayName = "TableHead";
296
+ var TableCell = React3.forwardRef((_a, ref) => {
297
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
298
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
299
+ "td",
300
+ __spreadValues({
301
+ ref,
302
+ className: cn(
303
+ "p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
304
+ className
305
+ )
306
+ }, props)
307
+ );
308
+ });
309
+ TableCell.displayName = "TableCell";
310
+ var TableCaption = React3.forwardRef((_a, ref) => {
311
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
312
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
313
+ "caption",
314
+ __spreadValues({
315
+ ref,
316
+ className: cn("mt-4 text-sm text-muted-foreground", className)
317
+ }, props)
318
+ );
319
+ });
320
+ TableCaption.displayName = "TableCaption";
321
+
322
+ // src/components/ui/checkbox.tsx
323
+ var React4 = __toESM(require("react"));
324
+ var CheckboxPrimitive = __toESM(require("@radix-ui/react-checkbox"));
325
+ var import_lucide_react = require("lucide-react");
326
+ var import_jsx_runtime4 = require("react/jsx-runtime");
327
+ var Checkbox = React4.forwardRef((_a, ref) => {
328
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
329
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
330
+ CheckboxPrimitive.Root,
331
+ __spreadProps(__spreadValues({
332
+ ref,
333
+ className: cn(
334
+ "grid place-content-center peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
335
+ className
336
+ )
337
+ }, props), {
338
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
339
+ CheckboxPrimitive.Indicator,
340
+ {
341
+ className: cn("grid place-content-center text-current"),
342
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.Check, { className: "h-4 w-4" })
343
+ }
344
+ )
345
+ })
346
+ );
347
+ });
348
+ Checkbox.displayName = CheckboxPrimitive.Root.displayName;
349
+
350
+ // src/components/ui/badge.tsx
351
+ var import_class_variance_authority2 = require("class-variance-authority");
352
+ var import_jsx_runtime5 = require("react/jsx-runtime");
353
+ var badgeVariants = (0, import_class_variance_authority2.cva)(
354
+ "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
355
+ {
356
+ variants: {
357
+ variant: {
358
+ default: "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
359
+ secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
360
+ destructive: "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
361
+ outline: "text-foreground"
362
+ }
363
+ },
364
+ defaultVariants: {
365
+ variant: "default"
366
+ }
367
+ }
368
+ );
369
+ function Badge(_a) {
370
+ var _b = _a, { className, variant } = _b, props = __objRest(_b, ["className", "variant"]);
371
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", __spreadValues({ className: cn(badgeVariants({ variant }), className) }, props));
372
+ }
373
+
374
+ // src/components/views/GridView.tsx
375
+ var import_jsx_runtime6 = require("react/jsx-runtime");
376
+ var BADGE_COLOR_MAP = {
377
+ gray: "bg-muted text-muted-foreground",
378
+ blue: "bg-blue-100 text-blue-700 dark:bg-blue-900/50 dark:text-blue-300",
379
+ green: "bg-green-100 text-green-700 dark:bg-green-900/50 dark:text-green-300",
380
+ yellow: "bg-amber-100 text-amber-700 dark:bg-amber-900/50 dark:text-amber-300",
381
+ red: "bg-red-100 text-red-700 dark:bg-red-900/50 dark:text-red-300",
382
+ purple: "bg-purple-100 text-purple-700 dark:bg-purple-900/50 dark:text-purple-300"
383
+ };
384
+ function GridView({ schema, records, onUpdateRecord, onDeleteRecord, onOpenModal }) {
385
+ const renderCellValue = (record, field) => {
386
+ var _a;
387
+ const value = record.fields[field.id];
388
+ switch (field.type) {
389
+ case "checkbox":
390
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
391
+ Checkbox,
392
+ {
393
+ checked: !!value,
394
+ onCheckedChange: (checked) => onUpdateRecord(record.id, { [field.id]: checked }),
395
+ onClick: (e) => e.stopPropagation()
396
+ }
397
+ );
398
+ case "select":
399
+ const option = (_a = field.options) == null ? void 0 : _a.find((o) => o.name === value);
400
+ return value ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Badge, { variant: "secondary", className: cn("font-normal", BADGE_COLOR_MAP[(option == null ? void 0 : option.color) || "gray"]), children: value }) : null;
401
+ case "multiSelect":
402
+ const values = Array.isArray(value) ? value : [];
403
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex flex-wrap gap-1", children: values.map((v) => {
404
+ var _a2;
405
+ const opt = (_a2 = field.options) == null ? void 0 : _a2.find((o) => o.name === v);
406
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Badge, { variant: "secondary", className: cn("font-normal", BADGE_COLOR_MAP[(opt == null ? void 0 : opt.color) || "gray"]), children: v }, v);
407
+ }) });
408
+ case "date":
409
+ return value ? new Date(value).toLocaleDateString() : null;
410
+ case "number":
411
+ return value != null ? Number(value).toLocaleString() : null;
412
+ default:
413
+ return value;
414
+ }
415
+ };
416
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "w-full grow overflow-hidden sm:pl-2 relative group flex flex-col h-full", children: [
417
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "relative w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "w-full h-full", style: { pointerEvents: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-t-grid-container": "true", tabIndex: 0, className: "relative outline-none w-full h-full", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "w-full h-full overflow-auto pb-10", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Table, { children: [
418
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TableHeader, { className: "bg-muted/50 sticky top-0 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(TableRow, { children: [
419
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TableHead, { className: "w-12 text-muted-foreground", children: "#" }),
420
+ schema.fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(TableHead, { className: "min-w-[150px]", children: [
421
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-medium", children: field.name }),
422
+ field.isPrimary && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Badge, { variant: "outline", className: "ml-2 text-xs", children: "Primary" })
423
+ ] }, field.id)),
424
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TableHead, { className: "w-[100px] text-right", children: "Actions" })
425
+ ] }) }),
426
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(TableBody, { children: [
427
+ records.map((record, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
428
+ TableRow,
429
+ {
430
+ className: "group cursor-pointer hover:bg-muted/50",
431
+ onClick: () => onOpenModal("view", record),
432
+ children: [
433
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TableCell, { className: "text-muted-foreground tabular-nums", children: index + 1 }),
434
+ schema.fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "min-h-[24px] flex items-center", children: renderCellValue(record, field) }) }, field.id)),
435
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TableCell, { className: "text-right", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-end gap-1 opacity-0 group-hover:opacity-100 transition-opacity", children: [
436
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
437
+ Button,
438
+ {
439
+ variant: "ghost",
440
+ size: "icon",
441
+ className: "h-8 w-8",
442
+ onClick: () => onOpenModal("view", record),
443
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.Eye, { className: "h-4 w-4" })
444
+ }
445
+ ),
446
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
447
+ Button,
448
+ {
449
+ variant: "ghost",
450
+ size: "icon",
451
+ className: "h-8 w-8",
452
+ onClick: () => onOpenModal("edit", record),
453
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.Pencil, { className: "h-4 w-4" })
454
+ }
455
+ ),
456
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
457
+ Button,
458
+ {
459
+ variant: "ghost",
460
+ size: "icon",
461
+ className: "h-8 w-8 text-muted-foreground hover:text-destructive",
462
+ onClick: () => onDeleteRecord(record.id),
463
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.Trash2, { className: "h-4 w-4" })
464
+ }
465
+ )
466
+ ] }) })
467
+ ]
468
+ },
469
+ record.id
470
+ )),
471
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TableCell, { colSpan: schema.fields.length + 2, className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
472
+ Button,
473
+ {
474
+ variant: "ghost",
475
+ size: "sm",
476
+ onClick: () => onOpenModal("add"),
477
+ className: "w-full justify-start px-4 h-10 text-muted-foreground hover:text-foreground rounded-none",
478
+ children: [
479
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.Plus, { className: "h-4 w-4 mr-2" }),
480
+ "Add new record"
481
+ ]
482
+ }
483
+ ) }) })
484
+ ] })
485
+ ] }) }) }) }) }),
486
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center h-6 pl-2 ml-1 text-xs bg-violet-200 dark:bg-zinc-600 rounded absolute bottom-3 left-0 shadow-sm z-20", children: [
487
+ records.length,
488
+ " records",
489
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: "inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 gap-2 hover:text-accent-foreground rounded-md text-xs ml-[2px] h-full rounded-l-none p-[2px] hover:bg-violet-300 dark:hover:bg-zinc-500", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", fill: "none", viewBox: "0 0 24 24", className: "w-3 h-3", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "m15 18-6-6 6-6" }) }) })
490
+ ] })
491
+ ] });
492
+ }
493
+
494
+ // src/components/views/FormView.tsx
495
+ var import_react2 = require("react");
496
+
497
+ // src/components/ui/card.tsx
498
+ var React5 = __toESM(require("react"));
499
+ var import_jsx_runtime7 = require("react/jsx-runtime");
500
+ var Card = React5.forwardRef((_a, ref) => {
501
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
502
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
503
+ "div",
504
+ __spreadValues({
505
+ ref,
506
+ className: cn(
507
+ "rounded-xl border bg-card text-card-foreground shadow",
508
+ className
509
+ )
510
+ }, props)
511
+ );
512
+ });
513
+ Card.displayName = "Card";
514
+ var CardHeader = React5.forwardRef((_a, ref) => {
515
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
516
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
517
+ "div",
518
+ __spreadValues({
519
+ ref,
520
+ className: cn("flex flex-col space-y-1.5 p-6", className)
521
+ }, props)
522
+ );
523
+ });
524
+ CardHeader.displayName = "CardHeader";
525
+ var CardTitle = React5.forwardRef((_a, ref) => {
526
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
527
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
528
+ "div",
529
+ __spreadValues({
530
+ ref,
531
+ className: cn("font-semibold leading-none tracking-tight", className)
532
+ }, props)
533
+ );
534
+ });
535
+ CardTitle.displayName = "CardTitle";
536
+ var CardDescription = React5.forwardRef((_a, ref) => {
537
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
538
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
539
+ "div",
540
+ __spreadValues({
541
+ ref,
542
+ className: cn("text-sm text-muted-foreground", className)
543
+ }, props)
544
+ );
545
+ });
546
+ CardDescription.displayName = "CardDescription";
547
+ var CardContent = React5.forwardRef((_a, ref) => {
548
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
549
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", __spreadValues({ ref, className: cn("p-6 pt-0", className) }, props));
550
+ });
551
+ CardContent.displayName = "CardContent";
552
+ var CardFooter = React5.forwardRef((_a, ref) => {
553
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
554
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
555
+ "div",
556
+ __spreadValues({
557
+ ref,
558
+ className: cn("flex items-center p-6 pt-0", className)
559
+ }, props)
560
+ );
561
+ });
562
+ CardFooter.displayName = "CardFooter";
563
+
564
+ // src/components/ui/alert.tsx
565
+ var React6 = __toESM(require("react"));
566
+ var import_class_variance_authority3 = require("class-variance-authority");
567
+ var import_jsx_runtime8 = require("react/jsx-runtime");
568
+ var alertVariants = (0, import_class_variance_authority3.cva)(
569
+ "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
570
+ {
571
+ variants: {
572
+ variant: {
573
+ default: "bg-background text-foreground",
574
+ destructive: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive"
575
+ }
576
+ },
577
+ defaultVariants: {
578
+ variant: "default"
579
+ }
580
+ }
581
+ );
582
+ var Alert = React6.forwardRef((_a, ref) => {
583
+ var _b = _a, { className, variant } = _b, props = __objRest(_b, ["className", "variant"]);
584
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
585
+ "div",
586
+ __spreadValues({
587
+ ref,
588
+ role: "alert",
589
+ className: cn(alertVariants({ variant }), className)
590
+ }, props)
591
+ );
592
+ });
593
+ Alert.displayName = "Alert";
594
+ var AlertTitle = React6.forwardRef((_a, ref) => {
595
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
596
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
597
+ "h5",
598
+ __spreadValues({
599
+ ref,
600
+ className: cn("mb-1 font-medium leading-none tracking-tight", className)
601
+ }, props)
602
+ );
603
+ });
604
+ AlertTitle.displayName = "AlertTitle";
605
+ var AlertDescription = React6.forwardRef((_a, ref) => {
606
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
607
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
608
+ "div",
609
+ __spreadValues({
610
+ ref,
611
+ className: cn("text-sm [&_p]:leading-relaxed", className)
612
+ }, props)
613
+ );
614
+ });
615
+ AlertDescription.displayName = "AlertDescription";
616
+
617
+ // src/components/views/FormView.tsx
618
+ var import_lucide_react4 = require("lucide-react");
619
+
620
+ // src/components/RecordForm.tsx
621
+ var import_react = require("react");
622
+
623
+ // src/components/ui/input.tsx
624
+ var React7 = __toESM(require("react"));
625
+ var import_jsx_runtime9 = require("react/jsx-runtime");
626
+ var Input = React7.forwardRef(
627
+ (_a, ref) => {
628
+ var _b = _a, { className, type } = _b, props = __objRest(_b, ["className", "type"]);
629
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
630
+ "input",
631
+ __spreadValues({
632
+ type,
633
+ className: cn(
634
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
635
+ className
636
+ ),
637
+ ref
638
+ }, props)
639
+ );
640
+ }
641
+ );
642
+ Input.displayName = "Input";
643
+
644
+ // src/components/ui/label.tsx
645
+ var React8 = __toESM(require("react"));
646
+ var LabelPrimitive = __toESM(require("@radix-ui/react-label"));
647
+ var import_class_variance_authority4 = require("class-variance-authority");
648
+ var import_jsx_runtime10 = require("react/jsx-runtime");
649
+ var labelVariants = (0, import_class_variance_authority4.cva)(
650
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
651
+ );
652
+ var Label = React8.forwardRef((_a, ref) => {
653
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
654
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
655
+ LabelPrimitive.Root,
656
+ __spreadValues({
657
+ ref,
658
+ className: cn(labelVariants(), className)
659
+ }, props)
660
+ );
661
+ });
662
+ Label.displayName = LabelPrimitive.Root.displayName;
663
+
664
+ // src/components/ui/select.tsx
665
+ var React9 = __toESM(require("react"));
666
+ var SelectPrimitive = __toESM(require("@radix-ui/react-select"));
667
+ var import_lucide_react3 = require("lucide-react");
668
+ var import_jsx_runtime11 = require("react/jsx-runtime");
669
+ var Select = SelectPrimitive.Root;
670
+ var SelectValue = SelectPrimitive.Value;
671
+ var SelectTrigger = React9.forwardRef((_a, ref) => {
672
+ var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
673
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
674
+ SelectPrimitive.Trigger,
675
+ __spreadProps(__spreadValues({
676
+ ref,
677
+ className: cn(
678
+ "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
679
+ className
680
+ )
681
+ }, props), {
682
+ children: [
683
+ children,
684
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.ChevronDown, { className: "h-4 w-4 opacity-50" }) })
685
+ ]
686
+ })
687
+ );
688
+ });
689
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
690
+ var SelectScrollUpButton = React9.forwardRef((_a, ref) => {
691
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
692
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
693
+ SelectPrimitive.ScrollUpButton,
694
+ __spreadProps(__spreadValues({
695
+ ref,
696
+ className: cn(
697
+ "flex cursor-default items-center justify-center py-1",
698
+ className
699
+ )
700
+ }, props), {
701
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.ChevronUp, { className: "h-4 w-4" })
702
+ })
703
+ );
704
+ });
705
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
706
+ var SelectScrollDownButton = React9.forwardRef((_a, ref) => {
707
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
708
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
709
+ SelectPrimitive.ScrollDownButton,
710
+ __spreadProps(__spreadValues({
711
+ ref,
712
+ className: cn(
713
+ "flex cursor-default items-center justify-center py-1",
714
+ className
715
+ )
716
+ }, props), {
717
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.ChevronDown, { className: "h-4 w-4" })
718
+ })
719
+ );
720
+ });
721
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
722
+ var SelectContent = React9.forwardRef((_a, ref) => {
723
+ var _b = _a, { className, children, position = "popper" } = _b, props = __objRest(_b, ["className", "children", "position"]);
724
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SelectPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
725
+ SelectPrimitive.Content,
726
+ __spreadProps(__spreadValues({
727
+ ref,
728
+ className: cn(
729
+ "relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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 origin-[--radix-select-content-transform-origin]",
730
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
731
+ className
732
+ ),
733
+ position
734
+ }, props), {
735
+ children: [
736
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SelectScrollUpButton, {}),
737
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
738
+ SelectPrimitive.Viewport,
739
+ {
740
+ className: cn(
741
+ "p-1",
742
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
743
+ ),
744
+ children
745
+ }
746
+ ),
747
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SelectScrollDownButton, {})
748
+ ]
749
+ })
750
+ ) });
751
+ });
752
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
753
+ var SelectLabel = React9.forwardRef((_a, ref) => {
754
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
755
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
756
+ SelectPrimitive.Label,
757
+ __spreadValues({
758
+ ref,
759
+ className: cn("px-2 py-1.5 text-sm font-semibold", className)
760
+ }, props)
761
+ );
762
+ });
763
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
764
+ var SelectItem = React9.forwardRef((_a, ref) => {
765
+ var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
766
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
767
+ SelectPrimitive.Item,
768
+ __spreadProps(__spreadValues({
769
+ ref,
770
+ className: cn(
771
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
772
+ className
773
+ )
774
+ }, props), {
775
+ children: [
776
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Check, { className: "h-4 w-4" }) }) }),
777
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SelectPrimitive.ItemText, { children })
778
+ ]
779
+ })
780
+ );
781
+ });
782
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
783
+ var SelectSeparator = React9.forwardRef((_a, ref) => {
784
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
785
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
786
+ SelectPrimitive.Separator,
787
+ __spreadValues({
788
+ ref,
789
+ className: cn("-mx-1 my-1 h-px bg-muted", className)
790
+ }, props)
791
+ );
792
+ });
793
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
794
+
795
+ // src/components/ui/textarea.tsx
796
+ var React10 = __toESM(require("react"));
797
+ var import_jsx_runtime12 = require("react/jsx-runtime");
798
+ var Textarea = React10.forwardRef((_a, ref) => {
799
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
800
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
801
+ "textarea",
802
+ __spreadValues({
803
+ className: cn(
804
+ "flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
805
+ className
806
+ ),
807
+ ref
808
+ }, props)
809
+ );
810
+ });
811
+ Textarea.displayName = "Textarea";
812
+
813
+ // src/components/RecordForm.tsx
814
+ var import_jsx_runtime13 = require("react/jsx-runtime");
815
+ var COLOR_MAP = {
816
+ gray: "bg-muted",
817
+ blue: "bg-blue-500",
818
+ green: "bg-green-500",
819
+ yellow: "bg-amber-500",
820
+ red: "bg-red-500",
821
+ purple: "bg-purple-500"
822
+ };
823
+ var DEFAULT_INITIAL_VALUES = {};
824
+ function RecordForm({ schema, initialValues = DEFAULT_INITIAL_VALUES, onSubmit, mode }) {
825
+ const [formData, setFormData] = (0, import_react.useState)(initialValues);
826
+ (0, import_react.useEffect)(() => {
827
+ setFormData(initialValues);
828
+ }, [initialValues]);
829
+ const handleChange = (fieldId, value) => {
830
+ if (mode === "view") return;
831
+ setFormData((prev) => __spreadProps(__spreadValues({}, prev), { [fieldId]: value }));
832
+ };
833
+ const handleSubmit = (e) => {
834
+ e.preventDefault();
835
+ if (onSubmit && mode !== "view") onSubmit(formData);
836
+ };
837
+ const isReadOnly = mode === "view";
838
+ const renderField = (field) => {
839
+ var _a, _b, _c;
840
+ const value = (_a = formData[field.id]) != null ? _a : "";
841
+ if (field.id === "description" || field.type === "text" && field.name.toLowerCase().includes("description")) {
842
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
843
+ Textarea,
844
+ {
845
+ value,
846
+ disabled: isReadOnly,
847
+ onChange: (e) => handleChange(field.id, e.target.value),
848
+ placeholder: isReadOnly ? "" : `Enter ${field.name}...`,
849
+ className: "min-h-[100px] resize-none"
850
+ }
851
+ );
852
+ }
853
+ switch (field.type) {
854
+ case "text":
855
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
856
+ Input,
857
+ {
858
+ value,
859
+ disabled: isReadOnly,
860
+ onChange: (e) => handleChange(field.id, e.target.value),
861
+ placeholder: isReadOnly ? "" : `Enter ${field.name}...`
862
+ }
863
+ );
864
+ case "number":
865
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
866
+ Input,
867
+ {
868
+ type: "number",
869
+ value,
870
+ disabled: isReadOnly,
871
+ onChange: (e) => handleChange(field.id, e.target.value),
872
+ placeholder: isReadOnly ? "" : `Enter ${field.name}...`
873
+ }
874
+ );
875
+ case "date":
876
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
877
+ Input,
878
+ {
879
+ type: "date",
880
+ value,
881
+ disabled: isReadOnly,
882
+ onChange: (e) => handleChange(field.id, e.target.value)
883
+ }
884
+ );
885
+ case "checkbox":
886
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
887
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
888
+ Checkbox,
889
+ {
890
+ id: field.id,
891
+ checked: !!value,
892
+ disabled: isReadOnly,
893
+ onCheckedChange: (checked) => handleChange(field.id, checked)
894
+ }
895
+ ),
896
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Label, { htmlFor: field.id, className: "cursor-pointer text-sm", children: value ? "Yes" : "No" })
897
+ ] });
898
+ case "select":
899
+ if (isReadOnly) {
900
+ return value ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Badge, { variant: "secondary", children: value }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-muted-foreground text-sm", children: "None" });
901
+ }
902
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Select, { value, onValueChange: (v) => handleChange(field.id, v), children: [
903
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SelectTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SelectValue, { placeholder: "Select..." }) }),
904
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SelectContent, { children: (_b = field.options) == null ? void 0 : _b.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SelectItem, { value: opt.name, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
905
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("w-2 h-2 rounded-full", COLOR_MAP[opt.color || "gray"]) }),
906
+ opt.name
907
+ ] }) }, opt.id)) })
908
+ ] });
909
+ case "multiSelect":
910
+ const selectedValues = Array.isArray(value) ? value : [];
911
+ if (isReadOnly) {
912
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
913
+ selectedValues.map((v) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Badge, { variant: "secondary", children: v }, v)),
914
+ selectedValues.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-muted-foreground text-sm", children: "None" })
915
+ ] });
916
+ }
917
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex flex-wrap gap-2", children: (_c = field.options) == null ? void 0 : _c.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
918
+ Badge,
919
+ {
920
+ variant: selectedValues.includes(opt.name) ? "default" : "outline",
921
+ className: "cursor-pointer",
922
+ onClick: () => {
923
+ const newValues = selectedValues.includes(opt.name) ? selectedValues.filter((v) => v !== opt.name) : [...selectedValues, opt.name];
924
+ handleChange(field.id, newValues);
925
+ },
926
+ children: opt.name
927
+ },
928
+ opt.id
929
+ )) });
930
+ default:
931
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
932
+ Input,
933
+ {
934
+ value,
935
+ disabled: isReadOnly,
936
+ onChange: (e) => handleChange(field.id, e.target.value),
937
+ placeholder: isReadOnly ? "" : `Enter ${field.name}...`
938
+ }
939
+ );
940
+ }
941
+ };
942
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("form", { id: "record-form", onSubmit: handleSubmit, className: "space-y-5", children: [
943
+ schema.fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "space-y-2", children: [
944
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Label, { className: "text-sm font-medium", children: [
945
+ field.name,
946
+ field.isPrimary && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Badge, { variant: "outline", className: "ml-2 text-xs", children: "Primary" })
947
+ ] }),
948
+ renderField(field)
949
+ ] }, field.id)),
950
+ mode !== "view" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex justify-end pt-4 border-t", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { type: "submit", children: mode === "add" ? "Create Record" : "Save Changes" }) })
951
+ ] });
952
+ }
953
+
954
+ // src/components/views/FormView.tsx
955
+ var import_jsx_runtime14 = require("react/jsx-runtime");
956
+ function FormView({ schema, onCreateRecord }) {
957
+ const [success, setSuccess] = (0, import_react2.useState)(false);
958
+ const handleSubmit = (formData) => {
959
+ onCreateRecord(formData);
960
+ setSuccess(true);
961
+ setTimeout(() => setSuccess(false), 3e3);
962
+ };
963
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "h-full overflow-auto p-8 bg-muted/30", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "max-w-xl mx-auto", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Card, { children: [
964
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(CardHeader, { children: [
965
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CardTitle, { children: "Add New Record" }),
966
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CardDescription, { children: "Fill out the form below to add a new entry to the database." })
967
+ ] }),
968
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(CardContent, { children: [
969
+ success && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Alert, { className: "mb-6 border-green-200 bg-green-50 text-green-800 dark:border-green-800 dark:bg-green-950 dark:text-green-200", children: [
970
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react4.CheckCircle2, { className: "h-4 w-4" }),
971
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AlertDescription, { children: "Record created successfully!" })
972
+ ] }),
973
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
974
+ RecordForm,
975
+ {
976
+ schema,
977
+ mode: "add",
978
+ onSubmit: handleSubmit
979
+ }
980
+ )
981
+ ] })
982
+ ] }) }) });
983
+ }
984
+
985
+ // src/components/views/KanbanView.tsx
986
+ var import_react3 = require("react");
987
+ var import_lucide_react5 = require("lucide-react");
988
+ var import_jsx_runtime15 = require("react/jsx-runtime");
989
+ var BADGE_COLOR_MAP2 = {
990
+ gray: "bg-muted text-muted-foreground hover:bg-muted/80",
991
+ blue: "bg-blue-100 text-blue-700 dark:bg-blue-900/50 dark:text-blue-300 hover:bg-blue-100/80",
992
+ green: "bg-green-100 text-green-700 dark:bg-green-900/50 dark:text-green-300 hover:bg-green-100/80",
993
+ yellow: "bg-amber-100 text-amber-700 dark:bg-amber-900/50 dark:text-amber-300 hover:bg-amber-100/80",
994
+ red: "bg-red-100 text-red-700 dark:bg-red-900/50 dark:text-red-300 hover:bg-red-100/80",
995
+ purple: "bg-purple-100 text-purple-700 dark:bg-purple-900/50 dark:text-purple-300 hover:bg-purple-100/80"
996
+ };
997
+ var COLUMN_DOT_COLOR_MAP = {
998
+ gray: "bg-gray-400",
999
+ blue: "bg-blue-500",
1000
+ green: "bg-green-500",
1001
+ yellow: "bg-amber-500",
1002
+ red: "bg-red-500",
1003
+ purple: "bg-purple-500"
1004
+ };
1005
+ var FIELD_ICON_MAP = {
1006
+ text: import_lucide_react5.AlignLeft,
1007
+ number: import_lucide_react5.Hash,
1008
+ select: import_lucide_react5.Tag,
1009
+ multiSelect: import_lucide_react5.Tags,
1010
+ date: import_lucide_react5.Calendar,
1011
+ checkbox: import_lucide_react5.CheckSquare,
1012
+ user: import_lucide_react5.User
1013
+ };
1014
+ function KanbanView({ schema, records, onUpdateRecord, onDeleteRecord, onOpenModal }) {
1015
+ const [draggedRecord, setDraggedRecord] = (0, import_react3.useState)(null);
1016
+ const selectField = getSelectField(schema);
1017
+ const primaryField = getPrimaryField(schema);
1018
+ const columns = (0, import_react3.useMemo)(() => {
1019
+ if (!(selectField == null ? void 0 : selectField.options)) return [];
1020
+ return [
1021
+ { id: "__empty__", name: "Uncategorized", color: "gray" },
1022
+ ...selectField.options
1023
+ ];
1024
+ }, [selectField]);
1025
+ const recordsByColumn = (0, import_react3.useMemo)(() => {
1026
+ const grouped = {};
1027
+ columns.forEach((col) => {
1028
+ grouped[col.id] = [];
1029
+ });
1030
+ records.forEach((record) => {
1031
+ var _a, _b;
1032
+ if (!selectField) return;
1033
+ const value = record.fields[selectField.id];
1034
+ const option = (_a = selectField.options) == null ? void 0 : _a.find((o) => o.name === value);
1035
+ const colId = (option == null ? void 0 : option.id) || "__empty__";
1036
+ (_b = grouped[colId]) == null ? void 0 : _b.push(record);
1037
+ });
1038
+ return grouped;
1039
+ }, [records, columns, selectField]);
1040
+ const handleDragOver = (e) => {
1041
+ e.preventDefault();
1042
+ };
1043
+ const handleDrop = (columnId) => {
1044
+ if (!draggedRecord || !selectField) return;
1045
+ const column = columns.find((c) => c.id === columnId);
1046
+ const value = columnId === "__empty__" ? "" : (column == null ? void 0 : column.name) || "";
1047
+ onUpdateRecord(draggedRecord, { [selectField.id]: value });
1048
+ setDraggedRecord(null);
1049
+ };
1050
+ if (!selectField) {
1051
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "h-full flex items-center justify-center text-muted-foreground", children: "No select field found in schema. Add a select field to enable Kanban view." });
1052
+ }
1053
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "w-full grow overflow-hidden bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "relative w-full h-full overflow-x-auto overflow-y-hidden p-2", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex h-full", children: columns.map((column) => {
1054
+ var _a, _b;
1055
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "h-full pr-4", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "w-[264px] h-full border bg-muted rounded-md shrink-0 flex flex-col overflow-hidden", children: [
1056
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex h-12 w-full shrink-0 items-center justify-between border-b bg-card px-4", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center space-x-2 overflow-hidden text-muted-foreground", children: [
1057
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn("w-2 h-2 rounded-full shrink-0", COLUMN_DOT_COLOR_MAP[column.color || "gray"]) }),
1058
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-sm font-semibold truncate", children: column.name }),
1059
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "rounded-xl border px-2 text-xs", children: ((_a = recordsByColumn[column.id]) == null ? void 0 : _a.length) || 0 })
1060
+ ] }) }) }),
1061
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1062
+ "div",
1063
+ {
1064
+ className: "flex-1 w-full overflow-y-auto min-h-0",
1065
+ onDragOver: handleDragOver,
1066
+ onDrop: () => handleDrop(column.id),
1067
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex flex-col pt-3 pb-3", children: (_b = recordsByColumn[column.id]) == null ? void 0 : _b.map((record) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "w-full px-3 mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1068
+ "div",
1069
+ {
1070
+ draggable: true,
1071
+ onDragStart: () => setDraggedRecord(record.id),
1072
+ onClick: () => onOpenModal("view", record),
1073
+ className: cn(
1074
+ "relative flex w-full grow flex-col space-y-2 gap-1 overflow-hidden rounded-md border border-border bg-card hover:border-primary/15 p-3 cursor-pointer transition-all",
1075
+ draggedRecord === record.id && "opacity-50 ring-2 ring-primary"
1076
+ ),
1077
+ children: [
1078
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "text-base font-semibold", children: primaryField ? record.fields[primaryField.id] || "Untitled" : "Untitled" }),
1079
+ schema.fields.filter((f) => !f.isPrimary && f.id !== selectField.id).map((field) => {
1080
+ const value = record.fields[field.id];
1081
+ if (value === void 0 || value === null || value === "" || value === false) return null;
1082
+ const Icon2 = FIELD_ICON_MAP[field.type] || import_lucide_react5.AlignLeft;
1083
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
1084
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "mb-1 flex items-center space-x-1 text-muted-foreground", children: [
1085
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Icon2, { className: "w-4 h-4 text-sm" }),
1086
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-xs", children: field.name })
1087
+ ] }),
1088
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "w-full text-[13px] leading-5 breaking-all line-clamp-6", children: field.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex gap-1 flex-wrap", children: (() => {
1089
+ var _a2;
1090
+ const option = (_a2 = field.options) == null ? void 0 : _a2.find((o) => o.name === value);
1091
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1092
+ "div",
1093
+ {
1094
+ className: cn(
1095
+ "text-xs px-2 h-5 rounded-md flex items-center gap-1 min-w-0 truncate",
1096
+ BADGE_COLOR_MAP2[(option == null ? void 0 : option.color) || "gray"]
1097
+ ),
1098
+ title: String(value),
1099
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "min-w-0 truncate", children: String(value) })
1100
+ }
1101
+ );
1102
+ })() }) : field.type === "checkbox" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex gap-1 flex-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn(
1103
+ "flex items-center justify-center w-5 h-5 rounded-sm border border-primary shadow bg-primary text-primary-foreground"
1104
+ ), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.CheckSquare, { className: "h-4 w-4" }) }) }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { title: String(value), className: "whitespace-pre-wrap break-all", children: String(value) }) })
1105
+ ] }, field.id);
1106
+ })
1107
+ ]
1108
+ }
1109
+ ) }, record.id)) })
1110
+ }
1111
+ ),
1112
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex items-center justify-center rounded-b-md bg-slate-50 px-3 py-2 dark:bg-muted", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1113
+ Button,
1114
+ {
1115
+ variant: "outline",
1116
+ className: "w-full h-9 gap-2 bg-background dark:bg-white/5 dark:hover:bg-white/10 shadow-none hover:bg-zinc-100 dark:hover:bg-zinc-800",
1117
+ onClick: () => onOpenModal("add"),
1118
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.Plus, { className: "w-5 h-5" })
1119
+ }
1120
+ ) })
1121
+ ] }) }, column.id);
1122
+ }) }) }) });
1123
+ }
1124
+
1125
+ // src/components/views/GalleryView.tsx
1126
+ var import_lucide_react7 = require("lucide-react");
1127
+
1128
+ // src/components/ui/dropdown-menu.tsx
1129
+ var React11 = __toESM(require("react"));
1130
+ var DropdownMenuPrimitive = __toESM(require("@radix-ui/react-dropdown-menu"));
1131
+ var import_lucide_react6 = require("lucide-react");
1132
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1133
+ var DropdownMenu = DropdownMenuPrimitive.Root;
1134
+ var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
1135
+ var DropdownMenuSubTrigger = React11.forwardRef((_a, ref) => {
1136
+ var _b = _a, { className, inset, children } = _b, props = __objRest(_b, ["className", "inset", "children"]);
1137
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1138
+ DropdownMenuPrimitive.SubTrigger,
1139
+ __spreadProps(__spreadValues({
1140
+ ref,
1141
+ className: cn(
1142
+ "flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1143
+ inset && "pl-8",
1144
+ className
1145
+ )
1146
+ }, props), {
1147
+ children: [
1148
+ children,
1149
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.ChevronRight, { className: "ml-auto" })
1150
+ ]
1151
+ })
1152
+ );
1153
+ });
1154
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
1155
+ var DropdownMenuSubContent = React11.forwardRef((_a, ref) => {
1156
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1157
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1158
+ DropdownMenuPrimitive.SubContent,
1159
+ __spreadValues({
1160
+ ref,
1161
+ className: cn(
1162
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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 origin-[--radix-dropdown-menu-content-transform-origin]",
1163
+ className
1164
+ )
1165
+ }, props)
1166
+ );
1167
+ });
1168
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
1169
+ var DropdownMenuContent = React11.forwardRef((_a, ref) => {
1170
+ var _b = _a, { className, sideOffset = 4 } = _b, props = __objRest(_b, ["className", "sideOffset"]);
1171
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1172
+ DropdownMenuPrimitive.Content,
1173
+ __spreadValues({
1174
+ ref,
1175
+ sideOffset,
1176
+ className: cn(
1177
+ "z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
1178
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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 origin-[--radix-dropdown-menu-content-transform-origin]",
1179
+ className
1180
+ )
1181
+ }, props)
1182
+ ) });
1183
+ });
1184
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
1185
+ var DropdownMenuItem = React11.forwardRef((_a, ref) => {
1186
+ var _b = _a, { className, inset } = _b, props = __objRest(_b, ["className", "inset"]);
1187
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1188
+ DropdownMenuPrimitive.Item,
1189
+ __spreadValues({
1190
+ ref,
1191
+ className: cn(
1192
+ "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
1193
+ inset && "pl-8",
1194
+ className
1195
+ )
1196
+ }, props)
1197
+ );
1198
+ });
1199
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
1200
+ var DropdownMenuCheckboxItem = React11.forwardRef((_a, ref) => {
1201
+ var _b = _a, { className, children, checked } = _b, props = __objRest(_b, ["className", "children", "checked"]);
1202
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1203
+ DropdownMenuPrimitive.CheckboxItem,
1204
+ __spreadProps(__spreadValues({
1205
+ ref,
1206
+ className: cn(
1207
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1208
+ className
1209
+ ),
1210
+ checked
1211
+ }, props), {
1212
+ children: [
1213
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.Check, { className: "h-4 w-4" }) }) }),
1214
+ children
1215
+ ]
1216
+ })
1217
+ );
1218
+ });
1219
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
1220
+ var DropdownMenuRadioItem = React11.forwardRef((_a, ref) => {
1221
+ var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
1222
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1223
+ DropdownMenuPrimitive.RadioItem,
1224
+ __spreadProps(__spreadValues({
1225
+ ref,
1226
+ className: cn(
1227
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1228
+ className
1229
+ )
1230
+ }, props), {
1231
+ children: [
1232
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.Circle, { className: "h-2 w-2 fill-current" }) }) }),
1233
+ children
1234
+ ]
1235
+ })
1236
+ );
1237
+ });
1238
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
1239
+ var DropdownMenuLabel = React11.forwardRef((_a, ref) => {
1240
+ var _b = _a, { className, inset } = _b, props = __objRest(_b, ["className", "inset"]);
1241
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1242
+ DropdownMenuPrimitive.Label,
1243
+ __spreadValues({
1244
+ ref,
1245
+ className: cn(
1246
+ "px-2 py-1.5 text-sm font-semibold",
1247
+ inset && "pl-8",
1248
+ className
1249
+ )
1250
+ }, props)
1251
+ );
1252
+ });
1253
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
1254
+ var DropdownMenuSeparator = React11.forwardRef((_a, ref) => {
1255
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1256
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1257
+ DropdownMenuPrimitive.Separator,
1258
+ __spreadValues({
1259
+ ref,
1260
+ className: cn("-mx-1 my-1 h-px bg-muted", className)
1261
+ }, props)
1262
+ );
1263
+ });
1264
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
1265
+ var DropdownMenuShortcut = (_a) => {
1266
+ var _b = _a, {
1267
+ className
1268
+ } = _b, props = __objRest(_b, [
1269
+ "className"
1270
+ ]);
1271
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1272
+ "span",
1273
+ __spreadValues({
1274
+ className: cn("ml-auto text-xs tracking-widest opacity-60", className)
1275
+ }, props)
1276
+ );
1277
+ };
1278
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
1279
+
1280
+ // src/components/views/GalleryView.tsx
1281
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1282
+ function GalleryView({ schema, records, onDeleteRecord, onOpenModal }) {
1283
+ const primaryField = getPrimaryField(schema);
1284
+ const displayFields = schema.fields.filter((f) => f.id !== (primaryField == null ? void 0 : primaryField.id)).slice(0, 3);
1285
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "h-full overflow-auto p-6 bg-muted/30", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4", children: [
1286
+ records.map((record) => {
1287
+ const title = primaryField ? record.fields[primaryField.id] : "Untitled";
1288
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1289
+ Card,
1290
+ {
1291
+ className: "group hover:shadow-md transition-all cursor-pointer overflow-hidden",
1292
+ onClick: () => onOpenModal("view", record),
1293
+ children: [
1294
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "aspect-[16/10] bg-muted flex items-center justify-center relative", children: [
1295
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-4xl font-semibold text-muted-foreground/20 select-none", children: (title || "U").charAt(0).toUpperCase() }),
1296
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(DropdownMenu, { children: [
1297
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DropdownMenuTrigger, { asChild: true, onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Button, { variant: "secondary", size: "icon", className: "h-8 w-8", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.MoreHorizontal, { className: "h-4 w-4" }) }) }),
1298
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(DropdownMenuContent, { align: "end", children: [
1299
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(DropdownMenuItem, { onClick: () => onOpenModal("view", record), children: [
1300
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.Eye, { className: "h-4 w-4 mr-2" }),
1301
+ "View"
1302
+ ] }),
1303
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(DropdownMenuItem, { onClick: () => onOpenModal("edit", record), children: [
1304
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.Pencil, { className: "h-4 w-4 mr-2" }),
1305
+ "Edit"
1306
+ ] }),
1307
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1308
+ DropdownMenuItem,
1309
+ {
1310
+ className: "text-destructive focus:text-destructive",
1311
+ onClick: () => onDeleteRecord(record.id),
1312
+ children: [
1313
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.Trash2, { className: "h-4 w-4 mr-2" }),
1314
+ "Delete"
1315
+ ]
1316
+ }
1317
+ )
1318
+ ] })
1319
+ ] }) })
1320
+ ] }),
1321
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(CardContent, { className: "p-4", children: [
1322
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h3", { className: "font-medium text-sm truncate mb-2", children: title || "Untitled" }),
1323
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "space-y-1.5", children: displayFields.map((field) => {
1324
+ const value = record.fields[field.id];
1325
+ if (value === void 0 || value === null || value === "" || value === false) return null;
1326
+ let displayValue = value;
1327
+ if (Array.isArray(value)) displayValue = value.join(", ");
1328
+ else if (typeof value === "boolean") displayValue = value ? "Yes" : "No";
1329
+ else if (field.type === "date") displayValue = new Date(value).toLocaleDateString();
1330
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-baseline gap-2 text-xs", children: [
1331
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "text-muted-foreground flex-shrink-0", children: [
1332
+ field.name,
1333
+ ":"
1334
+ ] }),
1335
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-foreground truncate", children: displayValue })
1336
+ ] }, field.id);
1337
+ }) })
1338
+ ] })
1339
+ ]
1340
+ },
1341
+ record.id
1342
+ );
1343
+ }),
1344
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1345
+ "div",
1346
+ {
1347
+ className: "flex flex-col items-center justify-center cursor-pointer border-2 border-dashed border-muted-foreground/20 rounded-lg transition-all hover:border-primary hover:bg-muted/50 min-h-[200px]",
1348
+ onClick: () => onOpenModal("add"),
1349
+ children: [
1350
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "h-10 w-10 rounded-full bg-muted flex items-center justify-center mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.Plus, { className: "h-5 w-5 text-muted-foreground" }) }),
1351
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-sm font-medium text-muted-foreground", children: "Add Record" })
1352
+ ]
1353
+ }
1354
+ )
1355
+ ] }) });
1356
+ }
1357
+
1358
+ // src/components/views/CalendarView.tsx
1359
+ var import_react4 = require("react");
1360
+ var import_lucide_react8 = require("lucide-react");
1361
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1362
+ function CalendarView({ schema, records, onUpdateRecord, onDeleteRecord, onOpenModal }) {
1363
+ const [currentDate, setCurrentDate] = (0, import_react4.useState)(/* @__PURE__ */ new Date());
1364
+ const dateField = getDateField(schema);
1365
+ const primaryField = getPrimaryField(schema);
1366
+ const monthStart = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1);
1367
+ const monthEnd = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0);
1368
+ const calendarDays = (0, import_react4.useMemo)(() => {
1369
+ const days = [];
1370
+ const firstDayOfWeek = monthStart.getDay();
1371
+ for (let i = firstDayOfWeek - 1; i >= 0; i--) {
1372
+ const date = new Date(monthStart);
1373
+ date.setDate(date.getDate() - i - 1);
1374
+ days.push(date);
1375
+ }
1376
+ for (let i = 1; i <= monthEnd.getDate(); i++) {
1377
+ days.push(new Date(currentDate.getFullYear(), currentDate.getMonth(), i));
1378
+ }
1379
+ const remaining = 42 - days.length;
1380
+ for (let i = 1; i <= remaining; i++) {
1381
+ const date = new Date(monthEnd);
1382
+ date.setDate(date.getDate() + i);
1383
+ days.push(date);
1384
+ }
1385
+ return days;
1386
+ }, [currentDate, monthStart, monthEnd]);
1387
+ const recordsByDate = (0, import_react4.useMemo)(() => {
1388
+ const map = {};
1389
+ if (!dateField) return map;
1390
+ records.forEach((record) => {
1391
+ const dateValue = record.fields[dateField.id];
1392
+ if (dateValue) {
1393
+ const date = new Date(dateValue);
1394
+ const key = date.toISOString().split("T")[0];
1395
+ if (!map[key]) map[key] = [];
1396
+ map[key].push(record);
1397
+ }
1398
+ });
1399
+ return map;
1400
+ }, [records, dateField]);
1401
+ const isToday = (date) => date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
1402
+ const isCurrentMonth = (date) => date.getMonth() === currentDate.getMonth();
1403
+ const handleDayClick = (date) => {
1404
+ if (!dateField) return;
1405
+ onOpenModal("add", void 0, { [dateField.id]: date.toISOString().split("T")[0] });
1406
+ };
1407
+ const handleDrop = (recordId, newDate) => {
1408
+ if (!dateField) return;
1409
+ onUpdateRecord(recordId, { [dateField.id]: newDate.toISOString().split("T")[0] });
1410
+ };
1411
+ const weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
1412
+ const monthNames = [
1413
+ "January",
1414
+ "February",
1415
+ "March",
1416
+ "April",
1417
+ "May",
1418
+ "June",
1419
+ "July",
1420
+ "August",
1421
+ "September",
1422
+ "October",
1423
+ "November",
1424
+ "December"
1425
+ ];
1426
+ if (!dateField) {
1427
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-full flex items-center justify-center text-muted-foreground", children: "No date field found in schema. Add a date field to enable Calendar view." });
1428
+ }
1429
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "h-full flex flex-col p-6 bg-muted/30", children: [
1430
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
1431
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-4", children: [
1432
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("h2", { className: "text-xl font-semibold", children: [
1433
+ monthNames[currentDate.getMonth()],
1434
+ " ",
1435
+ currentDate.getFullYear()
1436
+ ] }),
1437
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1438
+ Button,
1439
+ {
1440
+ variant: "outline",
1441
+ size: "sm",
1442
+ onClick: () => setCurrentDate(/* @__PURE__ */ new Date()),
1443
+ children: "Today"
1444
+ }
1445
+ )
1446
+ ] }),
1447
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-1", children: [
1448
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1449
+ Button,
1450
+ {
1451
+ variant: "outline",
1452
+ size: "icon",
1453
+ className: "h-8 w-8",
1454
+ onClick: () => setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, 1)),
1455
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.ChevronLeft, { className: "h-4 w-4" })
1456
+ }
1457
+ ),
1458
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1459
+ Button,
1460
+ {
1461
+ variant: "outline",
1462
+ size: "icon",
1463
+ className: "h-8 w-8",
1464
+ onClick: () => setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1)),
1465
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.ChevronRight, { className: "h-4 w-4" })
1466
+ }
1467
+ )
1468
+ ] })
1469
+ ] }),
1470
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex-1 border rounded-lg overflow-hidden bg-background flex flex-col", children: [
1471
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "grid grid-cols-7 bg-muted/50 border-b", children: weekDays.map((day) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "px-2 py-2 text-center text-xs font-medium text-muted-foreground", children: day }, day)) }),
1472
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "grid grid-cols-7 flex-1", children: calendarDays.map((date, index) => {
1473
+ const dateKey = date.toISOString().split("T")[0];
1474
+ const dayRecords = recordsByDate[dateKey] || [];
1475
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1476
+ "div",
1477
+ {
1478
+ className: cn(
1479
+ "min-h-[100px] p-1.5 border-b border-r transition-all group relative flex flex-col",
1480
+ !isCurrentMonth(date) && "bg-muted/30 text-muted-foreground/50",
1481
+ isCurrentMonth(date) && "hover:bg-muted/10",
1482
+ index % 7 === 6 && "border-r-0"
1483
+ ),
1484
+ onDragOver: (e) => e.preventDefault(),
1485
+ onDrop: (e) => {
1486
+ const recordId = e.dataTransfer.getData("recordId");
1487
+ if (recordId) handleDrop(recordId, date);
1488
+ },
1489
+ children: [
1490
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center justify-between mb-1", children: [
1491
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: cn(
1492
+ "text-xs w-6 h-6 flex items-center justify-center rounded-full",
1493
+ isToday(date) ? "bg-primary text-primary-foreground font-medium" : ""
1494
+ ), children: date.getDate() }),
1495
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1496
+ Button,
1497
+ {
1498
+ variant: "ghost",
1499
+ size: "icon",
1500
+ className: "h-5 w-5 opacity-0 group-hover:opacity-100 transition-opacity",
1501
+ onClick: () => handleDayClick(date),
1502
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Plus, { className: "h-3 w-3" })
1503
+ }
1504
+ )
1505
+ ] }),
1506
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex-1 space-y-0.5 overflow-y-auto", children: dayRecords.map((record) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1507
+ "div",
1508
+ {
1509
+ draggable: true,
1510
+ onDragStart: (e) => {
1511
+ e.stopPropagation();
1512
+ e.dataTransfer.setData("recordId", record.id);
1513
+ },
1514
+ onClick: (e) => {
1515
+ e.stopPropagation();
1516
+ onOpenModal("view", record);
1517
+ },
1518
+ className: "group/item relative",
1519
+ children: [
1520
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1521
+ Badge,
1522
+ {
1523
+ variant: "secondary",
1524
+ className: "w-full justify-start truncate text-xs py-0.5 cursor-grab active:cursor-grabbing hover:bg-primary/10",
1525
+ children: primaryField ? record.fields[primaryField.id] || "Untitled" : "Event"
1526
+ }
1527
+ ),
1528
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "absolute right-0 top-0 h-full flex items-center opacity-0 group-hover/item:opacity-100 bg-background/80 pr-1 rounded-r", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DropdownMenu, { children: [
1529
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DropdownMenuTrigger, { asChild: true, onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.MoreHorizontal, { className: "h-3 w-3 text-muted-foreground cursor-pointer" }) }),
1530
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DropdownMenuContent, { align: "end", children: [
1531
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DropdownMenuItem, { onClick: () => onOpenModal("view", record), children: [
1532
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Eye, { className: "h-4 w-4 mr-2" }),
1533
+ "View"
1534
+ ] }),
1535
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DropdownMenuItem, { onClick: () => onOpenModal("edit", record), children: [
1536
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Pencil, { className: "h-4 w-4 mr-2" }),
1537
+ "Edit"
1538
+ ] }),
1539
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DropdownMenuItem, { className: "text-destructive focus:text-destructive", onClick: () => onDeleteRecord(record.id), children: [
1540
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Trash2, { className: "h-4 w-4 mr-2" }),
1541
+ "Delete"
1542
+ ] })
1543
+ ] })
1544
+ ] }) })
1545
+ ]
1546
+ },
1547
+ record.id
1548
+ )) })
1549
+ ]
1550
+ },
1551
+ index
1552
+ );
1553
+ }) })
1554
+ ] })
1555
+ ] });
1556
+ }
1557
+
1558
+ // src/components/ui/dialog.tsx
1559
+ var React12 = __toESM(require("react"));
1560
+ var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"));
1561
+ var import_lucide_react9 = require("lucide-react");
1562
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1563
+ var Dialog = DialogPrimitive.Root;
1564
+ var DialogPortal = DialogPrimitive.Portal;
1565
+ var DialogOverlay = React12.forwardRef((_a, ref) => {
1566
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1567
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1568
+ DialogPrimitive.Overlay,
1569
+ __spreadValues({
1570
+ ref,
1571
+ className: cn(
1572
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1573
+ className
1574
+ )
1575
+ }, props)
1576
+ );
1577
+ });
1578
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
1579
+ var DialogContent = React12.forwardRef((_a, ref) => {
1580
+ var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
1581
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogPortal, { children: [
1582
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogOverlay, {}),
1583
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1584
+ DialogPrimitive.Content,
1585
+ __spreadProps(__spreadValues({
1586
+ ref,
1587
+ className: cn(
1588
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
1589
+ className
1590
+ )
1591
+ }, props), {
1592
+ children: [
1593
+ children,
1594
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
1595
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.X, { className: "h-4 w-4" }),
1596
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "sr-only", children: "Close" })
1597
+ ] })
1598
+ ]
1599
+ })
1600
+ )
1601
+ ] });
1602
+ });
1603
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
1604
+ var DialogHeader = (_a) => {
1605
+ var _b = _a, {
1606
+ className
1607
+ } = _b, props = __objRest(_b, [
1608
+ "className"
1609
+ ]);
1610
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1611
+ "div",
1612
+ __spreadValues({
1613
+ className: cn(
1614
+ "flex flex-col space-y-1.5 text-center sm:text-left",
1615
+ className
1616
+ )
1617
+ }, props)
1618
+ );
1619
+ };
1620
+ DialogHeader.displayName = "DialogHeader";
1621
+ var DialogFooter = (_a) => {
1622
+ var _b = _a, {
1623
+ className
1624
+ } = _b, props = __objRest(_b, [
1625
+ "className"
1626
+ ]);
1627
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1628
+ "div",
1629
+ __spreadValues({
1630
+ className: cn(
1631
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
1632
+ className
1633
+ )
1634
+ }, props)
1635
+ );
1636
+ };
1637
+ DialogFooter.displayName = "DialogFooter";
1638
+ var DialogTitle = React12.forwardRef((_a, ref) => {
1639
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1640
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1641
+ DialogPrimitive.Title,
1642
+ __spreadValues({
1643
+ ref,
1644
+ className: cn(
1645
+ "text-lg font-semibold leading-none tracking-tight",
1646
+ className
1647
+ )
1648
+ }, props)
1649
+ );
1650
+ });
1651
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
1652
+ var DialogDescription = React12.forwardRef((_a, ref) => {
1653
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
1654
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1655
+ DialogPrimitive.Description,
1656
+ __spreadValues({
1657
+ ref,
1658
+ className: cn("text-sm text-muted-foreground", className)
1659
+ }, props)
1660
+ );
1661
+ });
1662
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
1663
+
1664
+ // src/components/ui/scroll-area.tsx
1665
+ var React13 = __toESM(require("react"));
1666
+ var ScrollAreaPrimitive = __toESM(require("@radix-ui/react-scroll-area"));
1667
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1668
+ var ScrollArea = React13.forwardRef((_a, ref) => {
1669
+ var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
1670
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1671
+ ScrollAreaPrimitive.Root,
1672
+ __spreadProps(__spreadValues({
1673
+ ref,
1674
+ className: cn("relative overflow-hidden", className)
1675
+ }, props), {
1676
+ children: [
1677
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
1678
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ScrollBar, {}),
1679
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ScrollAreaPrimitive.Corner, {})
1680
+ ]
1681
+ })
1682
+ );
1683
+ });
1684
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
1685
+ var ScrollBar = React13.forwardRef((_a, ref) => {
1686
+ var _b = _a, { className, orientation = "vertical" } = _b, props = __objRest(_b, ["className", "orientation"]);
1687
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1688
+ ScrollAreaPrimitive.ScrollAreaScrollbar,
1689
+ __spreadProps(__spreadValues({
1690
+ ref,
1691
+ orientation,
1692
+ className: cn(
1693
+ "flex touch-none select-none transition-colors",
1694
+ orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
1695
+ orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]",
1696
+ className
1697
+ )
1698
+ }, props), {
1699
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ScrollAreaPrimitive.ScrollAreaThumb, { className: "relative flex-1 rounded-full bg-border" })
1700
+ })
1701
+ );
1702
+ });
1703
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
1704
+
1705
+ // src/components/RecordModal.tsx
1706
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1707
+ function RecordModal({
1708
+ isOpen,
1709
+ onClose,
1710
+ mode,
1711
+ schema,
1712
+ record,
1713
+ initialValues,
1714
+ onSubmit
1715
+ }) {
1716
+ const titles = {
1717
+ add: "Create New Record",
1718
+ edit: "Edit Record",
1719
+ view: "Record Details"
1720
+ };
1721
+ const descriptions = {
1722
+ add: "Enter the details for the new record.",
1723
+ edit: "Modify the values for this record.",
1724
+ view: "View the data for this record."
1725
+ };
1726
+ const handleSubmit = (values) => {
1727
+ onSubmit(values);
1728
+ onClose();
1729
+ };
1730
+ const formValues = mode === "add" ? initialValues : record == null ? void 0 : record.fields;
1731
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DialogContent, { className: "sm:max-w-[500px] max-h-[85vh] flex flex-col", children: [
1732
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DialogHeader, { children: [
1733
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DialogTitle, { children: titles[mode] }),
1734
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DialogDescription, { children: descriptions[mode] })
1735
+ ] }),
1736
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ScrollArea, { className: "flex-1 -mx-6 px-6", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1737
+ RecordForm,
1738
+ {
1739
+ schema,
1740
+ mode,
1741
+ initialValues: formValues || {},
1742
+ onSubmit: handleSubmit
1743
+ }
1744
+ ) })
1745
+ ] }) });
1746
+ }
1747
+
1748
+ // src/components/ThemeToggle.tsx
1749
+ var import_next_themes = require("next-themes");
1750
+ var import_lucide_react10 = require("lucide-react");
1751
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1752
+ function ThemeToggle() {
1753
+ const { setTheme, theme } = (0, import_next_themes.useTheme)();
1754
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenu, { children: [
1755
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Button, { variant: "ghost", size: "icon", className: "h-9 w-9", children: [
1756
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Sun, { className: "h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" }),
1757
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Moon, { className: "absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" }),
1758
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "sr-only", children: "Toggle theme" })
1759
+ ] }) }),
1760
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenuContent, { align: "end", children: [
1761
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuItem, { onClick: () => setTheme("light"), children: "Light" }),
1762
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuItem, { onClick: () => setTheme("dark"), children: "Dark" }),
1763
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuItem, { onClick: () => setTheme("system"), children: "System" })
1764
+ ] })
1765
+ ] });
1766
+ }
1767
+
1768
+ // src/components/DataViews.tsx
1769
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1770
+ function DataViews({ schema, dbClient, config }) {
1771
+ const [records, setRecords] = (0, import_react5.useState)([]);
1772
+ const [activeView, setActiveView] = (0, import_react5.useState)((config == null ? void 0 : config.defaultView) || "grid");
1773
+ const [modalState, setModalState] = (0, import_react5.useState)({
1774
+ isOpen: false,
1775
+ mode: "add"
1776
+ });
1777
+ const [mounted, setMounted] = (0, import_react5.useState)(false);
1778
+ const hasSelectField = !!getSelectField(schema);
1779
+ const hasDateField = !!getDateField(schema);
1780
+ const fetchRecords = async () => {
1781
+ try {
1782
+ const data = await dbClient.getRecords();
1783
+ setRecords(data);
1784
+ } catch (error) {
1785
+ console.error("Failed to fetch records:", error);
1786
+ }
1787
+ };
1788
+ (0, import_react5.useEffect)(() => {
1789
+ setMounted(true);
1790
+ fetchRecords();
1791
+ }, [dbClient]);
1792
+ const handleCreateRecord = async (fieldValues) => {
1793
+ try {
1794
+ const newRecord = await dbClient.createRecord({ fields: fieldValues });
1795
+ setRecords((prev) => [newRecord, ...prev]);
1796
+ return newRecord;
1797
+ } catch (error) {
1798
+ console.error("Failed to create record:", error);
1799
+ throw error;
1800
+ }
1801
+ };
1802
+ const handleUpdateRecord = async (recordId, fieldValues) => {
1803
+ try {
1804
+ const updatedRecord = await dbClient.updateRecord(recordId, { fields: fieldValues });
1805
+ setRecords((prev) => prev.map((r) => r.id === recordId ? updatedRecord : r));
1806
+ } catch (error) {
1807
+ console.error("Failed to update record:", error);
1808
+ throw error;
1809
+ }
1810
+ };
1811
+ const handleDeleteRecord = async (recordId) => {
1812
+ try {
1813
+ await dbClient.deleteRecord(recordId);
1814
+ setRecords((prev) => prev.filter((r) => r.id !== recordId));
1815
+ } catch (error) {
1816
+ console.error("Failed to delete record:", error);
1817
+ throw error;
1818
+ }
1819
+ };
1820
+ const openModal = (mode, record, initialValues) => {
1821
+ setModalState({ isOpen: true, mode, record, initialValues });
1822
+ };
1823
+ const commonProps = {
1824
+ schema,
1825
+ records,
1826
+ onCreateRecord: handleCreateRecord,
1827
+ onUpdateRecord: handleUpdateRecord,
1828
+ onDeleteRecord: handleDeleteRecord,
1829
+ onOpenModal: openModal
1830
+ };
1831
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "h-full w-full flex flex-col bg-background", children: [
1832
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("header", { className: "border-b px-6 py-3 flex items-center justify-between shrink-0", children: [
1833
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-3", children: [
1834
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-2xl", children: schema.icon }),
1835
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { className: "text-lg font-semibold", children: schema.name })
1836
+ ] }),
1837
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ThemeToggle, {})
1838
+ ] }),
1839
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Tabs, { value: activeView, onValueChange: (v) => setActiveView(v), className: "flex-1 flex flex-col overflow-hidden", children: [
1840
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "border-b px-4 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(TabsList, { className: "h-10", children: [
1841
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(TabsTrigger, { value: "grid", className: "gap-2", children: [
1842
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.LayoutGrid, { className: "h-4 w-4" }),
1843
+ "Grid"
1844
+ ] }),
1845
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(TabsTrigger, { value: "form", className: "gap-2", children: [
1846
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.FileText, { className: "h-4 w-4" }),
1847
+ "Form"
1848
+ ] }),
1849
+ hasSelectField && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(TabsTrigger, { value: "kanban", className: "gap-2", children: [
1850
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Columns, { className: "h-4 w-4" }),
1851
+ "Kanban"
1852
+ ] }),
1853
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(TabsTrigger, { value: "gallery", className: "gap-2", children: [
1854
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Image, { className: "h-4 w-4" }),
1855
+ "Gallery"
1856
+ ] }),
1857
+ hasDateField && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(TabsTrigger, { value: "calendar", className: "gap-2", children: [
1858
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Calendar, { className: "h-4 w-4" }),
1859
+ "Calendar"
1860
+ ] })
1861
+ ] }) }),
1862
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 overflow-auto relative", children: [
1863
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TabsContent, { value: "grid", className: "h-full m-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(GridView, __spreadValues({}, commonProps)) }),
1864
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TabsContent, { value: "form", className: "h-full m-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(FormView, __spreadValues({}, commonProps)) }),
1865
+ hasSelectField && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TabsContent, { value: "kanban", className: "h-full m-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(KanbanView, __spreadValues({}, commonProps)) }),
1866
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TabsContent, { value: "gallery", className: "h-full m-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(GalleryView, __spreadValues({}, commonProps)) }),
1867
+ hasDateField && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TabsContent, { value: "calendar", className: "h-full m-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CalendarView, __spreadValues({}, commonProps)) })
1868
+ ] })
1869
+ ] }),
1870
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1871
+ RecordModal,
1872
+ {
1873
+ isOpen: modalState.isOpen,
1874
+ onClose: () => setModalState((s) => __spreadProps(__spreadValues({}, s), { isOpen: false })),
1875
+ mode: modalState.mode,
1876
+ schema,
1877
+ record: modalState.record,
1878
+ initialValues: modalState.initialValues,
1879
+ onSubmit: (values) => {
1880
+ if (modalState.mode === "add") {
1881
+ handleCreateRecord(values);
1882
+ } else if (modalState.mode === "edit" && modalState.record) {
1883
+ handleUpdateRecord(modalState.record.id, values);
1884
+ }
1885
+ }
1886
+ }
1887
+ )
1888
+ ] });
1889
+ }
1890
+ // Annotate the CommonJS export names for ESM import in node:
1891
+ 0 && (module.exports = {
1892
+ DataViews,
1893
+ getDateField,
1894
+ getPrimaryField,
1895
+ getSelectField,
1896
+ tableSchema
1897
+ });