@skalfa/skalfa-component 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +79 -0
  3. package/dist/accordion/Accordion.component.d.ts +13 -0
  4. package/dist/accordion/Accordion.component.js +25 -0
  5. package/dist/breadcrumb/Breadcrumb.component.d.ts +14 -0
  6. package/dist/breadcrumb/Breadcrumb.component.js +21 -0
  7. package/dist/button/Button.component.d.ts +21 -0
  8. package/dist/button/Button.component.js +19 -0
  9. package/dist/card/AlertCard.component.d.ts +11 -0
  10. package/dist/card/AlertCard.component.js +9 -0
  11. package/dist/card/Card.component.d.ts +5 -0
  12. package/dist/card/Card.component.js +9 -0
  13. package/dist/card/DashboardCard.component.d.ts +9 -0
  14. package/dist/card/DashboardCard.component.js +13 -0
  15. package/dist/card/GalleryCard.component.d.ts +7 -0
  16. package/dist/card/GalleryCard.component.js +13 -0
  17. package/dist/card/ProductCard.component.d.ts +9 -0
  18. package/dist/card/ProductCard.component.js +13 -0
  19. package/dist/card/ProfileCard.component.d.ts +10 -0
  20. package/dist/card/ProfileCard.component.js +13 -0
  21. package/dist/carousel/Carousel.component.d.ts +13 -0
  22. package/dist/carousel/Carousel.component.js +37 -0
  23. package/dist/chip/Chip.component.d.ts +6 -0
  24. package/dist/chip/Chip.component.js +12 -0
  25. package/dist/index.d.ts +56 -0
  26. package/dist/index.js +85 -0
  27. package/dist/input/Checkbox.component.d.ts +13 -0
  28. package/dist/input/Checkbox.component.js +23 -0
  29. package/dist/input/Input.component.d.ts +23 -0
  30. package/dist/input/Input.component.js +134 -0
  31. package/dist/input/InputCheckbox.component.d.ts +27 -0
  32. package/dist/input/InputCheckbox.component.js +53 -0
  33. package/dist/input/InputCurrency.component.d.ts +21 -0
  34. package/dist/input/InputCurrency.component.js +30 -0
  35. package/dist/input/InputDate.component.d.ts +24 -0
  36. package/dist/input/InputDate.component.js +107 -0
  37. package/dist/input/InputDatetime.component.d.ts +17 -0
  38. package/dist/input/InputDatetime.component.js +75 -0
  39. package/dist/input/InputDocument.component.d.ts +22 -0
  40. package/dist/input/InputDocument.component.js +88 -0
  41. package/dist/input/InputImage.component.d.ts +23 -0
  42. package/dist/input/InputImage.component.js +260 -0
  43. package/dist/input/InputMap.component.d.ts +25 -0
  44. package/dist/input/InputMap.component.js +103 -0
  45. package/dist/input/InputNumber.component.d.ts +19 -0
  46. package/dist/input/InputNumber.component.js +40 -0
  47. package/dist/input/InputOtp.component.d.ts +14 -0
  48. package/dist/input/InputOtp.component.js +65 -0
  49. package/dist/input/InputPassword.component.d.ts +17 -0
  50. package/dist/input/InputPassword.component.js +59 -0
  51. package/dist/input/InputRadio.component.d.ts +27 -0
  52. package/dist/input/InputRadio.component.js +56 -0
  53. package/dist/input/InputTime.component.d.ts +23 -0
  54. package/dist/input/InputTime.component.js +73 -0
  55. package/dist/input/InputValues.component.d.ts +9 -0
  56. package/dist/input/InputValues.component.js +19 -0
  57. package/dist/input/Radio.component.d.ts +12 -0
  58. package/dist/input/Radio.component.js +22 -0
  59. package/dist/input/Select.component.d.ts +47 -0
  60. package/dist/input/Select.component.js +275 -0
  61. package/dist/modal/BottomSheet.component.d.ts +12 -0
  62. package/dist/modal/BottomSheet.component.js +161 -0
  63. package/dist/modal/FloatingPage.component.d.ts +12 -0
  64. package/dist/modal/FloatingPage.component.js +27 -0
  65. package/dist/modal/Modal.component.d.ts +12 -0
  66. package/dist/modal/Modal.component.js +27 -0
  67. package/dist/modal/ModalConfirm.component.d.ts +26 -0
  68. package/dist/modal/ModalConfirm.component.js +68 -0
  69. package/dist/modal/Toast.component.d.ts +11 -0
  70. package/dist/modal/Toast.component.js +58 -0
  71. package/dist/nav/Bottombar.component.d.ts +12 -0
  72. package/dist/nav/Bottombar.component.js +32 -0
  73. package/dist/nav/Footer.component.d.ts +37 -0
  74. package/dist/nav/Footer.component.js +49 -0
  75. package/dist/nav/Headbar.component.d.ts +14 -0
  76. package/dist/nav/Headbar.component.js +32 -0
  77. package/dist/nav/Navbar.component.d.ts +22 -0
  78. package/dist/nav/Navbar.component.js +26 -0
  79. package/dist/nav/Sidebar.component.d.ts +33 -0
  80. package/dist/nav/Sidebar.component.js +87 -0
  81. package/dist/nav/Tabbar.component.d.ts +13 -0
  82. package/dist/nav/Tabbar.component.js +17 -0
  83. package/dist/nav/Wizard.component.d.ts +9 -0
  84. package/dist/nav/Wizard.component.js +24 -0
  85. package/dist/src/accordion/Accordion.component.d.ts +13 -0
  86. package/dist/src/accordion/Accordion.component.js +25 -0
  87. package/dist/src/breadcrumb/Breadcrumb.component.d.ts +14 -0
  88. package/dist/src/breadcrumb/Breadcrumb.component.js +21 -0
  89. package/dist/src/button/Button.component.d.ts +21 -0
  90. package/dist/src/button/Button.component.js +19 -0
  91. package/dist/src/card/AlertCard.component.d.ts +11 -0
  92. package/dist/src/card/AlertCard.component.js +9 -0
  93. package/dist/src/card/Card.component.d.ts +5 -0
  94. package/dist/src/card/Card.component.js +9 -0
  95. package/dist/src/card/DashboardCard.component.d.ts +9 -0
  96. package/dist/src/card/DashboardCard.component.js +13 -0
  97. package/dist/src/card/GalleryCard.component.d.ts +7 -0
  98. package/dist/src/card/GalleryCard.component.js +13 -0
  99. package/dist/src/card/ProductCard.component.d.ts +9 -0
  100. package/dist/src/card/ProductCard.component.js +13 -0
  101. package/dist/src/card/ProfileCard.component.d.ts +10 -0
  102. package/dist/src/card/ProfileCard.component.js +13 -0
  103. package/dist/src/carousel/Carousel.component.d.ts +13 -0
  104. package/dist/src/carousel/Carousel.component.js +37 -0
  105. package/dist/src/chip/Chip.component.d.ts +6 -0
  106. package/dist/src/chip/Chip.component.js +12 -0
  107. package/dist/src/index.d.ts +13 -0
  108. package/dist/src/index.js +29 -0
  109. package/dist/src/input/Checkbox.component.d.ts +13 -0
  110. package/dist/src/input/Checkbox.component.js +23 -0
  111. package/dist/src/input/Input.component.d.ts +23 -0
  112. package/dist/src/input/Input.component.js +134 -0
  113. package/dist/src/input/InputCheckbox.component.d.ts +27 -0
  114. package/dist/src/input/InputCheckbox.component.js +53 -0
  115. package/dist/src/input/InputCurrency.component.d.ts +21 -0
  116. package/dist/src/input/InputCurrency.component.js +30 -0
  117. package/dist/src/input/InputDate.component.d.ts +24 -0
  118. package/dist/src/input/InputDate.component.js +107 -0
  119. package/dist/src/input/InputDatetime.component.d.ts +17 -0
  120. package/dist/src/input/InputDatetime.component.js +75 -0
  121. package/dist/src/input/InputDocument.component.d.ts +22 -0
  122. package/dist/src/input/InputDocument.component.js +88 -0
  123. package/dist/src/input/InputImage.component.d.ts +23 -0
  124. package/dist/src/input/InputImage.component.js +260 -0
  125. package/dist/src/input/InputMap.component.d.ts +25 -0
  126. package/dist/src/input/InputMap.component.js +101 -0
  127. package/dist/src/input/InputNumber.component.d.ts +19 -0
  128. package/dist/src/input/InputNumber.component.js +40 -0
  129. package/dist/src/input/InputOtp.component.d.ts +14 -0
  130. package/dist/src/input/InputOtp.component.js +65 -0
  131. package/dist/src/input/InputPassword.component.d.ts +17 -0
  132. package/dist/src/input/InputPassword.component.js +59 -0
  133. package/dist/src/input/InputRadio.component.d.ts +27 -0
  134. package/dist/src/input/InputRadio.component.js +56 -0
  135. package/dist/src/input/InputTime.component.d.ts +23 -0
  136. package/dist/src/input/InputTime.component.js +73 -0
  137. package/dist/src/input/InputValues.component.d.ts +9 -0
  138. package/dist/src/input/InputValues.component.js +19 -0
  139. package/dist/src/input/Radio.component.d.ts +12 -0
  140. package/dist/src/input/Radio.component.js +22 -0
  141. package/dist/src/input/Select.component.d.ts +47 -0
  142. package/dist/src/input/Select.component.js +275 -0
  143. package/dist/src/modal/BottomSheet.component.d.ts +12 -0
  144. package/dist/src/modal/BottomSheet.component.js +161 -0
  145. package/dist/src/modal/FloatingPage.component.d.ts +12 -0
  146. package/dist/src/modal/FloatingPage.component.js +27 -0
  147. package/dist/src/modal/Modal.component.d.ts +12 -0
  148. package/dist/src/modal/Modal.component.js +27 -0
  149. package/dist/src/modal/ModalConfirm.component.d.ts +26 -0
  150. package/dist/src/modal/ModalConfirm.component.js +68 -0
  151. package/dist/src/modal/Toast.component.d.ts +11 -0
  152. package/dist/src/modal/Toast.component.js +58 -0
  153. package/dist/src/nav/Bottombar.component.d.ts +12 -0
  154. package/dist/src/nav/Bottombar.component.js +32 -0
  155. package/dist/src/nav/Footer.component.d.ts +37 -0
  156. package/dist/src/nav/Footer.component.js +49 -0
  157. package/dist/src/nav/Headbar.component.d.ts +14 -0
  158. package/dist/src/nav/Headbar.component.js +32 -0
  159. package/dist/src/nav/Navbar.component.d.ts +22 -0
  160. package/dist/src/nav/Navbar.component.js +26 -0
  161. package/dist/src/nav/Sidebar.component.d.ts +33 -0
  162. package/dist/src/nav/Sidebar.component.js +87 -0
  163. package/dist/src/nav/Tabbar.component.d.ts +13 -0
  164. package/dist/src/nav/Tabbar.component.js +17 -0
  165. package/dist/src/nav/Wizard.component.d.ts +9 -0
  166. package/dist/src/nav/Wizard.component.js +24 -0
  167. package/dist/src/supervision/FormSupervision.component.d.ts +93 -0
  168. package/dist/src/supervision/FormSupervision.component.js +168 -0
  169. package/dist/src/supervision/TableSupervision.component.d.ts +78 -0
  170. package/dist/src/supervision/TableSupervision.component.js +273 -0
  171. package/dist/src/table/ControlBar.component.d.ts +34 -0
  172. package/dist/src/table/ControlBar.component.js +205 -0
  173. package/dist/src/table/FilterComponent.d.ts +45 -0
  174. package/dist/src/table/FilterComponent.js +132 -0
  175. package/dist/src/table/Pagination.component.d.ts +8 -0
  176. package/dist/src/table/Pagination.component.js +32 -0
  177. package/dist/src/table/Table.component.d.ts +61 -0
  178. package/dist/src/table/Table.component.js +101 -0
  179. package/dist/src/typography/TypographyArticle.component.d.ts +8 -0
  180. package/dist/src/typography/TypographyArticle.component.js +7 -0
  181. package/dist/src/typography/TypographyColumn.component.d.ts +6 -0
  182. package/dist/src/typography/TypographyColumn.component.js +7 -0
  183. package/dist/src/typography/TypographyContent.component.d.ts +6 -0
  184. package/dist/src/typography/TypographyContent.component.js +7 -0
  185. package/dist/src/typography/TypographyTips.component.d.ts +6 -0
  186. package/dist/src/typography/TypographyTips.component.js +7 -0
  187. package/dist/src/wrap/Draggable.component.d.ts +34 -0
  188. package/dist/src/wrap/Draggable.component.js +214 -0
  189. package/dist/src/wrap/Image.component.d.ts +2 -0
  190. package/dist/src/wrap/Image.component.js +13 -0
  191. package/dist/src/wrap/OutsideClick.component.d.ts +6 -0
  192. package/dist/src/wrap/OutsideClick.component.js +34 -0
  193. package/dist/src/wrap/ScrollContainer.component.d.ts +10 -0
  194. package/dist/src/wrap/ScrollContainer.component.js +54 -0
  195. package/dist/src/wrap/ShortcutProvider.d.ts +1 -0
  196. package/dist/src/wrap/ShortcutProvider.js +42 -0
  197. package/dist/src/wrap/Swipe.component.d.ts +14 -0
  198. package/dist/src/wrap/Swipe.component.js +61 -0
  199. package/dist/supervision/FormSupervision.component.d.ts +93 -0
  200. package/dist/supervision/FormSupervision.component.js +168 -0
  201. package/dist/supervision/TableSupervision.component.d.ts +78 -0
  202. package/dist/supervision/TableSupervision.component.js +273 -0
  203. package/dist/table/ControlBar.component.d.ts +34 -0
  204. package/dist/table/ControlBar.component.js +205 -0
  205. package/dist/table/FilterComponent.d.ts +45 -0
  206. package/dist/table/FilterComponent.js +132 -0
  207. package/dist/table/Pagination.component.d.ts +8 -0
  208. package/dist/table/Pagination.component.js +32 -0
  209. package/dist/table/Table.component.d.ts +61 -0
  210. package/dist/table/Table.component.js +101 -0
  211. package/dist/typography/TypographyArticle.component.d.ts +8 -0
  212. package/dist/typography/TypographyArticle.component.js +7 -0
  213. package/dist/typography/TypographyColumn.component.d.ts +6 -0
  214. package/dist/typography/TypographyColumn.component.js +7 -0
  215. package/dist/typography/TypographyContent.component.d.ts +6 -0
  216. package/dist/typography/TypographyContent.component.js +7 -0
  217. package/dist/typography/TypographyTips.component.d.ts +6 -0
  218. package/dist/typography/TypographyTips.component.js +7 -0
  219. package/dist/wrap/Draggable.component.d.ts +1 -0
  220. package/dist/wrap/Draggable.component.js +214 -0
  221. package/dist/wrap/Image.component.d.ts +2 -0
  222. package/dist/wrap/Image.component.js +13 -0
  223. package/dist/wrap/OutsideClick.component.d.ts +6 -0
  224. package/dist/wrap/OutsideClick.component.js +34 -0
  225. package/dist/wrap/ScrollContainer.component.d.ts +10 -0
  226. package/dist/wrap/ScrollContainer.component.js +54 -0
  227. package/dist/wrap/ShortcutProvider.d.ts +1 -0
  228. package/dist/wrap/ShortcutProvider.js +42 -0
  229. package/dist/wrap/Swipe.component.d.ts +14 -0
  230. package/dist/wrap/Swipe.component.js +61 -0
  231. package/package.json +44 -0
