@jameskabz/nextcraft-ui 0.6.3 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/craft/components.cjs +64 -1779
  2. package/dist/craft/components.cjs.map +1 -1
  3. package/dist/craft/components.js +31 -42
  4. package/dist/craft/components.js.map +1 -1
  5. package/dist/craft/forms.cjs +6 -1347
  6. package/dist/craft/forms.cjs.map +1 -1
  7. package/dist/craft/forms.js +3 -8
  8. package/dist/craft/forms.js.map +1 -1
  9. package/dist/craft/layout.cjs +20 -374
  10. package/dist/craft/layout.cjs.map +1 -1
  11. package/dist/craft/layout.js +10 -14
  12. package/dist/craft/layout.js.map +1 -1
  13. package/dist/craft/table.cjs +8 -632
  14. package/dist/craft/table.cjs.map +1 -1
  15. package/dist/craft/table.js +4 -8
  16. package/dist/craft/table.js.map +1 -1
  17. package/dist/craft/theme.cjs +5 -137
  18. package/dist/craft/theme.cjs.map +1 -1
  19. package/dist/craft/theme.js +2 -6
  20. package/dist/craft/theme.js.map +1 -1
  21. package/dist/index.cjs +103 -3426
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.js +50 -70
  24. package/dist/index.js.map +1 -1
  25. package/dist/styles.css +0 -31
  26. package/package.json +6 -1
  27. package/dist/chunk-6F7FN2ZF.js +0 -671
  28. package/dist/chunk-6F7FN2ZF.js.map +0 -1
  29. package/dist/chunk-7Q4Z47HT.js +0 -657
  30. package/dist/chunk-7Q4Z47HT.js.map +0 -1
  31. package/dist/chunk-7SKDTIEK.js +0 -49
  32. package/dist/chunk-7SKDTIEK.js.map +0 -1
  33. package/dist/chunk-FEFH5O5K.js +0 -49
  34. package/dist/chunk-FEFH5O5K.js.map +0 -1
  35. package/dist/chunk-M2EKVXB6.js +0 -127
  36. package/dist/chunk-M2EKVXB6.js.map +0 -1
  37. package/dist/chunk-SBLIF6UU.js +0 -1029
  38. package/dist/chunk-SBLIF6UU.js.map +0 -1
  39. package/dist/chunk-VQ6T3HIX.js +0 -9
  40. package/dist/chunk-VQ6T3HIX.js.map +0 -1
  41. package/dist/chunk-YVZL4GET.js +0 -328
  42. package/dist/chunk-YVZL4GET.js.map +0 -1
  43. package/dist/chunk-ZRV4Y374.js +0 -582
  44. package/dist/chunk-ZRV4Y374.js.map +0 -1
