sales-frontend-components 0.0.50 → 0.0.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1,12 +1,94 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { flexRender, useReactTable, getSortedRowModel, getCoreRowModel, getPaginationRowModel } from '@tanstack/react-table';
3
- import { Table, DatePicker, SegmentGroup, FormField, Button, Icon } from 'sales-frontend-design-system';
4
- import styles from './data-table/data-table.module.scss';
5
- import React, { useState, useRef, useEffect, useCallback, useImperativeHandle } from 'react';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
2
  import { useController } from 'react-hook-form';
7
- import styles$1 from './form/form-signautre/form-signature.module.scss';
8
- import styles$2 from './step-indicator/step-indicator.module.scss';
9
- import styles$3 from './camera/camera.module.scss';
3
+ import { DatePicker, SegmentGroup, FormField, Icon } from 'sales-frontend-design-system';
4
+ import React, { useState, useEffect, useRef, useCallback } from 'react';
5
+ import styles from './step-indicator/step-indicator.module.scss';
6
+ import styles$1 from './camera/camera.module.scss';
7
+
8
+ const FormDatePicker = ({
9
+ name,
10
+ control,
11
+ disabled,
12
+ ...props
13
+ }) => {
14
+ const { field, fieldState } = useController({ name, control, disabled });
15
+ const baseProps = {
16
+ ...props,
17
+ id: field.name,
18
+ defaultValue: field.value,
19
+ disabled: field.disabled,
20
+ error: fieldState.invalid,
21
+ onBlur: field.onBlur
22
+ };
23
+ return /* @__PURE__ */ jsx(DatePicker, { ...baseProps });
24
+ };
25
+
26
+ const FormSegmentGroup = ({
27
+ name,
28
+ control,
29
+ disabled,
30
+ ...props
31
+ }) => {
32
+ const { field, fieldState } = useController({ name, control, disabled });
33
+ return /* @__PURE__ */ jsx(
34
+ SegmentGroup,
35
+ {
36
+ ...props,
37
+ tabIndex: 0,
38
+ id: field.name,
39
+ ref: field.ref,
40
+ defaultValue: field.value,
41
+ disabled: field.disabled,
42
+ error: fieldState.invalid,
43
+ onBlur: field.onBlur,
44
+ onValueChange: (selected) => {
45
+ field.onChange(selected);
46
+ props.onValueChange?.(selected);
47
+ }
48
+ }
49
+ );
50
+ };
51
+
52
+ const FormTextField = ({
53
+ name,
54
+ control,
55
+ disabled,
56
+ error,
57
+ onBlur,
58
+ onChange,
59
+ rootProps,
60
+ ...props
61
+ }) => {
62
+ const { field, fieldState } = useController({ name, control, disabled });
63
+ return /* @__PURE__ */ jsx(
64
+ FormField.TextField,
65
+ {
66
+ ...props,
67
+ id: field.name,
68
+ size: "medium",
69
+ autoComplete: "off",
70
+ name: field.name,
71
+ value: field.value ?? "",
72
+ disabled: field.disabled,
73
+ error: fieldState.invalid || error,
74
+ onChange: (e) => {
75
+ field.onChange(e);
76
+ onChange?.(e);
77
+ },
78
+ onBlur: (e) => {
79
+ field.onBlur();
80
+ onBlur?.(e);
81
+ },
82
+ rootProps: {
83
+ ...rootProps,
84
+ onClear: () => {
85
+ field.onChange("");
86
+ rootProps?.onClear?.();
87
+ }
88
+ }
89
+ }
90
+ );
91
+ };
10
92
 
