sales-frontend-components 0.0.34 → 0.0.35

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,10 +1,11 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { flexRender, useReactTable, getSortedRowModel, getCoreRowModel, getPaginationRowModel } from '@tanstack/react-table';
3
3
  import styles from './data-table/data-table.module.scss';
4
- import { Table, DatePicker, SegmentGroup, FormField } from 'sales-frontend-design-system';
5
- import React, { useState } from 'react';
4
+ import { Table, DatePicker, SegmentGroup, FormField, Button } from 'sales-frontend-design-system';
5
+ import React, { useState, useRef, useEffect, useCallback, useImperativeHandle } from 'react';
6
6
  import { useController } from 'react-hook-form';
7
- import styles$1 from './step-indicator/step-indicator.module.scss';
7
+ import styles$1 from './form/form-signautre/form-signature.module.scss';
8
+ import styles$2 from './step-indicator/step-indicator.module.scss';
8
9
 
9
10
  function getDefaultExportFromCjs (x) {
10
11
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
@@ -97,7 +98,7 @@ function requireBind () {
97
98
  var bindExports = requireBind();
98
99
  var classNames = /*@__PURE__*/getDefaultExportFromCjs(bindExports);
99
100
 
100
- const cx$1 = classNames.bind(styles);
101
+ const cx$2 = classNames.bind(styles);
101
102
  const DataTable = ({ table, isError, isLoading, msgText, ...props }) => {
102
103
  return /* @__PURE__ */ jsxs(
103
104
  Table,
@@ -112,7 +113,7 @@ const DataTable = ({ table, isError, isLoading, msgText, ...props }) => {
112
113
  "th",
113
114
  {
114
115
  colSpan: header.colSpan,
115
- className: cx$1({
116
+ className: cx$2({
116
117
  "is-resizing": header.column.getIsResizing()
117
118
  // 3. 리사이징 중일 때 클래스 추가
118
119
  }),
@@ -124,7 +125,7 @@ const DataTable = ({ table, isError, isLoading, msgText, ...props }) => {
124
125
  {
125
126
  onMouseDown: header.getResizeHandler(),
126
127
  onTouchStart: header.getResizeHandler(),
127
- className: cx$1("resize-handle")
128
+ className: cx$2("resize-handle")
128
129
  }
129
130
  )
130
131
  ]
@@ -145,7 +146,7 @@ const DataTable = ({ table, isError, isLoading, msgText, ...props }) => {
145
146
  },
146
147
  cell.id
147
148
  )) }, row.id)
148
- )) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { className: cx$1("feedback-cell"), colSpan: table.getVisibleLeafColumns().length, children: isLoading ? /* @__PURE__ */ jsx("div", { children: "Loading..." }) : /* @__PURE__ */ jsx("div", { children: msgText || (isError ? "Error" : "No data") }) }) }) })
149
+ )) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { className: cx$2("feedback-cell"), colSpan: table.getVisibleLeafColumns().length, children: isLoading ? /* @__PURE__ */ jsx("div", { children: "Loading..." }) : /* @__PURE__ */ jsx("div", { children: msgText || (isError ? "Error" : "No data") }) }) }) })
149
150
  ]
150
151
  }
151
152
  );
@@ -294,7 +295,398 @@ const FormTextField = ({
294
295
  );
295
296
  };
296
297
 
