@skalfa/skalfa-component 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accordion/Accordion.component.d.ts +1 -1
- package/dist/breadcrumb/Breadcrumb.component.d.ts +1 -1
- package/dist/button/Button.component.d.ts +1 -1
- package/dist/card/AlertCard.component.d.ts +1 -1
- package/dist/card/Card.component.d.ts +1 -1
- package/dist/card/DashboardCard.component.d.ts +1 -1
- package/dist/card/GalleryCard.component.d.ts +1 -1
- package/dist/card/ProductCard.component.d.ts +1 -1
- package/dist/card/ProfileCard.component.d.ts +1 -1
- package/dist/carousel/Carousel.component.d.ts +1 -1
- package/dist/chip/Chip.component.d.ts +1 -1
- package/dist/input/Checkbox.component.d.ts +1 -1
- package/dist/input/Input.component.d.ts +1 -1
- package/dist/input/InputCheckbox.component.d.ts +1 -1
- package/dist/input/InputCurrency.component.d.ts +1 -1
- package/dist/input/InputDate.component.d.ts +1 -1
- package/dist/input/InputDate.component.js +4 -4
- package/dist/input/InputDatetime.component.d.ts +1 -1
- package/dist/input/InputDocument.component.d.ts +1 -1
- package/dist/input/InputMap.component.d.ts +1 -1
- package/dist/input/InputNumber.component.d.ts +1 -1
- package/dist/input/InputPassword.component.d.ts +1 -1
- package/dist/input/InputRadio.component.d.ts +1 -1
- package/dist/input/InputTime.component.d.ts +1 -1
- package/dist/input/InputValues.component.d.ts +1 -1
- package/dist/input/Radio.component.d.ts +1 -1
- package/dist/input/Select.component.d.ts +1 -1
- package/dist/modal/FloatingPage.component.d.ts +1 -1
- package/dist/modal/Modal.component.d.ts +1 -1
- package/dist/modal/ModalConfirm.component.d.ts +1 -1
- package/dist/modal/Toast.component.d.ts +1 -1
- package/dist/nav/Bottombar.component.d.ts +1 -1
- package/dist/nav/Footer.component.d.ts +1 -1
- package/dist/nav/Headbar.component.d.ts +4 -11
- package/dist/nav/Headbar.component.js +3 -23
- package/dist/nav/Navbar.component.d.ts +1 -1
- package/dist/nav/Sidebar.component.d.ts +2 -2
- package/dist/nav/Tabbar.component.d.ts +1 -1
- package/dist/nav/Wizard.component.d.ts +1 -1
- package/dist/supervision/FormSupervision.component.d.ts +1 -1
- package/dist/supervision/TableSupervision.component.d.ts +1 -1
- package/dist/table/ControlBar.component.d.ts +1 -1
- package/dist/table/FilterComponent.d.ts +2 -2
- package/dist/table/Pagination.component.d.ts +1 -1
- package/dist/table/Table.component.d.ts +1 -1
- package/dist/typography/TypographyArticle.component.d.ts +1 -1
- package/dist/typography/TypographyColumn.component.d.ts +1 -1
- package/dist/typography/TypographyContent.component.d.ts +1 -1
- package/dist/typography/TypographyTips.component.d.ts +1 -1
- package/dist/wrap/Image.component.d.ts +1 -1
- package/dist/wrap/ScrollContainer.component.d.ts +1 -1
- package/dist/wrap/ShortcutProvider.d.ts +1 -1
- package/dist/wrap/Swipe.component.d.ts +1 -1
- package/package.json +2 -2
- package/dist/src/accordion/Accordion.component.d.ts +0 -13
- package/dist/src/accordion/Accordion.component.js +0 -25
- package/dist/src/breadcrumb/Breadcrumb.component.d.ts +0 -14
- package/dist/src/breadcrumb/Breadcrumb.component.js +0 -21
- package/dist/src/button/Button.component.d.ts +0 -21
- package/dist/src/button/Button.component.js +0 -19
- package/dist/src/card/AlertCard.component.d.ts +0 -11
- package/dist/src/card/AlertCard.component.js +0 -9
- package/dist/src/card/Card.component.d.ts +0 -5
- package/dist/src/card/Card.component.js +0 -9
- package/dist/src/card/DashboardCard.component.d.ts +0 -9
- package/dist/src/card/DashboardCard.component.js +0 -13
- package/dist/src/card/GalleryCard.component.d.ts +0 -7
- package/dist/src/card/GalleryCard.component.js +0 -13
- package/dist/src/card/ProductCard.component.d.ts +0 -9
- package/dist/src/card/ProductCard.component.js +0 -13
- package/dist/src/card/ProfileCard.component.d.ts +0 -10
- package/dist/src/card/ProfileCard.component.js +0 -13
- package/dist/src/carousel/Carousel.component.d.ts +0 -13
- package/dist/src/carousel/Carousel.component.js +0 -37
- package/dist/src/chip/Chip.component.d.ts +0 -6
- package/dist/src/chip/Chip.component.js +0 -12
- package/dist/src/index.d.ts +0 -13
- package/dist/src/index.js +0 -29
- package/dist/src/input/Checkbox.component.d.ts +0 -13
- package/dist/src/input/Checkbox.component.js +0 -23
- package/dist/src/input/Input.component.d.ts +0 -23
- package/dist/src/input/Input.component.js +0 -134
- package/dist/src/input/InputCheckbox.component.d.ts +0 -27
- package/dist/src/input/InputCheckbox.component.js +0 -53
- package/dist/src/input/InputCurrency.component.d.ts +0 -21
- package/dist/src/input/InputCurrency.component.js +0 -30
- package/dist/src/input/InputDate.component.d.ts +0 -24
- package/dist/src/input/InputDate.component.js +0 -107
- package/dist/src/input/InputDatetime.component.d.ts +0 -17
- package/dist/src/input/InputDatetime.component.js +0 -75
- package/dist/src/input/InputDocument.component.d.ts +0 -22
- package/dist/src/input/InputDocument.component.js +0 -88
- package/dist/src/input/InputImage.component.d.ts +0 -23
- package/dist/src/input/InputImage.component.js +0 -260
- package/dist/src/input/InputMap.component.d.ts +0 -25
- package/dist/src/input/InputMap.component.js +0 -101
- package/dist/src/input/InputNumber.component.d.ts +0 -19
- package/dist/src/input/InputNumber.component.js +0 -40
- package/dist/src/input/InputOtp.component.d.ts +0 -14
- package/dist/src/input/InputOtp.component.js +0 -65
- package/dist/src/input/InputPassword.component.d.ts +0 -17
- package/dist/src/input/InputPassword.component.js +0 -59
- package/dist/src/input/InputRadio.component.d.ts +0 -27
- package/dist/src/input/InputRadio.component.js +0 -56
- package/dist/src/input/InputTime.component.d.ts +0 -23
- package/dist/src/input/InputTime.component.js +0 -73
- package/dist/src/input/InputValues.component.d.ts +0 -9
- package/dist/src/input/InputValues.component.js +0 -19
- package/dist/src/input/Radio.component.d.ts +0 -12
- package/dist/src/input/Radio.component.js +0 -22
- package/dist/src/input/Select.component.d.ts +0 -47
- package/dist/src/input/Select.component.js +0 -275
- package/dist/src/modal/BottomSheet.component.d.ts +0 -12
- package/dist/src/modal/BottomSheet.component.js +0 -161
- package/dist/src/modal/FloatingPage.component.d.ts +0 -12
- package/dist/src/modal/FloatingPage.component.js +0 -27
- package/dist/src/modal/Modal.component.d.ts +0 -12
- package/dist/src/modal/Modal.component.js +0 -27
- package/dist/src/modal/ModalConfirm.component.d.ts +0 -26
- package/dist/src/modal/ModalConfirm.component.js +0 -68
- package/dist/src/modal/Toast.component.d.ts +0 -11
- package/dist/src/modal/Toast.component.js +0 -58
- package/dist/src/nav/Bottombar.component.d.ts +0 -12
- package/dist/src/nav/Bottombar.component.js +0 -32
- package/dist/src/nav/Footer.component.d.ts +0 -37
- package/dist/src/nav/Footer.component.js +0 -49
- package/dist/src/nav/Headbar.component.d.ts +0 -14
- package/dist/src/nav/Headbar.component.js +0 -32
- package/dist/src/nav/Navbar.component.d.ts +0 -22
- package/dist/src/nav/Navbar.component.js +0 -26
- package/dist/src/nav/Sidebar.component.d.ts +0 -33
- package/dist/src/nav/Sidebar.component.js +0 -87
- package/dist/src/nav/Tabbar.component.d.ts +0 -13
- package/dist/src/nav/Tabbar.component.js +0 -17
- package/dist/src/nav/Wizard.component.d.ts +0 -9
- package/dist/src/nav/Wizard.component.js +0 -24
- package/dist/src/supervision/FormSupervision.component.d.ts +0 -93
- package/dist/src/supervision/FormSupervision.component.js +0 -168
- package/dist/src/supervision/TableSupervision.component.d.ts +0 -78
- package/dist/src/supervision/TableSupervision.component.js +0 -273
- package/dist/src/table/ControlBar.component.d.ts +0 -34
- package/dist/src/table/ControlBar.component.js +0 -205
- package/dist/src/table/FilterComponent.d.ts +0 -45
- package/dist/src/table/FilterComponent.js +0 -132
- package/dist/src/table/Pagination.component.d.ts +0 -8
- package/dist/src/table/Pagination.component.js +0 -32
- package/dist/src/table/Table.component.d.ts +0 -61
- package/dist/src/table/Table.component.js +0 -101
- package/dist/src/typography/TypographyArticle.component.d.ts +0 -8
- package/dist/src/typography/TypographyArticle.component.js +0 -7
- package/dist/src/typography/TypographyColumn.component.d.ts +0 -6
- package/dist/src/typography/TypographyColumn.component.js +0 -7
- package/dist/src/typography/TypographyContent.component.d.ts +0 -6
- package/dist/src/typography/TypographyContent.component.js +0 -7
- package/dist/src/typography/TypographyTips.component.d.ts +0 -6
- package/dist/src/typography/TypographyTips.component.js +0 -7
- package/dist/src/wrap/Draggable.component.d.ts +0 -34
- package/dist/src/wrap/Draggable.component.js +0 -214
- package/dist/src/wrap/Image.component.d.ts +0 -2
- package/dist/src/wrap/Image.component.js +0 -13
- package/dist/src/wrap/OutsideClick.component.d.ts +0 -6
- package/dist/src/wrap/OutsideClick.component.js +0 -34
- package/dist/src/wrap/ScrollContainer.component.d.ts +0 -10
- package/dist/src/wrap/ScrollContainer.component.js +0 -54
- package/dist/src/wrap/ShortcutProvider.d.ts +0 -1
- package/dist/src/wrap/ShortcutProvider.js +0 -42
- package/dist/src/wrap/Swipe.component.d.ts +0 -14
- package/dist/src/wrap/Swipe.component.js +0 -61
|
@@ -1,260 +0,0 @@
|
|
|
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;
|
|
@@ -1,25 +0,0 @@
|
|
|
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>;
|
|
@@ -1,101 +0,0 @@
|
|
|
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 _utils_1 = require("@utils");
|
|
16
|
-
const _components_1 = require("@components");
|
|
17
|
-
function InputMapComponent({ label, tip, leftIcon, rightIcon, value, invalid, validations, register, unregister, onChange, className = "", ...props }) {
|
|
18
|
-
const { isSm } = (0, _utils_1.useResponsive)();
|
|
19
|
-
// =========================>
|
|
20
|
-
// ## Invalid handler
|
|
21
|
-
// =========================>
|
|
22
|
-
const inputHandler = (0, _utils_1.useInputHandler)(props.name, value, validations, register, unregister, false);
|
|
23
|
-
const randomId = (0, _utils_1.useInputRandomId)();
|
|
24
|
-
// =========================>
|
|
25
|
-
// ## Invalid handler
|
|
26
|
-
// =========================>
|
|
27
|
-
const [invalidMessage] = (0, _utils_1.useValidation)(inputHandler.value, validations, invalid, inputHandler.idle);
|
|
28
|
-
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) => {
|
|
29
|
-
props.onFocus?.(e);
|
|
30
|
-
inputHandler.setFocus(true);
|
|
31
|
-
inputHandler.setIdle(false);
|
|
32
|
-
}, 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) => {
|
|
33
|
-
inputHandler.setValue(e);
|
|
34
|
-
onChange?.(e);
|
|
35
|
-
} }) }))] }) }), 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) => {
|
|
36
|
-
inputHandler.setValue(e);
|
|
37
|
-
onChange?.(e);
|
|
38
|
-
} }) }) }))] }));
|
|
39
|
-
}
|
|
40
|
-
const InputMapPickerComponent = ({ onChange, value }) => {
|
|
41
|
-
const mapRef = (0, react_1.useRef)(null);
|
|
42
|
-
const [addressLoading, setAddressLoading] = (0, react_1.useState)(false);
|
|
43
|
-
const [drag, setDrag] = (0, react_1.useState)(false);
|
|
44
|
-
// =========================>
|
|
45
|
-
// ## Map Events
|
|
46
|
-
// =========================>
|
|
47
|
-
const setCurrentPosition = () => {
|
|
48
|
-
if (navigator.geolocation) {
|
|
49
|
-
navigator.geolocation.getCurrentPosition((pos) => {
|
|
50
|
-
const newPos = {
|
|
51
|
-
lat: pos.coords.latitude,
|
|
52
|
-
lng: pos.coords.longitude,
|
|
53
|
-
address: "",
|
|
54
|
-
};
|
|
55
|
-
onChange?.(newPos);
|
|
56
|
-
mapRef.current?.panTo(new google.maps.LatLng(newPos.lat, newPos.lng));
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
const handleDragEnd = (0, react_1.useCallback)(() => {
|
|
61
|
-
if (mapRef.current) {
|
|
62
|
-
const center = mapRef.current.getCenter();
|
|
63
|
-
if (center) {
|
|
64
|
-
onChange?.({
|
|
65
|
-
lat: center.lat(),
|
|
66
|
-
lng: center.lng(),
|
|
67
|
-
address: "",
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
setDrag(false);
|
|
71
|
-
}
|
|
72
|
-
}, []);
|
|
73
|
-
// =========================>
|
|
74
|
-
// ## Reverse Geocode
|
|
75
|
-
// =========================>
|
|
76
|
-
(0, react_1.useEffect)(() => {
|
|
77
|
-
if (value?.lat && value?.lng) {
|
|
78
|
-
setAddressLoading(true);
|
|
79
|
-
onChange?.((prev) => ({ ...prev, address: "" }));
|
|
80
|
-
axios_1.default.get(`https://api.geoapify.com/v1/geocode/reverse?lat=${value?.lat}&lon=${value?.lng}&apiKey=${process.env.NEXT_PUBLIC_GEOAPIFY_KEY}`)
|
|
81
|
-
.then((res) => {
|
|
82
|
-
if (res.status === 200 && !res.data.error) {
|
|
83
|
-
const data = res.data.features?.at(0)?.properties;
|
|
84
|
-
const address = (data?.address_line1 || "") + " " + (data?.address_line2 || "");
|
|
85
|
-
onChange?.((prev) => ({ ...prev, address }));
|
|
86
|
-
onChange?.({ ...value, address });
|
|
87
|
-
}
|
|
88
|
-
})
|
|
89
|
-
.finally(() => setAddressLoading(false));
|
|
90
|
-
}
|
|
91
|
-
}, [value?.lat, value?.lng]);
|
|
92
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "relative w-full", children: [(0, jsx_runtime_1.jsx)(api_1.LoadScript, { googleMapsApiKey: process.env.NEXT_PUBLIC_MAP_KEY || "", children: (0, jsx_runtime_1.jsx)(api_1.GoogleMap, { mapContainerStyle: { width: "100%", height: "100%" }, center: {
|
|
93
|
-
lat: value?.lat || -6.208,
|
|
94
|
-
lng: value?.lng || 106.689,
|
|
95
|
-
}, zoom: 18, options: {
|
|
96
|
-
streetViewControl: false,
|
|
97
|
-
mapTypeControl: false,
|
|
98
|
-
fullscreenControl: false,
|
|
99
|
-
}, 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" }) })] }));
|
|
100
|
-
};
|
|
101
|
-
exports.InputMapPickerComponent = InputMapPickerComponent;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React, { 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): React.JSX.Element;
|
|
@@ -1,40 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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>;
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
"use strict";
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.InputOtpComponent = void 0;
|
|
5
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
-
const react_1 = require("react");
|
|
7
|
-
const _utils_1 = require("@utils");
|
|
8
|
-
const InputOtpComponent = ({ label, tip, name, disabled, value, invalid, length = 6, onChange, className = "", }) => {
|
|
9
|
-
const [isFocus, setIsFocus] = (0, react_1.useState)(false);
|
|
10
|
-
const inputsRef = (0, react_1.useRef)([]);
|
|
11
|
-
const [otp, setOtp] = (0, react_1.useState)((value || "").split("").concat(Array(length).fill("")).slice(0, length));
|
|
12
|
-
(0, react_1.useEffect)(() => {
|
|
13
|
-
const handleFocusChange = () => {
|
|
14
|
-
const anyFocused = inputsRef.current.some((input) => input === document.activeElement);
|
|
15
|
-
setIsFocus(anyFocused);
|
|
16
|
-
};
|
|
17
|
-
window.addEventListener("focusin", handleFocusChange);
|
|
18
|
-
window.addEventListener("focusout", handleFocusChange);
|
|
19
|
-
return () => {
|
|
20
|
-
window.removeEventListener("focusin", handleFocusChange);
|
|
21
|
-
window.removeEventListener("focusout", handleFocusChange);
|
|
22
|
-
};
|
|
23
|
-
}, []);
|
|
24
|
-
const emitChange = (newOtp) => {
|
|
25
|
-
const val = newOtp.join("");
|
|
26
|
-
onChange?.(val);
|
|
27
|
-
};
|
|
28
|
-
const handleChange = (val, index) => {
|
|
29
|
-
if (!/^[0-9]?$/.test(val))
|
|
30
|
-
return;
|
|
31
|
-
const newOtp = [...otp];
|
|
32
|
-
newOtp[index] = val;
|
|
33
|
-
setOtp(newOtp);
|
|
34
|
-
emitChange(newOtp);
|
|
35
|
-
(val && index < length - 1) && inputsRef.current[index + 1]?.focus();
|
|
36
|
-
};
|
|
37
|
-
const handleKeyDown = (e, index) => {
|
|
38
|
-
if (e.key === "Backspace") {
|
|
39
|
-
if (otp[index]) {
|
|
40
|
-
const newOtp = [...otp];
|
|
41
|
-
newOtp[index] = "";
|
|
42
|
-
setOtp(newOtp);
|
|
43
|
-
emitChange(newOtp);
|
|
44
|
-
}
|
|
45
|
-
else if (index > 0) {
|
|
46
|
-
inputsRef.current[index - 1]?.focus();
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
const handlePaste = (e) => {
|
|
51
|
-
e.preventDefault();
|
|
52
|
-
const paste = e.clipboardData.getData("text").trim();
|
|
53
|
-
if (!/^[0-9]+$/.test(paste))
|
|
54
|
-
return;
|
|
55
|
-
const pasted = paste.slice(0, length).split("");
|
|
56
|
-
const newOtp = [...otp];
|
|
57
|
-
for (let i = 0; i < pasted.length; i++)
|
|
58
|
-
newOtp[i] = pasted[i];
|
|
59
|
-
setOtp(newOtp);
|
|
60
|
-
emitChange(newOtp);
|
|
61
|
-
inputsRef.current[Math.min(pasted.length, length - 1)]?.focus();
|
|
62
|
-
};
|
|
63
|
-
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.jsx)("label", { className: (0, _utils_1.cn)("input-label", disabled && "input-label-disabled", isFocus && "input-label-focus", !!invalid && "input-label-error", (0, _utils_1.pcn)(className, "label"), disabled && (0, _utils_1.pcn)(className, "label", "disabled"), isFocus && (0, _utils_1.pcn)(className, "label", "focus"), !!invalid && (0, _utils_1.pcn)(className, "label", "error")), children: label }), tip && ((0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-tip", disabled && "input-tip-disabled", (0, _utils_1.pcn)(className, "tip"), disabled && (0, _utils_1.pcn)(className, "tip", "disabled")), children: tip })), (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("input input-otp-box", isFocus && "input-otp-box-focus", !!invalid && "input-error"), children: [(0, jsx_runtime_1.jsx)("div", { className: "input-otp-digits-container", children: otp.map((digit, index) => ((0, jsx_runtime_1.jsx)("input", { type: "text", ref: (el) => { inputsRef.current[index] = el; }, inputMode: "numeric", maxLength: 1, value: digit, onChange: (e) => handleChange(e.target.value, index), onKeyDown: (e) => handleKeyDown(e, index), onPaste: handlePaste, className: "input-otp-cell", placeholder: "-", autoFocus: index === 0 }, index))) }), (0, jsx_runtime_1.jsx)("input", { type: "hidden", name: name, value: otp.join("") })] }), invalid && ((0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-error-message", (0, _utils_1.pcn)(className, "error")), children: invalid }))] }) }));
|
|
64
|
-
};
|
|
65
|
-
exports.InputOtpComponent = InputOtpComponent;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { InputHTMLAttributes, ReactNode } from "react";
|
|
2
|
-
import { ValidationRules } from "@utils";
|
|
3
|
-
export interface InputPasswordProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "onChange"> {
|
|
4
|
-
label?: string;
|
|
5
|
-
tip?: string | ReactNode;
|
|
6
|
-
leftIcon?: any;
|
|
7
|
-
rightIcon?: any;
|
|
8
|
-
value?: string;
|
|
9
|
-
invalid?: string;
|
|
10
|
-
validations?: ValidationRules;
|
|
11
|
-
onChange?: (value: string, confirm?: string) => any;
|
|
12
|
-
register?: (name: string, validations?: ValidationRules) => void;
|
|
13
|
-
unregister?: (name: string) => void;
|
|
14
|
-
/** Use custom class with: "label::", "tip::", "error::", "icon::". */
|
|
15
|
-
className?: string;
|
|
16
|
-
}
|
|
17
|
-
export declare function InputPasswordComponent({ label, tip, leftIcon, rightIcon, value, invalid, validations, register, unregister, onChange, className, ...props }: InputPasswordProps): import("react").JSX.Element;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
"use strict";
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.InputPasswordComponent = InputPasswordComponent;
|
|
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 _utils_1 = require("@utils");
|
|
9
|
-
function InputPasswordComponent({ label, tip, leftIcon, rightIcon, value, invalid, validations, register, unregister, onChange, className = "", ...props }) {
|
|
10
|
-
const [password, setPassword] = (0, react_1.useState)("");
|
|
11
|
-
const [confirmPassword, setConfirmPassword] = (0, react_1.useState)("");
|
|
12
|
-
const [strength, setStrength] = (0, react_1.useState)("");
|
|
13
|
-
// =========================>
|
|
14
|
-
// ## Initial
|
|
15
|
-
// =========================>
|
|
16
|
-
const inputHandler = (0, _utils_1.useInputHandler)(props.name, value, validations, register, unregister, false);
|
|
17
|
-
const randomId = (0, _utils_1.useInputRandomId)();
|
|
18
|
-
const randomConfirmId = (0, _utils_1.useInputRandomId)();
|
|
19
|
-
// =========================>
|
|
20
|
-
// ## Invalid handler
|
|
21
|
-
// =========================>
|
|
22
|
-
const [invalidMessage] = (0, _utils_1.useValidation)(inputHandler.value, validations, invalid, inputHandler.idle);
|
|
23
|
-
// =========================>
|
|
24
|
-
// ## Password strength handler
|
|
25
|
-
// =========================>
|
|
26
|
-
(0, react_1.useEffect)(() => {
|
|
27
|
-
if (!password)
|
|
28
|
-
return setStrength("");
|
|
29
|
-
const hasLetter = /[A-Za-z]/.test(password);
|
|
30
|
-
const hasNumber = /\d/.test(password);
|
|
31
|
-
const hasSymbol = /[^A-Za-z0-9]/.test(password);
|
|
32
|
-
if (hasLetter && !hasNumber && !hasSymbol)
|
|
33
|
-
setStrength("weak");
|
|
34
|
-
else if (hasLetter && hasNumber && !hasSymbol)
|
|
35
|
-
setStrength("strong");
|
|
36
|
-
else if (hasLetter && hasNumber && hasSymbol)
|
|
37
|
-
setStrength("excellent");
|
|
38
|
-
else
|
|
39
|
-
setStrength("weak");
|
|
40
|
-
}, [password]);
|
|
41
|
-
// =========================>
|
|
42
|
-
// ## Check match confirm password
|
|
43
|
-
// =========================>
|
|
44
|
-
const isConfirmMismatch = confirmPassword && password !== confirmPassword;
|
|
45
|
-
return ((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.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)("input", { ...props, type: "password", id: randomId, className: (0, _utils_1.cn)("input", leftIcon && "input-with-left-icon", rightIcon && "input-with-right-icon", !!invalidMessage && "input-error", (0, _utils_1.pcn)(className, "base")), value: password, onChange: (e) => {
|
|
46
|
-
setPassword(e.target.value);
|
|
47
|
-
inputHandler.setIdle(false);
|
|
48
|
-
onChange?.(e.target.value, confirmPassword);
|
|
49
|
-
}, onFocus: (e) => {
|
|
50
|
-
props.onFocus?.(e);
|
|
51
|
-
inputHandler.setFocus(true);
|
|
52
|
-
}, onBlur: (e) => {
|
|
53
|
-
props.onBlur?.(e);
|
|
54
|
-
setTimeout(() => inputHandler.setFocus(false), 100);
|
|
55
|
-
}, autoComplete: "off" }), leftIcon && ((0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { className: (0, _utils_1.cn)("input-icon", "input-icon-left", (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", (0, _utils_1.pcn)(className, "icon")), icon: rightIcon }))] }), invalidMessage && ((0, jsx_runtime_1.jsx)("small", { className: "input-error-message", children: invalidMessage })), strength && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mt-1", children: [(0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("password-strength-bar", strength === "weak" && "password-strength-bar-weak", strength === "strong" && "password-strength-bar-strong", strength === "excellent" && "password-strength-bar-excellent") }), (0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("password-strength-bar", strength === "weak" && "password-strength-bar-empty", strength === "strong" && "password-strength-bar-strong", strength === "excellent" && "password-strength-bar-excellent") }), (0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("password-strength-bar", (strength === "weak" || strength === "strong") && "password-strength-bar-empty", strength === "excellent" && "password-strength-bar-excellent") }), (0, jsx_runtime_1.jsx)("span", { className: (0, _utils_1.cn)("password-strength-text", strength === "weak" && "password-strength-text-weak", strength === "strong" && "password-strength-text-strong", strength === "excellent" && "password-strength-text-excellent"), children: strength === "weak" ? "Weak" : strength === "strong" ? "Strong" : "Excellent" })] })), (0, jsx_runtime_1.jsxs)("div", { className: "input-password-confirm-wrapper", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: randomConfirmId, className: (0, _utils_1.cn)("input-label", (0, _utils_1.pcn)(className, "label")), children: "Password Confirm" }), (0, jsx_runtime_1.jsx)("div", { className: "relative", children: (0, jsx_runtime_1.jsx)("input", { ...props, id: randomConfirmId, type: "password", className: (0, _utils_1.cn)("input", leftIcon && "input-with-left-icon", rightIcon && "input-with-right-icon", (0, _utils_1.pcn)(className, "base"), isConfirmMismatch && "input-error"), value: confirmPassword, onChange: (e) => {
|
|
56
|
-
setConfirmPassword(e.target.value);
|
|
57
|
-
onChange?.(password, e.target.value);
|
|
58
|
-
}, autoComplete: "off" }) })] }), isConfirmMismatch && ((0, jsx_runtime_1.jsx)("small", { className: "input-error-message", children: "Password confirmation not match" }))] }));
|
|
59
|
-
}
|