@@ -0,0 +1,88 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.InputDocumentPicker = void 0;
5
+ exports.InputDocumentComponent = InputDocumentComponent;
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ const react_1 = require("react");
8
+ const free_solid_svg_icons_1 = require("@fortawesome/free-solid-svg-icons");
9
+ const react_fontawesome_1 = require("@fortawesome/react-fontawesome");
10
+ const _utils_1 = require("@utils");
11
+ const _components_1 = require("@components");
12
+ const DocumentViewerComponent = (props) => {
13
+ const Comp = _utils_1.registry.get("DocumentViewerComponent");
14
+ return Comp ? (0, jsx_runtime_1.jsx)(Comp, { ...props }) : null;
15
+ };
16
+ const DocumentViewerIcon = (ext) => {
17
+ const getIcon = _utils_1.registry.get("DocumentViewerIcon");
18
+ return getIcon ? getIcon(ext) : null;
19
+ };
20
+ function InputDocumentComponent({ label, tip, leftIcon, rightIcon, className = "", value, invalid, validations, register, unregister, onChange, ...props }) {
21
+ const { isSm } = (0, _utils_1.useResponsive)();
22
+ // =========================>
23
+ // ## Initial
24
+ // =========================>
25
+ const inputHandler = (0, _utils_1.useInputHandler)(props.name, value, validations, register, unregister, props.type == "file");
26
+ const randomId = (0, _utils_1.useInputRandomId)();
27
+ // =========================>
28
+ // ## Invalid handler
29
+ // =========================>
30
+ const [invalidMessage] = (0, _utils_1.useValidation)(inputHandler.value, validations, invalid, inputHandler.idle);
31
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "input-container", children: [(0, jsx_runtime_1.jsxs)("label", { htmlFor: randomId, className: (0, _utils_1.cn)("input-label", props.disabled && "input-label-disabled", inputHandler.focus && "input-label-focus", !!invalidMessage && "input-label-error", (0, _utils_1.pcn)(className, "label"), props.disabled && (0, _utils_1.pcn)(className, "label", "disabled"), inputHandler.focus && (0, _utils_1.pcn)(className, "label", "focus"), !!invalidMessage && (0, _utils_1.pcn)(className, "label", "focus")), children: [label, validations && _utils_1.validation.hasRules(validations, "required") && (0, jsx_runtime_1.jsx)("span", { className: "text-danger ml-1", children: "*" })] }), tip && ((0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-tip", props.disabled && "input-tip-disabled", (0, _utils_1.pcn)(className, "tip"), props.disabled && (0, _utils_1.pcn)(className, "tip", "disabled")), children: tip })), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)("input", { ...props, id: randomId, placeholder: !inputHandler.value ? props.placeholder : "", className: (0, _utils_1.cn)("input cursor-pointer", props.type == "file" && "input-file", leftIcon && "input-with-left-icon", rightIcon && "input-with-right-icon", (0, _utils_1.pcn)(className, "base"), !!invalidMessage && "input-error", !!invalidMessage && (0, _utils_1.pcn)(className, "base", "error")), onFocus: (e) => {
32
+ props.onFocus?.(e);
33
+ inputHandler.setFocus(true);
34
+ }, inputMode: "none" }), (inputHandler.value) && ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("input-document-values", leftIcon ? "input-document-values-left-icon" : "input-document-values-no-icon"), style: { maxWidth: `calc(100% - ${leftIcon ? "5.2rem" : "2rem"})` }, onClick: () => {
35
+ inputHandler.setFocus(true);
36
+ }, children: (Array.isArray(inputHandler.value) ? inputHandler.value : []).map((f) => {
37
+ return ((0, jsx_runtime_1.jsxs)("span", { className: "input-document-value-item", children: [(0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: DocumentViewerIcon(f.file.name.split(".").pop()?.toLowerCase()), className: "text-light-foreground" }), (0, jsx_runtime_1.jsx)("span", { className: "line-clamp-1", children: f.file.name })] }, f.id));
38
+ }) })), leftIcon && ((0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { className: (0, _utils_1.cn)("input-icon", "input-icon-left", props.disabled && "input-icon-disabled", inputHandler.focus && "input-icon-focus", (0, _utils_1.pcn)(className, "icon"), props.disabled && (0, _utils_1.pcn)(className, "icon", "disabled"), inputHandler.focus && (0, _utils_1.pcn)(className, "icon", "focus")), icon: leftIcon })), rightIcon && ((0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { className: (0, _utils_1.cn)("input-icon", "input-icon-right", props.disabled && "input-icon-disabled", inputHandler.focus && "input-icon-focus", (0, _utils_1.pcn)(className, "icon"), props.disabled && (0, _utils_1.pcn)(className, "icon", "disabled"), inputHandler.focus && (0, _utils_1.pcn)(className, "icon", "focus")), icon: rightIcon }))] }), invalidMessage && (0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-error-message", (0, _utils_1.pcn)(className, "error")), children: invalidMessage })] }), !isSm ? ((0, jsx_runtime_1.jsx)(_components_1.FloatingPageComponent, { show: inputHandler.focus, onClose: () => inputHandler.setFocus(false), title: label, footer: (0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { label: "Selesai", variant: "outline", onClick: () => inputHandler.setFocus(false), block: true }), children: (0, jsx_runtime_1.jsx)(exports.InputDocumentPicker, { value: inputHandler.value, onChange: (e) => {
39
+ inputHandler.setValue(e);
40
+ if (inputHandler.idle)
41
+ inputHandler.setIdle(false);
42
+ onChange?.(e);
43
+ } }) })) : ((0, jsx_runtime_1.jsx)(_components_1.BottomSheetComponent, { show: inputHandler.focus, onClose: () => inputHandler.setFocus(false), size: '98vh', footer: (0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { label: "Selesai", variant: "outline", onClick: () => inputHandler.setFocus(false), block: true }), children: (0, jsx_runtime_1.jsx)(exports.InputDocumentPicker, { value: inputHandler.value, onChange: (e) => {
44
+ inputHandler.setValue(e);
45
+ if (inputHandler.idle)
46
+ inputHandler.setIdle(false);
47
+ onChange?.(e);
48
+ } }) }))] }));
49
+ }
50
+ const InputDocumentPicker = ({ value, onChange }) => {
51
+ const { isSm } = (0, _utils_1.useResponsive)();
52
+ const fileInputRef = (0, react_1.useRef)(null);
53
+ const [previewActive, setPreviewActive] = (0, react_1.useState)(null);
54
+ const files = Array.isArray(value) ? value : [];
55
+ function updateFiles(next) {
56
+ onChange?.(next);
57
+ }
58
+ function handleFilePick(e) {
59
+ const picked = e.target.files;
60
+ if (!picked)
61
+ return;
62
+ const next = [...files];
63
+ Array.from(picked).forEach((f) => {
64
+ const id = Math.random().toString(36).substring(7);
65
+ next.push({
66
+ id,
67
+ file: f,
68
+ url: URL.createObjectURL(f),
69
+ type: f.type,
70
+ });
71
+ if (!previewActive)
72
+ setPreviewActive(id);
73
+ });
74
+ updateFiles(next);
75
+ e.target.value = "";
76
+ }
77
+ function removeFile(id) {
78
+ const next = files.filter((x) => x.id !== id);
79
+ updateFiles(next);
80
+ if (previewActive === id) {
81
+ setPreviewActive(next[0]?.id || null);
82
+ }
83
+ }
84
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsxs)("div", { className: "p-4 flex flex-col gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "input-document-dropzone", children: files.find((x) => x.id === previewActive)?.file ? ((0, jsx_runtime_1.jsx)(DocumentViewerComponent, { file: files.find((x) => x.id === previewActive)?.file })) : ((0, jsx_runtime_1.jsxs)("div", { className: "input-document-empty-box", onClick: () => fileInputRef.current?.click(), children: [(0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: free_solid_svg_icons_1.faPlus, className: "text-3xl" }), (0, jsx_runtime_1.jsx)("p", { className: "text-lg", children: "Tambah Dokumen" })] })) }), (0, jsx_runtime_1.jsx)("input", { ref: fileInputRef, type: "file", multiple: true, className: "hidden", onChange: handleFilePick }), (0, jsx_runtime_1.jsx)("div", { className: "input-document-thumbs-container", children: (0, jsx_runtime_1.jsxs)("div", { className: "input-document-thumbs-grid", children: [files.map((f) => {
85
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("input-document-thumb-wrapper", previewActive === f.id && "input-document-thumb-wrapper-active"), onClick: () => setPreviewActive(f.id), children: [(0, jsx_runtime_1.jsx)(DocumentViewerComponent, { file: f.file, mode: "thumb" }), (0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { icon: free_solid_svg_icons_1.faTimes, onClick: () => removeFile(f.id), variant: "light", paint: "danger", className: "absolute top-2 right-2", size: isSm ? "xs" : "sm" })] }, f.id));
86
+ }), (0, jsx_runtime_1.jsxs)("div", { className: "input-document-upload-box", onClick: () => fileInputRef.current?.click(), children: [(0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: free_solid_svg_icons_1.faPlus }), (0, jsx_runtime_1.jsx)("p", { className: "text-[10px] text-center", children: "Tambah Dokumen" })] })] }) })] }) }));
87
+ };
88
+ exports.InputDocumentPicker = InputDocumentPicker;
@@ -0,0 +1,23 @@
1
+ import { ValidationRules } from "@utils";
2
+ export interface InputImageProps {
3
+ name: string;
4
+ label?: string;
5
+ tip?: string;
6
+ value?: string | File;
7
+ aspect?: string;
8
+ invalid?: string;
9
+ disabled?: boolean;
10
+ validations?: ValidationRules;
11
+ onChange?: (file?: File | null) => void;
12
+ register?: (name: string, validations?: ValidationRules) => void;
13
+ unregister?: (name: string) => void;
14
+ className?: string;
15
+ }
16
+ export declare const InputImageComponent: React.FC<InputImageProps>;
17
+ interface CropperProps {
18
+ src: string;
19
+ aspect: number;
20
+ onDone?: (file: File) => void;
21
+ }
22
+ export declare const CanvasCropper: React.FC<CropperProps>;
23
+ export {};
@@ -0,0 +1,260 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.CanvasCropper = exports.InputImageComponent = void 0;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("react");
7
+ const react_fontawesome_1 = require("@fortawesome/react-fontawesome");
8
+ const free_solid_svg_icons_1 = require("@fortawesome/free-solid-svg-icons");
9
+ const _utils_1 = require("@utils");
10
+ const _components_1 = require("@components");
11
+ const InputImageComponent = ({ name, label, tip, value, disabled, aspect = "1/1", invalid, validations, onChange, register, unregister, className = "", }) => {
12
+ const { isSm } = (0, _utils_1.useResponsive)();
13
+ const randomId = (0, _utils_1.useInputRandomId)();
14
+ const inputRef = (0, react_1.useRef)(null);
15
+ const [preview, setPreview] = (0, react_1.useState)("");
16
+ const [drag, setDrag] = (0, react_1.useState)(false);
17
+ const [cropSrc, setCropSrc] = (0, react_1.useState)(null);
18
+ const [openCrop, setOpenCrop] = (0, react_1.useState)(false);
19
+ const inputHandler = (0, _utils_1.useInputHandler)(name, value, validations, register, unregister, true);
20
+ const [invalidMessage, setInvalidMessage] = (0, _utils_1.useValidation)(inputHandler.value, validations, invalid, inputHandler.idle);
21
+ (0, react_1.useEffect)(() => {
22
+ if (value) {
23
+ const url = typeof value === "object" ? URL.createObjectURL(value) : value;
24
+ setPreview(url);
25
+ return () => {
26
+ typeof value === "object" && URL.revokeObjectURL(url);
27
+ };
28
+ }
29
+ else {
30
+ setPreview("");
31
+ }
32
+ }, [value]);
33
+ const openCropper = (file) => {
34
+ const reader = new FileReader();
35
+ reader.onload = () => {
36
+ setCropSrc(reader.result);
37
+ setOpenCrop(true);
38
+ };
39
+ reader.readAsDataURL(file);
40
+ };
41
+ const onUpload = (e) => {
42
+ const file = e.target.files?.[0];
43
+ if (!file)
44
+ return;
45
+ const allowed = ["image/jpeg", "image/jpg", "image/png", "image/webp"];
46
+ if (!allowed.includes(file.type)) {
47
+ setInvalidMessage("Format gambar tidak diperbolehkan (JPG/PNG/WebP)");
48
+ return;
49
+ }
50
+ openCropper(file);
51
+ };
52
+ const onCropDone = (file) => {
53
+ const url = URL.createObjectURL(file);
54
+ setPreview(url);
55
+ onChange?.(file);
56
+ setOpenCrop(false);
57
+ };
58
+ const onCropCancel = () => {
59
+ setOpenCrop(false);
60
+ inputRef.current.value = "";
61
+ };
62
+ const remove = () => {
63
+ setPreview("");
64
+ onChange?.(null);
65
+ inputRef.current && (inputRef.current.value = "");
66
+ };
67
+ const onDropFile = (e) => {
68
+ e.preventDefault();
69
+ setDrag(false);
70
+ const file = e.dataTransfer.files?.[0];
71
+ file && openCropper(file);
72
+ };
73
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "input-container w-full", children: [label && ((0, jsx_runtime_1.jsxs)("label", { htmlFor: randomId, className: (0, _utils_1.cn)("input-label", disabled && "input-label-disabled", inputHandler.focus && "input-label-focus", !!invalidMessage && "input-label-error", (0, _utils_1.pcn)(className, "label")), children: [label, validations && _utils_1.validation.hasRules(validations, "required") && (0, jsx_runtime_1.jsx)("span", { className: "text-danger ml-1", children: "*" })] })), tip && ((0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-tip", disabled && "input-tip-disabled", (0, _utils_1.pcn)(className, "tip")), children: tip })), (0, jsx_runtime_1.jsx)("label", { htmlFor: randomId, children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("input-image-dropzone", drag ? "input-image-dropzone-drag" : "", invalidMessage && "input-image-dropzone-error", (0, _utils_1.pcn)(className, "input")), style: {
74
+ aspectRatio: aspect,
75
+ backgroundImage: preview ? `url(${preview})` : undefined,
76
+ backgroundSize: "cover",
77
+ backgroundPosition: "center",
78
+ }, onDragOver: (e) => e.preventDefault(), onDragEnter: (e) => {
79
+ e.preventDefault();
80
+ setDrag(true);
81
+ }, onDragLeave: () => setDrag(false), onDrop: onDropFile, children: [(0, jsx_runtime_1.jsxs)("div", { className: "input-image-dropzone-content", children: [(0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: drag ? free_solid_svg_icons_1.faHandHolding : free_solid_svg_icons_1.faImages, className: "text-3xl" }), (0, jsx_runtime_1.jsx)("p", { className: "input-image-dropzone-text", children: drag ? "Letakkan di sini" : preview ? "Klik atau seret untuk ganti Gambar" : "Klik atau seret gambar" })] }), (0, jsx_runtime_1.jsx)("input", { id: randomId, ref: inputRef, type: "file", accept: "image/*", className: "hidden", disabled: disabled, onChange: onUpload })] }) }), preview && !disabled && ((0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { icon: free_solid_svg_icons_1.faTimes, paint: "danger", size: "sm", className: "absolute top-10 right-4", onClick: remove })), invalidMessage && ((0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-error-message", (0, _utils_1.pcn)(className, "error")), children: invalidMessage })), !isSm ? ((0, jsx_runtime_1.jsx)(_components_1.ModalComponent, { show: openCrop, onClose: onCropCancel, title: "Sesuaikan Gambar", className: "w-max max-w-[350px]", children: cropSrc && ((0, jsx_runtime_1.jsx)("div", { className: "p-4", children: (0, jsx_runtime_1.jsx)(exports.CanvasCropper, { src: cropSrc, aspect: eval(aspect.replace(":", "/")), onDone: onCropDone }) })) })) : ((0, jsx_runtime_1.jsx)(_components_1.BottomSheetComponent, { show: openCrop, onClose: onCropCancel, size: 400, children: cropSrc && ((0, jsx_runtime_1.jsx)("div", { className: "p-4", children: (0, jsx_runtime_1.jsx)(exports.CanvasCropper, { src: cropSrc, aspect: eval(aspect.replace(":", "/")), onDone: onCropDone }) })) }))] }));
82
+ };
83
+ exports.InputImageComponent = InputImageComponent;
84
+ const CanvasCropper = ({ src, aspect, onDone, }) => {
85
+ const canvasRef = (0, react_1.useRef)(null);
86
+ const previewRef = (0, react_1.useRef)(null);
87
+ const pinchDistRef = (0, react_1.useRef)(0);
88
+ const pinchStartZoomRef = (0, react_1.useRef)(1);
89
+ const [img, setImg] = (0, react_1.useState)(null);
90
+ const [zoom, setZoom] = (0, react_1.useState)(1);
91
+ const [minZoom, setMinZoom] = (0, react_1.useState)(1);
92
+ const [maxZoom, setMaxZoom] = (0, react_1.useState)(4);
93
+ const [pos, setPos] = (0, react_1.useState)({ x: 0, y: 0 });
94
+ const [dragging, setDragging] = (0, react_1.useState)(false);
95
+ const [start, setStart] = (0, react_1.useState)({ x: 0, y: 0 });
96
+ const CROP_SIZE = 280;
97
+ const CROP_W = CROP_SIZE * aspect;
98
+ const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
99
+ (0, react_1.useEffect)(() => {
100
+ const i = new Image();
101
+ i.onload = () => setImg(i);
102
+ i.src = src;
103
+ }, [src]);
104
+ const renderCanvas = () => {
105
+ if (!img)
106
+ return;
107
+ const canvas = canvasRef.current;
108
+ const ctx = canvas.getContext("2d");
109
+ canvas.width = CROP_W;
110
+ canvas.height = CROP_SIZE;
111
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
112
+ const scaledW = img.width * zoom;
113
+ const scaledH = img.height * zoom;
114
+ const x = pos.x - scaledW / 2 + CROP_W / 2;
115
+ const y = pos.y - scaledH / 2 + CROP_SIZE / 2;
116
+ ctx.drawImage(img, x, y, scaledW, scaledH);
117
+ };
118
+ (0, react_1.useEffect)(() => {
119
+ renderCanvas();
120
+ }, [img, zoom, pos]);
121
+ (0, react_1.useEffect)(() => {
122
+ if (!img)
123
+ return;
124
+ const imgW = img.naturalWidth;
125
+ const imgH = img.naturalHeight;
126
+ const scaleW = CROP_W / imgW;
127
+ const scaleH = CROP_SIZE / imgH;
128
+ const base = Math.max(scaleW, scaleH);
129
+ setMinZoom(base);
130
+ setZoom(base);
131
+ setMaxZoom(base * 4);
132
+ }, [img]);
133
+ const handleDown = (e) => {
134
+ setDragging(true);
135
+ setStart({ x: e.clientX, y: e.clientY });
136
+ };
137
+ const handleUp = () => setDragging(false);
138
+ const handleMove = (e) => {
139
+ if (!dragging)
140
+ return;
141
+ const dx = e.clientX - start.x;
142
+ const dy = e.clientY - start.y;
143
+ setStart({ x: e.clientX, y: e.clientY });
144
+ setPos((p) => {
145
+ const scaledW = img.naturalWidth * zoom;
146
+ const scaledH = img.naturalHeight * zoom;
147
+ const minX = (scaledW - CROP_W) / 2;
148
+ const maxX = -(scaledW - CROP_W) / 2;
149
+ const minY = (scaledH - CROP_SIZE) / 2;
150
+ const maxY = -(scaledH - CROP_SIZE) / 2;
151
+ return {
152
+ x: clamp(p.x + dx, maxX, minX),
153
+ y: clamp(p.y + dy, maxY, minY),
154
+ };
155
+ });
156
+ };
157
+ const performCrop = () => {
158
+ if (!img)
159
+ return;
160
+ const preview = previewRef.current;
161
+ const pctx = preview.getContext("2d");
162
+ preview.width = CROP_W;
163
+ preview.height = CROP_SIZE;
164
+ const scaledW = img.width * zoom;
165
+ const scaledH = img.height * zoom;
166
+ const x = pos.x - scaledW / 2 + CROP_W / 2;
167
+ const y = pos.y - scaledH / 2 + CROP_SIZE / 2;
168
+ pctx.drawImage(img, x, y, scaledW, scaledH);
169
+ preview.toBlob((blob) => {
170
+ const file = new File([blob], "cropped.png", { type: "image/png" });
171
+ onDone?.(file);
172
+ });
173
+ };
174
+ const handleWheel = (e) => {
175
+ e.preventDefault();
176
+ setZoom((z) => {
177
+ let next = z - e.deltaY * 0.002;
178
+ next = Math.max(minZoom, Math.min(maxZoom, next));
179
+ const scaledW = img.naturalWidth * next;
180
+ const scaledH = img.naturalHeight * next;
181
+ const minX = (scaledW - CROP_W) / 2;
182
+ const maxX = -(scaledW - CROP_W) / 2;
183
+ const minY = (scaledH - CROP_SIZE) / 2;
184
+ const maxY = -(scaledH - CROP_SIZE) / 2;
185
+ setPos((p) => ({
186
+ x: clamp(p.x, maxX, minX),
187
+ y: clamp(p.y, maxY, minY),
188
+ }));
189
+ return next;
190
+ });
191
+ };
192
+ const handleTouchStart = (e) => {
193
+ if (e.touches.length === 2) {
194
+ const t1 = e.touches[0];
195
+ const t2 = e.touches[1];
196
+ const dist = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY);
197
+ pinchDistRef.current = dist;
198
+ pinchStartZoomRef.current = zoom;
199
+ e.preventDefault();
200
+ }
201
+ // Jika satu jari → drag
202
+ if (e.touches.length === 1) {
203
+ setDragging(true);
204
+ setStart({
205
+ x: e.touches[0].clientX,
206
+ y: e.touches[0].clientY,
207
+ });
208
+ }
209
+ };
210
+ const handleTouchMove = (e) => {
211
+ if (e.touches.length === 2) {
212
+ const t1 = e.touches[0];
213
+ const t2 = e.touches[1];
214
+ const currDist = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY);
215
+ const diff = currDist - pinchDistRef.current;
216
+ let nextZoom = pinchStartZoomRef.current + diff * 0.005;
217
+ nextZoom = Math.max(minZoom, Math.min(maxZoom, nextZoom));
218
+ setZoom(nextZoom);
219
+ setPos((p) => {
220
+ const scaledW = img.naturalWidth * nextZoom;
221
+ const scaledH = img.naturalHeight * nextZoom;
222
+ const minX = (scaledW - CROP_W) / 2;
223
+ const maxX = -(scaledW - CROP_W) / 2;
224
+ const minY = (scaledH - CROP_SIZE) / 2;
225
+ const maxY = -(scaledH - CROP_SIZE) / 2;
226
+ return {
227
+ x: Math.max(maxX, Math.min(minX, p.x)),
228
+ y: Math.max(maxY, Math.min(minY, p.y)),
229
+ };
230
+ });
231
+ e.preventDefault();
232
+ return;
233
+ }
234
+ if (dragging && e.touches.length === 1) {
235
+ const { clientX, clientY } = e.touches[0];
236
+ const dx = clientX - start.x;
237
+ const dy = clientY - start.y;
238
+ setStart({ x: clientX, y: clientY });
239
+ setPos((p) => {
240
+ const scaledW = img.naturalWidth * zoom;
241
+ const scaledH = img.naturalHeight * zoom;
242
+ const minX = (scaledW - CROP_W) / 2;
243
+ const maxX = -(scaledW - CROP_W) / 2;
244
+ const minY = (scaledH - CROP_SIZE) / 2;
245
+ const maxY = -(scaledH - CROP_SIZE) / 2;
246
+ return {
247
+ x: Math.max(maxX, Math.min(minX, p.x + dx)),
248
+ y: Math.max(maxY, Math.min(minY, p.y + dy)),
249
+ };
250
+ });
251
+ e.preventDefault();
252
+ }
253
+ };
254
+ const handleTouchEnd = () => {
255
+ setDragging(false);
256
+ pinchDistRef.current = 0;
257
+ };
258
+ return ((0, jsx_runtime_1.jsxs)("div", { style: { touchAction: "none" }, children: [(0, jsx_runtime_1.jsxs)("div", { className: "input-image-cropper-wrapper", style: { width: CROP_W, height: CROP_SIZE }, onMouseMove: handleMove, onMouseUp: handleUp, onMouseLeave: handleUp, onWheel: handleWheel, onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, children: [(0, jsx_runtime_1.jsx)("canvas", { ref: canvasRef, width: CROP_W, height: CROP_SIZE, onMouseDown: handleDown, className: "cursor-move" }), (0, jsx_runtime_1.jsxs)("div", { className: "input-image-cropper-grid-container", style: { width: CROP_W, height: CROP_SIZE }, children: [(0, jsx_runtime_1.jsx)("div", { className: "input-image-cropper-grid-border" }), (0, jsx_runtime_1.jsxs)("div", { className: "absolute inset-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "input-image-cropper-grid-line-h input-image-cropper-grid-line-h-1" }), (0, jsx_runtime_1.jsx)("div", { className: "input-image-cropper-grid-line-h input-image-cropper-grid-line-h-2" }), (0, jsx_runtime_1.jsx)("div", { className: "input-image-cropper-grid-line-v input-image-cropper-grid-line-v-1" }), (0, jsx_runtime_1.jsx)("div", { className: "input-image-cropper-grid-line-v input-image-cropper-grid-line-v-2" })] })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "p-4 pb-2", children: (0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { label: "Selesai", variant: "outline", onClick: performCrop, block: true }) }), (0, jsx_runtime_1.jsx)("canvas", { ref: previewRef, className: "hidden" })] }));
259
+ };
260
+ exports.CanvasCropper = CanvasCropper;
@@ -0,0 +1,25 @@
1
+ import { ValidationRules } from "@utils";
2
+ export interface ValueMapProps {
3
+ lat: number | null;
4
+ lng: number | null;
5
+ address?: string;
6
+ }
7
+ export interface InputMapProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange"> {
8
+ label?: string;
9
+ tip?: string | React.ReactNode;
10
+ leftIcon?: any;
11
+ rightIcon?: any;
12
+ value?: any;
13
+ invalid?: string;
14
+ validations?: ValidationRules;
15
+ onChange?: (value: any) => any;
16
+ register?: (name: string, validations?: ValidationRules) => void;
17
+ unregister?: (name: string) => void;
18
+ className?: string;
19
+ }
20
+ export declare function InputMapComponent({ label, tip, leftIcon, rightIcon, value, invalid, validations, register, unregister, onChange, className, ...props }: InputMapProps): import("react").JSX.Element;
21
+ export interface MapPickerProps {
22
+ value?: any;
23
+ onChange?: (value: any) => any;
24
+ }
25
+ export declare const InputMapPickerComponent: React.FC<MapPickerProps>;
@@ -0,0 +1,103 @@
1
+ "use client";
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.InputMapPickerComponent = void 0;
8
+ exports.InputMapComponent = InputMapComponent;
9
+ const jsx_runtime_1 = require("react/jsx-runtime");
10
+ const react_1 = require("react");
11
+ const axios_1 = __importDefault(require("axios"));
12
+ const react_fontawesome_1 = require("@fortawesome/react-fontawesome");
13
+ const free_solid_svg_icons_1 = require("@fortawesome/free-solid-svg-icons");
14
+ const api_1 = require("@react-google-maps/api");
15
+ const LoadScriptComponent = api_1.LoadScript;
16
+ const GoogleMapComponent = api_1.GoogleMap;
17
+ const _utils_1 = require("@utils");
18
+ const _components_1 = require("@components");
19
+ function InputMapComponent({ label, tip, leftIcon, rightIcon, value, invalid, validations, register, unregister, onChange, className = "", ...props }) {
20
+ const { isSm } = (0, _utils_1.useResponsive)();
21
+ // =========================>
22
+ // ## Invalid handler
23
+ // =========================>
24
+ const inputHandler = (0, _utils_1.useInputHandler)(props.name, value, validations, register, unregister, false);
25
+ const randomId = (0, _utils_1.useInputRandomId)();
26
+ // =========================>
27
+ // ## Invalid handler
28
+ // =========================>
29
+ const [invalidMessage] = (0, _utils_1.useValidation)(inputHandler.value, validations, invalid, inputHandler.idle);
30
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "input-container", children: [label && ((0, jsx_runtime_1.jsxs)("label", { htmlFor: randomId, className: (0, _utils_1.cn)("input-label", props.disabled && "input-label-disabled", inputHandler.focus && "input-label-focus", !!invalidMessage && "input-label-error", (0, _utils_1.pcn)(className, "label")), children: [label, validations && _utils_1.validation.hasRules(validations, "required") && (0, jsx_runtime_1.jsx)("span", { className: "text-danger ml-1", children: "*" })] })), tip && ((0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-tip", props.disabled && "input-tip-disabled", (0, _utils_1.pcn)(className, "tip")), children: tip })), (0, jsx_runtime_1.jsx)(_components_1.OutsideClickComponent, { onOutsideClick: !isSm ? () => inputHandler.setFocus(false) : undefined, children: (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)("input", { ...props, id: randomId, className: (0, _utils_1.cn)("input", leftIcon && "input-with-left-icon", rightIcon && "input-with-right-icon", (0, _utils_1.pcn)(className, "input"), !!invalidMessage && "input-error"), value: inputHandler.value?.address || "", readOnly: true, onFocus: (e) => {
31
+ props.onFocus?.(e);
32
+ inputHandler.setFocus(true);
33
+ inputHandler.setIdle(false);
34
+ }, autoComplete: "off" }), leftIcon && ((0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { className: (0, _utils_1.cn)("input-icon", "input-icon-left", props.disabled && "input-icon-disabled", inputHandler.focus && "input-icon-focus", (0, _utils_1.pcn)(className, "icon")), icon: leftIcon })), rightIcon && ((0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { className: (0, _utils_1.cn)("input-icon", "input-icon-right", props.disabled && "input-icon-disabled", inputHandler.focus && "input-icon-focus", (0, _utils_1.pcn)(className, "icon")), icon: rightIcon })), !isSm && inputHandler.focus && ((0, jsx_runtime_1.jsx)("div", { className: "input-map-suggest-container", style: { height: 300 }, children: (0, jsx_runtime_1.jsx)(exports.InputMapPickerComponent, { value: inputHandler.value, onChange: (e) => {
35
+ inputHandler.setValue(e);
36
+ onChange?.(e);
37
+ } }) }))] }) }), invalidMessage && ((0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-error-message", (0, _utils_1.pcn)(className, "error")), children: invalidMessage }))] }), isSm && ((0, jsx_runtime_1.jsx)(_components_1.BottomSheetComponent, { show: inputHandler.focus, onClose: () => inputHandler.setFocus(false), size: 450, footer: (0, jsx_runtime_1.jsx)("div", { className: "p-4", children: (0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { label: "Selesai", variant: "outline", onClick: () => inputHandler.setFocus(false), block: true }) }), children: (0, jsx_runtime_1.jsx)("div", { className: "p-4", children: (0, jsx_runtime_1.jsx)(exports.InputMapPickerComponent, { onChange: (e) => {
38
+ inputHandler.setValue(e);
39
+ onChange?.(e);
40
+ } }) }) }))] }));
41
+ }
42
+ const InputMapPickerComponent = ({ onChange, value }) => {
43
+ const mapRef = (0, react_1.useRef)(null);
44
+ const [addressLoading, setAddressLoading] = (0, react_1.useState)(false);
45
+ const [drag, setDrag] = (0, react_1.useState)(false);
46
+ // =========================>
47
+ // ## Map Events
48
+ // =========================>
49
+ const setCurrentPosition = () => {
50
+ if (navigator.geolocation) {
51
+ navigator.geolocation.getCurrentPosition((pos) => {
52
+ const newPos = {
53
+ lat: pos.coords.latitude,
54
+ lng: pos.coords.longitude,
55
+ address: "",
56
+ };
57
+ onChange?.(newPos);
58
+ mapRef.current?.panTo(new google.maps.LatLng(newPos.lat, newPos.lng));
59
+ });
60
+ }
61
+ };
62
+ const handleDragEnd = (0, react_1.useCallback)(() => {
63
+ if (mapRef.current) {
64
+ const center = mapRef.current.getCenter();
65
+ if (center) {
66
+ onChange?.({
67
+ lat: center.lat(),
68
+ lng: center.lng(),
69
+ address: "",
70
+ });
71
+ }
72
+ setDrag(false);
73
+ }
74
+ }, []);
75
+ // =========================>
76
+ // ## Reverse Geocode
77
+ // =========================>
78
+ (0, react_1.useEffect)(() => {
79
+ if (value?.lat && value?.lng) {
80
+ setAddressLoading(true);
81
+ onChange?.((prev) => ({ ...prev, address: "" }));
82
+ axios_1.default.get(`https://api.geoapify.com/v1/geocode/reverse?lat=${value?.lat}&lon=${value?.lng}&apiKey=${process.env.NEXT_PUBLIC_GEOAPIFY_KEY}`)
83
+ .then((res) => {
84
+ if (res.status === 200 && !res.data.error) {
85
+ const data = res.data.features?.at(0)?.properties;
86
+ const address = (data?.address_line1 || "") + " " + (data?.address_line2 || "");
87
+ onChange?.((prev) => ({ ...prev, address }));
88
+ onChange?.({ ...value, address });
89
+ }
90
+ })
91
+ .finally(() => setAddressLoading(false));
92
+ }
93
+ }, [value?.lat, value?.lng]);
94
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "relative w-full", children: [(0, jsx_runtime_1.jsx)(LoadScriptComponent, { googleMapsApiKey: process.env.NEXT_PUBLIC_MAP_KEY || "", children: (0, jsx_runtime_1.jsx)(GoogleMapComponent, { mapContainerStyle: { width: "100%", height: "100%" }, center: {
95
+ lat: value?.lat || -6.208,
96
+ lng: value?.lng || 106.689,
97
+ }, zoom: 18, options: {
98
+ streetViewControl: false,
99
+ mapTypeControl: false,
100
+ fullscreenControl: false,
101
+ }, onLoad: (map) => { mapRef.current = map; }, onDrag: () => setDrag(true), onDragEnd: handleDragEnd }) }), (0, jsx_runtime_1.jsx)("div", { className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none", children: (0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: free_solid_svg_icons_1.faLocationDot, className: (0, _utils_1.cn)("input-map-marker", drag && "input-map-marker-drag") }) }), (0, jsx_runtime_1.jsx)("div", { className: "input-map-badge-left", children: addressLoading && !value?.address ? ((0, jsx_runtime_1.jsx)("div", { className: "py-4 w-[200px]" })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-sm", children: value?.address })) }), (0, jsx_runtime_1.jsx)("div", { className: "input-map-badge-right", onClick: () => setCurrentPosition(), children: (0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: free_solid_svg_icons_1.faLocationCrosshairs, className: "text-lg" }) })] }));
102
+ };
103
+ exports.InputMapPickerComponent = InputMapPickerComponent;
@@ -0,0 +1,19 @@
1
+ import { InputHTMLAttributes, ReactNode } from "react";
2
+ import { ValidationRules } from "@utils";
3
+ export interface InputNumberProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "onChange"> {
4
+ label?: string;
5
+ tip?: string | ReactNode;
6
+ leftIcon?: any;
7
+ rightIcon?: any;
8
+ value?: number;
9
+ invalid?: string;
10
+ validations?: ValidationRules;
11
+ min?: number;
12
+ max?: number;
13
+ onChange?: (value: number) => any;
14
+ register?: (name: string, validations?: ValidationRules) => void;
15
+ unregister?: (name: string) => void;
16
+ /** Use custom class with: "label::", "tip::", "error::", "icon::", "suggest::", "suggest-item::". */
17
+ className?: string;
18
+ }
19
+ export declare function InputNumberComponent({ label, tip, leftIcon, rightIcon, value, invalid, validations, min, max, onChange, register, unregister, className, ...props }: InputNumberProps): import("react").JSX.Element;
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.InputNumberComponent = InputNumberComponent;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_fontawesome_1 = require("@fortawesome/react-fontawesome");
7
+ const free_solid_svg_icons_1 = require("@fortawesome/free-solid-svg-icons");
8
+ const _utils_1 = require("@utils");
9
+ function InputNumberComponent({ label, tip, leftIcon, rightIcon, value, invalid, validations, min, max, onChange, register, unregister, className = "", ...props }) {
10
+ // =========================>
11
+ // ## Initial
12
+ // =========================>
13
+ const inputHandler = (0, _utils_1.useInputHandler)(props.name, value, validations, register, unregister, false);
14
+ const randomId = (0, _utils_1.useInputRandomId)();
15
+ // =========================>
16
+ // ## Invalid handler
17
+ // =========================>
18
+ const [invalidMessage] = (0, _utils_1.useValidation)(inputHandler.value, validations, invalid, inputHandler.idle);
19
+ // =========================>
20
+ // ## Change value handler
21
+ // =========================>
22
+ const handleInputChange = (e) => {
23
+ const newValue = e.target.value;
24
+ const regex = /^-?\d*\.?\d*$/;
25
+ if (regex.test(newValue)) {
26
+ inputHandler.setValue(newValue);
27
+ inputHandler.setIdle(false);
28
+ onChange?.(Number(newValue));
29
+ }
30
+ };
31
+ const handleBlur = (e) => {
32
+ props.onBlur?.(e);
33
+ setTimeout(() => inputHandler.setFocus(false), 100);
34
+ };
35
+ const handleFocus = (e) => {
36
+ props.onFocus?.(e);
37
+ inputHandler.setFocus(true);
38
+ };
39
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsxs)("div", { className: "input-container", children: [(0, jsx_runtime_1.jsxs)("label", { htmlFor: randomId, className: (0, _utils_1.cn)("input-label", props.disabled && "input-label-disabled", inputHandler.focus && "input-label-focus", !!invalidMessage && "input-label-error", (0, _utils_1.pcn)(className, "label"), props.disabled && (0, _utils_1.pcn)(className, "label", "disabled"), inputHandler.focus && (0, _utils_1.pcn)(className, "label", "focus"), !!invalidMessage && (0, _utils_1.pcn)(className, "label", "focus")), children: [label, validations && _utils_1.validation.hasRules(validations, "required") && (0, jsx_runtime_1.jsx)("span", { className: "text-danger ml-1", children: "*" })] }), tip && ((0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-tip", props.disabled && "input-tip-disabled", (0, _utils_1.pcn)(className, "tip"), props.disabled && (0, _utils_1.pcn)(className, "tip", "disabled")), children: tip })), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)("input", { ...props, id: randomId, className: (0, _utils_1.cn)("input", leftIcon && "input-with-left-icon", rightIcon && "input-with-right-icon", (0, _utils_1.pcn)(className, "input"), !!invalidMessage && "input-error", !!invalidMessage && (0, _utils_1.pcn)(className, "input", "error")), value: inputHandler.value, onChange: handleInputChange, onFocus: handleFocus, onBlur: handleBlur, autoComplete: "off", min: min, max: max }), leftIcon && ((0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { className: (0, _utils_1.cn)("input-icon", "input-icon-left", props.disabled && "input-icon-disabled", inputHandler.focus && "input-icon-focus", (0, _utils_1.pcn)(className, "icon"), props.disabled && (0, _utils_1.pcn)(className, "icon", "disabled"), inputHandler.focus && (0, _utils_1.pcn)(className, "icon", "focus")), icon: leftIcon })), (0, jsx_runtime_1.jsx)("label", { htmlFor: randomId, className: (0, _utils_1.cn)("input-icon", "input-icon-right", props.disabled && "input-icon-disabled", inputHandler.focus && "input-icon-focus", (0, _utils_1.pcn)(className, "icon"), props.disabled && (0, _utils_1.pcn)(className, "icon", "disabled"), inputHandler.focus && (0, _utils_1.pcn)(className, "icon", "focus")), children: (0, jsx_runtime_1.jsxs)("div", { className: "input-number-sort-container", children: [(0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { className: "input-number-sort-up", icon: free_solid_svg_icons_1.faSortUp, onClick: () => inputHandler.setValue(String(Number(inputHandler.value) + 1)) }), (0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { className: "input-number-sort-down", icon: free_solid_svg_icons_1.faSortDown, onClick: () => inputHandler.setValue(String(Number(inputHandler.value) - 1)) })] }) })] }), invalidMessage && ((0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-error-message", (0, _utils_1.pcn)(className, "error")), children: invalidMessage }))] }) }));
40
+ }
@@ -0,0 +1,14 @@
1
+ import { FC, ReactNode } from "react";
2
+ export interface InputOtpProps {
3
+ label?: string;
4
+ tip?: string | ReactNode;
5
+ name: string;
6
+ disabled?: boolean;
7
+ value?: string;
8
+ invalid?: string;
9
+ length?: number;
10
+ onChange?: (value: string) => any;
11
+ /** Use custom class with: "label::", "tip::", "error::". */
12
+ className?: string;
13
+ }
14
+ export declare const InputOtpComponent: FC<InputOtpProps>;