@@ -1,657 +0,0 @@
1
- import {
2
- CraftButton,
3
- CraftCheckbox,
4
- CraftCurrencyInput,
5
- CraftDatePicker,
6
- CraftModal,
7
- CraftNumberInput,
8
- CraftSelect,
9
- CraftSubmitButton,
10
- CraftSwitch,
11
- CraftTextarea
12
- } from "./chunk-6F7FN2ZF.js";
13
- import {
14
- CraftInput
15
- } from "./chunk-7SKDTIEK.js";
16
- import {
17
- cn
18
- } from "./chunk-VQ6T3HIX.js";
19
-
20
- // src/components/craft-form.tsx
21
- import * as React from "react";
22
- import { FormProvider } from "react-hook-form";
23
- import { jsx, jsxs } from "react/jsx-runtime";
24
- function CraftForm({
25
- form,
26
- onSubmit,
27
- open,
28
- defaultOpen = false,
29
- onOpenChange,
30
- trigger,
31
- title,
32
- description,
33
- submitLabel = "Save",
34
- cancelLabel = "Cancel",
35
- tone,
36
- className,
37
- children,
38
- footer,
39
- disableSubmitWhenInvalid = true,
40
- closeOnSubmit = true,
41
- formClassName
42
- }) {
43
- const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
44
- const isControlled = typeof open === "boolean";
45
- const isOpen = isControlled ? open : uncontrolledOpen;
46
- const setOpen = React.useCallback(
47
- (next) => {
48
- if (!isControlled) setUncontrolledOpen(next);
49
- onOpenChange == null ? void 0 : onOpenChange(next);
50
- },
51
- [isControlled, onOpenChange]
52
- );
53
- const formId = React.useId();
54
- const handleSubmit = form.handleSubmit(async (values) => {
55
- await onSubmit(values);
56
- if (closeOnSubmit) setOpen(false);
57
- });
58
- const footerContent = footer != null ? footer : /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
59
- /* @__PURE__ */ jsx(CraftButton, { type: "button", variant: "ghost", onClick: () => setOpen(false), children: cancelLabel }),
60
- /* @__PURE__ */ jsx(
61
- CraftSubmitButton,
62
- {
63
- form: formId,
64
- disableWhenInvalid: disableSubmitWhenInvalid,
65
- children: submitLabel
66
- }
67
- )
68
- ] });
69
- return /* @__PURE__ */ jsx(FormProvider, { ...form, children: /* @__PURE__ */ jsx(
70
- CraftModal,
71
- {
72
- open: isOpen,
73
- onOpenChange: setOpen,
74
- trigger,
75
- title,
76
- description,
77
- tone,
78
- className,
79
- footer: footerContent,
80
- children: /* @__PURE__ */ jsx(
81
- "form",
82
- {
83
- id: formId,
84
- onSubmit: handleSubmit,
85
- className: cn("space-y-5", formClassName),
86
- children
87
- }
88
- )
89
- }
90
- ) });
91
- }
92
-
93
- // src/components/craft-form-field.tsx
94
- import {
95
- Controller,
96
- useFormContext
97
- } from "react-hook-form";
98
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
99
- function getFieldError(errors, name) {
100
- if (!errors || typeof errors !== "object") return void 0;
101
- const segments = name.split(".");
102
- let current = errors;
103
- for (const segment of segments) {
104
- if (!current || typeof current !== "object") return void 0;
105
- current = current[segment];
106
- }
107
- return current;
108
- }
109
- var baseInputClass = "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)] focus:outline-none focus:ring-4 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed border-[rgb(var(--nc-border)/0.35)] focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)] px-5 py-3 text-base placeholder:text-[rgb(var(--nc-fg-soft))]";
110
- function CraftFormField({
111
- name,
112
- label,
113
- description,
114
- type = "text",
115
- options = [],
116
- placeholder,
117
- tone,
118
- className,
119
- inputClassName,
120
- labelClassName,
121
- descriptionClassName,
122
- rules,
123
- disabled,
124
- fieldProps
125
- }) {
126
- const { register, control, formState } = useFormContext();
127
- const error = getFieldError(formState.errors, name);
128
- const errorMessage = typeof (error == null ? void 0 : error.message) === "string" ? error.message : void 0;
129
- if (type === "hidden") {
130
- return /* @__PURE__ */ jsx2("input", { type: "hidden", ...register(name, rules) });
131
- }
132
- const labelNode = label ? /* @__PURE__ */ jsx2(
133
- "label",
134
- {
135
- htmlFor: name,
136
- className: cn(
137
- "text-sm font-semibold text-[rgb(var(--nc-fg))]",
138
- labelClassName
139
- ),
140
- children: label
141
- }
142
- ) : null;
143
- const descriptionNode = description ? /* @__PURE__ */ jsx2(
144
- "p",
145
- {
146
- className: cn(
147
- "text-xs text-[rgb(var(--nc-fg-muted))]",
148
- descriptionClassName
149
- ),
150
- children: description
151
- }
152
- ) : null;
153
- const errorNode = errorMessage ? /* @__PURE__ */ jsx2("p", { className: "text-xs text-[rgb(var(--nc-accent-3))]", children: errorMessage }) : null;
154
- const renderInput = () => {
155
- if (type === "textarea") {
156
- return /* @__PURE__ */ jsx2(
157
- CraftTextarea,
158
- {
159
- id: name,
160
- placeholder,
161
- tone,
162
- className: inputClassName,
163
- disabled,
164
- ...fieldProps,
165
- ...register(name, rules)
166
- }
167
- );
168
- }
169
- if (type === "select" || type === "multiselect") {
170
- return /* @__PURE__ */ jsxs2(
171
- CraftSelect,
172
- {
173
- id: name,
174
- tone,
175
- className: inputClassName,
176
- multiple: type === "multiselect",
177
- disabled,
178
- ...fieldProps,
179
- ...register(name, rules),
180
- children: [
181
- placeholder && /* @__PURE__ */ jsx2("option", { value: "", disabled: true, children: placeholder }),
182
- options.map((option) => /* @__PURE__ */ jsx2(
183
- "option",
184
- {
185
- value: option.value,
186
- disabled: option.disabled,
187
- children: option.label
188
- },
189
- option.value
190
- ))
191
- ]
192
- }
193
- );
194
- }
195
- if (type === "checkbox") {
196
- return /* @__PURE__ */ jsx2(
197
- CraftCheckbox,
198
- {
199
- tone,
200
- label,
201
- description,
202
- disabled,
203
- ...fieldProps,
204
- ...register(name, rules)
205
- }
206
- );
207
- }
208
- if (type === "switch") {
209
- return /* @__PURE__ */ jsx2(
210
- CraftSwitch,
211
- {
212
- tone,
213
- label,
214
- disabled,
215
- ...fieldProps,
216
- ...register(name, rules)
217
- }
218
- );
219
- }
220
- if (type === "date") {
221
- return /* @__PURE__ */ jsx2(
222
- Controller,
223
- {
224
- control,
225
- name,
226
- rules,
227
- render: ({ field }) => {
228
- var _a;
229
- return /* @__PURE__ */ jsx2(
230
- CraftDatePicker,
231
- {
232
- value: (_a = field.value) != null ? _a : "",
233
- onChange: field.onChange,
234
- tone,
235
- placeholder,
236
- ...fieldProps
237
- }
238
- );
239
- }
240
- }
241
- );
242
- }
243
- if (type === "number") {
244
- return /* @__PURE__ */ jsx2(
245
- CraftNumberInput,
246
- {
247
- id: name,
248
- tone,
249
- placeholder,
250
- className: inputClassName,
251
- disabled,
252
- ...fieldProps,
253
- ...register(name, rules)
254
- }
255
- );
256
- }
257
- if (type === "currency") {
258
- return /* @__PURE__ */ jsx2(
259
- CraftCurrencyInput,
260
- {
261
- id: name,
262
- tone,
263
- placeholder,
264
- className: inputClassName,
265
- disabled,
266
- ...fieldProps,
267
- ...register(name, rules)
268
- }
269
- );
270
- }
271
- if (type === "radio") {
272
- return /* @__PURE__ */ jsx2("div", { className: "grid gap-3", children: options.map((option) => /* @__PURE__ */ jsxs2(
273
- "label",
274
- {
275
- className: cn(
276
- "flex items-center gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.08)] px-4 py-3 text-sm text-[rgb(var(--nc-fg))]",
277
- "transition-all duration-200",
278
- "focus-within:ring-2 focus-within:ring-[rgb(var(--nc-accent-1)/0.5)]",
279
- option.disabled ? "opacity-60" : "cursor-pointer"
280
- ),
281
- "data-nc-theme": tone,
282
- children: [
283
- /* @__PURE__ */ jsx2(
284
- "input",
285
- {
286
- type: "radio",
287
- value: option.value,
288
- disabled: option.disabled || disabled,
289
- className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
290
- ...fieldProps,
291
- ...register(name, rules)
292
- }
293
- ),
294
- /* @__PURE__ */ jsx2("span", { children: option.label })
295
- ]
296
- },
297
- option.value
298
- )) });
299
- }
300
- if (type === "range" || type === "slider") {
301
- return /* @__PURE__ */ jsx2(
302
- "input",
303
- {
304
- id: name,
305
- type: "range",
306
- className: cn(
307
- "w-full accent-[rgb(var(--nc-accent-1))]",
308
- inputClassName
309
- ),
310
- disabled,
311
- ...fieldProps,
312
- ...register(name, rules)
313
- }
314
- );
315
- }
316
- if (type === "file" || type === "multifile") {
317
- return /* @__PURE__ */ jsx2(
318
- "input",
319
- {
320
- id: name,
321
- type: "file",
322
- multiple: type === "multifile",
323
- className: cn(
324
- baseInputClass,
325
- "file:mr-4 file:rounded-xl file:border-0 file:bg-[rgb(var(--nc-surface)/0.35)] file:px-4 file:py-2 file:text-sm file:font-semibold file:text-[rgb(var(--nc-fg))]",
326
- inputClassName
327
- ),
328
- disabled,
329
- ...fieldProps,
330
- ...register(name, rules)
331
- }
332
- );
333
- }
334
- const inputType = type === "search" || type === "password" || type === "email" || type === "tel" || type === "url" || type === "time" || type === "datetime-local" || type === "month" || type === "week" || type === "color" ? type : "text";
335
- return /* @__PURE__ */ jsx2(
336
- CraftInput,
337
- {
338
- id: name,
339
- type: inputType,
340
- placeholder,
341
- tone,
342
- className: inputClassName,
343
- disabled,
344
- ...fieldProps,
345
- ...register(name, rules)
346
- }
347
- );
348
- };
349
- const showLabel = type !== "checkbox" && type !== "switch";
350
- const showDescriptionAbove = type !== "checkbox" && type !== "switch";
351
- const showDescriptionBelow = type === "switch";
352
- return /* @__PURE__ */ jsxs2("div", { className: cn("space-y-2", className), "data-nc-theme": tone, children: [
353
- showLabel ? labelNode : null,
354
- showDescriptionAbove ? descriptionNode : null,
355
- renderInput(),
356
- showDescriptionBelow ? descriptionNode : null,
357
- errorNode
358
- ] });
359
- }
360
-
361
- // src/components/craft-form-builder.tsx
362
- import * as React2 from "react";
363
- import {
364
- FormProvider as FormProvider2,
365
- useForm
366
- } from "react-hook-form";
367
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
368
- function defaultValueForField(field) {
369
- var _a, _b, _c, _d;
370
- if (field.defaultValue !== void 0) return field.defaultValue;
371
- switch (field.type) {
372
- case "checkbox":
373
- case "switch":
374
- return false;
375
- case "number":
376
- case "slider":
377
- case "range":
378
- return (_a = field.min) != null ? _a : 0;
379
- case "multifile":
380
- return [];
381
- case "file":
382
- return null;
383
- case "multiselect":
384
- return [];
385
- case "radio":
386
- return (_d = (_c = (_b = field.options) == null ? void 0 : _b[0]) == null ? void 0 : _c.value) != null ? _d : "";
387
- default:
388
- return "";
389
- }
390
- }
391
- function buildDefaultValues(fields, initialData) {
392
- const values = {};
393
- fields.forEach((field) => {
394
- const initialValue = initialData == null ? void 0 : initialData[field.name];
395
- if (initialValue !== void 0 && initialValue !== null) {
396
- values[field.name] = initialValue;
397
- } else {
398
- values[field.name] = defaultValueForField(field);
399
- }
400
- });
401
- return values;
402
- }
403
- function buildRules(field, getValues) {
404
- var _a;
405
- const rules = { ...field.rules };
406
- const mergeValidate = (current, next) => {
407
- if (!current) return next;
408
- if (typeof current === "function") {
409
- return (value) => {
410
- const result = current(
411
- value,
412
- getValues()
413
- );
414
- if (result !== true) return result;
415
- return next(value);
416
- };
417
- }
418
- if (typeof current === "object") {
419
- return (value) => {
420
- const entries = Object.entries(current);
421
- for (const [, validator] of entries) {
422
- const result = validator(
423
- value,
424
- getValues()
425
- );
426
- if (result !== true) return result;
427
- }
428
- return next(value);
429
- };
430
- }
431
- return next;
432
- };
433
- if (field.required && field.type !== "hidden") {
434
- if (field.type === "checkbox" || field.type === "switch") {
435
- rules.validate = mergeValidate(
436
- rules.validate,
437
- (value) => {
438
- var _a2;
439
- return value ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
440
- }
441
- );
442
- } else if (field.type === "multiselect") {
443
- rules.validate = mergeValidate(
444
- rules.validate,
445
- (value) => {
446
- var _a2;
447
- return Array.isArray(value) && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
448
- }
449
- );
450
- } else if (field.type === "file") {
451
- rules.validate = mergeValidate(
452
- rules.validate,
453
- (value) => {
454
- var _a2;
455
- return value instanceof FileList && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
456
- }
457
- );
458
- } else if (field.type === "multifile") {
459
- rules.validate = mergeValidate(
460
- rules.validate,
461
- (value) => {
462
- var _a2;
463
- return Array.isArray(value) && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
464
- }
465
- );
466
- } else {
467
- rules.required = `${String((_a = field.label) != null ? _a : field.name)} is required`;
468
- }
469
- }
470
- if (field.min !== void 0) {
471
- rules.min = { value: field.min, message: `Min ${field.min}` };
472
- }
473
- if (field.max !== void 0) {
474
- rules.max = { value: field.max, message: `Max ${field.max}` };
475
- }
476
- if (field.type === "email") {
477
- rules.pattern = {
478
- value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
479
- message: "Please enter a valid email address"
480
- };
481
- }
482
- if (field.type === "url") {
483
- rules.pattern = {
484
- value: /^https?:\/\/.+/,
485
- message: "Please enter a valid URL"
486
- };
487
- }
488
- if (field.validate) {
489
- rules.validate = mergeValidate(
490
- rules.validate,
491
- (value) => {
492
- var _a2;
493
- return (_a2 = field.validate) == null ? void 0 : _a2.call(field, value, getValues());
494
- }
495
- );
496
- }
497
- return rules;
498
- }
499
- function CraftFormBuilder({
500
- title = "Form",
501
- description,
502
- fields,
503
- initialData = null,
504
- open,
505
- defaultOpen = false,
506
- onOpenChange,
507
- trigger,
508
- submitLabel = "Submit",
509
- cancelLabel = "Cancel",
510
- resetLabel = "Reset",
511
- showReset = true,
512
- showCancel = true,
513
- tone,
514
- className,
515
- formClassName,
516
- loading = false,
517
- disableSubmitWhenInvalid = true,
518
- closeOnSubmit = true,
519
- closeOnCancel = true,
520
- onSubmit,
521
- onReset,
522
- onCancel,
523
- customValidation
524
- }) {
525
- const [uncontrolledOpen, setUncontrolledOpen] = React2.useState(defaultOpen);
526
- const isControlled = typeof open === "boolean";
527
- const isOpen = isControlled ? open : uncontrolledOpen;
528
- const setOpen = React2.useCallback(
529
- (next) => {
530
- if (!isControlled) setUncontrolledOpen(next);
531
- onOpenChange == null ? void 0 : onOpenChange(next);
532
- },
533
- [isControlled, onOpenChange]
534
- );
535
- const defaultValues = React2.useMemo(
536
- () => buildDefaultValues(fields, initialData),
537
- [fields, initialData]
538
- );
539
- const form = useForm({
540
- mode: "onChange",
541
- defaultValues
542
- });
543
- const formId = React2.useId();
544
- React2.useEffect(() => {
545
- form.reset(defaultValues);
546
- }, [defaultValues, form]);
547
- const handleSubmit = form.handleSubmit(async (values) => {
548
- if (customValidation) {
549
- const customErrors = customValidation(values);
550
- if (customErrors && Object.keys(customErrors).length > 0) {
551
- Object.entries(customErrors).forEach(([key, message]) => {
552
- if (message) {
553
- form.setError(key, {
554
- type: "custom",
555
- message: String(message)
556
- });
557
- }
558
- });
559
- return;
560
- }
561
- }
562
- await onSubmit(values);
563
- if (closeOnSubmit) setOpen(false);
564
- });
565
- const handleReset = () => {
566
- form.reset(defaultValues);
567
- onReset == null ? void 0 : onReset();
568
- };
569
- const handleCancel = () => {
570
- onCancel == null ? void 0 : onCancel();
571
- if (closeOnCancel) setOpen(false);
572
- };
573
- return /* @__PURE__ */ jsx3(FormProvider2, { ...form, children: /* @__PURE__ */ jsx3(
574
- CraftModal,
575
- {
576
- open: isOpen,
577
- onOpenChange: setOpen,
578
- trigger,
579
- title,
580
- description,
581
- tone,
582
- className,
583
- footer: /* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
584
- showReset && /* @__PURE__ */ jsx3(
585
- CraftButton,
586
- {
587
- type: "button",
588
- variant: "outline",
589
- onClick: handleReset,
590
- disabled: loading,
591
- children: resetLabel
592
- }
593
- ),
594
- showCancel && /* @__PURE__ */ jsx3(
595
- CraftButton,
596
- {
597
- type: "button",
598
- variant: "ghost",
599
- onClick: handleCancel,
600
- disabled: loading,
601
- children: cancelLabel
602
- }
603
- ),
604
- /* @__PURE__ */ jsx3(
605
- CraftSubmitButton,
606
- {
607
- loading,
608
- disableWhenInvalid: disableSubmitWhenInvalid,
609
- form: formId,
610
- children: submitLabel
611
- }
612
- )
613
- ] }),
614
- children: /* @__PURE__ */ jsx3(
615
- "form",
616
- {
617
- id: formId,
618
- onSubmit: handleSubmit,
619
- className: cn("space-y-5", formClassName),
620
- children: fields.map((field) => /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
621
- field.helpText && /* @__PURE__ */ jsx3("p", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: field.helpText }),
622
- /* @__PURE__ */ jsx3(
623
- CraftFormField,
624
- {
625
- name: field.name,
626
- label: field.label,
627
- description: field.description,
628
- type: field.type,
629
- placeholder: field.placeholder,
630
- options: field.options,
631
- tone,
632
- disabled: field.disabled || loading,
633
- rules: buildRules(field, form.getValues),
634
- fieldProps: {
635
- min: field.min,
636
- max: field.max,
637
- step: field.step,
638
- rows: field.rows,
639
- accept: field.accept,
640
- multiple: field.type === "multifile",
641
- ...field.fieldProps
642
- }
643
- }
644
- )
645
- ] }, field.name))
646
- }
647
- )
648
- }
649
- ) });
650
- }
651
-
652
- export {
653
- CraftForm,
654
- CraftFormField,
655
- CraftFormBuilder
656
- };
657
- //# sourceMappingURL=chunk-7Q4Z47HT.js.map