@jameskabz/nextcraft-ui 0.6.15 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +37 -3
  2. package/dist/components/craft-button.cjs +64 -4
  3. package/dist/components/craft-button.cjs.map +1 -1
  4. package/dist/components/craft-button.d.cts +5 -2
  5. package/dist/components/craft-button.d.ts +5 -2
  6. package/dist/components/craft-button.js +65 -5
  7. package/dist/components/craft-button.js.map +1 -1
  8. package/dist/components/craft-checkbox.cjs +2 -2
  9. package/dist/components/craft-checkbox.cjs.map +1 -1
  10. package/dist/components/craft-checkbox.js +2 -2
  11. package/dist/components/craft-checkbox.js.map +1 -1
  12. package/dist/components/craft-create-edit-drawer.cjs +5 -3
  13. package/dist/components/craft-create-edit-drawer.cjs.map +1 -1
  14. package/dist/components/craft-create-edit-drawer.js +5 -3
  15. package/dist/components/craft-create-edit-drawer.js.map +1 -1
  16. package/dist/components/craft-data-table-header.cjs +74 -0
  17. package/dist/components/craft-data-table-header.cjs.map +1 -0
  18. package/dist/components/craft-data-table-header.d.cts +17 -0
  19. package/dist/components/craft-data-table-header.d.ts +17 -0
  20. package/dist/components/craft-data-table-header.js +50 -0
  21. package/dist/components/craft-data-table-header.js.map +1 -0
  22. package/dist/components/craft-data-table-pagination.cjs +107 -0
  23. package/dist/components/craft-data-table-pagination.cjs.map +1 -0
  24. package/dist/components/craft-data-table-pagination.d.cts +25 -0
  25. package/dist/components/craft-data-table-pagination.d.ts +25 -0
  26. package/dist/components/craft-data-table-pagination.js +83 -0
  27. package/dist/components/craft-data-table-pagination.js.map +1 -0
  28. package/dist/components/craft-data-table.cjs +424 -192
  29. package/dist/components/craft-data-table.cjs.map +1 -1
  30. package/dist/components/craft-data-table.d.cts +61 -9
  31. package/dist/components/craft-data-table.d.ts +61 -9
  32. package/dist/components/craft-data-table.js +424 -192
  33. package/dist/components/craft-data-table.js.map +1 -1
  34. package/dist/components/craft-form-field.cjs +67 -11
  35. package/dist/components/craft-form-field.cjs.map +1 -1
  36. package/dist/components/craft-form-field.d.cts +4 -1
  37. package/dist/components/craft-form-field.d.ts +4 -1
  38. package/dist/components/craft-form-field.js +57 -11
  39. package/dist/components/craft-form-field.js.map +1 -1
  40. package/dist/components/craft-form-modal.cjs +29 -28
  41. package/dist/components/craft-form-modal.cjs.map +1 -1
  42. package/dist/components/craft-form-modal.js +29 -28
  43. package/dist/components/craft-form-modal.js.map +1 -1
  44. package/dist/components/craft-form.cjs +5 -3
  45. package/dist/components/craft-form.cjs.map +1 -1
  46. package/dist/components/craft-form.js +5 -3
  47. package/dist/components/craft-form.js.map +1 -1
  48. package/dist/components/craft-icon.cjs +26 -32
  49. package/dist/components/craft-icon.cjs.map +1 -1
  50. package/dist/components/craft-icon.d.cts +1 -2
  51. package/dist/components/craft-icon.d.ts +1 -2
  52. package/dist/components/craft-icon.js +36 -32
  53. package/dist/components/craft-icon.js.map +1 -1
  54. package/dist/components/craft-loader.cjs +195 -0
  55. package/dist/components/craft-loader.cjs.map +1 -0
  56. package/dist/components/craft-loader.d.cts +21 -0
  57. package/dist/components/craft-loader.d.ts +21 -0
  58. package/dist/components/craft-loader.js +171 -0
  59. package/dist/components/craft-loader.js.map +1 -0
  60. package/dist/components/craft-switch.cjs +4 -11
  61. package/dist/components/craft-switch.cjs.map +1 -1
  62. package/dist/components/craft-switch.js +4 -11
  63. package/dist/components/craft-switch.js.map +1 -1
  64. package/dist/components/layout/app-template.cjs +2 -3
  65. package/dist/components/layout/app-template.cjs.map +1 -1
  66. package/dist/components/layout/app-template.d.cts +1 -2
  67. package/dist/components/layout/app-template.d.ts +1 -2
  68. package/dist/components/layout/app-template.js +2 -3
  69. package/dist/components/layout/app-template.js.map +1 -1
  70. package/dist/index.cjs +9 -3
  71. package/dist/index.cjs.map +1 -1
  72. package/dist/index.d.cts +4 -2
  73. package/dist/index.d.ts +4 -2
  74. package/dist/index.js +6 -2
  75. package/dist/index.js.map +1 -1
  76. package/dist/styles.css +245 -32
  77. package/package.json +8 -8
@@ -38,7 +38,6 @@ var import_react_hook_form = require("react-hook-form");
38
38
  var import_cn = require("../utils/cn");
39
39
  var import_craft_modal = require("../components/craft-modal");
40
40
  var import_craft_button = require("../components/craft-button");