11
93
  function getDefaultExportFromCjs (x) {
12
94
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
@@ -99,629 +181,7 @@ function requireBind () {
99
181
  var bindExports = requireBind();
100
182
  var classNames = /*@__PURE__*/getDefaultExportFromCjs(bindExports);
101
183
 
102
- const cx$3 = classNames.bind(styles);
103
- const DataTable = ({ table, isError, isLoading, msgText, ...props }) => {
104
- return /* @__PURE__ */ jsxs(
105
- Table,
106
- {
107
- ...props,
108
- selectable: true,
109
- style: {
110
- // minWidth: table.getCenterTotalSize() // 테이블 전체 너비를 컬럼 너비의 합으로 설정
111
- },
112
- children: [
113
- /* @__PURE__ */ jsx("thead", { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx("tr", { children: headerGroup.headers.map((header) => /* @__PURE__ */ jsxs(
114
- "th",
115
- {
116
- colSpan: header.colSpan,
117
- className: cx$3({
118
- "is-resizing": header.column.getIsResizing()
119
- // 3. 리사이징 중일 때 클래스 추가
120
- }),
121
- style: header.column.columnDef.size ? { width: header.getSize(), minWidth: header.getSize(), maxWidth: header.getSize() } : void 0,
122
- children: [
123
- header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()),
124
- header.column.getCanResize() && /* @__PURE__ */ jsx(
125
- "div",
126
- {
127
- onMouseDown: header.getResizeHandler(),
128
- onTouchStart: header.getResizeHandler(),
129
- className: cx$3("resize-handle")
130
- }
131
- )
132
- ]
133
- },
134
- header.id
135
- )) }, headerGroup.id)) }),
136
- /* @__PURE__ */ jsx("tbody", { children: !isLoading && !isError && table.getRowModel().rows.length > 0 ? table.getRowModel().rows.map((row) => (
137
- // TODO aria-disabled 스타일을 어떻게 적용할 것인지?
138
- /* @__PURE__ */ jsx("tr", { "aria-selected": row.getIsSelected(), children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(
139
- "td",
140
- {
141
- style: cell.column.columnDef.size ? {
142
- width: cell.column.getSize(),
143
- minWidth: cell.column.getSize(),
144
- maxWidth: cell.column.getSize()
145
- } : void 0,
146
- children: flexRender(cell.column.columnDef.cell, cell.getContext())
147
- },
148
- cell.id
149
- )) }, row.id)
150
- )) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { className: cx$3("feedback-cell"), colSpan: table.getVisibleLeafColumns().length, children: isLoading ? /* @__PURE__ */ jsx("div", { children: "Loading..." }) : /* @__PURE__ */ jsx("div", { children: msgText || (isError ? "Error" : "No data") }) }) }) })
151
- ]
152
- }
153
- );
154
- };
155
-
156
- const useTable = ({
157
- data,
158
- columns,
159
- defaultColumn = { size: 150, enableResizing: true },
160
- initialState,
161
- onSortingChange,
162
- enableRowSelection,
163
- enableColumnResizing,
164
- mode = "SSR",
165
- meta,
166
- debug
167
- }) => {
168
- const [sorting, setSorting] = React.useState(initialState?.sorting || []);
169
- const [rowSelection, setRowSelection] = useState(initialState?.rowSelection || {});
170
- const [pagination, setPagination] = React.useState(initialState?.pagination || {});
171
- const [columnVisibility, setColumnVisibility] = React.useState(initialState?.columnVisibility || {});
172
- const getOption = (mode2) => {
173
- if (mode2 === "SSR") {
174
- return {
175
- manualSorting: true,
176
- manualPagination: true,
177
- onSortingChange
178
- };
179
- } else {
180
- return {
181
- getPaginationRowModel: getPaginationRowModel(),
182
- onPaginationChange: setPagination,
183
- onSortingChange: setSorting
184
- };
185
- }
186
- };
187
- const table = useReactTable({
188
- meta,
189
- data,
190
- columns,
191
- columnResizeMode: "onChange",
192
- defaultColumn,
193
- enableColumnResizing,
194
- enableRowSelection,
195
- initialState,
196
- state: {
197
- sorting,
198
- rowSelection,
199
- pagination,
200
- columnVisibility
201
- },
202
- onRowSelectionChange: setRowSelection,
203
- onColumnVisibilityChange: setColumnVisibility,
204
- getCoreRowModel: getCoreRowModel(),
205
- getSortedRowModel: getSortedRowModel(),
206
- ...getOption(mode),
207
- debugTable: debug,
208
- debugHeaders: debug,
209
- debugColumns: debug
210
- });
211
- return table;
212
- };
213
-
214
- const FormDatePicker = ({
215
- name,
216
- control,
217
- disabled,
218
- ...props
219
- }) => {
220
- const { field, fieldState } = useController({ name, control, disabled });
221
- const baseProps = {
222
- ...props,
223
- id: field.name,
224
- defaultValue: field.value,
225
- disabled: field.disabled,
226
- error: fieldState.invalid,
227
- onBlur: field.onBlur
228
- };
229
- return /* @__PURE__ */ jsx(DatePicker, { ...baseProps });
230
- };
231
-
232
- const FormSegmentGroup = ({
233
- name,
234
- control,
235
- disabled,
236
- ...props
237
- }) => {
238
- const { field, fieldState } = useController({ name, control, disabled });
239
- return /* @__PURE__ */ jsx(
240
- SegmentGroup,
241
- {
242
- ...props,
243
- tabIndex: 0,
244
- id: field.name,
245
- ref: field.ref,
246
- defaultValue: field.value,
247
- disabled: field.disabled,
248
- error: fieldState.invalid,
249
- onBlur: field.onBlur,
250
- onValueChange: (selected) => {
251
- field.onChange(selected);
252
- props.onValueChange?.(selected);
253
- }
254
- }
255
- );
256
- };
257
-
258
- const FormTextField = ({
259
- name,
260
- control,
261
- disabled,
262
- error,
263
- onBlur,
264
- onChange,
265
- rootProps,
266
- ...props
267
- }) => {
268
- const { field, fieldState } = useController({ name, control, disabled });
269
- return /* @__PURE__ */ jsx(
270
- FormField.TextField,
271
- {
272
- ...props,
273
- id: field.name,
274
- size: "medium",
275
- autoComplete: "off",
276
- name: field.name,
277
- value: field.value ?? "",
278
- disabled: field.disabled,
279
- error: fieldState.invalid || error,
280
- onChange: (e) => {
281
- field.onChange(e);
282
- onChange?.(e);
283
- },
284
- onBlur: (e) => {
285
- field.onBlur();
286
- onBlur?.(e);
287
- },
288
- rootProps: {
289
- ...rootProps,
290
- onClear: () => {
291
- field.onChange("");
292
- rootProps?.onClear?.();
293
- }
294
- }
295
- }
296
- );
297
- };
298
-
299
- const cx$2 = classNames.bind(styles$1);
300
- const FormSignature = ({
301
- label,
302
- error,
303
- errorMsg,
304
- onSubmit,
305
- onRecentSignatureLoad,
306
- onChangeSignature,
307
- onReset,
308
- isShowRecentSignatureButton,
309
- isShowResetButton,
310
- ref,
311
- canvasWidth = 632,
312
- canvasHeight = 230
313
- }) => {
314
- const canvasRef = useRef(null);
315
- const containerRef = useRef(null);
316
- const [isDrawing, setIsDrawing] = useState(false);
317
- const [isEmpty, setIsEmpty] = useState(true);
318
- const [signatureData, setSignatureData] = useState("");
319
- const [isLoadingSignature, setIsLoadingSignature] = useState(false);
320
- const [isMousePressed, setIsMousePressed] = useState(false);
321
- const [totalLineLength, setTotalLineLength] = useState(0);
322
- const [lastPoint, setLastPoint] = useState(null);
323
- const [strokeLengths, setStrokeLengths] = useState([]);
324
- const [currentStrokeLength, setCurrentStrokeLength] = useState(0);
325
- useEffect(() => {
326
- const canvas = canvasRef.current;
327
- if (!canvas) {
328
- return;
329
- }
330
- const ctx = canvas.getContext("2d");
331
- if (!ctx) {
332
- return;
333
- }
334
- ctx.strokeStyle = "#000000";
335
- ctx.lineWidth = Math.max(1, canvasWidth / 400);
336
- ctx.lineCap = "round";
337
- ctx.lineJoin = "round";
338
- }, [canvasWidth]);
339
- useEffect(() => {
340
- const handleGlobalMouseUp = () => {
341
- setIsMousePressed(false);
342
- if (isDrawing) {
343
- stopDrawing();
344
- }
345
- };
346
- document.addEventListener("mouseup", handleGlobalMouseUp);
347
- return () => {
348
- document.removeEventListener("mouseup", handleGlobalMouseUp);
349
- };
350
- }, [isDrawing]);
351
- const getCanvasCoordinates = useCallback((e) => {
352
- const canvas = canvasRef.current;
353
- if (!canvas) {
354
- return { x: 0, y: 0 };
355
- }
356
- const rect = canvas.getBoundingClientRect();
357
- const scaleX = canvas.width / rect.width;
358
- const scaleY = canvas.height / rect.height;
359
- return {
360
- x: (e.clientX - rect.left) * scaleX,
361
- y: (e.clientY - rect.top) * scaleY
362
- };
363
- }, []);
364
- const calculateDistance = useCallback((point1, point2) => {
365
- return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
366
- }, []);
367
- const startDrawing = useCallback(
368
- (e) => {
369
- const canvas = canvasRef.current;
370
- if (!canvas) {
371
- return;
372
- }
373
- const ctx = canvas.getContext("2d");
374
- if (!ctx) {
375
- return;
376
- }
377
- const { x, y } = getCanvasCoordinates(e);
378
- setIsDrawing(true);
379
- setIsMousePressed(true);
380
- setIsEmpty(false);
381
- setLastPoint({ x, y });
382
- setCurrentStrokeLength(0);
383
- ctx.beginPath();
384
- ctx.moveTo(x, y);
385
- },
386
- [getCanvasCoordinates]
387
- );
388
- const draw = useCallback(
389
- (e) => {
390
- if (!isDrawing) {
391
- return;
392
- }
393
- const canvas = canvasRef.current;
394
- if (!canvas) {
395
- return;
396
- }
397
- const ctx = canvas.getContext("2d");
398
- if (!ctx) {
399
- return;
400
- }
401
- const { x, y } = getCanvasCoordinates(e);
402
- const currentPoint = { x, y };
403
- if (lastPoint) {
404
- const distance = calculateDistance(lastPoint, currentPoint);
405
- if (distance > 0.5) {
406
- setCurrentStrokeLength((prev) => prev + distance);
407
- setTotalLineLength((prev) => prev + distance);
408
- }
409
- }
410
- ctx.lineTo(x, y);
411
- ctx.stroke();
412
- setLastPoint(currentPoint);
413
- const data = canvas.toDataURL();
414
- setSignatureData(data);
415
- onChangeSignature?.();
416
- },
417
- [isDrawing, getCanvasCoordinates, calculateDistance, lastPoint, onChangeSignature]
418
- );
419
- const stopDrawing = useCallback(() => {
420
- if (isDrawing && currentStrokeLength > 0) {
421
- setStrokeLengths((prev) => [...prev, currentStrokeLength]);
422
- }
423
- setIsDrawing(false);
424
- setLastPoint(null);
425
- }, [isDrawing, currentStrokeLength]);
426
- const handleMouseEnter = useCallback(
427
- (e) => {
428
- if (isMousePressed && !isDrawing) {
429
- const canvas = canvasRef.current;
430
- if (!canvas) {
431
- return;
432
- }
433
- const ctx = canvas.getContext("2d");
434
- if (!ctx) {
435
- return;
436
- }
437
- const { x, y } = getCanvasCoordinates(e);
438
- setIsDrawing(true);
439
- setLastPoint({ x, y });
440
- ctx.beginPath();
441
- ctx.moveTo(x, y);
442
- }
443
- },
444
- [isMousePressed, isDrawing, getCanvasCoordinates]
445
- );
446
- const handleMouseLeave = useCallback(() => {
447
- if (isDrawing) {
448
- setIsDrawing(false);
449
- setLastPoint(null);
450
- }
451
- }, [isDrawing]);
452
- const clearSignature = useCallback(() => {
453
- const canvas = canvasRef.current;
454
- if (!canvas) {
455
- return;
456
- }
457
- const ctx = canvas.getContext("2d");
458
- if (!ctx) {
459
- return;
460
- }
461
- ctx.clearRect(0, 0, canvasWidth, canvasHeight);
462
- setIsEmpty(true);
463
- setSignatureData("");
464
- setTotalLineLength(0);
465
- setLastPoint(null);
466
- setStrokeLengths([]);
467
- setCurrentStrokeLength(0);
468
- }, [canvasWidth, canvasHeight]);
469
- const loadSignatureToCanvas = useCallback(
470
- (imageDataURL) => {
471
- return new Promise((resolve, reject) => {
472
- const canvas = canvasRef.current;
473
- if (!canvas) {
474
- reject(new Error("Canvas not found"));
475
- return;
476
- }
477
- const ctx = canvas.getContext("2d");
478
- if (!ctx) {
479
- reject(new Error("Canvas context not found"));
480
- return;
481
- }
482
- const img = new Image();
483
- img.onload = () => {
484
- ctx.clearRect(0, 0, canvasWidth, canvasHeight);
485
- ctx.drawImage(img, 0, 0, canvasWidth, canvasHeight);
486
- setIsEmpty(false);
487
- setSignatureData(imageDataURL);
488
- setTotalLineLength(0);
489
- setStrokeLengths([]);
490
- setCurrentStrokeLength(0);
491
- setLastPoint(null);
492
- resolve();
493
- };
494
- img.onerror = () => {
495
- reject(new Error("Failed to load signature image"));
496
- };
497
- img.src = imageDataURL;
498
- });
499
- },
500
- [canvasWidth, canvasHeight]
501
- );
502
- const validateForm = useCallback(() => {
503
- return !(!signatureData || isEmpty);
504
- }, [signatureData, isEmpty]);
505
- const getSignatureDataObject = useCallback(() => {
506
- if (!signatureData || isEmpty) {
507
- return null;
508
- }
509
- return {
510
- signature: signatureData,
511
- totalLineLength: Math.round(totalLineLength),
512
- strokeCount: strokeLengths.length,
513
- strokeLengths: strokeLengths.map((length) => Math.round(length)),
514
- averageStrokeLength: strokeLengths.length > 0 ? Math.round(totalLineLength / strokeLengths.length) : 0
515
- };
516
- }, [signatureData, isEmpty, totalLineLength, strokeLengths]);
517
- const handleSubmit = useCallback(() => {
518
- if (!validateForm()) {
519
- return;
520
- }
521
- const data = getSignatureDataObject();
522
- if (data) {
523
- console.log("\uC81C\uCD9C\uB41C \uB370\uC774\uD130:", data);
524
- onSubmit(data);
525
- }
526
- }, [validateForm, getSignatureDataObject, onSubmit]);
527
- const handleReset = useCallback(() => {
528
- clearSignature();
529
- onReset?.();
530
- }, [clearSignature, onReset]);
531
- const handleRecentSignatureLoad = useCallback(async () => {
532
- if (!onRecentSignatureLoad) {
533
- return;
534
- }
535
- try {
536
- setIsLoadingSignature(true);
537
- const loadedSignature = await onRecentSignatureLoad();
538
- if (loadedSignature) {
539
- await loadSignatureToCanvas(loadedSignature);
540
- console.log("\uCD5C\uADFC \uC11C\uBA85\uC744 \uC131\uACF5\uC801\uC73C\uB85C \uBD88\uB7EC\uC654\uC2B5\uB2C8\uB2E4.");
541
- } else {
542
- alert("\uBD88\uB7EC\uC62C \uCD5C\uADFC \uC11C\uBA85\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
543
- }
544
- } catch (error2) {
545
- console.error("\uCD5C\uADFC \uC11C\uBA85 \uBD88\uB7EC\uC624\uAE30 \uC2E4\uD328:", error2);
546
- alert("\uCD5C\uADFC \uC11C\uBA85\uC744 \uBD88\uB7EC\uC624\uB294\uB370 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
547
- } finally {
548
- setIsLoadingSignature(false);
549
- }
550
- }, [onRecentSignatureLoad, loadSignatureToCanvas]);
551
- useImperativeHandle(
552
- ref,
553
- () => ({
554
- submit: handleSubmit,
555
- clear: clearSignature,
556
- getSignatureData: getSignatureDataObject,
557
- isValid: validateForm
558
- }),
559
- [handleSubmit, clearSignature, getSignatureDataObject, validateForm]
560
- );
561
- return /* @__PURE__ */ jsxs("div", { children: [
562
- /* @__PURE__ */ jsxs("div", { className: cx$2("form-label"), children: [
563
- /* @__PURE__ */ jsx("label", { className: "typo-subtitle3 text-body_1", children: label }),
564
- /* @__PURE__ */ jsxs("div", { className: cx$2("form-label-button-box"), children: [
565
- isShowResetButton && /* @__PURE__ */ jsx(
566
- Button,
567
- {
568
- appearance: "filled",
569
- variant: "neutral",
570
- size: "xsmall",
571
- onClick: handleReset,
572
- className: "text-nowrap-i",
573
- disabled: isEmpty,
574
- children: "\uB2E4\uC2DC \uC791\uC131"
575
- }
576
- ),
577
- isShowRecentSignatureButton && /* @__PURE__ */ jsx(
578
- Button,
579
- {
580
- appearance: "filled",
581
- variant: "neutral",
582
- size: "xsmall",
583
- className: "text-nowrap-i",
584
- onClick: handleRecentSignatureLoad,
585
- disabled: isLoadingSignature,
586
- children: isLoadingSignature ? "\uBD88\uB7EC\uC624\uB294 \uC911..." : "\uCD5C\uADFC \uC131\uBA85 \uBD88\uB7EC\uC624\uAE30"
587
- }
588
- )
589
- ] })
590
- ] }),
591
- /* @__PURE__ */ jsx("div", { className: cx$2("form-signature", error && "is-error"), ref: containerRef, children: /* @__PURE__ */ jsx(
592
- "canvas",
593
- {
594
- ref: canvasRef,
595
- width: canvasWidth,
596
- height: canvasHeight,
597
- className: "border border-gray-200 rounded cursor-crosshair bg-white",
598
- style: { width: "100%", height: `${canvasHeight}px` },
599
- onMouseDown: startDrawing,
600
- onMouseMove: draw,
601
- onMouseUp: stopDrawing,
602
- onMouseEnter: handleMouseEnter,
603
- onMouseLeave: handleMouseLeave
604
- }
605
- ) }),
606
- error && /* @__PURE__ */ jsx("div", { className: cx$2("error-msg-box"), children: /* @__PURE__ */ jsx("span", { className: cx$2("error-msg"), children: errorMsg || "\uC11C\uBA85\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694." }) })
607
- ] });
608
- };
609
-
610
- const useFormSignature = ({ onSubmit, onError, onClear, minLength = 100 } = {}) => {
611
- const signatureRef = useRef(null);
612
- const [signatureData, setSignatureData] = useState(null);
613
- const [isError, setIsError] = useState(false);
614
- const [errorMessage, setErrorMessage] = useState("");
615
- const [isLoadedFromRecent, setIsLoadedFromRecent] = useState(false);
616
- const handleSignatureSubmit = useCallback(
617
- (data) => {
618
- setSignatureData(data);
619
- setIsError(false);
620
- setErrorMessage("");
621
- onSubmit?.(data);
622
- },
623
- [onSubmit]
624
- );
625
- const submit = useCallback(() => {
626
- try {
627
- if (!signatureRef.current?.isValid()) {
628
- setIsError(true);
629
- setErrorMessage("\uC11C\uBA85\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694.");
630
- return false;
631
- }
632
- const data = signatureRef.current.getSignatureData();
633
- if (!data) {
634
- setIsError(true);
635
- setErrorMessage("\uC11C\uBA85 \uB370\uC774\uD130\uB97C \uAC00\uC838\uC62C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
636
- return false;
637
- }
638
- if (!isLoadedFromRecent && data.totalLineLength < minLength) {
639
- setIsError(true);
640
- setErrorMessage(`\uC11C\uBA85\uC744 \uB2E4\uC2DC \uD655\uC778\uD574 \uC8FC\uC138\uC694.`);
641
- return false;
642
- }
643
- setIsError(false);
644
- setErrorMessage("");
645
- signatureRef.current.submit();
646
- return true;
647
- } catch (error) {
648
- const errorObj = error instanceof Error ? error : new Error("\uC54C \uC218 \uC5C6\uB294 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
649
- setIsError(true);
650
- setErrorMessage(errorObj.message);
651
- onError?.(errorObj);
652
- return false;
653
- }
654
- }, [onError, minLength, isLoadedFromRecent]);
655
- const clear = useCallback(() => {
656
- signatureRef.current?.clear();
657
- setSignatureData(null);
658
- setIsError(false);
659
- setErrorMessage("");
660
- setIsLoadedFromRecent(false);
661
- onClear?.();
662
- }, [onClear]);
663
- const loadRecentSignature = useCallback(async () => {
664
- setIsLoadedFromRecent(true);
665
- setIsError(false);
666
- setErrorMessage("");
667
- return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAADmCAYAAAAtKeFcAAAAAXNSR0IArs4c6QAAH/dJREFUeF7t3U3vNFlZB+AbeRsYYVQmBsYYwYkxMRFN1I0BGXcaV6zcupeFfgKBLyALXLDR+AlgYeISEFzhQtQQYxBFhTHKxAHD8Cbqc4Yupp6m+9/1cs5dp6qvTp7MzDNd5+U6p0/Vr6ur6lXhRYAAAQIECBAgQIAAgSSBVyXVoxoCBAgQIECAAAECBAiEAGISECBAgAABAgQIECCQJiCApFGriAABAgQIECBAgAABAcQcIECAAAECBAgQIEAgTUAASaNWEQECBAgQIECAAAECAog5QIAAAQIECBAgQIBAmoAAkkatIgIECBAgQIAAAQIEBBBzgAABAgQIECBAgACBNAEBJI1aRQQIECBAgAABAgQICCDmAAECBAgQIECAAAECaQICSBq1iggQIECAAAECBAgQEEDMAQIECBAgQIAAAQIE0gQEkDRqFREgQIAAAQIECBAgIICYAwQIECBAgAABAgQIpAkIIGnUKiJAgAABAgQIECBAQAAxBwgQIECAAAECBAgQSBMQQNKoVUSAAAECBAgQIECAgABiDhAgQIAAAQIECBAgkCYggKRRq4gAAQIECBAgQIAAAQHEHCBAgAABAgQIECBAIE1AAEmjVhEBAgQIECBAgAABAgKIOUCAAAECBAgQIECAQJqAAJJGrSICBAgQIECAAAECBAQQc4AAAQIECBAgQIAAgTQBASSNWkUECBAgQIAAAQIECAgg5gABAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIINvPgf87NeGJiPjW9s2p2oKhb+WfP1S1ZIURIECAAAECBAjsUkAA2X7YhoP0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AgQIECBAgMAPCgggZgUBAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIIOYAAQIECBAgQIAAAQJpAgJIGrWKCBAgQIAAAQIECBAQQMwBAgQIECBAgAABAgTSBASQNGoVESBAgAABAgQIECAggJgDBAgQIECAAAECBAikCQggadQqIkCAAAECBAgQIEBAADEHCBAgQIAAAQIECBBIExBA0qhVRIAAAQIECBAgQICAAGIOECBAgAABAgQIECCQJiCApFGriAABAgQIECBAgAABAcQcIECAAAECBAgQIEAgTUAASaNWEQECBAgQIECAAAECAog5QIAAAQIECBAgQIBAmoAAkkatIgIECBAgQIAAAQIEBBBzgAABAgQIECBAgACBNAEBJI1aRQQIECBAgAABAgQICCDmAAECBAgQIECAAAECaQICSBq1iggQIECAAAECBAgQEEDMAQIECBAgQIAAAQIE0gQEkDRqFREgQIAAAQIECBAgIICYAwQIECBAgAABAgQIpAkIIGnUKiJAgAABAgQIECBAQAAxBwgQIECAAAECBAgQSBMQQNKoVUSAAAECBAgQIECAgABiDhAgQIAAAQIECBAgkCYggKRRq4gAAQIECBAgQIAAAQHEHCBAgAABAgQIECBAIE1AAEmjVhEBAgQIECBAgAABAgKIOUCAAAECBAgQIECAQJqAAJJGrSICBAgQIECAAAECBAQQc4AAAQIECBAgQIAAgTQBASSNWkUECBAgQIAAAQIECAgg5gABAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIIOYAAQIECBAgQIAAAQJpAgJIGrWKCBAgQIAAAQIECBAQQMwBAgQIECBAgAABAgTSBASQNGoVESBAgAABAgQIECAggJgDBAgQIECAAAECBAikCQggadQqIkCAAAECBAgQIEBAADEHCBAgQIAAAQIECBBIExBA0qhVRIAAAQIECBAgQICAAGIOECBAgAABAgQIECCQJiCApFGriAABAgQIECBAgAABAcQcIECAAAECBAgQIEAgTUAASaNWEQECBAgQIECAAAECAog5QIAAAQIECBAgQIBAmoAAkkatIgIECBAgQIAAAQIEBBBzgAABAgQIECBAgACBNAEBJI1aRQQIECBAgAABAgQICCDmAAECBAgQIECAAAECaQICSBq1iggQIECAAAECBAgQEEDMAQIECBAgQIAAAQIE0gQEkDRqFREgQIAAAQIECBAgIICYAwQIECBAgAABAgQIpAkIIGnUKiJAgAABAgQIECBAQAAxBwgQIECAAAECBAgQSBMQQNKoVUSAAAECBAgQIECAgABiDhAgQIAAAQIECBAgkCYggKRRq4gAAQIECBAgQIAAAQHEHCBAgAABAgQIECBAIE1AAEmjVhEBAgQIECBAgAABAgKIOUCAAAECBAgQIECAQJqAAJJGrSICBAgQIECAAAECBAQQc4AAAQIECBAgQIAAgTQBASSNWkUECBAgQIAAAQIECAgg5gABAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIIOYAAQIECBAgQIAAAQJpAgJIGrWKCBAgQIAAAQIECBAQQMwBAgQIECBAgAABAgTSBASQNGoVESBAgAABAgQIECDw/zxD0hRoJglmAAAAAElFTkSuQmCC";
668
- }, []);
669
- const isValid = useCallback(() => {
670
- const basicValid = signatureRef.current?.isValid() ?? false;
671
- if (!basicValid) {
672
- return false;
673
- }
674
- const data = signatureRef.current?.getSignatureData();
675
- if (!data) {
676
- return false;
677
- }
678
- if (isLoadedFromRecent) {
679
- return true;
680
- }
681
- return data.totalLineLength >= minLength;
682
- }, [minLength, isLoadedFromRecent]);
683
- const getSignatureData = useCallback(() => {
684
- return signatureRef.current?.getSignatureData() ?? null;
685
- }, []);
686
- const handleSignatureChange = useCallback(() => {
687
- setIsError(false);
688
- setErrorMessage("");
689
- }, []);
690
- const handleReset = useCallback(() => {
691
- setSignatureData(null);
692
- setIsError(false);
693
- setErrorMessage("");
694
- setIsLoadedFromRecent(false);
695
- onClear?.();
696
- }, [onClear]);
697
- const getErrorMessage = useCallback(() => {
698
- return errorMessage;
699
- }, [errorMessage]);
700
- return {
701
- // ref
702
- signatureRef,
703
- // state
704
- signatureData,
705
- isError,
706
- isLoadedFromRecent,
707
- // 최근 서명 불러옴 여부 노출
708
- // actions
709
- submit,
710
- clear,
711
- loadRecentSignature,
712
- handleSignatureChange,
713
- // 일반적인 서명 변경
714
- handleReset,
715
- // 다시 작성
716
- handleSignatureSubmit,
717
- // utilities
718
- isValid,
719
- getSignatureData,
720
- getErrorMessage
721
- };
722
- };
723
-
724
- const cx$1 = classNames.bind(styles$2);
184
+ const cx$1 = classNames.bind(styles);
725
185
  const StepIndicator = ({
726
186
  items,
727
187
  onClickItem,
@@ -753,7 +213,7 @@ const StepIndicator = ({
753
213
  ] });
754
214
  };
755
215
 
756
- const cx = classNames.bind(styles$3);
216
+ const cx = classNames.bind(styles$1);
757
217
  function Attachment({
758
218
  photos,
759
219
  onAddPhoto,
@@ -993,19 +453,18 @@ const DEFAULT_DOWNLOAD_PROPS = {
993
453
  width: 500,
994
454
  height: 500
995
455
  };
996
- function usePaint(paintProps = {}) {
456
+ function useCanvasPaint(paintProps = {}) {
997
457
  const { pen = { strokeWeight: 5, strokeColor: "black" }, onChange, onStart, onEnd } = paintProps;
998
- const canvasRef = useRef(null);
458
+ const [canvasRefState, setCanvasRefState] = useState(null);
999
459
  const contextRef = useRef(null);
1000
460
  const [isPainting, setIsPainting] = useState(false);
1001
461
  const [history, setHistory] = useState([]);
1002
462
  const [historyIndex, setHistoryIndex] = useState(-1);
1003
463
  const saveState = useCallback(() => {
1004
- const canvas = canvasRef.current;
1005
- if (!canvas) {
464
+ if (!canvasRefState) {
1006
465
  return;
1007
466
  }
1008
- const dataUrl = canvas.toDataURL();
467
+ const dataUrl = canvasRefState.toDataURL();
1009
468
  const newHistory = history.slice(0, historyIndex + 1);
1010
469
  if (newHistory.length >= HISTORY_SIZE) {
1011
470
  newHistory.shift();
@@ -1014,39 +473,37 @@ function usePaint(paintProps = {}) {
1014
473
  setHistory(newHistory);
1015
474
  setHistoryIndex(newHistory.length - 1);
1016
475
  onChange && onChange();
1017
- }, [history, historyIndex, onChange]);
476
+ }, [history, historyIndex, onChange, canvasRefState]);
1018
477
  const restoreState = useCallback(
1019
478
  (index) => {
1020
- const canvas = canvasRef.current;
1021
479
  const context = contextRef.current;
1022
- if (!canvas || !context || !history[index]) {
480
+ if (!canvasRefState || !context || !history[index]) {
1023
481
  return;
1024
482
  }
1025
483
  const dataUrl = history[index];
1026
484
  const img = new Image();
1027
485
  img.onload = () => {
1028
- context.clearRect(0, 0, canvas.width, canvas.height);
486
+ context.clearRect(0, 0, canvasRefState.width, canvasRefState.height);
1029
487
  context.drawImage(img, 0, 0);
1030
488
  };
1031
489
  img.src = dataUrl;
1032
490
  onChange && onChange();
1033
491
  },
1034
- [history, onChange]
492
+ [history, onChange, canvasRefState]
1035
493
  );
1036
494
  useEffect(() => {
1037
- const canvas = canvasRef.current;
1038
- if (!canvas) {
495
+ if (!canvasRefState) {
1039
496
  return;
1040
497
  }
1041
- const context = canvas.getContext("2d", { willReadFrequently: true });
498
+ const context = canvasRefState.getContext("2d", { willReadFrequently: true });
1042
499
  if (!context) {
1043
500
  return;
1044
501
  }
1045
502
  contextRef.current = context;
1046
- const initialDataUrl = canvas.toDataURL();
503
+ const initialDataUrl = canvasRefState.toDataURL();
1047
504
  setHistory([initialDataUrl]);
1048
505
  setHistoryIndex(0);
1049
- }, []);
506
+ }, [canvasRefState]);
1050
507
  useEffect(() => {
1051
508
  const context = contextRef.current;
1052
509
  if (context) {
@@ -1054,19 +511,53 @@ function usePaint(paintProps = {}) {
1054
511
  context.strokeStyle = pen.strokeColor;
1055
512
  }
1056
513
  }, [pen]);
514
+ const getEventPosition = useCallback(
515
+ (event) => {
516
+ if (!canvasRefState) {
517
+ return null;
518
+ }
519
+ const rect = canvasRefState.getBoundingClientRect();
520
+ const scaleX = canvasRefState.width / rect.width;
521
+ const scaleY = canvasRefState.height / rect.height;
522
+ let clientX;
523
+ let clientY;
524
+ if (event instanceof MouseEvent) {
525
+ clientX = event.clientX;
526
+ clientY = event.clientY;
527
+ } else if (event instanceof TouchEvent) {
528
+ const touch = event.touches[0];
529
+ if (!touch) {
530
+ return null;
531
+ }
532
+ clientX = touch.clientX;
533
+ clientY = touch.clientY;
534
+ } else {
535
+ return null;
536
+ }
537
+ const offsetX = (clientX - rect.left) * scaleX;
538
+ const offsetY = (clientY - rect.top) * scaleY;
539
+ return { offsetX, offsetY };
540
+ },
541
+ [canvasRefState]
542
+ );
1057
543
  const startPainting = useCallback(
1058
544
  (event) => {
545
+ event.preventDefault();
1059
546
  const context = contextRef.current;
1060
547
  if (!context) {
1061
548
  return;
1062
549
  }
550
+ const pos = getEventPosition(event);
551
+ if (!pos) {
552
+ return;
553
+ }
1063
554
  onStart && onStart();
1064
- const { offsetX, offsetY } = event;
555
+ const { offsetX, offsetY } = pos;
1065
556
  context.beginPath();
1066
557
  context.moveTo(offsetX, offsetY);
1067
558
  setIsPainting(true);
1068
559
  },
1069
- [onStart]
560
+ [onStart, getEventPosition]
1070
561
  );
1071
562
  const stopPainting = useCallback(() => {
1072
563
  const context = contextRef.current;
@@ -1080,47 +571,48 @@ function usePaint(paintProps = {}) {
1080
571
  }, [isPainting, onEnd, saveState]);
1081
572
  const paint = useCallback(
1082
573
  (event) => {
574
+ event.preventDefault();
1083
575
  if (!isPainting || !contextRef.current) {
1084
576
  return;
1085
577
  }
1086
- const { offsetX, offsetY } = event;
578
+ const pos = getEventPosition(event);
579
+ if (!pos) {
580
+ return;
581
+ }
582
+ const { offsetX, offsetY } = pos;
1087
583
  contextRef.current.lineTo(offsetX, offsetY);
1088
584
  contextRef.current.stroke();
1089
585
  },
1090
- [isPainting]
1091
- );
1092
- const handleMouseEnter = useCallback(
1093
- (event) => {
1094
- if (event.buttons === 1 && !isPainting) {
1095
- startPainting(event);
1096
- }
1097
- },
1098
- [isPainting, startPainting]
586
+ [isPainting, getEventPosition]
1099
587
  );
1100
588
  useEffect(() => {
1101
- const canvas = canvasRef.current;
1102
- if (!canvas) {
589
+ if (!canvasRefState) {
1103
590
  return;
1104
591
  }
1105
- canvas.addEventListener("mousedown", startPainting);
1106
- canvas.addEventListener("mouseup", stopPainting);
1107
- canvas.addEventListener("mousemove", paint);
1108
- canvas.addEventListener("mouseleave", stopPainting);
1109
- canvas.addEventListener("mouseenter", handleMouseEnter);
592
+ canvasRefState.addEventListener("mousedown", startPainting);
593
+ canvasRefState.addEventListener("mouseup", stopPainting);
594
+ canvasRefState.addEventListener("mousemove", paint);
595
+ canvasRefState.addEventListener("mouseleave", stopPainting);
596
+ canvasRefState.addEventListener("touchstart", startPainting);
597
+ canvasRefState.addEventListener("touchend", stopPainting);
598
+ canvasRefState.addEventListener("touchmove", paint);
599
+ canvasRefState.addEventListener("touchcancel", stopPainting);
1110
600
  return () => {
1111
- canvas.removeEventListener("mousedown", startPainting);
1112
- canvas.removeEventListener("mouseup", stopPainting);
1113
- canvas.removeEventListener("mousemove", paint);
1114
- canvas.removeEventListener("mouseleave", stopPainting);
1115
- canvas.removeEventListener("mouseenter", handleMouseEnter);
601
+ canvasRefState.removeEventListener("mousedown", startPainting);
602
+ canvasRefState.removeEventListener("mouseup", stopPainting);
603
+ canvasRefState.removeEventListener("mousemove", paint);
604
+ canvasRefState.removeEventListener("mouseleave", stopPainting);
605
+ canvasRefState.removeEventListener("touchstart", startPainting);
606
+ canvasRefState.removeEventListener("touchend", stopPainting);
607
+ canvasRefState.removeEventListener("touchmove", paint);
608
+ canvasRefState.removeEventListener("touchcancel", stopPainting);
1116
609
  };
1117
- }, [startPainting, stopPainting, paint, handleMouseEnter]);
610
+ }, [startPainting, stopPainting, paint, canvasRefState]);
1118
611
  const clear = () => {
1119
- const canvas = canvasRef.current;
1120
612
  const context = contextRef.current;
1121
- if (canvas && context) {
1122
- context.clearRect(0, 0, canvas.width, canvas.height);
1123
- const initialDataUrl = canvas.toDataURL();
613
+ if (canvasRefState && context) {
614
+ context.clearRect(0, 0, canvasRefState.width, canvasRefState.height);
615
+ const initialDataUrl = canvasRefState.toDataURL();
1124
616
  setHistory([initialDataUrl]);
1125
617
  setHistoryIndex(0);
1126
618
  onChange && onChange();
@@ -1141,15 +633,14 @@ function usePaint(paintProps = {}) {
1141
633
  }
1142
634
  };
1143
635
  const loadImage = (base64String) => {
1144
- const canvas = canvasRef.current;
1145
636
  const context = contextRef.current;
1146
- if (!canvas || !context) {
637
+ if (!canvasRefState || !context) {
1147
638
  return;
1148
639
  }
1149
640
  const img = new Image();
1150
641
  img.onload = () => {
1151
- context.clearRect(0, 0, canvas.width, canvas.height);
1152
- context.drawImage(img, 0, 0, canvas.width, canvas.height);
642
+ context.clearRect(0, 0, canvasRefState.width, canvasRefState.height);
643
+ context.drawImage(img, 0, 0, canvasRefState.width, canvasRefState.height);
1153
644
  saveState();
1154
645
  };
1155
646
  img.src = base64String;
@@ -1157,7 +648,7 @@ function usePaint(paintProps = {}) {
1157
648
  const getBase64String = (imageProps) => {
1158
649
  const props = { ...DEFAULT_DOWNLOAD_PROPS, ...imageProps };
1159
650
  const { fileExtendsion, transparent, backgroundColor, width, height } = props;
1160
- const originalCanvas = canvasRef.current;
651
+ const originalCanvas = canvasRefState;
1161
652
  if (!originalCanvas) {
1162
653
  return;
1163
654
  }
@@ -1177,7 +668,7 @@ function usePaint(paintProps = {}) {
1177
668
  const download = (downloadProps) => {
1178
669
  const props = { ...DEFAULT_DOWNLOAD_PROPS, ...downloadProps };
1179
670
  const { fileName, fileExtendsion, transparent, backgroundColor, width, height } = props;
1180
- const originalCanvas = canvasRef.current;
671
+ const originalCanvas = canvasRefState;
1181
672
  if (!originalCanvas) {
1182
673
  return;
1183
674
  }
@@ -1197,16 +688,39 @@ function usePaint(paintProps = {}) {
1197
688
  link.click();
1198
689
  }
1199
690
  };
691
+ const isCanvasBlank = () => {
692
+ if (!canvasRefState) {
693
+ return true;
694
+ }
695
+ const { width, height } = canvasRefState;
696
+ const ctx = canvasRefState.getContext("2d");
697
+ if (!ctx) {
698
+ console.error("2D context not available");
699
+ return true;
700
+ }
701
+ const imageData = ctx.getImageData(0, 0, width, height);
702
+ const { data } = imageData;
703
+ for (let i = 0; i < data.length; i += 4) {
704
+ if (data[i + 3] !== 0) {
705
+ return false;
706
+ }
707
+ }
708
+ return true;
709
+ };
1200
710
  return {
1201
711
  clear,
1202
712
  undo,
1203
713
  redo,
1204
714
  loadImage,
1205
715
  download,
1206
- canvasRef,
1207
- getBase64String
716
+ getBase64String,
717
+ isCanvasBlank,
718
+ setCanvasRefState,
719
+ canvasRefState
1208
720
  };
1209
721
  }
1210
722
 
1211
- export { Attachment, DataTable, FormDatePicker, FormSegmentGroup, FormSignature, FormTextField, StepIndicator, resize, useCamera, useFormSignature, usePaint, useTable };
723
+ const testSignatureBase64Data = "data:image/png;base64,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";
724
+
725
+ export { Attachment, FormDatePicker, FormSegmentGroup, FormTextField, StepIndicator, resize, testSignatureBase64Data, useCamera, useCanvasPaint };
1212
726
  //# sourceMappingURL=index.esm.js.map