297
- const cx = classNames.bind(styles$1);
298
+ const cx$1 = classNames.bind(styles$1);
299
+ const FormSignature = ({
300
+ label,
301
+ error,
302
+ errorMsg,
303
+ onSubmit,
304
+ onRecentSignatureLoad,
305
+ onChangeSignature,
306
+ onReset,
307
+ isShowRecentSignatureButton,
308
+ isShowResetButton,
309
+ ref,
310
+ canvasWidth = 632,
311
+ canvasHeight = 230
312
+ }) => {
313
+ const canvasRef = useRef(null);
314
+ const containerRef = useRef(null);
315
+ const [isDrawing, setIsDrawing] = useState(false);
316
+ const [isEmpty, setIsEmpty] = useState(true);
317
+ const [signatureData, setSignatureData] = useState("");
318
+ const [isLoadingSignature, setIsLoadingSignature] = useState(false);
319
+ const [isMousePressed, setIsMousePressed] = useState(false);
320
+ const [totalLineLength, setTotalLineLength] = useState(0);
321
+ const [lastPoint, setLastPoint] = useState(null);
322
+ const [strokeLengths, setStrokeLengths] = useState([]);
323
+ const [currentStrokeLength, setCurrentStrokeLength] = useState(0);
324
+ useEffect(() => {
325
+ const canvas = canvasRef.current;
326
+ if (!canvas) return;
327
+ const ctx = canvas.getContext("2d");
328
+ if (!ctx) return;
329
+ ctx.strokeStyle = "#000000";
330
+ ctx.lineWidth = Math.max(1, canvasWidth / 400);
331
+ ctx.lineCap = "round";
332
+ ctx.lineJoin = "round";
333
+ }, [canvasWidth]);
334
+ useEffect(() => {
335
+ const handleGlobalMouseUp = () => {
336
+ setIsMousePressed(false);
337
+ if (isDrawing) {
338
+ stopDrawing();
339
+ }
340
+ };
341
+ document.addEventListener("mouseup", handleGlobalMouseUp);
342
+ return () => {
343
+ document.removeEventListener("mouseup", handleGlobalMouseUp);
344
+ };
345
+ }, [isDrawing]);
346
+ const getCanvasCoordinates = useCallback((e) => {
347
+ const canvas = canvasRef.current;
348
+ if (!canvas) return { x: 0, y: 0 };
349
+ const rect = canvas.getBoundingClientRect();
350
+ const scaleX = canvas.width / rect.width;
351
+ const scaleY = canvas.height / rect.height;
352
+ return {
353
+ x: (e.clientX - rect.left) * scaleX,
354
+ y: (e.clientY - rect.top) * scaleY
355
+ };
356
+ }, []);
357
+ const calculateDistance = useCallback((point1, point2) => {
358
+ return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
359
+ }, []);
360
+ const startDrawing = useCallback(
361
+ (e) => {
362
+ const canvas = canvasRef.current;
363
+ if (!canvas) return;
364
+ const ctx = canvas.getContext("2d");
365
+ if (!ctx) return;
366
+ const { x, y } = getCanvasCoordinates(e);
367
+ setIsDrawing(true);
368
+ setIsMousePressed(true);
369
+ setIsEmpty(false);
370
+ setLastPoint({ x, y });
371
+ setCurrentStrokeLength(0);
372
+ ctx.beginPath();
373
+ ctx.moveTo(x, y);
374
+ },
375
+ [getCanvasCoordinates]
376
+ );
377
+ const draw = useCallback(
378
+ (e) => {
379
+ if (!isDrawing) return;
380
+ const canvas = canvasRef.current;
381
+ if (!canvas) return;
382
+ const ctx = canvas.getContext("2d");
383
+ if (!ctx) return;
384
+ const { x, y } = getCanvasCoordinates(e);
385
+ const currentPoint = { x, y };
386
+ if (lastPoint) {
387
+ const distance = calculateDistance(lastPoint, currentPoint);
388
+ if (distance > 0.5) {
389
+ setCurrentStrokeLength((prev) => prev + distance);
390
+ setTotalLineLength((prev) => prev + distance);
391
+ }
392
+ }
393
+ ctx.lineTo(x, y);
394
+ ctx.stroke();
395
+ setLastPoint(currentPoint);
396
+ const data = canvas.toDataURL();
397
+ setSignatureData(data);
398
+ onChangeSignature?.();
399
+ },
400
+ [isDrawing, getCanvasCoordinates, calculateDistance, lastPoint, onChangeSignature]
401
+ );
402
+ const stopDrawing = useCallback(() => {
403
+ if (isDrawing && currentStrokeLength > 0) {
404
+ setStrokeLengths((prev) => [...prev, currentStrokeLength]);
405
+ }
406
+ setIsDrawing(false);
407
+ setLastPoint(null);
408
+ }, [isDrawing, currentStrokeLength]);
409
+ const handleMouseEnter = useCallback(
410
+ (e) => {
411
+ if (isMousePressed && !isDrawing) {
412
+ const canvas = canvasRef.current;
413
+ if (!canvas) return;
414
+ const ctx = canvas.getContext("2d");
415
+ if (!ctx) return;
416
+ const { x, y } = getCanvasCoordinates(e);
417
+ setIsDrawing(true);
418
+ setLastPoint({ x, y });
419
+ ctx.beginPath();
420
+ ctx.moveTo(x, y);
421
+ }
422
+ },
423
+ [isMousePressed, isDrawing, getCanvasCoordinates]
424
+ );
425
+ const handleMouseLeave = useCallback(() => {
426
+ if (isDrawing) {
427
+ setIsDrawing(false);
428
+ setLastPoint(null);
429
+ }
430
+ }, [isDrawing]);
431
+ const clearSignature = useCallback(() => {
432
+ const canvas = canvasRef.current;
433
+ if (!canvas) return;
434
+ const ctx = canvas.getContext("2d");
435
+ if (!ctx) return;
436
+ ctx.clearRect(0, 0, canvasWidth, canvasHeight);
437
+ setIsEmpty(true);
438
+ setSignatureData("");
439
+ setTotalLineLength(0);
440
+ setLastPoint(null);
441
+ setStrokeLengths([]);
442
+ setCurrentStrokeLength(0);
443
+ }, [canvasWidth, canvasHeight]);
444
+ const loadSignatureToCanvas = useCallback(
445
+ (imageDataURL) => {
446
+ return new Promise((resolve, reject) => {
447
+ const canvas = canvasRef.current;
448
+ if (!canvas) {
449
+ reject(new Error("Canvas not found"));
450
+ return;
451
+ }
452
+ const ctx = canvas.getContext("2d");
453
+ if (!ctx) {
454
+ reject(new Error("Canvas context not found"));
455
+ return;
456
+ }
457
+ const img = new Image();
458
+ img.onload = () => {
459
+ ctx.clearRect(0, 0, canvasWidth, canvasHeight);
460
+ ctx.drawImage(img, 0, 0, canvasWidth, canvasHeight);
461
+ setIsEmpty(false);
462
+ setSignatureData(imageDataURL);
463
+ setTotalLineLength(0);
464
+ setStrokeLengths([]);
465
+ setCurrentStrokeLength(0);
466
+ setLastPoint(null);
467
+ resolve();
468
+ };
469
+ img.onerror = () => {
470
+ reject(new Error("Failed to load signature image"));
471
+ };
472
+ img.src = imageDataURL;
473
+ });
474
+ },
475
+ [canvasWidth, canvasHeight]
476
+ );
477
+ const validateForm = useCallback(() => {
478
+ return !(!signatureData || isEmpty);
479
+ }, [signatureData, isEmpty]);
480
+ const getSignatureDataObject = useCallback(() => {
481
+ if (!signatureData || isEmpty) {
482
+ return null;
483
+ }
484
+ return {
485
+ signature: signatureData,
486
+ totalLineLength: Math.round(totalLineLength),
487
+ strokeCount: strokeLengths.length,
488
+ strokeLengths: strokeLengths.map((length) => Math.round(length)),
489
+ averageStrokeLength: strokeLengths.length > 0 ? Math.round(totalLineLength / strokeLengths.length) : 0
490
+ };
491
+ }, [signatureData, isEmpty, totalLineLength, strokeLengths]);
492
+ const handleSubmit = useCallback(() => {
493
+ if (!validateForm()) return;
494
+ const data = getSignatureDataObject();
495
+ if (data) {
496
+ console.log("\uC81C\uCD9C\uB41C \uB370\uC774\uD130:", data);
497
+ onSubmit(data);
498
+ }
499
+ }, [validateForm, getSignatureDataObject, onSubmit]);
500
+ const handleReset = useCallback(() => {
501
+ clearSignature();
502
+ onReset?.();
503
+ }, [clearSignature, onReset]);
504
+ const handleRecentSignatureLoad = useCallback(async () => {
505
+ if (!onRecentSignatureLoad) return;
506
+ try {
507
+ setIsLoadingSignature(true);
508
+ const loadedSignature = await onRecentSignatureLoad();
509
+ if (loadedSignature) {
510
+ await loadSignatureToCanvas(loadedSignature);
511
+ console.log("\uCD5C\uADFC \uC11C\uBA85\uC744 \uC131\uACF5\uC801\uC73C\uB85C \uBD88\uB7EC\uC654\uC2B5\uB2C8\uB2E4.");
512
+ } else {
513
+ alert("\uBD88\uB7EC\uC62C \uCD5C\uADFC \uC11C\uBA85\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
514
+ }
515
+ } catch (error2) {
516
+ console.error("\uCD5C\uADFC \uC11C\uBA85 \uBD88\uB7EC\uC624\uAE30 \uC2E4\uD328:", error2);
517
+ alert("\uCD5C\uADFC \uC11C\uBA85\uC744 \uBD88\uB7EC\uC624\uB294\uB370 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
518
+ } finally {
519
+ setIsLoadingSignature(false);
520
+ }
521
+ }, [onRecentSignatureLoad, loadSignatureToCanvas]);
522
+ useImperativeHandle(
523
+ ref,
524
+ () => ({
525
+ submit: handleSubmit,
526
+ clear: clearSignature,
527
+ getSignatureData: getSignatureDataObject,
528
+ isValid: validateForm
529
+ }),
530
+ [handleSubmit, clearSignature, getSignatureDataObject, validateForm]
531
+ );
532
+ return /* @__PURE__ */ jsxs("div", { children: [
533
+ /* @__PURE__ */ jsxs("div", { className: cx$1("form-label"), children: [
534
+ /* @__PURE__ */ jsx("label", { className: "typo-subtitle3 text-body_1", children: label }),
535
+ /* @__PURE__ */ jsxs("div", { className: cx$1("form-label-button-box"), children: [
536
+ isShowResetButton && /* @__PURE__ */ jsx(
537
+ Button,
538
+ {
539
+ appearance: "filled",
540
+ variant: "neutral",
541
+ size: "xsmall",
542
+ onClick: handleReset,
543
+ className: "text-nowrap-i",
544
+ disabled: isEmpty,
545
+ children: "\uB2E4\uC2DC \uC791\uC131"
546
+ }
547
+ ),
548
+ isShowRecentSignatureButton && /* @__PURE__ */ jsx(
549
+ Button,
550
+ {
551
+ appearance: "filled",
552
+ variant: "neutral",
553
+ size: "xsmall",
554
+ className: "text-nowrap-i",
555
+ onClick: handleRecentSignatureLoad,
556
+ disabled: isLoadingSignature,
557
+ children: isLoadingSignature ? "\uBD88\uB7EC\uC624\uB294 \uC911..." : "\uCD5C\uADFC \uC131\uBA85 \uBD88\uB7EC\uC624\uAE30"
558
+ }
559
+ )
560
+ ] })
561
+ ] }),
562
+ /* @__PURE__ */ jsx("div", { className: cx$1("form-signature", error && "is-error"), ref: containerRef, children: /* @__PURE__ */ jsx(
563
+ "canvas",
564
+ {
565
+ ref: canvasRef,
566
+ width: canvasWidth,
567
+ height: canvasHeight,
568
+ className: "border border-gray-200 rounded cursor-crosshair bg-white",
569
+ style: { width: "100%", height: `${canvasHeight}px` },
570
+ onMouseDown: startDrawing,
571
+ onMouseMove: draw,
572
+ onMouseUp: stopDrawing,
573
+ onMouseEnter: handleMouseEnter,
574
+ onMouseLeave: handleMouseLeave
575
+ }
576
+ ) }),
577
+ error && /* @__PURE__ */ jsx("div", { className: cx$1("error-msg-box"), children: /* @__PURE__ */ jsx("span", { className: cx$1("error-msg"), children: errorMsg || "\uC11C\uBA85\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694." }) })
578
+ ] });
579
+ };
580
+
581
+ const useFormSignature = ({ onSubmit, onError, onClear, minLength = 100 } = {}) => {
582
+ const signatureRef = useRef(null);
583
+ const [signatureData, setSignatureData] = useState(null);
584
+ const [isError, setIsError] = useState(false);
585
+ const [errorMessage, setErrorMessage] = useState("");
586
+ const [isLoadedFromRecent, setIsLoadedFromRecent] = useState(false);
587
+ const handleSignatureSubmit = useCallback(
588
+ (data) => {
589
+ setSignatureData(data);
590
+ setIsError(false);
591
+ setErrorMessage("");
592
+ onSubmit?.(data);
593
+ },
594
+ [onSubmit]
595
+ );
596
+ const submit = useCallback(() => {
597
+ try {
598
+ if (!signatureRef.current?.isValid()) {
599
+ setIsError(true);
600
+ setErrorMessage("\uC11C\uBA85\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694.");
601
+ return false;
602
+ }
603
+ const data = signatureRef.current.getSignatureData();
604
+ if (!data) {
605
+ setIsError(true);
606
+ setErrorMessage("\uC11C\uBA85 \uB370\uC774\uD130\uB97C \uAC00\uC838\uC62C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
607
+ return false;
608
+ }
609
+ if (!isLoadedFromRecent && data.totalLineLength < minLength) {
610
+ setIsError(true);
611
+ setErrorMessage(`\uC11C\uBA85\uC744 \uB2E4\uC2DC \uD655\uC778\uD574 \uC8FC\uC138\uC694.`);
612
+ return false;
613
+ }
614
+ setIsError(false);
615
+ setErrorMessage("");
616
+ signatureRef.current.submit();
617
+ return true;
618
+ } catch (error) {
619
+ const errorObj = error instanceof Error ? error : new Error("\uC54C \uC218 \uC5C6\uB294 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
620
+ setIsError(true);
621
+ setErrorMessage(errorObj.message);
622
+ onError?.(errorObj);
623
+ return false;
624
+ }
625
+ }, [onError, minLength, isLoadedFromRecent]);
626
+ const clear = useCallback(() => {
627
+ signatureRef.current?.clear();
628
+ setSignatureData(null);
629
+ setIsError(false);
630
+ setErrorMessage("");
631
+ setIsLoadedFromRecent(false);
632
+ onClear?.();
633
+ }, [onClear]);
634
+ const loadRecentSignature = useCallback(async () => {
635
+ setIsLoadedFromRecent(true);
636
+ setIsError(false);
637
+ setErrorMessage("");
638
+ return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAADmCAYAAAAtKeFcAAAAAXNSR0IArs4c6QAAH/dJREFUeF7t3U3vNFlZB+AbeRsYYVQmBsYYwYkxMRFN1I0BGXcaV6zcupeFfgKBLyALXLDR+AlgYeISEFzhQtQQYxBFhTHKxAHD8Cbqc4Yupp6m+9/1cs5dp6qvTp7MzDNd5+U6p0/Vr6ur6lXhRYAAAQIECBAgQIAAgSSBVyXVoxoCBAgQIECAAAECBAiEAGISECBAgAABAgQIECCQJiCApFGriAABAgQIECBAgAABAcQcIECAAAECBAgQIEAgTUAASaNWEQECBAgQIECAAAECAog5QIAAAQIECBAgQIBAmoAAkkatIgIECBAgQIAAAQIEBBBzgAABAgQIECBAgACBNAEBJI1aRQQIECBAgAABAgQICCDmAAECBAgQIECAAAECaQICSBq1iggQIECAAAECBAgQEEDMAQIECBAgQIAAAQIE0gQEkDRqFREgQIAAAQIECBAgIICYAwQIECBAgAABAgQIpAkIIGnUKiJAgAABAgQIECBAQAAxBwgQIECAAAECBAgQSBMQQNKoVUSAAAECBAgQIECAgABiDhAgQIAAAQIECBAgkCYggKRRq4gAAQIECBAgQIAAAQHEHCBAgAABAgQIECBAIE1AAEmjVhEBAgQIECBAgAABAgKIOUCAAAECBAgQIECAQJqAAJJGrSICBAgQIECAAAECBAQQc4AAAQIECBAgQIAAgTQBASSNWkUECBAgQIAAAQIECAgg5gABAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIINvPgf87NeGJiPjW9s2p2oKhb+WfP1S1ZIURIECAAAECBAjsUkAA2X7YhoP0Ej5KCDnSa+hb6ZO5dqSR1RcCBAgQIECAwEIBB4UL4SpuJoBUxFQUAQIECBAgQIBA3wICyPbjMwSQlyLiye2bU7UFzoBU5VQYAQIELgq8KSLeEBH/wYcAAQJ7EBBAth8lAWT7MdACAgQI7FXgHyLiZ06Nt0/f6yhqN4E7E7BYbT/gQwD5WkQ8tX1zqrbAGZCqnAojQIDAYwLj8OFmHyYHAQK7ERBAth8qAWT7MdACAgQI7FHAlzx7HDVtJkDAnYk6mAPDDuSFiHi6g/bUbIKdY01NZREgQOBxgWGN/XREvBsOAQIE9iLgDMj2IzXsQJ6PiGe2b07VFgggVTkVRoAAgccEhjX2YxHxXjYECBDYi4AAsv1ICSDbj8E9tuBXI+IvO38+y/sj4rcj4h2nB1mWh1mWNet83br13/c4vvp8HwL3GEC+HRGv7XztajX7/nfC+teqbuUSqCoggFTlXFTYkZ8W7gzIoimRslHv8+7jEfHcCglr2wo8m+5GYDggvaczIMPaVX6yXH66fA+vS8Fj3G/r3T3MgoP10aTdfkC/HBFvOzXjaHcxEUDWza9/PH37X+6QVl4vnv759nXFvrx17wGktHF8BuT1o8/IlB2vta3CJFFE9wL3FkB62qfcCgWZk8d6l6mtrioCJm0VxtWFjBeyI41JTzuL1YOUXEAJHz99pc4ac2QPAaR0/3wn/0REfOuKi/mWPElVt7nA8Pn4o4h43+atad+Anj7j47a07/n3vjQqP0MdXkc9bsiwVEcHAjUOZDroxiGaMCxmRxqTnnYWayfJ/0TEq9cWsnD7r0bEN09//qzSgUbvAeTSt4u3zhAeab4tnCo2uzOB70TEayLi3gLIOx9ddP/ZK9eEZU2Bn4yIf0mo7Nq6J4Ak4KuincCRDnbbKeWULIDkOM+tZcvgceuAe25fxu/vOYCcf7M41UEAWTMjbLtHgSGA3MO+/PzzfcR95pw5+N3RGZF7GP85Nt67AwGTtp9BOuJiutcDwodOrZdAculAfvi78q3UpVfZWQyv8zLKQcT4Ve7yUl4tb8vcawA5t5+zRu11vvWzCmnJFgLZP+Wp1cfS7vLnXyOi1pnZh9p2LYAM28xZK2oZbFmOALKlvrpXC9zbB3Y1WMMCBJCGuDOKvnYwUBb78lOHo7x6DCBrwkcZFwHkKLPzfvqx1/BxPkJfjIgaN8eYEkDKNWDlWrBLdvd0TDM+O39P/b6f1eHgPTVp5w1wzzuLcqekp+Z1p/m793ZAeOmnP+WMxkPB4zci4s8jopzFeF1z0XoV9BZA1oYPAaTe3FBSG4GH9h/lC47x/5+6r7l2xrX0YHzW9aEenZ+RHb/32tnZcpOM8irXYZRXxgXwg8kQQErg+fyFa/Pu5bhGAGnzOVVqksC9fFBrcU7dKdSqb2k5vYSRPQeQqZ+NvfVxmFNDu8sBzFYX14/n91rH84vWp47f0s+Y7QjMFbiXs6tzXaa8/9b6UOMLjCnt6Ok9AkhPo6EtswXspGeTvXxb0GsHTkv/viye5cmu5VW+cXroW63ynvNvtt44vxuLthi+eZq68a2dxtRyMt9Xrrsoz2aZ+tpjH0vfxmdAPvjoL8ozN7Z8XTs4m7JGCR9bjpy65wicn214U0R8Y04Bd/jeqeFi6vuOQiiAHGUk77QfU3bud0qT0u3yzfP5qfc1Y1Ju1/rmxi2f0769HpzPIRz38cmIeGnOxhu+dxxAypj++qMnj39iw/ZMeajXpbknfGw4aKom0FhgbqiY+/7GzW9avADSlFfhrQXmHEy2bsu9lX/pG9/yd+MHDe3d5N4CSBmvvYzh+fzbOoCcz/UlP3e0nu19xdB+Aq8ILA0Tl9aOuWfv9zAOAsgeRkkbrwrYYW83Oc4Xyb0cuM4Ru8cAUnx6+VyVM2Lji0iH2/u+9ayNZUc2/ARwzvhmvXdKGOnFPMtEPQSOLrBm/3FpzTjaGjE8A6anfc7R56T+VRQ42geyIk3zogSQ5sTNK1hz3UKrxpXQUV5Tf4rXy0XorTyUS4DA/gTWhI9xb8/X6OcbP18pU1oAydRWV3UBAaQ66aQCrx24Hu0sSK2dyCTUDd6UEUDKWYvxTQmu3VqznMWYGjrGVEd7vskG00CVBAhUFqi17yjX5L1h1LYjHfMIIJUnneJyBY70YcyVW17beGEdAselv1teQz9b1tqJ9NOjV1py3rcWfZ3y06NrNrduxTyULYD0OLu0icD9CtRcS5+LiI8/+snpBx5xbn2nv9ojKoDUFlVeqoAAksr9cmXD4np+tuOIIaTmjiR/pB6u8bxv5UB+fAOBGp+tcvZjzrUZt0LHuEcCSG8zSnsIXBYYHvr3joj49wsPPB3WiPLA1HInvj2/xuvqnPXsWp9LACl/yh3+trzLX4sxGe8fauxvWrRRmQSuCpi0uZPj1gH5+Tfeex+fW/3N1a9X27V+7Wn8BJB680FJBFoJvBgRTy0ofI/7jvH6+UJEPL2g3/e0iQByT6N9wL7ucZHa8zAMC+xD7pd+drPXcbq3ADI+wzXM017Hbhib3u+Alfl5f+hZJIPXkW6TnWmrrmUCn4yIX1u26cvPJNrTGZGj7i8WDt/NzQSQm0Te0LNArwdHPZstbdvcxfU8iJz/ZGtpOzK3m9vnzLYtrWtKn/ZwJkQAeXwGTL3e5gsR8ezSyWM7AjMF5v4093we7+n5F1PW1pl8h367AHLo4T1+5wSQvDG+du3HrRbM3QHdKi/z/x9xhzK1T72HkL0EkClPSM+Y08Xrn4SPDGp1jATG60i5hqE8MHTKa29n0qeuq1P6fi/v+WZEvP7UWcdy9zLqB+qnSZs3mFN+fnWtNXsNIUfcqcwZx55DSM8BZMvQYU3MWxPVdFvgfA0pAWTqxdR7CSH/Obre49MR8e7bLN4REQKIabBrATvbnOGrcSDe88HslOB0hLm2ZBx7HbfsALJlqJjyKd/jTxyn9Mt79i0w9aeBt3rZ6+22yy1yy12qykv4uDWKj///8tDZ4dlPR9i/zuu9d+9ewKTNGcIlB66XWraXb7SGttfqd84o3a5laX96HLehTeVe8q+73fVF71gTOob2Tbno++sR8cZTC61pi4bKRp0KrPkMjbvU6+di+JzPObPT6VClN0sASSdXYU2BXhelmn3soaxhka3xLeulg9ka5bZwWnrA3qItNcqc8/Or8/rGp8t7ODBoEUDWHizNCR1jQwGkxuxWRq8Ca86ClG3Ln1d32rnhGR2dNq/rZn0qIt7li5eux0jjHhAQQHKmx5oD12stPN8p9RhCjhRAysPAfrrCYt/L2ZAWAeTagdKluVlzbtQsK2dFUAsBAgTWCXw4In73FDCnnCleV5utCVQWEEAqg14orvXB0bj83kJI6763H71XaqgVQIYSzw/Wsz+LLQLIWyPiy6NBeWinWGtu1Concy6pi0BtgRZfctVuY8/lnZ+9Lc9HKn/KmevPjq5T6akPQwCZ+yynj546UX72NlxDUuZPMTh/fSQi3tdTp7XlOALZBz3HkZvek4wDpF5DSEbfp4/EunfWDiClNVuGkKHurZ4TUGNufCUi3nIaVmvZuvlt630LjH++uOYnW/tWWNb6Wz8dLQ+DHC6UX1ZDm61Km8pF/F+MiLefVXEpZCxZIy+V3aY3Sr07gSUT8u6QVnZ42Bm0PjvRYwipcZC5kr/a5uUuMsM3+jU/Nw8dLPx+RHyoWg8eL0gAaQSrWAIbCDgD8jh6OSsw97qX8pDRcj3ZX5yK+vzpn63W4KXTpFz7Mbx+5fQvw/NAppQ5zJWvnQJM2eZLVzZ09mOKqPcsEqh5ILWoAXewUeaOobcQcpQA8jcR8fOnudoiSF4LIQLIwwuEMyB3sIDq4iSBzP3MpAZt+Kal4ePZDds8VL02XAzlXAoZ5f+9t4M+agKBlwUEkLYTYYsD8J5CSMaDkh46g/CBR8P7/gpDnDWOw08BWoSccwZnQCpMDEUQ6ETg3gPItf1Ai2Oc8dnwrYe//IS2vD4zasi1BzkORk9HxAtbN1z9BFp8OKm+IpB14Hrt4LL8fcbB7ENj3nLHeOu3zrUDSOvPy3CdScaYHSGAlAve33aafK3HxrpGoGeBluvsHvp9qY2t1oR/i4ifSECZEy6mNGeYIy2f/TSlHd5D4GWBVh9QvN8TyLr+45L3+OC8fLM+9/ewtcZwbNBqvj0fEc/UavCFco64cxdAGk4YRRNIFjjKGnXrgvBbX3Zl3Y52aj2X7iyVPDW+X50AspW8ei8KtDogxP14ANnKuYcQcussxdq50jp8lPaVn5KV1xNrG9vR9sO4vBQRT27QrhpnB1vcmWwDClUSWCXQ6wPp5h58L91PZpwxXjVAFTf+8Yj4RkT894Iyt/7SaUGTbXJkgaUf+COb1OpbjQOsGm0Zt2Pu/cLX1n8ePpz6XStab3sBpJ6lkghsJTC+zq60oZd9+tovnnrpx1bjeq3eNWe6BJDeRvPO2+ND3m4C9BJASg+3CiElcLxmRGy+tZtvc0s+QgAZ353M3Jo7A7y/F4FfjohPnzWmXOg8fpUvj85f5dar49uvlm3G6+2W/VsaQHyOr4/aD4/OfFxz+r2I+OtTEZ84K2rrNX/L+ajuDgV82NsMSk/hY+jhuE3ZZyJ889Jmnq0pdeudUY3nqggga2aAbXsQ+LGkOxKVux6Vux957VegPLfjTafmXzp2K4HjPaPulSedj0PI1mv+fuW1vImAANKE9bEzDj0ZbxVCLHxt5tmaUocx2erAZLhXf2nHBx91ZOntkks5n4uId67BsC2BDQWWni3IbPLQxuG6jl7OtFwyKGcBfuT0P5auK5m2U+r6akS8efTG8+OKcfgoZ0BejIgSQIZXj1+KTum39xxYoKeD46Mwj+/i0aPveCEqt/nLuLBaAOlvdg9j8rGNHk41PntRdGrdMrk/aS0ikCtQHtBZXm9pWG1PP/cad7OEjz8c/cVR1pWHAsQ4fFx7eK0A0vDDoOhlAj0eIC/rST9b9R5AilR2CBFA+pmfpSXjnXSNAPJLEfFXCy6ALWcvvhQRf3L6qcD5b5b7UtMaAscRmBtShjW8/LP86ems43ifW9p26bhm78c61y4+L2c7fuE0LYWP43w+76Ine/9Q9jhIewgg5yGk9TwQQPqZqee/E76205rT4vHBydT7488p33sJECBwSWDuz9da7+tajdJ5APnnR1/c/NSosofWcWc/Wo2KclcJ7PXDuKrTjTfeYwApJC3nggDSeNLNLH440/BflX5+JYDMHABvJ0BgtcC18DHcQWzKw3db7vdWd3BUwPganPGXPOUs8kci4n0PVLb19X41HZR1IIG9fPj2RL6XAHJ+UVvLECKA7GkGz2+rADLfzBYECCwXOA8fU45lLgWW7DtCLu3xedunBI+hLgFkqbrtmgpM+dA2bcABC99LACn040Wt/Hurn88IIMsm+nOPro0of3q/k4sAsmx8bUWAwHyBJeFjXMt4+70EkI9GxG9FxEuPbrX78Zlnrof+Ph8Rz8zntgWBNgICSH3XPQWQ0vvheQwCSP25sKbEEjzKjqa8zu/nvqbcFtsKIC1UlUmAwCWBGtc03NOaJYD4HHUpIIDUH5a9BZDheQxF4pOnb9xrqzgDclu0GF26g8sebiN5Tzvz2yPpHQS2FSh3ufuD07MgysXK41dZ48s1YHu+49z5BdlTtMf75fH7W37x9lC7fjYi/v605rf65cFQ/+D1hYh4dgqW9xDIEBBA6ivvLYCcP4+hxl2RzlUFkIfn2aci4l0X3vKnEfE79ado9RIFkOqkCiQwS2AIHcMD+B7aeA9fajzU/rkB5Fr4KHVsdQxU4yzO1AkigEyV8r5Uga0+fKmdTK5sbwGk8JQQ8scnpw818BoWwK89ekjUUw3KP0KRly6QnNqvrT/HAsjUkfI+AnUFxmew55a89boxt73D+9eslefbtj77cK2PWwSQv42Idy5Ftx2B2gJ7XYBqO9Qsb48BpGb/L5UlgDws/NA3dFPHZsvPsgAydZS8j0BdgTUBZNySLdePuSJLA0hPfcwMIMMcEUDmzjTvbyrQ0weyaUeTCl97d46kZqZXI4BcJz+fM+W//+709qcj4nWnf3/D6Z+vPf2zfHN3fp/7rT7PAkj6R0qFBL4vUM5gl1dZL8avt43+44XR+vHmK3blDktP7sS1fGkz57XVmY5rbcwMIHOcvJdAmsBWByxpHUys6CsR8Zaz+vh+D0QAuTwRL535mDtnejjjJoAkLjSqIjBB4HxtubSuXHoW1J5CyASGbt8igHQ7NBqWJTD3YCerXXurx5mPh0dMALkdQNZ8FudelFnr83Xp7E1v3zTW6qtyCOxJYO4B7qWfNa1Zk/ZktUVb547PFm1UJ4GmAhaYOrwCiACyZCbVOnvRSwCxniyZBbYhUFdg6bpiP1Z3HB4qTQDJs1ZTpwIOGOoMzFYHgHVa374UZ0CcAWk/y9RAgEARWBpABj37s/bzSABpb6yGzgUEkDoD9M1TMU/UKe5wpQyLbbkQ8vxCycN1dkaH1h4o1DjYmNHcH3jrpWtYyh1Xxq9h7IeLRr979v/H7//OwsZ8OyKeWbitzQgcTWD8uSyfv7k/ixRA2s8IAaS9sRo6FxBAOh+ggzRPALk8kGsDSC8/mbj0+/Eep+7zp0YJKz2OjjbVElhzc4vxbX0dH9QakR8s52gB5BMR8Z4NH+zYbqSU3EzAAtOMVsEjgWGxLQeADv5egTn/pnLupDn//G71ea7xHJO5fW/9/i80rODrMx8I9typLb8YES0eFNqwq4reSGDulxPlM3x+tmSr9WQjstRqWwSQL5968I0KPSlr1K1XuYva8HrX6V/MmVtq/v/3BUwWkyFDQAC5rFzrwN3n+HHfYUc8fg5CxjxfWsf4Z2mfuxBOxgcrL0bEjy6tyHZ3JTD1p1jugJU/LdYEkJ7XN/ui/Lm02xpNlt0O3a4aPiy25VvlZ3fV8vaNXfvzpSW/8W7fq/3U0PPOvCiWcDJ+4KQAsp+51UNLl6wvjgvaj9yScWnfqnU1fCsiXAe7zvCutrbQ3NVwb9ZZAWQzehV3LlCeYv1zozaeP93+UvOt250PamfNm3Kwa07lDlq5cc3rK1TpurYKiIrYRsCis437vdX64Yj4TWc/7m3Y9XelwDiclJ/TlD+fiYh3ryzX5vcncC2EOIO63VyYEgyH1gka242TmhsJCCCNYBVLgAABAgQIECBAgMAPCgggZgUBAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIIOYAAQIECBAgQIAAAQJpAgJIGrWKCBAgQIAAAQIECBAQQMwBAgQIECBAgAABAgTSBASQNGoVESBAgAABAgQIECAggJgDBAgQIECAAAECBAikCQggadQqIkCAAAECBAgQIEBAADEHCBAgQIAAAQIECBBIExBA0qhVRIAAAQIECBAgQICAAGIOECBAgAABAgQIECCQJiCApFGriAABAgQIECBAgAABAcQcIECAAAECBAgQIEAgTUAASaNWEQECBAgQIECAAAECAog5QIAAAQIECBAgQIBAmoAAkkatIgIECBAgQIAAAQIEBBBzgAABAgQIECBAgACBNAEBJI1aRQQIECBAgAABAgQICCDmAAECBAgQIECAAAECaQICSBq1iggQIECAAAECBAgQEEDMAQIECBAgQIAAAQIE0gQEkDRqFREgQIAAAQIECBAgIICYAwQIECBAgAABAgQIpAkIIGnUKiJAgAABAgQIECBAQAAxBwgQIECAAAECBAgQSBMQQNKoVUSAAAECBAgQIECAgABiDhAgQIAAAQIECBAgkCYggKRRq4gAAQIECBAgQIAAAQHEHCBAgAABAgQIECBAIE1AAEmjVhEBAgQIECBAgAABAgKIOUCAAAECBAgQIECAQJqAAJJGrSICBAgQIECAAAECBAQQc4AAAQIECBAgQIAAgTQBASSNWkUECBAgQIAAAQIECAgg5gABAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIIOYAAQIECBAgQIAAAQJpAgJIGrWKCBAgQIAAAQIECBAQQMwBAgQIECBAgAABAgTSBASQNGoVESBAgAABAgQIECAggJgDBAgQIECAAAECBAikCQggadQqIkCAAAECBAgQIEBAADEHCBAgQIAAAQIECBBIExBA0qhVRIAAAQIECBAgQICAAGIOECBAgAABAgQIECCQJiCApFGriAABAgQIECBAgAABAcQcIECAAAECBAgQIEAgTUAASaNWEQECBAgQIECAAAECAog5QIAAAQIECBAgQIBAmoAAkkatIgIECBAgQIAAAQIEBBBzgAABAgQIECBAgACBNAEBJI1aRQQIECBAgAABAgQICCDmAAECBAgQIECAAAECaQICSBq1iggQIECAAAECBAgQEEDMAQIECBAgQIAAAQIE0gQEkDRqFREgQIAAAQIECBAgIICYAwQIECBAgAABAgQIpAkIIGnUKiJAgAABAgQIECBAQAAxBwgQIECAAAECBAgQSBMQQNKoVUSAAAECBAgQIECAgABiDhAgQIAAAQIECBAgkCYggKRRq4gAAQIECBAgQIAAAQHEHCBAgAABAgQIECBAIE1AAEmjVhEBAgQIECBAgAABAgKIOUCAAAECBAgQIECAQJqAAJJGrSICBAgQIECAAAECBAQQc4AAAQIECBAgQIAAgTQBASSNWkUECBAgQIAAAQIECAgg5gABAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIIOYAAQIECBAgQIAAAQJpAgJIGrWKCBAgQIAAAQIECBAQQMwBAgQIECBAgAABAgTSBASQNGoVESBAgAABAgQIECDw/zxD0hRoJglmAAAAAElFTkSuQmCC";
639
+ }, []);
640
+ const isValid = useCallback(() => {
641
+ const basicValid = signatureRef.current?.isValid() ?? false;
642
+ if (!basicValid) return false;
643
+ const data = signatureRef.current?.getSignatureData();
644
+ if (!data) return false;
645
+ if (isLoadedFromRecent) return true;
646
+ return data.totalLineLength >= minLength;
647
+ }, [minLength, isLoadedFromRecent]);
648
+ const getSignatureData = useCallback(() => {
649
+ return signatureRef.current?.getSignatureData() ?? null;
650
+ }, []);
651
+ const handleSignatureChange = useCallback(() => {
652
+ setIsError(false);
653
+ setErrorMessage("");
654
+ }, []);
655
+ const handleReset = useCallback(() => {
656
+ setSignatureData(null);
657
+ setIsError(false);
658
+ setErrorMessage("");
659
+ setIsLoadedFromRecent(false);
660
+ onClear?.();
661
+ }, [onClear]);
662
+ const getErrorMessage = useCallback(() => {
663
+ return errorMessage;
664
+ }, [errorMessage]);
665
+ return {
666
+ // ref
667
+ signatureRef,
668
+ // state
669
+ signatureData,
670
+ isError,
671
+ isLoadedFromRecent,
672
+ // 최근 서명 불러옴 여부 노출
673
+ // actions
674
+ submit,
675
+ clear,
676
+ loadRecentSignature,
677
+ handleSignatureChange,
678
+ // 일반적인 서명 변경
679
+ handleReset,
680
+ // 다시 작성
681
+ handleSignatureSubmit,
682
+ // utilities
683
+ isValid,
684
+ getSignatureData,
685
+ getErrorMessage
686
+ };
687
+ };
688
+
689
+ const cx = classNames.bind(styles$2);
298
690
  const StepIndicator = ({
299
691
  items,
300
692
  onClickItem,
@@ -326,5 +718,5 @@ const StepIndicator = ({
326
718
  ] });
327
719
  };
328
720
 
329
- export { DataTable, FormDatePicker, FormSegmentGroup, FormTextField, StepIndicator, useTable };
721
+ export { DataTable, FormDatePicker, FormSegmentGroup, FormSignature, FormTextField, StepIndicator, useFormSignature, useTable };
330
722
  //# sourceMappingURL=index.esm.js.map