41
- var import_craft_submit_button = require("../components/craft-submit-button");
42
41
  function CraftForm({
43
42
  form,
44
43
  onSubmit,
@@ -69,6 +68,7 @@ function CraftForm({
69
68
  [isControlled, onOpenChange]
70
69
  );
71
70
  const formId = React.useId();
71
+ const isSubmitDisabled = disableSubmitWhenInvalid && !form.formState.isValid;
72
72
  const handleSubmit = form.handleSubmit(async (values) => {
73
73
  await onSubmit(values);
74
74
  if (closeOnSubmit) setOpen(false);
@@ -76,10 +76,12 @@ function CraftForm({
76
76
  const footerContent = footer != null ? footer : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
77
77
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_craft_button.CraftButton, { type: "button", variant: "ghost", onClick: () => setOpen(false), children: cancelLabel }),
78
78
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
79
- import_craft_submit_button.CraftSubmitButton,
79
+ import_craft_button.CraftButton,
80
80
  {
81
+ type: "submit",
82
+ variant: "solid",
81
83
  form: formId,
82
- disableWhenInvalid: disableSubmitWhenInvalid,
84
+ disabled: isSubmitDisabled,
83
85
  children: submitLabel
84
86
  }
85
87
  )
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/craft-form.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { FormProvider, type FieldValues, type UseFormReturn } from \"react-hook-form\";\n\nimport { cn } from \"@/utils/cn\";\nimport type { ThemeName } from \"@/theme/theme-context\";\nimport { CraftModal } from \"@/components/craft-modal\";\nimport { CraftButton } from \"@/components/craft-button\";\nimport { CraftSubmitButton } from \"@/components/craft-submit-button\";\n\nexport type CraftFormProps<TValues extends FieldValues> = {\n form: UseFormReturn<TValues>;\n onSubmit: (values: TValues) => void | Promise<void>;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n trigger?: React.ReactNode;\n title?: React.ReactNode;\n description?: React.ReactNode;\n submitLabel?: React.ReactNode;\n cancelLabel?: React.ReactNode;\n tone?: ThemeName;\n className?: string;\n children?: React.ReactNode;\n footer?: React.ReactNode;\n disableSubmitWhenInvalid?: boolean;\n closeOnSubmit?: boolean;\n formClassName?: string;\n};\n\nexport function CraftForm<TValues extends FieldValues>({\n form,\n onSubmit,\n open,\n defaultOpen = false,\n onOpenChange,\n trigger,\n title,\n description,\n submitLabel = \"Save\",\n cancelLabel = \"Cancel\",\n tone,\n className,\n children,\n footer,\n disableSubmitWhenInvalid = true,\n closeOnSubmit = true,\n formClassName,\n}: CraftFormProps<TValues>) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);\n const isControlled = typeof open === \"boolean\";\n const isOpen = isControlled ? open : uncontrolledOpen;\n\n const setOpen = React.useCallback(\n (next: boolean) => {\n if (!isControlled) setUncontrolledOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange]\n );\n\n const formId = React.useId();\n\n const handleSubmit = form.handleSubmit(async (values) => {\n await onSubmit(values);\n if (closeOnSubmit) setOpen(false);\n });\n\n const footerContent = footer ?? (\n <div className=\"flex flex-wrap items-center justify-end gap-3\">\n <CraftButton type=\"button\" variant=\"ghost\" onClick={() => setOpen(false)}>\n {cancelLabel}\n </CraftButton>\n <CraftSubmitButton\n form={formId}\n disableWhenInvalid={disableSubmitWhenInvalid}\n >\n {submitLabel}\n </CraftSubmitButton>\n </div>\n );\n\n return (\n <FormProvider {...form}>\n <CraftModal\n open={isOpen}\n onOpenChange={setOpen}\n trigger={trigger}\n title={title}\n description={description}\n tone={tone}\n className={className}\n footer={footerContent}\n >\n <form\n id={formId}\n onSubmit={handleSubmit}\n className={cn(\"space-y-5\", formClassName)}\n >\n {children}\n </form>\n </CraftModal>\n </FormProvider>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAsEI;AApEJ,YAAuB;AACvB,6BAAmE;AAEnE,gBAAmB;AAEnB,yBAA2B;AAC3B,0BAA4B;AAC5B,iCAAkC;AAsB3B,SAAS,UAAuC;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,2BAA2B;AAAA,EAC3B,gBAAgB;AAAA,EAChB;AACF,GAA4B;AAC1B,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,MAAM,SAAS,WAAW;AAC1E,QAAM,eAAe,OAAO,SAAS;AACrC,QAAM,SAAS,eAAe,OAAO;AAErC,QAAM,UAAU,MAAM;AAAA,IACpB,CAAC,SAAkB;AACjB,UAAI,CAAC,aAAc,qBAAoB,IAAI;AAC3C,mDAAe;AAAA,IACjB;AAAA,IACA,CAAC,cAAc,YAAY;AAAA,EAC7B;AAEA,QAAM,SAAS,MAAM,MAAM;AAE3B,QAAM,eAAe,KAAK,aAAa,OAAO,WAAW;AACvD,UAAM,SAAS,MAAM;AACrB,QAAI,cAAe,SAAQ,KAAK;AAAA,EAClC,CAAC;AAED,QAAM,gBAAgB,0BACpB,6CAAC,SAAI,WAAU,iDACb;AAAA,gDAAC,mCAAY,MAAK,UAAS,SAAQ,SAAQ,SAAS,MAAM,QAAQ,KAAK,GACpE,uBACH;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,oBAAoB;AAAA,QAEnB;AAAA;AAAA,IACH;AAAA,KACF;AAGF,SACE,4CAAC,uCAAc,GAAG,MAChB;AAAA,IAAC;AAAA;AAAA,MACC,MAAM;AAAA,MACN,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MAER;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,UAAU;AAAA,UACV,eAAW,cAAG,aAAa,aAAa;AAAA,UAEvC;AAAA;AAAA,MACH;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/craft-form.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { FormProvider, type FieldValues, type UseFormReturn } from \"react-hook-form\";\n\nimport { cn } from \"@/utils/cn\";\nimport type { ThemeName } from \"@/theme/theme-context\";\nimport { CraftModal } from \"@/components/craft-modal\";\nimport { CraftButton } from \"@/components/craft-button\";\n\nexport type CraftFormProps<TValues extends FieldValues> = {\n form: UseFormReturn<TValues>;\n onSubmit: (values: TValues) => void | Promise<void>;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n trigger?: React.ReactNode;\n title?: React.ReactNode;\n description?: React.ReactNode;\n submitLabel?: React.ReactNode;\n cancelLabel?: React.ReactNode;\n tone?: ThemeName;\n className?: string;\n children?: React.ReactNode;\n footer?: React.ReactNode;\n disableSubmitWhenInvalid?: boolean;\n closeOnSubmit?: boolean;\n formClassName?: string;\n};\n\nexport function CraftForm<TValues extends FieldValues>({\n form,\n onSubmit,\n open,\n defaultOpen = false,\n onOpenChange,\n trigger,\n title,\n description,\n submitLabel = \"Save\",\n cancelLabel = \"Cancel\",\n tone,\n className,\n children,\n footer,\n disableSubmitWhenInvalid = true,\n closeOnSubmit = true,\n formClassName,\n}: CraftFormProps<TValues>) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);\n const isControlled = typeof open === \"boolean\";\n const isOpen = isControlled ? open : uncontrolledOpen;\n\n const setOpen = React.useCallback(\n (next: boolean) => {\n if (!isControlled) setUncontrolledOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange]\n );\n\n const formId = React.useId();\n const isSubmitDisabled =\n disableSubmitWhenInvalid && !form.formState.isValid;\n\n const handleSubmit = form.handleSubmit(async (values) => {\n await onSubmit(values);\n if (closeOnSubmit) setOpen(false);\n });\n\n const footerContent = footer ?? (\n <div className=\"flex flex-wrap items-center justify-end gap-3\">\n <CraftButton type=\"button\" variant=\"ghost\" onClick={() => setOpen(false)}>\n {cancelLabel}\n </CraftButton>\n <CraftButton\n type=\"submit\"\n variant=\"solid\"\n form={formId}\n disabled={isSubmitDisabled}\n >\n {submitLabel}\n </CraftButton>\n </div>\n );\n\n return (\n <FormProvider {...form}>\n <CraftModal\n open={isOpen}\n onOpenChange={setOpen}\n trigger={trigger}\n title={title}\n description={description}\n tone={tone}\n className={className}\n footer={footerContent}\n >\n <form\n id={formId}\n onSubmit={handleSubmit}\n className={cn(\"space-y-5\", formClassName)}\n >\n {children}\n </form>\n </CraftModal>\n </FormProvider>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAuEI;AArEJ,YAAuB;AACvB,6BAAmE;AAEnE,gBAAmB;AAEnB,yBAA2B;AAC3B,0BAA4B;AAsBrB,SAAS,UAAuC;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,2BAA2B;AAAA,EAC3B,gBAAgB;AAAA,EAChB;AACF,GAA4B;AAC1B,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,MAAM,SAAS,WAAW;AAC1E,QAAM,eAAe,OAAO,SAAS;AACrC,QAAM,SAAS,eAAe,OAAO;AAErC,QAAM,UAAU,MAAM;AAAA,IACpB,CAAC,SAAkB;AACjB,UAAI,CAAC,aAAc,qBAAoB,IAAI;AAC3C,mDAAe;AAAA,IACjB;AAAA,IACA,CAAC,cAAc,YAAY;AAAA,EAC7B;AAEA,QAAM,SAAS,MAAM,MAAM;AAC3B,QAAM,mBACJ,4BAA4B,CAAC,KAAK,UAAU;AAE9C,QAAM,eAAe,KAAK,aAAa,OAAO,WAAW;AACvD,UAAM,SAAS,MAAM;AACrB,QAAI,cAAe,SAAQ,KAAK;AAAA,EAClC,CAAC;AAED,QAAM,gBAAgB,0BACpB,6CAAC,SAAI,WAAU,iDACb;AAAA,gDAAC,mCAAY,MAAK,UAAS,SAAQ,SAAQ,SAAS,MAAM,QAAQ,KAAK,GACpE,uBACH;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAM;AAAA,QACN,UAAU;AAAA,QAET;AAAA;AAAA,IACH;AAAA,KACF;AAGF,SACE,4CAAC,uCAAc,GAAG,MAChB;AAAA,IAAC;AAAA;AAAA,MACC,MAAM;AAAA,MACN,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MAER;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,UAAU;AAAA,UACV,eAAW,cAAG,aAAa,aAAa;AAAA,UAEvC;AAAA;AAAA,MACH;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
@@ -5,7 +5,6 @@ import { FormProvider } from "react-hook-form";
5
5
  import { cn } from "../utils/cn";
6
6
  import { CraftModal } from "../components/craft-modal";
7
7
  import { CraftButton } from "../components/craft-button";
8
- import { CraftSubmitButton } from "../components/craft-submit-button";
9
8
  function CraftForm({
10
9
  form,
11
10
  onSubmit,
@@ -36,6 +35,7 @@ function CraftForm({
36
35
  [isControlled, onOpenChange]
37
36
  );
38
37
  const formId = React.useId();
38
+ const isSubmitDisabled = disableSubmitWhenInvalid && !form.formState.isValid;
39
39
  const handleSubmit = form.handleSubmit(async (values) => {
40
40
  await onSubmit(values);
41
41
  if (closeOnSubmit) setOpen(false);
@@ -43,10 +43,12 @@ function CraftForm({
43
43
  const footerContent = footer != null ? footer : /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
44
44
  /* @__PURE__ */ jsx(CraftButton, { type: "button", variant: "ghost", onClick: () => setOpen(false), children: cancelLabel }),
45
45
  /* @__PURE__ */ jsx(
46
- CraftSubmitButton,
46
+ CraftButton,
47
47
  {
48
+ type: "submit",
49
+ variant: "solid",
48
50
  form: formId,
49
- disableWhenInvalid: disableSubmitWhenInvalid,
51
+ disabled: isSubmitDisabled,
50
52
  children: submitLabel
51
53
  }
52
54
  )
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/craft-form.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { FormProvider, type FieldValues, type UseFormReturn } from \"react-hook-form\";\n\nimport { cn } from \"@/utils/cn\";\nimport type { ThemeName } from \"@/theme/theme-context\";\nimport { CraftModal } from \"@/components/craft-modal\";\nimport { CraftButton } from \"@/components/craft-button\";\nimport { CraftSubmitButton } from \"@/components/craft-submit-button\";\n\nexport type CraftFormProps<TValues extends FieldValues> = {\n form: UseFormReturn<TValues>;\n onSubmit: (values: TValues) => void | Promise<void>;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n trigger?: React.ReactNode;\n title?: React.ReactNode;\n description?: React.ReactNode;\n submitLabel?: React.ReactNode;\n cancelLabel?: React.ReactNode;\n tone?: ThemeName;\n className?: string;\n children?: React.ReactNode;\n footer?: React.ReactNode;\n disableSubmitWhenInvalid?: boolean;\n closeOnSubmit?: boolean;\n formClassName?: string;\n};\n\nexport function CraftForm<TValues extends FieldValues>({\n form,\n onSubmit,\n open,\n defaultOpen = false,\n onOpenChange,\n trigger,\n title,\n description,\n submitLabel = \"Save\",\n cancelLabel = \"Cancel\",\n tone,\n className,\n children,\n footer,\n disableSubmitWhenInvalid = true,\n closeOnSubmit = true,\n formClassName,\n}: CraftFormProps<TValues>) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);\n const isControlled = typeof open === \"boolean\";\n const isOpen = isControlled ? open : uncontrolledOpen;\n\n const setOpen = React.useCallback(\n (next: boolean) => {\n if (!isControlled) setUncontrolledOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange]\n );\n\n const formId = React.useId();\n\n const handleSubmit = form.handleSubmit(async (values) => {\n await onSubmit(values);\n if (closeOnSubmit) setOpen(false);\n });\n\n const footerContent = footer ?? (\n <div className=\"flex flex-wrap items-center justify-end gap-3\">\n <CraftButton type=\"button\" variant=\"ghost\" onClick={() => setOpen(false)}>\n {cancelLabel}\n </CraftButton>\n <CraftSubmitButton\n form={formId}\n disableWhenInvalid={disableSubmitWhenInvalid}\n >\n {submitLabel}\n </CraftSubmitButton>\n </div>\n );\n\n return (\n <FormProvider {...form}>\n <CraftModal\n open={isOpen}\n onOpenChange={setOpen}\n trigger={trigger}\n title={title}\n description={description}\n tone={tone}\n className={className}\n footer={footerContent}\n >\n <form\n id={formId}\n onSubmit={handleSubmit}\n className={cn(\"space-y-5\", formClassName)}\n >\n {children}\n </form>\n </CraftModal>\n </FormProvider>\n );\n}\n"],"mappings":";AAsEI,SACE,KADF;AApEJ,YAAY,WAAW;AACvB,SAAS,oBAA0D;AAEnE,SAAS,UAAU;AAEnB,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAsB3B,SAAS,UAAuC;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,2BAA2B;AAAA,EAC3B,gBAAgB;AAAA,EAChB;AACF,GAA4B;AAC1B,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,MAAM,SAAS,WAAW;AAC1E,QAAM,eAAe,OAAO,SAAS;AACrC,QAAM,SAAS,eAAe,OAAO;AAErC,QAAM,UAAU,MAAM;AAAA,IACpB,CAAC,SAAkB;AACjB,UAAI,CAAC,aAAc,qBAAoB,IAAI;AAC3C,mDAAe;AAAA,IACjB;AAAA,IACA,CAAC,cAAc,YAAY;AAAA,EAC7B;AAEA,QAAM,SAAS,MAAM,MAAM;AAE3B,QAAM,eAAe,KAAK,aAAa,OAAO,WAAW;AACvD,UAAM,SAAS,MAAM;AACrB,QAAI,cAAe,SAAQ,KAAK;AAAA,EAClC,CAAC;AAED,QAAM,gBAAgB,0BACpB,qBAAC,SAAI,WAAU,iDACb;AAAA,wBAAC,eAAY,MAAK,UAAS,SAAQ,SAAQ,SAAS,MAAM,QAAQ,KAAK,GACpE,uBACH;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,oBAAoB;AAAA,QAEnB;AAAA;AAAA,IACH;AAAA,KACF;AAGF,SACE,oBAAC,gBAAc,GAAG,MAChB;AAAA,IAAC;AAAA;AAAA,MACC,MAAM;AAAA,MACN,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MAER;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,UAAU;AAAA,UACV,WAAW,GAAG,aAAa,aAAa;AAAA,UAEvC;AAAA;AAAA,MACH;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/craft-form.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { FormProvider, type FieldValues, type UseFormReturn } from \"react-hook-form\";\n\nimport { cn } from \"@/utils/cn\";\nimport type { ThemeName } from \"@/theme/theme-context\";\nimport { CraftModal } from \"@/components/craft-modal\";\nimport { CraftButton } from \"@/components/craft-button\";\n\nexport type CraftFormProps<TValues extends FieldValues> = {\n form: UseFormReturn<TValues>;\n onSubmit: (values: TValues) => void | Promise<void>;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n trigger?: React.ReactNode;\n title?: React.ReactNode;\n description?: React.ReactNode;\n submitLabel?: React.ReactNode;\n cancelLabel?: React.ReactNode;\n tone?: ThemeName;\n className?: string;\n children?: React.ReactNode;\n footer?: React.ReactNode;\n disableSubmitWhenInvalid?: boolean;\n closeOnSubmit?: boolean;\n formClassName?: string;\n};\n\nexport function CraftForm<TValues extends FieldValues>({\n form,\n onSubmit,\n open,\n defaultOpen = false,\n onOpenChange,\n trigger,\n title,\n description,\n submitLabel = \"Save\",\n cancelLabel = \"Cancel\",\n tone,\n className,\n children,\n footer,\n disableSubmitWhenInvalid = true,\n closeOnSubmit = true,\n formClassName,\n}: CraftFormProps<TValues>) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);\n const isControlled = typeof open === \"boolean\";\n const isOpen = isControlled ? open : uncontrolledOpen;\n\n const setOpen = React.useCallback(\n (next: boolean) => {\n if (!isControlled) setUncontrolledOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange]\n );\n\n const formId = React.useId();\n const isSubmitDisabled =\n disableSubmitWhenInvalid && !form.formState.isValid;\n\n const handleSubmit = form.handleSubmit(async (values) => {\n await onSubmit(values);\n if (closeOnSubmit) setOpen(false);\n });\n\n const footerContent = footer ?? (\n <div className=\"flex flex-wrap items-center justify-end gap-3\">\n <CraftButton type=\"button\" variant=\"ghost\" onClick={() => setOpen(false)}>\n {cancelLabel}\n </CraftButton>\n <CraftButton\n type=\"submit\"\n variant=\"solid\"\n form={formId}\n disabled={isSubmitDisabled}\n >\n {submitLabel}\n </CraftButton>\n </div>\n );\n\n return (\n <FormProvider {...form}>\n <CraftModal\n open={isOpen}\n onOpenChange={setOpen}\n trigger={trigger}\n title={title}\n description={description}\n tone={tone}\n className={className}\n footer={footerContent}\n >\n <form\n id={formId}\n onSubmit={handleSubmit}\n className={cn(\"space-y-5\", formClassName)}\n >\n {children}\n </form>\n </CraftModal>\n </FormProvider>\n );\n}\n"],"mappings":";AAuEI,SACE,KADF;AArEJ,YAAY,WAAW;AACvB,SAAS,oBAA0D;AAEnE,SAAS,UAAU;AAEnB,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAsBrB,SAAS,UAAuC;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,2BAA2B;AAAA,EAC3B,gBAAgB;AAAA,EAChB;AACF,GAA4B;AAC1B,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,MAAM,SAAS,WAAW;AAC1E,QAAM,eAAe,OAAO,SAAS;AACrC,QAAM,SAAS,eAAe,OAAO;AAErC,QAAM,UAAU,MAAM;AAAA,IACpB,CAAC,SAAkB;AACjB,UAAI,CAAC,aAAc,qBAAoB,IAAI;AAC3C,mDAAe;AAAA,IACjB;AAAA,IACA,CAAC,cAAc,YAAY;AAAA,EAC7B;AAEA,QAAM,SAAS,MAAM,MAAM;AAC3B,QAAM,mBACJ,4BAA4B,CAAC,KAAK,UAAU;AAE9C,QAAM,eAAe,KAAK,aAAa,OAAO,WAAW;AACvD,UAAM,SAAS,MAAM;AACrB,QAAI,cAAe,SAAQ,KAAK;AAAA,EAClC,CAAC;AAED,QAAM,gBAAgB,0BACpB,qBAAC,SAAI,WAAU,iDACb;AAAA,wBAAC,eAAY,MAAK,UAAS,SAAQ,SAAQ,SAAS,MAAM,QAAQ,KAAK,GACpE,uBACH;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAM;AAAA,QACN,UAAU;AAAA,QAET;AAAA;AAAA,IACH;AAAA,KACF;AAGF,SACE,oBAAC,gBAAc,GAAG,MAChB;AAAA,IAAC;AAAA;AAAA,MACC,MAAM;AAAA,MACN,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MAER;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,UAAU;AAAA,UACV,WAAW,GAAG,aAAa,aAAa;AAAA,UAEvC;AAAA;AAAA,MACH;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
@@ -35,54 +35,48 @@ __export(craft_icon_exports, {
35
35
  module.exports = __toCommonJS(craft_icon_exports);
36
36
  var import_jsx_runtime = require("react/jsx-runtime");
37
37
  var React = __toESM(require("react"), 1);
38
+ var import_react_fontawesome = require("@fortawesome/react-fontawesome");
39
+ var import_free_solid_svg_icons = require("@fortawesome/free-solid-svg-icons");
38
40
  var import_cn = require("../utils/cn");
39
41
  const CraftIconContext = React.createContext(null);
40
42
  function CraftIconProvider({ icons, children }) {
41
43
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CraftIconContext.Provider, { value: icons, children });
42
44
  }
45
+ const fontAwesomeIcons = {
46
+ "layout-dashboard": import_free_solid_svg_icons.faGauge,
47
+ dashboard: import_free_solid_svg_icons.faGauge,
48
+ folder: import_free_solid_svg_icons.faFolder,
49
+ "folder-open": import_free_solid_svg_icons.faFolderOpen,
50
+ users: import_free_solid_svg_icons.faUsers,
51
+ "credit-card": import_free_solid_svg_icons.faCreditCard,
52
+ pen: import_free_solid_svg_icons.faPen,
53
+ edit: import_free_solid_svg_icons.faPen,
54
+ trash: import_free_solid_svg_icons.faTrash,
55
+ delete: import_free_solid_svg_icons.faTrash,
56
+ archive: import_free_solid_svg_icons.faArchive,
57
+ search: import_free_solid_svg_icons.faSearch
58
+ };
43
59
  function CraftIcon({
44
60
  name,
45
61
  className,
46
62
  "aria-label": ariaLabel,
47
- icons,
48
- useLucide = true
63
+ icons
49
64
  }) {
50
65
  const contextRegistry = React.useContext(CraftIconContext);
51
66
  const registry = icons != null ? icons : contextRegistry;
52
67
  const icon = registry == null ? void 0 : registry[name];
53
- const [LucideIcon, setLucideIcon] = React.useState(
54
- null
55
- );
56
- React.useEffect(() => {
57
- if (!useLucide || icon || LucideIcon) return;
58
- let mounted = true;
59
- (async () => {
60
- try {
61
- const mod = await import("lucide-react/dynamic.mjs");
62
- if (mounted) {
63
- setLucideIcon(() => mod.DynamicIcon);
64
- }
65
- } catch (error) {
66
- if (mounted) setLucideIcon(null);
67
- if (process.env.NODE_ENV !== "production") {
68
- console.warn(
69
- "[CraftIcon] Failed to load lucide-react/dynamic. Ensure lucide-react is installed."
70
- );
71
- console.warn(error);
72
- }
73
- }
74
- })();
75
- return () => {
76
- mounted = false;
77
- };
78
- }, [LucideIcon, icon, useLucide]);
79
68
  if (!icon) {
80
- if (!useLucide) return null;
81
- if (!LucideIcon) return null;
69
+ const faIcon = fontAwesomeIcons[name];
70
+ if (!faIcon) {
71
+ if (process.env.NODE_ENV !== "production") {
72
+ console.warn(`[CraftIcon] Unknown icon name: ${name}`);
73
+ }
74
+ return null;
75
+ }
82
76
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
83
- LucideIcon,
77
+ import_react_fontawesome.FontAwesomeIcon,
84
78
  {
85
- name,
79
+ icon: faIcon,
86
80
  className,
87
81
  "aria-hidden": ariaLabel ? void 0 : true,
88
82
  "aria-label": ariaLabel
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/craft-icon.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nexport type CraftIconRegistry = Record<string, React.ReactNode>;\n\nconst CraftIconContext = React.createContext<CraftIconRegistry | null>(null);\n\nexport type CraftIconProviderProps = {\n icons: CraftIconRegistry;\n children: React.ReactNode;\n};\n\nexport function CraftIconProvider({ icons, children }: CraftIconProviderProps) {\n return <CraftIconContext.Provider value={icons}>{children}</CraftIconContext.Provider>;\n}\n\nexport type CraftIconProps = {\n name: string;\n className?: string;\n \"aria-label\"?: string;\n icons?: CraftIconRegistry;\n useLucide?: boolean;\n};\n\ntype DynamicIconComponent = React.ComponentType<{\n name: string;\n className?: string;\n \"aria-hidden\"?: boolean;\n \"aria-label\"?: string;\n}>;\n\nexport function CraftIcon({\n name,\n className,\n \"aria-label\": ariaLabel,\n icons,\n useLucide = true,\n}: CraftIconProps) {\n const contextRegistry = React.useContext(CraftIconContext);\n const registry = icons ?? contextRegistry;\n const icon = registry?.[name];\n const [LucideIcon, setLucideIcon] = React.useState<DynamicIconComponent | null>(\n null\n );\n\n React.useEffect(() => {\n if (!useLucide || icon || LucideIcon) return;\n let mounted = true;\n (async () => {\n try {\n const mod = await import(\"lucide-react/dynamic.mjs\");\n if (mounted) {\n setLucideIcon(() => mod.DynamicIcon as DynamicIconComponent);\n }\n } catch (error) {\n if (mounted) setLucideIcon(null);\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n \"[CraftIcon] Failed to load lucide-react/dynamic. Ensure lucide-react is installed.\"\n );\n console.warn(error);\n }\n }\n })();\n return () => {\n mounted = false;\n };\n }, [LucideIcon, icon, useLucide]);\n\n if (!icon) {\n if (!useLucide) return null;\n if (!LucideIcon) return null;\n return (\n <LucideIcon\n name={name}\n className={className}\n aria-hidden={ariaLabel ? undefined : true}\n aria-label={ariaLabel}\n />\n );\n }\n\n type IconElementProps = {\n className?: string;\n \"aria-hidden\"?: boolean;\n \"aria-label\"?: string;\n };\n\n if (React.isValidElement<IconElementProps>(icon)) {\n return React.cloneElement(icon, {\n className: cn(icon.props.className, className),\n \"aria-hidden\": ariaLabel ? undefined : true,\n \"aria-label\": ariaLabel,\n });\n }\n\n return (\n <span className={className} aria-label={ariaLabel}>\n {icon}\n </span>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBS;AAdT,YAAuB;AAEvB,gBAAmB;AAInB,MAAM,mBAAmB,MAAM,cAAwC,IAAI;AAOpE,SAAS,kBAAkB,EAAE,OAAO,SAAS,GAA2B;AAC7E,SAAO,4CAAC,iBAAiB,UAAjB,EAA0B,OAAO,OAAQ,UAAS;AAC5D;AAiBO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA,YAAY;AACd,GAAmB;AACjB,QAAM,kBAAkB,MAAM,WAAW,gBAAgB;AACzD,QAAM,WAAW,wBAAS;AAC1B,QAAM,OAAO,qCAAW;AACxB,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM;AAAA,IACxC;AAAA,EACF;AAEA,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,aAAa,QAAQ,WAAY;AACtC,QAAI,UAAU;AACd,KAAC,YAAY;AACX,UAAI;AACF,cAAM,MAAM,MAAM,OAAO,0BAA0B;AACnD,YAAI,SAAS;AACX,wBAAc,MAAM,IAAI,WAAmC;AAAA,QAC7D;AAAA,MACF,SAAS,OAAO;AACd,YAAI,QAAS,eAAc,IAAI;AAC/B,YAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,kBAAQ;AAAA,YACN;AAAA,UACF;AACA,kBAAQ,KAAK,KAAK;AAAA,QACpB;AAAA,MACF;AAAA,IACF,GAAG;AACH,WAAO,MAAM;AACX,gBAAU;AAAA,IACZ;AAAA,EACF,GAAG,CAAC,YAAY,MAAM,SAAS,CAAC;AAEhC,MAAI,CAAC,MAAM;AACT,QAAI,CAAC,UAAW,QAAO;AACvB,QAAI,CAAC,WAAY,QAAO;AACxB,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,eAAa,YAAY,SAAY;AAAA,QACrC,cAAY;AAAA;AAAA,IACd;AAAA,EAEJ;AAQA,MAAI,MAAM,eAAiC,IAAI,GAAG;AAChD,WAAO,MAAM,aAAa,MAAM;AAAA,MAC9B,eAAW,cAAG,KAAK,MAAM,WAAW,SAAS;AAAA,MAC7C,eAAe,YAAY,SAAY;AAAA,MACvC,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,SACE,4CAAC,UAAK,WAAsB,cAAY,WACrC,gBACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/craft-icon.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport type { IconDefinition } from \"@fortawesome/fontawesome-svg-core\";\nimport {\n faArchive,\n faCreditCard,\n faFolder,\n faFolderOpen,\n faGauge,\n faPen,\n faSearch,\n faTrash,\n faUsers,\n} from \"@fortawesome/free-solid-svg-icons\";\n\nimport { cn } from \"@/utils/cn\";\n\nexport type CraftIconRegistry = Record<string, React.ReactNode>;\n\nconst CraftIconContext = React.createContext<CraftIconRegistry | null>(null);\n\nexport type CraftIconProviderProps = {\n icons: CraftIconRegistry;\n children: React.ReactNode;\n};\n\nexport function CraftIconProvider({ icons, children }: CraftIconProviderProps) {\n return <CraftIconContext.Provider value={icons}>{children}</CraftIconContext.Provider>;\n}\n\nexport type CraftIconProps = {\n name: string;\n className?: string;\n \"aria-label\"?: string;\n icons?: CraftIconRegistry;\n};\n\nconst fontAwesomeIcons: Record<string, IconDefinition> = {\n \"layout-dashboard\": faGauge,\n dashboard: faGauge,\n folder: faFolder,\n \"folder-open\": faFolderOpen,\n users: faUsers,\n \"credit-card\": faCreditCard,\n pen: faPen,\n edit: faPen,\n trash: faTrash,\n delete: faTrash,\n archive: faArchive,\n search: faSearch,\n};\n\nexport function CraftIcon({\n name,\n className,\n \"aria-label\": ariaLabel,\n icons,\n}: CraftIconProps) {\n const contextRegistry = React.useContext(CraftIconContext);\n const registry = icons ?? contextRegistry;\n const icon = registry?.[name];\n\n if (!icon) {\n const faIcon = fontAwesomeIcons[name];\n if (!faIcon) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(`[CraftIcon] Unknown icon name: ${name}`);\n }\n return null;\n }\n\n return (\n <FontAwesomeIcon\n icon={faIcon}\n className={className}\n aria-hidden={ariaLabel ? undefined : true}\n aria-label={ariaLabel}\n />\n );\n }\n\n type IconElementProps = {\n className?: string;\n \"aria-hidden\"?: boolean;\n \"aria-label\"?: string;\n };\n\n if (React.isValidElement<IconElementProps>(icon)) {\n return React.cloneElement(icon, {\n className: cn(icon.props.className, className),\n \"aria-hidden\": ariaLabel ? undefined : true,\n \"aria-label\": ariaLabel,\n });\n }\n\n return (\n <span className={className} aria-label={ariaLabel}>\n {icon}\n </span>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6BS;AA3BT,YAAuB;AACvB,+BAAgC;AAEhC,kCAUO;AAEP,gBAAmB;AAInB,MAAM,mBAAmB,MAAM,cAAwC,IAAI;AAOpE,SAAS,kBAAkB,EAAE,OAAO,SAAS,GAA2B;AAC7E,SAAO,4CAAC,iBAAiB,UAAjB,EAA0B,OAAO,OAAQ,UAAS;AAC5D;AASA,MAAM,mBAAmD;AAAA,EACvD,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,OAAO;AAAA,EACP,eAAe;AAAA,EACf,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AACV;AAEO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AACF,GAAmB;AACjB,QAAM,kBAAkB,MAAM,WAAW,gBAAgB;AACzD,QAAM,WAAW,wBAAS;AAC1B,QAAM,OAAO,qCAAW;AAExB,MAAI,CAAC,MAAM;AACT,UAAM,SAAS,iBAAiB,IAAI;AACpC,QAAI,CAAC,QAAQ;AACX,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,gBAAQ,KAAK,kCAAkC,IAAI,EAAE;AAAA,MACvD;AACA,aAAO;AAAA,IACT;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN;AAAA,QACA,eAAa,YAAY,SAAY;AAAA,QACrC,cAAY;AAAA;AAAA,IACd;AAAA,EAEJ;AAQA,MAAI,MAAM,eAAiC,IAAI,GAAG;AAChD,WAAO,MAAM,aAAa,MAAM;AAAA,MAC9B,eAAW,cAAG,KAAK,MAAM,WAAW,SAAS;AAAA,MAC7C,eAAe,YAAY,SAAY;AAAA,MACvC,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,SACE,4CAAC,UAAK,WAAsB,cAAY,WACrC,gBACH;AAEJ;","names":[]}
@@ -12,8 +12,7 @@ type CraftIconProps = {
12
12
  className?: string;
13
13
  "aria-label"?: string;
14
14
  icons?: CraftIconRegistry;
15
- useLucide?: boolean;
16
15
  };
17
- declare function CraftIcon({ name, className, "aria-label": ariaLabel, icons, useLucide, }: CraftIconProps): react_jsx_runtime.JSX.Element | null;
16
+ declare function CraftIcon({ name, className, "aria-label": ariaLabel, icons, }: CraftIconProps): react_jsx_runtime.JSX.Element | null;
18
17
 
19
18
  export { CraftIcon, type CraftIconProps, CraftIconProvider, type CraftIconProviderProps, type CraftIconRegistry };
@@ -12,8 +12,7 @@ type CraftIconProps = {
12
12
  className?: string;
13
13
  "aria-label"?: string;
14
14
  icons?: CraftIconRegistry;
15
- useLucide?: boolean;
16
15
  };
17
- declare function CraftIcon({ name, className, "aria-label": ariaLabel, icons, useLucide, }: CraftIconProps): react_jsx_runtime.JSX.Element | null;
16
+ declare function CraftIcon({ name, className, "aria-label": ariaLabel, icons, }: CraftIconProps): react_jsx_runtime.JSX.Element | null;
18
17
 
19
18
  export { CraftIcon, type CraftIconProps, CraftIconProvider, type CraftIconProviderProps, type CraftIconRegistry };
@@ -1,54 +1,58 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
5
+ import {
6
+ faArchive,
7
+ faCreditCard,
8
+ faFolder,
9
+ faFolderOpen,
10
+ faGauge,
11
+ faPen,
12
+ faSearch,
13
+ faTrash,
14
+ faUsers
15
+ } from "@fortawesome/free-solid-svg-icons";
4
16
  import { cn } from "../utils/cn";
5
17
  const CraftIconContext = React.createContext(null);
6
18
  function CraftIconProvider({ icons, children }) {
7
19
  return /* @__PURE__ */ jsx(CraftIconContext.Provider, { value: icons, children });
8
20
  }
21
+ const fontAwesomeIcons = {
22
+ "layout-dashboard": faGauge,
23
+ dashboard: faGauge,
24
+ folder: faFolder,
25
+ "folder-open": faFolderOpen,
26
+ users: faUsers,
27
+ "credit-card": faCreditCard,
28
+ pen: faPen,
29
+ edit: faPen,
30
+ trash: faTrash,
31
+ delete: faTrash,
32
+ archive: faArchive,
33
+ search: faSearch
34
+ };
9
35
  function CraftIcon({
10
36
  name,
11
37
  className,
12
38
  "aria-label": ariaLabel,
13
- icons,
14
- useLucide = true
39
+ icons
15
40
  }) {
16
41
  const contextRegistry = React.useContext(CraftIconContext);
17
42
  const registry = icons != null ? icons : contextRegistry;
18
43
  const icon = registry == null ? void 0 : registry[name];
19
- const [LucideIcon, setLucideIcon] = React.useState(
20
- null
21
- );
22
- React.useEffect(() => {
23
- if (!useLucide || icon || LucideIcon) return;
24
- let mounted = true;
25
- (async () => {
26
- try {
27
- const mod = await import("lucide-react/dynamic.mjs");
28
- if (mounted) {
29
- setLucideIcon(() => mod.DynamicIcon);
30
- }
31
- } catch (error) {
32
- if (mounted) setLucideIcon(null);
33
- if (process.env.NODE_ENV !== "production") {
34
- console.warn(
35
- "[CraftIcon] Failed to load lucide-react/dynamic. Ensure lucide-react is installed."
36
- );
37
- console.warn(error);
38
- }
39
- }
40
- })();
41
- return () => {
42
- mounted = false;
43
- };
44
- }, [LucideIcon, icon, useLucide]);
45
44
  if (!icon) {
46
- if (!useLucide) return null;
47
- if (!LucideIcon) return null;
45
+ const faIcon = fontAwesomeIcons[name];
46
+ if (!faIcon) {
47
+ if (process.env.NODE_ENV !== "production") {
48
+ console.warn(`[CraftIcon] Unknown icon name: ${name}`);
49
+ }
50
+ return null;
51
+ }
48
52
  return /* @__PURE__ */ jsx(
49
- LucideIcon,
53
+ FontAwesomeIcon,
50
54
  {
51
- name,
55
+ icon: faIcon,
52
56
  className,
53
57
  "aria-hidden": ariaLabel ? void 0 : true,
54
58
  "aria-label": ariaLabel
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/craft-icon.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nexport type CraftIconRegistry = Record<string, React.ReactNode>;\n\nconst CraftIconContext = React.createContext<CraftIconRegistry | null>(null);\n\nexport type CraftIconProviderProps = {\n icons: CraftIconRegistry;\n children: React.ReactNode;\n};\n\nexport function CraftIconProvider({ icons, children }: CraftIconProviderProps) {\n return <CraftIconContext.Provider value={icons}>{children}</CraftIconContext.Provider>;\n}\n\nexport type CraftIconProps = {\n name: string;\n className?: string;\n \"aria-label\"?: string;\n icons?: CraftIconRegistry;\n useLucide?: boolean;\n};\n\ntype DynamicIconComponent = React.ComponentType<{\n name: string;\n className?: string;\n \"aria-hidden\"?: boolean;\n \"aria-label\"?: string;\n}>;\n\nexport function CraftIcon({\n name,\n className,\n \"aria-label\": ariaLabel,\n icons,\n useLucide = true,\n}: CraftIconProps) {\n const contextRegistry = React.useContext(CraftIconContext);\n const registry = icons ?? contextRegistry;\n const icon = registry?.[name];\n const [LucideIcon, setLucideIcon] = React.useState<DynamicIconComponent | null>(\n null\n );\n\n React.useEffect(() => {\n if (!useLucide || icon || LucideIcon) return;\n let mounted = true;\n (async () => {\n try {\n const mod = await import(\"lucide-react/dynamic.mjs\");\n if (mounted) {\n setLucideIcon(() => mod.DynamicIcon as DynamicIconComponent);\n }\n } catch (error) {\n if (mounted) setLucideIcon(null);\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n \"[CraftIcon] Failed to load lucide-react/dynamic. Ensure lucide-react is installed.\"\n );\n console.warn(error);\n }\n }\n })();\n return () => {\n mounted = false;\n };\n }, [LucideIcon, icon, useLucide]);\n\n if (!icon) {\n if (!useLucide) return null;\n if (!LucideIcon) return null;\n return (\n <LucideIcon\n name={name}\n className={className}\n aria-hidden={ariaLabel ? undefined : true}\n aria-label={ariaLabel}\n />\n );\n }\n\n type IconElementProps = {\n className?: string;\n \"aria-hidden\"?: boolean;\n \"aria-label\"?: string;\n };\n\n if (React.isValidElement<IconElementProps>(icon)) {\n return React.cloneElement(icon, {\n className: cn(icon.props.className, className),\n \"aria-hidden\": ariaLabel ? undefined : true,\n \"aria-label\": ariaLabel,\n });\n }\n\n return (\n <span className={className} aria-label={ariaLabel}>\n {icon}\n </span>\n );\n}\n"],"mappings":";AAgBS;AAdT,YAAY,WAAW;AAEvB,SAAS,UAAU;AAInB,MAAM,mBAAmB,MAAM,cAAwC,IAAI;AAOpE,SAAS,kBAAkB,EAAE,OAAO,SAAS,GAA2B;AAC7E,SAAO,oBAAC,iBAAiB,UAAjB,EAA0B,OAAO,OAAQ,UAAS;AAC5D;AAiBO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA,YAAY;AACd,GAAmB;AACjB,QAAM,kBAAkB,MAAM,WAAW,gBAAgB;AACzD,QAAM,WAAW,wBAAS;AAC1B,QAAM,OAAO,qCAAW;AACxB,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM;AAAA,IACxC;AAAA,EACF;AAEA,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,aAAa,QAAQ,WAAY;AACtC,QAAI,UAAU;AACd,KAAC,YAAY;AACX,UAAI;AACF,cAAM,MAAM,MAAM,OAAO,0BAA0B;AACnD,YAAI,SAAS;AACX,wBAAc,MAAM,IAAI,WAAmC;AAAA,QAC7D;AAAA,MACF,SAAS,OAAO;AACd,YAAI,QAAS,eAAc,IAAI;AAC/B,YAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,kBAAQ;AAAA,YACN;AAAA,UACF;AACA,kBAAQ,KAAK,KAAK;AAAA,QACpB;AAAA,MACF;AAAA,IACF,GAAG;AACH,WAAO,MAAM;AACX,gBAAU;AAAA,IACZ;AAAA,EACF,GAAG,CAAC,YAAY,MAAM,SAAS,CAAC;AAEhC,MAAI,CAAC,MAAM;AACT,QAAI,CAAC,UAAW,QAAO;AACvB,QAAI,CAAC,WAAY,QAAO;AACxB,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,eAAa,YAAY,SAAY;AAAA,QACrC,cAAY;AAAA;AAAA,IACd;AAAA,EAEJ;AAQA,MAAI,MAAM,eAAiC,IAAI,GAAG;AAChD,WAAO,MAAM,aAAa,MAAM;AAAA,MAC9B,WAAW,GAAG,KAAK,MAAM,WAAW,SAAS;AAAA,MAC7C,eAAe,YAAY,SAAY;AAAA,MACvC,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,SACE,oBAAC,UAAK,WAAsB,cAAY,WACrC,gBACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/craft-icon.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport type { IconDefinition } from \"@fortawesome/fontawesome-svg-core\";\nimport {\n faArchive,\n faCreditCard,\n faFolder,\n faFolderOpen,\n faGauge,\n faPen,\n faSearch,\n faTrash,\n faUsers,\n} from \"@fortawesome/free-solid-svg-icons\";\n\nimport { cn } from \"@/utils/cn\";\n\nexport type CraftIconRegistry = Record<string, React.ReactNode>;\n\nconst CraftIconContext = React.createContext<CraftIconRegistry | null>(null);\n\nexport type CraftIconProviderProps = {\n icons: CraftIconRegistry;\n children: React.ReactNode;\n};\n\nexport function CraftIconProvider({ icons, children }: CraftIconProviderProps) {\n return <CraftIconContext.Provider value={icons}>{children}</CraftIconContext.Provider>;\n}\n\nexport type CraftIconProps = {\n name: string;\n className?: string;\n \"aria-label\"?: string;\n icons?: CraftIconRegistry;\n};\n\nconst fontAwesomeIcons: Record<string, IconDefinition> = {\n \"layout-dashboard\": faGauge,\n dashboard: faGauge,\n folder: faFolder,\n \"folder-open\": faFolderOpen,\n users: faUsers,\n \"credit-card\": faCreditCard,\n pen: faPen,\n edit: faPen,\n trash: faTrash,\n delete: faTrash,\n archive: faArchive,\n search: faSearch,\n};\n\nexport function CraftIcon({\n name,\n className,\n \"aria-label\": ariaLabel,\n icons,\n}: CraftIconProps) {\n const contextRegistry = React.useContext(CraftIconContext);\n const registry = icons ?? contextRegistry;\n const icon = registry?.[name];\n\n if (!icon) {\n const faIcon = fontAwesomeIcons[name];\n if (!faIcon) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(`[CraftIcon] Unknown icon name: ${name}`);\n }\n return null;\n }\n\n return (\n <FontAwesomeIcon\n icon={faIcon}\n className={className}\n aria-hidden={ariaLabel ? undefined : true}\n aria-label={ariaLabel}\n />\n );\n }\n\n type IconElementProps = {\n className?: string;\n \"aria-hidden\"?: boolean;\n \"aria-label\"?: string;\n };\n\n if (React.isValidElement<IconElementProps>(icon)) {\n return React.cloneElement(icon, {\n className: cn(icon.props.className, className),\n \"aria-hidden\": ariaLabel ? undefined : true,\n \"aria-label\": ariaLabel,\n });\n }\n\n return (\n <span className={className} aria-label={ariaLabel}>\n {icon}\n </span>\n );\n}\n"],"mappings":";AA6BS;AA3BT,YAAY,WAAW;AACvB,SAAS,uBAAuB;AAEhC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,UAAU;AAInB,MAAM,mBAAmB,MAAM,cAAwC,IAAI;AAOpE,SAAS,kBAAkB,EAAE,OAAO,SAAS,GAA2B;AAC7E,SAAO,oBAAC,iBAAiB,UAAjB,EAA0B,OAAO,OAAQ,UAAS;AAC5D;AASA,MAAM,mBAAmD;AAAA,EACvD,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,OAAO;AAAA,EACP,eAAe;AAAA,EACf,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AACV;AAEO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AACF,GAAmB;AACjB,QAAM,kBAAkB,MAAM,WAAW,gBAAgB;AACzD,QAAM,WAAW,wBAAS;AAC1B,QAAM,OAAO,qCAAW;AAExB,MAAI,CAAC,MAAM;AACT,UAAM,SAAS,iBAAiB,IAAI;AACpC,QAAI,CAAC,QAAQ;AACX,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,gBAAQ,KAAK,kCAAkC,IAAI,EAAE;AAAA,MACvD;AACA,aAAO;AAAA,IACT;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN;AAAA,QACA,eAAa,YAAY,SAAY;AAAA,QACrC,cAAY;AAAA;AAAA,IACd;AAAA,EAEJ;AAQA,MAAI,MAAM,eAAiC,IAAI,GAAG;AAChD,WAAO,MAAM,aAAa,MAAM;AAAA,MAC9B,WAAW,GAAG,KAAK,MAAM,WAAW,SAAS;AAAA,MAC7C,eAAe,YAAY,SAAY;AAAA,MACvC,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,SACE,oBAAC,UAAK,WAAsB,cAAY,WACrC,gBACH;AAEJ;","names":[]}
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var craft_loader_exports = {};
21
+ __export(craft_loader_exports, {
22
+ CraftLoader: () => CraftLoader
23
+ });
24
+ module.exports = __toCommonJS(craft_loader_exports);
25
+ var import_jsx_runtime = require("react/jsx-runtime");
26
+ var import_cn = require("../utils/cn");
27
+ const sizeMap = {
28
+ small: 16,
29
+ medium: 24,
30
+ large: 32,
31
+ xl: 40
32
+ };
33
+ function Spinner({ size, color }) {
34
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
35
+ "svg",
36
+ {
37
+ className: "animate-spin",
38
+ width: size,
39
+ height: size,
40
+ viewBox: "0 0 24 24",
41
+ fill: "none",
42
+ "aria-hidden": "true",
43
+ children: [
44
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
45
+ "circle",
46
+ {
47
+ cx: "12",
48
+ cy: "12",
49
+ r: "10",
50
+ stroke: color,
51
+ strokeWidth: "4",
52
+ className: "opacity-25"
53
+ }
54
+ ),
55
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
56
+ "path",
57
+ {
58
+ d: "M4 12a8 8 0 018-8",
59
+ stroke: color,
60
+ strokeWidth: "4",
61
+ strokeLinecap: "round",
62
+ className: "opacity-75"
63
+ }
64
+ )
65
+ ]
66
+ }
67
+ );
68
+ }
69
+ function Dots({ size, color }) {
70
+ const dotSize = Math.max(4, Math.floor(size / 6));
71
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex items-center gap-2", children: [0, 1, 2].map((index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
72
+ "span",
73
+ {
74
+ className: "inline-flex animate-bounce rounded-full",
75
+ style: {
76
+ width: dotSize,
77
+ height: dotSize,
78
+ backgroundColor: color,
79
+ animationDelay: `${index * 120}ms`
80
+ }
81
+ },
82
+ index
83
+ )) });
84
+ }
85
+ function Bars({ size, color }) {
86
+ const barHeight = size;
87
+ const barWidth = Math.max(3, Math.floor(size / 6));
88
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex items-end gap-1", children: [0, 1, 2, 3].map((index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
89
+ "span",
90
+ {
91
+ className: "inline-flex animate-pulse rounded-sm",
92
+ style: {
93
+ width: barWidth,
94
+ height: barHeight - index * 4,
95
+ backgroundColor: color,
96
+ animationDelay: `${index * 100}ms`
97
+ }
98
+ },
99
+ index
100
+ )) });
101
+ }
102
+ function Pulse({ size, color }) {
103
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
104
+ "span",
105
+ {
106
+ className: "inline-flex animate-pulse rounded-full",
107
+ style: { width: size, height: size, backgroundColor: color }
108
+ }
109
+ );
110
+ }
111
+ function Ripple({ size, color }) {
112
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
113
+ "span",
114
+ {
115
+ className: "inline-flex rounded-full border-2 animate-ping",
116
+ style: { width: size, height: size, borderColor: color }
117
+ }
118
+ );
119
+ }
120
+ function Ring({ size, color }) {
121
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
122
+ "span",
123
+ {
124
+ className: "inline-flex animate-spin rounded-full border-2 border-t-transparent",
125
+ style: { width: size, height: size, borderColor: color }
126
+ }
127
+ );
128
+ }
129
+ function Bounce({ size, color }) {
130
+ const dotSize = Math.max(4, Math.floor(size / 5));
131
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex items-center gap-2", children: [0, 1].map((index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
132
+ "span",
133
+ {
134
+ className: "inline-flex animate-bounce rounded-full",
135
+ style: {
136
+ width: dotSize,
137
+ height: dotSize,
138
+ backgroundColor: color,
139
+ animationDelay: `${index * 140}ms`
140
+ }
141
+ },
142
+ index
143
+ )) });
144
+ }
145
+ function CraftLoader({
146
+ loading = false,
147
+ type = "dots",
148
+ size = "medium",
149
+ color = "rgb(var(--nc-accent-1))",
150
+ overlay = false,
151
+ text,
152
+ textPosition = "bottom",
153
+ backgroundColor = "rgba(0, 0, 0, 0.35)",
154
+ tone,
155
+ className
156
+ }) {
157
+ if (!loading) return null;
158
+ const px = sizeMap[size];
159
+ const content = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
160
+ "div",
161
+ {
162
+ className: (0, import_cn.cn)(
163
+ "flex flex-col items-center justify-center gap-3",
164
+ textPosition === "top" && "flex-col-reverse",
165
+ className
166
+ ),
167
+ "data-nc-theme": tone,
168
+ children: [
169
+ type === "spin" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: px, color }),
170
+ type === "dots" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Dots, { size: px, color }),
171
+ type === "bars" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Bars, { size: px, color }),
172
+ type === "pulse" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pulse, { size: px, color }),
173
+ type === "ripple" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Ripple, { size: px, color }),
174
+ type === "ring" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Ring, { size: px, color }),
175
+ type === "bounce" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Bounce, { size: px, color }),
176
+ text ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: text }) : null
177
+ ]
178
+ }
179
+ );
180
+ if (!overlay) return content;
181
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
182
+ "div",
183
+ {
184
+ className: "absolute inset-0 z-10 flex items-center justify-center",
185
+ style: { backgroundColor },
186
+ "data-nc-theme": tone,
187
+ children: content
188
+ }
189
+ );
190
+ }
191
+ // Annotate the CommonJS export names for ESM import in node:
192
+ 0 && (module.exports = {
193
+ CraftLoader
194
+ });
195
+ //# sourceMappingURL=craft-loader.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/craft-loader.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/utils/cn\";\nimport type { ThemeName } from \"@/theme/theme-context\";\n\nexport type CraftLoaderType =\n | \"spin\"\n | \"pulse\"\n | \"bounce\"\n | \"ripple\"\n | \"bars\"\n | \"dots\"\n | \"ring\";\n\nexport type CraftLoaderSize = \"small\" | \"medium\" | \"large\" | \"xl\";\n\nexport type CraftLoaderProps = {\n loading?: boolean;\n type?: CraftLoaderType;\n size?: CraftLoaderSize;\n color?: string;\n overlay?: boolean;\n text?: React.ReactNode;\n textPosition?: \"top\" | \"bottom\";\n backgroundColor?: string;\n tone?: ThemeName;\n className?: string;\n};\n\nconst sizeMap: Record<CraftLoaderSize, number> = {\n small: 16,\n medium: 24,\n large: 32,\n xl: 40,\n};\n\nfunction Spinner({ size, color }: { size: number; color: string }) {\n return (\n <svg\n className=\"animate-spin\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke={color}\n strokeWidth=\"4\"\n className=\"opacity-25\"\n />\n <path\n d=\"M4 12a8 8 0 018-8\"\n stroke={color}\n strokeWidth=\"4\"\n strokeLinecap=\"round\"\n className=\"opacity-75\"\n />\n </svg>\n );\n}\n\nfunction Dots({ size, color }: { size: number; color: string }) {\n const dotSize = Math.max(4, Math.floor(size / 6));\n return (\n <div className=\"flex items-center gap-2\">\n {[0, 1, 2].map((index) => (\n <span\n key={index}\n className=\"inline-flex animate-bounce rounded-full\"\n style={{\n width: dotSize,\n height: dotSize,\n backgroundColor: color,\n animationDelay: `${index * 120}ms`,\n }}\n />\n ))}\n </div>\n );\n}\n\nfunction Bars({ size, color }: { size: number; color: string }) {\n const barHeight = size;\n const barWidth = Math.max(3, Math.floor(size / 6));\n return (\n <div className=\"flex items-end gap-1\">\n {[0, 1, 2, 3].map((index) => (\n <span\n key={index}\n className=\"inline-flex animate-pulse rounded-sm\"\n style={{\n width: barWidth,\n height: barHeight - index * 4,\n backgroundColor: color,\n animationDelay: `${index * 100}ms`,\n }}\n />\n ))}\n </div>\n );\n}\n\nfunction Pulse({ size, color }: { size: number; color: string }) {\n return (\n <span\n className=\"inline-flex animate-pulse rounded-full\"\n style={{ width: size, height: size, backgroundColor: color }}\n />\n );\n}\n\nfunction Ripple({ size, color }: { size: number; color: string }) {\n return (\n <span\n className=\"inline-flex rounded-full border-2 animate-ping\"\n style={{ width: size, height: size, borderColor: color }}\n />\n );\n}\n\nfunction Ring({ size, color }: { size: number; color: string }) {\n return (\n <span\n className=\"inline-flex animate-spin rounded-full border-2 border-t-transparent\"\n style={{ width: size, height: size, borderColor: color }}\n />\n );\n}\n\nfunction Bounce({ size, color }: { size: number; color: string }) {\n const dotSize = Math.max(4, Math.floor(size / 5));\n return (\n <div className=\"flex items-center gap-2\">\n {[0, 1].map((index) => (\n <span\n key={index}\n className=\"inline-flex animate-bounce rounded-full\"\n style={{\n width: dotSize,\n height: dotSize,\n backgroundColor: color,\n animationDelay: `${index * 140}ms`,\n }}\n />\n ))}\n </div>\n );\n}\n\nexport function CraftLoader({\n loading = false,\n type = \"dots\",\n size = \"medium\",\n color = \"rgb(var(--nc-accent-1))\",\n overlay = false,\n text,\n textPosition = \"bottom\",\n backgroundColor = \"rgba(0, 0, 0, 0.35)\",\n tone,\n className,\n}: CraftLoaderProps) {\n if (!loading) return null;\n\n const px = sizeMap[size];\n\n const content = (\n <div\n className={cn(\n \"flex flex-col items-center justify-center gap-3\",\n textPosition === \"top\" && \"flex-col-reverse\",\n className\n )}\n data-nc-theme={tone}\n >\n {type === \"spin\" && <Spinner size={px} color={color} />}\n {type === \"dots\" && <Dots size={px} color={color} />}\n {type === \"bars\" && <Bars size={px} color={color} />}\n {type === \"pulse\" && <Pulse size={px} color={color} />}\n {type === \"ripple\" && <Ripple size={px} color={color} />}\n {type === \"ring\" && <Ring size={px} color={color} />}\n {type === \"bounce\" && <Bounce size={px} color={color} />}\n {text ? <span className=\"text-xs text-[rgb(var(--nc-fg-muted))]\">{text}</span> : null}\n </div>\n );\n\n if (!overlay) return content;\n\n return (\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center\"\n style={{ backgroundColor }}\n data-nc-theme={tone}\n >\n {content}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,21 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { ThemeName } from '../theme/theme-context.cjs';
4
+
5
+ type CraftLoaderType = "spin" | "pulse" | "bounce" | "ripple" | "bars" | "dots" | "ring";
6
+ type CraftLoaderSize = "small" | "medium" | "large" | "xl";
7
+ type CraftLoaderProps = {
8
+ loading?: boolean;
9
+ type?: CraftLoaderType;
10
+ size?: CraftLoaderSize;
11
+ color?: string;
12
+ overlay?: boolean;
13
+ text?: React.ReactNode;
14
+ textPosition?: "top" | "bottom";
15
+ backgroundColor?: string;
16
+ tone?: ThemeName;
17
+ className?: string;
18
+ };
19
+ declare function CraftLoader({ loading, type, size, color, overlay, text, textPosition, backgroundColor, tone, className, }: CraftLoaderProps): react_jsx_runtime.JSX.Element | null;
20
+
21
+ export { CraftLoader, type CraftLoaderProps, type CraftLoaderSize, type CraftLoaderType };
@@ -0,0 +1,21 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { ThemeName } from '../theme/theme-context.js';
4
+
5
+ type CraftLoaderType = "spin" | "pulse" | "bounce" | "ripple" | "bars" | "dots" | "ring";
6
+ type CraftLoaderSize = "small" | "medium" | "large" | "xl";
7
+ type CraftLoaderProps = {
8
+ loading?: boolean;
9
+ type?: CraftLoaderType;
10
+ size?: CraftLoaderSize;
11
+ color?: string;
12
+ overlay?: boolean;
13
+ text?: React.ReactNode;
14
+ textPosition?: "top" | "bottom";
15
+ backgroundColor?: string;
16
+ tone?: ThemeName;
17
+ className?: string;
18
+ };
19
+ declare function CraftLoader({ loading, type, size, color, overlay, text, textPosition, backgroundColor, tone, className, }: CraftLoaderProps): react_jsx_runtime.JSX.Element | null;
20
+
21
+ export { CraftLoader, type CraftLoaderProps, type CraftLoaderSize, type CraftLoaderType };