sales-frontend-components 0.0.50 → 0.0.51

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.cjs.js CHANGED
@@ -6,9 +6,8 @@ var salesFrontendDesignSystem = require('sales-frontend-design-system');
6
6
  var styles = require('./data-table/data-table.module.scss');
7
7
  var React = require('react');
8
8
  var reactHookForm = require('react-hook-form');
9
- var styles$1 = require('./form/form-signautre/form-signature.module.scss');
10
- var styles$2 = require('./step-indicator/step-indicator.module.scss');
11
- var styles$3 = require('./camera/camera.module.scss');
9
+ var styles$1 = require('./step-indicator/step-indicator.module.scss');
10
+ var styles$2 = require('./camera/camera.module.scss');
12
11
 
13
12
  function getDefaultExportFromCjs (x) {
14
13
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
@@ -101,7 +100,7 @@ function requireBind () {
101
100
  var bindExports = requireBind();
102
101
  var classNames = /*@__PURE__*/getDefaultExportFromCjs(bindExports);
103
102
 
104
- const cx$3 = classNames.bind(styles);
103
+ const cx$2 = classNames.bind(styles);
105
104
  const DataTable = ({ table, isError, isLoading, msgText, ...props }) => {
106
105
  return /* @__PURE__ */ jsxRuntime.jsxs(
107
106
  salesFrontendDesignSystem.Table,
@@ -116,7 +115,7 @@ const DataTable = ({ table, isError, isLoading, msgText, ...props }) => {
116
115
  "th",
117
116
  {
118
117
  colSpan: header.colSpan,
119
- className: cx$3({
118
+ className: cx$2({
120
119
  "is-resizing": header.column.getIsResizing()
121
120
  // 3. 리사이징 중일 때 클래스 추가
122
121
  }),
@@ -128,7 +127,7 @@ const DataTable = ({ table, isError, isLoading, msgText, ...props }) => {
128
127
  {
129
128
  onMouseDown: header.getResizeHandler(),
130
129
  onTouchStart: header.getResizeHandler(),
131
- className: cx$3("resize-handle")
130
+ className: cx$2("resize-handle")
132
131
  }
133
132
  )
134
133
  ]
@@ -149,7 +148,7 @@ const DataTable = ({ table, isError, isLoading, msgText, ...props }) => {
149
148
  },
150
149
  cell.id
151
150
  )) }, row.id)
152
- )) : /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: cx$3("feedback-cell"), colSpan: table.getVisibleLeafColumns().length, children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Loading..." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: msgText || (isError ? "Error" : "No data") }) }) }) })
151
+ )) : /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: cx$2("feedback-cell"), colSpan: table.getVisibleLeafColumns().length, children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Loading..." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: msgText || (isError ? "Error" : "No data") }) }) }) })
153
152
  ]
154
153
  }
155
154
  );
@@ -298,432 +297,7 @@ const FormTextField = ({
298
297
  );
299
298
  };
300
299
 
301
- const cx$2 = classNames.bind(styles$1);
302
- const FormSignature = ({
303
- label,
304
- error,
305
- errorMsg,
306
- onSubmit,
307
- onRecentSignatureLoad,
308
- onChangeSignature,
309
- onReset,
310
- isShowRecentSignatureButton,
311
- isShowResetButton,
312
- ref,
313
- canvasWidth = 632,
314
- canvasHeight = 230
315
- }) => {
316
- const canvasRef = React.useRef(null);
317
- const containerRef = React.useRef(null);
318
- const [isDrawing, setIsDrawing] = React.useState(false);
319
- const [isEmpty, setIsEmpty] = React.useState(true);
320
- const [signatureData, setSignatureData] = React.useState("");
321
- const [isLoadingSignature, setIsLoadingSignature] = React.useState(false);
322
- const [isMousePressed, setIsMousePressed] = React.useState(false);
323
- const [totalLineLength, setTotalLineLength] = React.useState(0);
324
- const [lastPoint, setLastPoint] = React.useState(null);
325
- const [strokeLengths, setStrokeLengths] = React.useState([]);
326
- const [currentStrokeLength, setCurrentStrokeLength] = React.useState(0);
327
- React.useEffect(() => {
328
- const canvas = canvasRef.current;
329
- if (!canvas) {
330
- return;
331
- }
332
- const ctx = canvas.getContext("2d");
333
- if (!ctx) {
334
- return;
335
- }
336
- ctx.strokeStyle = "#000000";
337
- ctx.lineWidth = Math.max(1, canvasWidth / 400);
338
- ctx.lineCap = "round";
339
- ctx.lineJoin = "round";
340
- }, [canvasWidth]);
341
- React.useEffect(() => {
342
- const handleGlobalMouseUp = () => {
343
- setIsMousePressed(false);
344
- if (isDrawing) {
345
- stopDrawing();
346
- }
347
- };
348
- document.addEventListener("mouseup", handleGlobalMouseUp);
349
- return () => {
350
- document.removeEventListener("mouseup", handleGlobalMouseUp);
351
- };
352
- }, [isDrawing]);
353
- const getCanvasCoordinates = React.useCallback((e) => {
354
- const canvas = canvasRef.current;
355
- if (!canvas) {
356
- return { x: 0, y: 0 };
357
- }
358
- const rect = canvas.getBoundingClientRect();
359
- const scaleX = canvas.width / rect.width;
360
- const scaleY = canvas.height / rect.height;
361
- return {
362
- x: (e.clientX - rect.left) * scaleX,
363
- y: (e.clientY - rect.top) * scaleY
364
- };
365
- }, []);
366
- const calculateDistance = React.useCallback((point1, point2) => {
367
- return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
368
- }, []);
369
- const startDrawing = React.useCallback(
370
- (e) => {
371
- const canvas = canvasRef.current;
372
- if (!canvas) {
373
- return;
374
- }
375
- const ctx = canvas.getContext("2d");
376
- if (!ctx) {
377
- return;
378
- }
379
- const { x, y } = getCanvasCoordinates(e);
380
- setIsDrawing(true);
381
- setIsMousePressed(true);
382
- setIsEmpty(false);
383
- setLastPoint({ x, y });
384
- setCurrentStrokeLength(0);
385
- ctx.beginPath();
386
- ctx.moveTo(x, y);
387
- },
388
- [getCanvasCoordinates]
389
- );
390
- const draw = React.useCallback(
391
- (e) => {
392
- if (!isDrawing) {
393
- return;
394
- }
395
- const canvas = canvasRef.current;
396
- if (!canvas) {
397
- return;
398
- }
399
- const ctx = canvas.getContext("2d");
400
- if (!ctx) {
401
- return;
402
- }
403
- const { x, y } = getCanvasCoordinates(e);
404
- const currentPoint = { x, y };
405
- if (lastPoint) {
406
- const distance = calculateDistance(lastPoint, currentPoint);
407
- if (distance > 0.5) {
408
- setCurrentStrokeLength((prev) => prev + distance);
409
- setTotalLineLength((prev) => prev + distance);
410
- }
411
- }
412
- ctx.lineTo(x, y);
413
- ctx.stroke();
414
- setLastPoint(currentPoint);
415
- const data = canvas.toDataURL();
416
- setSignatureData(data);
417
- onChangeSignature?.();
418
- },
419
- [isDrawing, getCanvasCoordinates, calculateDistance, lastPoint, onChangeSignature]
420
- );
421
- const stopDrawing = React.useCallback(() => {
422
- if (isDrawing && currentStrokeLength > 0) {
423
- setStrokeLengths((prev) => [...prev, currentStrokeLength]);
424
- }
425
- setIsDrawing(false);
426
- setLastPoint(null);
427
- }, [isDrawing, currentStrokeLength]);
428
- const handleMouseEnter = React.useCallback(
429
- (e) => {
430
- if (isMousePressed && !isDrawing) {
431
- const canvas = canvasRef.current;
432
- if (!canvas) {
433
- return;
434
- }
435
- const ctx = canvas.getContext("2d");
436
- if (!ctx) {
437
- return;
438
- }
439
- const { x, y } = getCanvasCoordinates(e);
440
- setIsDrawing(true);
441
- setLastPoint({ x, y });
442
- ctx.beginPath();
443
- ctx.moveTo(x, y);
444
- }
445
- },
446
- [isMousePressed, isDrawing, getCanvasCoordinates]
447
- );
448
- const handleMouseLeave = React.useCallback(() => {
449
- if (isDrawing) {
450
- setIsDrawing(false);
451
- setLastPoint(null);
452
- }
453
- }, [isDrawing]);
454
- const clearSignature = React.useCallback(() => {
455
- const canvas = canvasRef.current;
456
- if (!canvas) {
457
- return;
458
- }
459
- const ctx = canvas.getContext("2d");
460
- if (!ctx) {
461
- return;
462
- }
463
- ctx.clearRect(0, 0, canvasWidth, canvasHeight);
464
- setIsEmpty(true);
465
- setSignatureData("");
466
- setTotalLineLength(0);
467
- setLastPoint(null);
468
- setStrokeLengths([]);
469
- setCurrentStrokeLength(0);
470
- }, [canvasWidth, canvasHeight]);
471
- const loadSignatureToCanvas = React.useCallback(
472
- (imageDataURL) => {
473
- return new Promise((resolve, reject) => {
474
- const canvas = canvasRef.current;
475
- if (!canvas) {
476
- reject(new Error("Canvas not found"));
477
- return;
478
- }
479
- const ctx = canvas.getContext("2d");
480
- if (!ctx) {
481
- reject(new Error("Canvas context not found"));
482
- return;
483
- }
484
- const img = new Image();
485
- img.onload = () => {
486
- ctx.clearRect(0, 0, canvasWidth, canvasHeight);
487
- ctx.drawImage(img, 0, 0, canvasWidth, canvasHeight);
488
- setIsEmpty(false);
489
- setSignatureData(imageDataURL);
490
- setTotalLineLength(0);
491
- setStrokeLengths([]);
492
- setCurrentStrokeLength(0);
493
- setLastPoint(null);
494
- resolve();
495
- };
496
- img.onerror = () => {
497
- reject(new Error("Failed to load signature image"));
498
- };
499
- img.src = imageDataURL;
500
- });
501
- },
502
- [canvasWidth, canvasHeight]
503
- );
504
- const validateForm = React.useCallback(() => {
505
- return !(!signatureData || isEmpty);
506
- }, [signatureData, isEmpty]);
507
- const getSignatureDataObject = React.useCallback(() => {
508
- if (!signatureData || isEmpty) {
509
- return null;
510
- }
511
- return {
512
- signature: signatureData,
513
- totalLineLength: Math.round(totalLineLength),
514
- strokeCount: strokeLengths.length,
515
- strokeLengths: strokeLengths.map((length) => Math.round(length)),
516
- averageStrokeLength: strokeLengths.length > 0 ? Math.round(totalLineLength / strokeLengths.length) : 0
517
- };
518
- }, [signatureData, isEmpty, totalLineLength, strokeLengths]);
519
- const handleSubmit = React.useCallback(() => {
520
- if (!validateForm()) {
521
- return;
522
- }
523
- const data = getSignatureDataObject();
524
- if (data) {
525
- console.log("\uC81C\uCD9C\uB41C \uB370\uC774\uD130:", data);
526
- onSubmit(data);
527
- }
528
- }, [validateForm, getSignatureDataObject, onSubmit]);
529
- const handleReset = React.useCallback(() => {
530
- clearSignature();
531
- onReset?.();
532
- }, [clearSignature, onReset]);
533
- const handleRecentSignatureLoad = React.useCallback(async () => {
534
- if (!onRecentSignatureLoad) {
535
- return;
536
- }
537
- try {
538
- setIsLoadingSignature(true);
539
- const loadedSignature = await onRecentSignatureLoad();
540
- if (loadedSignature) {
541
- await loadSignatureToCanvas(loadedSignature);
542
- console.log("\uCD5C\uADFC \uC11C\uBA85\uC744 \uC131\uACF5\uC801\uC73C\uB85C \uBD88\uB7EC\uC654\uC2B5\uB2C8\uB2E4.");
543
- } else {
544
- alert("\uBD88\uB7EC\uC62C \uCD5C\uADFC \uC11C\uBA85\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
545
- }
546
- } catch (error2) {
547
- console.error("\uCD5C\uADFC \uC11C\uBA85 \uBD88\uB7EC\uC624\uAE30 \uC2E4\uD328:", error2);
548
- alert("\uCD5C\uADFC \uC11C\uBA85\uC744 \uBD88\uB7EC\uC624\uB294\uB370 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
549
- } finally {
550
- setIsLoadingSignature(false);
551
- }
552
- }, [onRecentSignatureLoad, loadSignatureToCanvas]);
553
- React.useImperativeHandle(
554
- ref,
555
- () => ({
556
- submit: handleSubmit,
557
- clear: clearSignature,
558
- getSignatureData: getSignatureDataObject,
559
- isValid: validateForm
560
- }),
561
- [handleSubmit, clearSignature, getSignatureDataObject, validateForm]
562
- );
563
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
564
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx$2("form-label"), children: [
565
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "typo-subtitle3 text-body_1", children: label }),
566
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx$2("form-label-button-box"), children: [
567
- isShowResetButton && /* @__PURE__ */ jsxRuntime.jsx(
568
- salesFrontendDesignSystem.Button,
569
- {
570
- appearance: "filled",
571
- variant: "neutral",
572
- size: "xsmall",
573
- onClick: handleReset,
574
- className: "text-nowrap-i",
575
- disabled: isEmpty,
576
- children: "\uB2E4\uC2DC \uC791\uC131"
577
- }
578
- ),
579
- isShowRecentSignatureButton && /* @__PURE__ */ jsxRuntime.jsx(
580
- salesFrontendDesignSystem.Button,
581
- {
582
- appearance: "filled",
583
- variant: "neutral",
584
- size: "xsmall",
585
- className: "text-nowrap-i",
586
- onClick: handleRecentSignatureLoad,
587
- disabled: isLoadingSignature,
588
- children: isLoadingSignature ? "\uBD88\uB7EC\uC624\uB294 \uC911..." : "\uCD5C\uADFC \uC131\uBA85 \uBD88\uB7EC\uC624\uAE30"
589
- }
590
- )
591
- ] })
592
- ] }),
593
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cx$2("form-signature", error && "is-error"), ref: containerRef, children: /* @__PURE__ */ jsxRuntime.jsx(
594
- "canvas",
595
- {
596
- ref: canvasRef,
597
- width: canvasWidth,
598
- height: canvasHeight,
599
- className: "border border-gray-200 rounded cursor-crosshair bg-white",
600
- style: { width: "100%", height: `${canvasHeight}px` },
601
- onMouseDown: startDrawing,
602
- onMouseMove: draw,
603
- onMouseUp: stopDrawing,
604
- onMouseEnter: handleMouseEnter,
605
- onMouseLeave: handleMouseLeave
606
- }
607
- ) }),
608
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cx$2("error-msg-box"), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx$2("error-msg"), children: errorMsg || "\uC11C\uBA85\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694." }) })
609
- ] });
610
- };
611
-
612
- const useFormSignature = ({ onSubmit, onError, onClear, minLength = 100 } = {}) => {
613
- const signatureRef = React.useRef(null);
614
- const [signatureData, setSignatureData] = React.useState(null);
615
- const [isError, setIsError] = React.useState(false);
616
- const [errorMessage, setErrorMessage] = React.useState("");
617
- const [isLoadedFromRecent, setIsLoadedFromRecent] = React.useState(false);
618
- const handleSignatureSubmit = React.useCallback(
619
- (data) => {
620
- setSignatureData(data);
621
- setIsError(false);
622
- setErrorMessage("");
623
- onSubmit?.(data);
624
- },
625
- [onSubmit]
626
- );
627
- const submit = React.useCallback(() => {
628
- try {
629
- if (!signatureRef.current?.isValid()) {
630
- setIsError(true);
631
- setErrorMessage("\uC11C\uBA85\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694.");
632
- return false;
633
- }
634
- const data = signatureRef.current.getSignatureData();
635
- if (!data) {
636
- setIsError(true);
637
- setErrorMessage("\uC11C\uBA85 \uB370\uC774\uD130\uB97C \uAC00\uC838\uC62C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
638
- return false;
639
- }
640
- if (!isLoadedFromRecent && data.totalLineLength < minLength) {
641
- setIsError(true);
642
- setErrorMessage(`\uC11C\uBA85\uC744 \uB2E4\uC2DC \uD655\uC778\uD574 \uC8FC\uC138\uC694.`);
643
- return false;
644
- }
645
- setIsError(false);
646
- setErrorMessage("");
647
- signatureRef.current.submit();
648
- return true;
649
- } catch (error) {
650
- const errorObj = error instanceof Error ? error : new Error("\uC54C \uC218 \uC5C6\uB294 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
651
- setIsError(true);
652
- setErrorMessage(errorObj.message);
653
- onError?.(errorObj);
654
- return false;
655
- }
656
- }, [onError, minLength, isLoadedFromRecent]);
657
- const clear = React.useCallback(() => {
658
- signatureRef.current?.clear();
659
- setSignatureData(null);
660
- setIsError(false);
661
- setErrorMessage("");
662
- setIsLoadedFromRecent(false);
663
- onClear?.();
664
- }, [onClear]);
665
- const loadRecentSignature = React.useCallback(async () => {
666
- setIsLoadedFromRecent(true);
667
- setIsError(false);
668
- setErrorMessage("");
669
- return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAADmCAYAAAAtKeFcAAAAAXNSR0IArs4c6QAAH/dJREFUeF7t3U3vNFlZB+AbeRsYYVQmBsYYwYkxMRFN1I0BGXcaV6zcupeFfgKBLyALXLDR+AlgYeISEFzhQtQQYxBFhTHKxAHD8Cbqc4Yupp6m+9/1cs5dp6qvTp7MzDNd5+U6p0/Vr6ur6lXhRYAAAQIECBAgQIAAgSSBVyXVoxoCBAgQIECAAAECBAiEAGISECBAgAABAgQIECCQJiCApFGriAABAgQIECBAgAABAcQcIECAAAECBAgQIEAgTUAASaNWEQECBAgQIECAAAECAog5QIAAAQIECBAgQIBAmoAAkkatIgIECBAgQIAAAQIEBBBzgAABAgQIECBAgACBNAEBJI1aRQQIECBAgAABAgQICCDmAAECBAgQIECAAAECaQICSBq1iggQIECAAAECBAgQEEDMAQIECBAgQIAAAQIE0gQEkDRqFREgQIAAAQIECBAgIICYAwQIECBAgAABAgQIpAkIIGnUKiJAgAABAgQIECBAQAAxBwgQIECAAAECBAgQSBMQQNKoVUSAAAECBAgQIECAgABiDhAgQIAAAQIECBAgkCYggKRRq4gAAQIECBAgQIAAAQHEHCBAgAABAgQIECBAIE1AAEmjVhEBAgQIECBAgAABAgKIOUCAAAECBAgQIECAQJqAAJJGrSICBAgQIECAAAECBAQQc4AAAQIECBAgQIAAgTQBASSNWkUECBAgQIAAAQIECAgg5gABAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIINvPgf87NeGJiPjW9s2p2oKhb+WfP1S1ZIURIECAAAECBAjsUkAA2X7YhoP0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AgQIECBAgMAPCgggZgUBAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIIOYAAQIECBAgQIAAAQJpAgJIGrWKCBAgQIAAAQIECBAQQMwBAgQIECBAgAABAgTSBASQNGoVESBAgAABAgQIECAggJgDBAgQIECAAAECBAikCQggadQqIkCAAAECBAgQIEBAADEHCBAgQIAAAQIECBBIExBA0qhVRIAAAQIECBAgQICAAGIOECBAgAABAgQIECCQJiCApFGriAABAgQIECBAgAABAcQcIECAAAECBAgQIEAgTUAASaNWEQECBAgQIECAAAECAog5QIAAAQIECBAgQIBAmoAAkkatIgIECBAgQIAAAQIEBBBzgAABAgQIECBAgACBNAEBJI1aRQQIECBAgAABAgQICCDmAAECBAgQIECAAAECaQICSBq1iggQIECAAAECBAgQEEDMAQIECBAgQIAAAQIE0gQEkDRqFREgQIAAAQIECBAgIICYAwQIECBAgAABAgQIpAkIIGnUKiJAgAABAgQIECBAQAAxBwgQIECAAAECBAgQSBMQQNKoVUSAAAECBAgQIECAgABiDhAgQIAAAQIECBAgkCYggKRRq4gAAQIECBAgQIAAAQHEHCBAgAABAgQIECBAIE1AAEmjVhEBAgQIECBAgAABAgKIOUCAAAECBAgQIECAQJqAAJJGrSICBAgQIECAAAECBAQQc4AAAQIECBAgQIAAgTQBASSNWkUECBAgQIAAAQIECAgg5gABAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIIOYAAQIECBAgQIAAAQJpAgJIGrWKCBAgQIAAAQIECBAQQMwBAgQIECBAgAABAgTSBASQNGoVESBAgAABAgQIECAggJgDBAgQIECAAAECBAikCQggadQqIkCAAAECBAgQIEBAADEHCBAgQIAAAQIECBBIExBA0qhVRIAAAQIECBAgQICAAGIOECBAgAABAgQIECCQJiCApFGriAABAgQIECBAgAABAcQcIECAAAECBAgQIEAgTUAASaNWEQECBAgQIECAAAECAog5QIAAAQIECBAgQIBAmoAAkkatIgIECBAgQIAAAQIEBBBzgAABAgQIECBAgACBNAEBJI1aRQQIECBAgAABAgQICCDmAAECBAgQIECAAAECaQICSBq1iggQIECAAAECBAgQEEDMAQIECBAgQIAAAQIE0gQEkDRqFREgQIAAAQIECBAgIICYAwQIECBAgAABAgQIpAkIIGnUKiJAgAABAgQIECBAQAAxBwgQIECAAAECBAgQSBMQQNKoVUSAAAECBAgQIECAgABiDhAgQIAAAQIECBAgkCYggKRRq4gAAQIECBAgQIAAAQHEHCBAgAABAgQIECBAIE1AAEmjVhEBAgQIECBAgAABAgKIOUCAAAECBAgQIECAQJqAAJJGrSICBAgQIECAAAECBAQQc4AAAQIECBAgQIAAgTQBASSNWkUECBAgQIAAAQIECAgg5gABAgQIECBAgAABAmkCAkgatYoIECBAgAABAgQIEBBAzAECBAgQIECAAAECBNIEBJA0ahURIECAAAECBAgQICCAmAMECBAgQIAAAQIECKQJCCBp1CoiQIAAAQIECBAgQEAAMQcIECBAgAABAgQIEEgTEEDSqFVEgAABAgQIECBAgIAAYg4QIECAAAECBAgQIJAmIICkUauIAAECBAgQIECAAAEBxBwgQIAAAQIECBAgQCBNQABJo1YRAQIECBAgQIAAAQICiDlAgAABAgQIECBAgECagACSRq0iAgQIECBAgAABAgQEEHOAAAECBAgQIECAAIE0AQEkjVpFBAgQIECAAAECBAgIIOYAAQIECBAgQIAAAQJpAgJIGrWKCBAgQIAAAQIECBAQQMwBAgQIECBAgAABAgTSBASQNGoVESBAgAABAgQIECDw/zxD0hRoJglmAAAAAElFTkSuQmCC";
670
- }, []);
671
- const isValid = React.useCallback(() => {
672
- const basicValid = signatureRef.current?.isValid() ?? false;
673
- if (!basicValid) {
674
- return false;
675
- }
676
- const data = signatureRef.current?.getSignatureData();
677
- if (!data) {
678
- return false;
679
- }
680
- if (isLoadedFromRecent) {
681
- return true;
682
- }
683
- return data.totalLineLength >= minLength;
684
- }, [minLength, isLoadedFromRecent]);
685
- const getSignatureData = React.useCallback(() => {
686
- return signatureRef.current?.getSignatureData() ?? null;
687
- }, []);
688
- const handleSignatureChange = React.useCallback(() => {
689
- setIsError(false);
690
- setErrorMessage("");
691
- }, []);
692
- const handleReset = React.useCallback(() => {
693
- setSignatureData(null);
694
- setIsError(false);
695
- setErrorMessage("");
696
- setIsLoadedFromRecent(false);
697
- onClear?.();
698
- }, [onClear]);
699
- const getErrorMessage = React.useCallback(() => {
700
- return errorMessage;
701
- }, [errorMessage]);
702
- return {
703
- // ref
704
- signatureRef,
705
- // state
706
- signatureData,
707
- isError,
708
- isLoadedFromRecent,
709
- // 최근 서명 불러옴 여부 노출
710
- // actions
711
- submit,
712
- clear,
713
- loadRecentSignature,
714
- handleSignatureChange,
715
- // 일반적인 서명 변경
716
- handleReset,
717
- // 다시 작성
718
- handleSignatureSubmit,
719
- // utilities
720
- isValid,
721
- getSignatureData,
722
- getErrorMessage
723
- };
724
- };
725
-
726
- const cx$1 = classNames.bind(styles$2);
300
+ const cx$1 = classNames.bind(styles$1);
727
301
  const StepIndicator = ({
728
302
  items,
729
303
  onClickItem,
@@ -755,7 +329,7 @@ const StepIndicator = ({
755
329
  ] });
756
330
  };
757
331
 
758
- const cx = classNames.bind(styles$3);
332
+ const cx = classNames.bind(styles$2);
759
333
  function Attachment({
760
334
  photos,
761
335
  onAddPhoto,
@@ -995,19 +569,18 @@ const DEFAULT_DOWNLOAD_PROPS = {
995
569
  width: 500,
996
570
  height: 500
997
571
  };
998
- function usePaint(paintProps = {}) {
572
+ function useCanvasPaint(paintProps = {}) {
999
573
  const { pen = { strokeWeight: 5, strokeColor: "black" }, onChange, onStart, onEnd } = paintProps;
1000
- const canvasRef = React.useRef(null);
574
+ const [canvasRefState, setCanvasRefState] = React.useState(null);
1001
575
  const contextRef = React.useRef(null);
1002
576
  const [isPainting, setIsPainting] = React.useState(false);
1003
577
  const [history, setHistory] = React.useState([]);
1004
578
  const [historyIndex, setHistoryIndex] = React.useState(-1);
1005
579
  const saveState = React.useCallback(() => {
1006
- const canvas = canvasRef.current;
1007
- if (!canvas) {
580
+ if (!canvasRefState) {
1008
581
  return;
1009
582
  }
1010
- const dataUrl = canvas.toDataURL();
583
+ const dataUrl = canvasRefState.toDataURL();
1011
584
  const newHistory = history.slice(0, historyIndex + 1);
1012
585
  if (newHistory.length >= HISTORY_SIZE) {
1013
586
  newHistory.shift();
@@ -1016,39 +589,37 @@ function usePaint(paintProps = {}) {
1016
589
  setHistory(newHistory);
1017
590
  setHistoryIndex(newHistory.length - 1);
1018
591
  onChange && onChange();
1019
- }, [history, historyIndex, onChange]);
592
+ }, [history, historyIndex, onChange, canvasRefState]);
1020
593
  const restoreState = React.useCallback(
1021
594
  (index) => {
1022
- const canvas = canvasRef.current;
1023
595
  const context = contextRef.current;
1024
- if (!canvas || !context || !history[index]) {
596
+ if (!canvasRefState || !context || !history[index]) {
1025
597
  return;
1026
598
  }
1027
599
  const dataUrl = history[index];
1028
600
  const img = new Image();
1029
601
  img.onload = () => {
1030
- context.clearRect(0, 0, canvas.width, canvas.height);
602
+ context.clearRect(0, 0, canvasRefState.width, canvasRefState.height);
1031
603
  context.drawImage(img, 0, 0);
1032
604
  };
1033
605
  img.src = dataUrl;
1034
606
  onChange && onChange();
1035
607
  },
1036
- [history, onChange]
608
+ [history, onChange, canvasRefState]
1037
609
  );
1038
610
  React.useEffect(() => {
1039
- const canvas = canvasRef.current;
1040
- if (!canvas) {
611
+ if (!canvasRefState) {
1041
612
  return;
1042
613
  }
1043
- const context = canvas.getContext("2d", { willReadFrequently: true });
614
+ const context = canvasRefState.getContext("2d", { willReadFrequently: true });
1044
615
  if (!context) {
1045
616
  return;
1046
617
  }
1047
618
  contextRef.current = context;
1048
- const initialDataUrl = canvas.toDataURL();
619
+ const initialDataUrl = canvasRefState.toDataURL();
1049
620
  setHistory([initialDataUrl]);
1050
621
  setHistoryIndex(0);
1051
- }, []);
622
+ }, [canvasRefState]);
1052
623
  React.useEffect(() => {
1053
624
  const context = contextRef.current;
1054
625
  if (context) {
@@ -1056,19 +627,53 @@ function usePaint(paintProps = {}) {
1056
627
  context.strokeStyle = pen.strokeColor;
1057
628
  }
1058
629
  }, [pen]);
630
+ const getEventPosition = React.useCallback(
631
+ (event) => {
632
+ if (!canvasRefState) {
633
+ return null;
634
+ }
635
+ const rect = canvasRefState.getBoundingClientRect();
636
+ const scaleX = canvasRefState.width / rect.width;
637
+ const scaleY = canvasRefState.height / rect.height;
638
+ let clientX;
639
+ let clientY;
640
+ if (event instanceof MouseEvent) {
641
+ clientX = event.clientX;
642
+ clientY = event.clientY;
643
+ } else if (event instanceof TouchEvent) {
644
+ const touch = event.touches[0];
645
+ if (!touch) {
646
+ return null;
647
+ }
648
+ clientX = touch.clientX;
649
+ clientY = touch.clientY;
650
+ } else {
651
+ return null;
652
+ }
653
+ const offsetX = (clientX - rect.left) * scaleX;
654
+ const offsetY = (clientY - rect.top) * scaleY;
655
+ return { offsetX, offsetY };
656
+ },
657
+ [canvasRefState]
658
+ );
1059
659
  const startPainting = React.useCallback(
1060
660
  (event) => {
661
+ event.preventDefault();
1061
662
  const context = contextRef.current;
1062
663
  if (!context) {
1063
664
  return;
1064
665
  }
666
+ const pos = getEventPosition(event);
667
+ if (!pos) {
668
+ return;
669
+ }
1065
670
  onStart && onStart();
1066
- const { offsetX, offsetY } = event;
671
+ const { offsetX, offsetY } = pos;
1067
672
  context.beginPath();
1068
673
  context.moveTo(offsetX, offsetY);
1069
674
  setIsPainting(true);
1070
675
  },
1071
- [onStart]
676
+ [onStart, getEventPosition]
1072
677
  );
1073
678
  const stopPainting = React.useCallback(() => {
1074
679
  const context = contextRef.current;
@@ -1082,47 +687,48 @@ function usePaint(paintProps = {}) {
1082
687
  }, [isPainting, onEnd, saveState]);
1083
688
  const paint = React.useCallback(
1084
689
  (event) => {
690
+ event.preventDefault();
1085
691
  if (!isPainting || !contextRef.current) {
1086
692
  return;
1087
693
  }
1088
- const { offsetX, offsetY } = event;
694
+ const pos = getEventPosition(event);
695
+ if (!pos) {
696
+ return;
697
+ }
698
+ const { offsetX, offsetY } = pos;
1089
699
  contextRef.current.lineTo(offsetX, offsetY);
1090
700
  contextRef.current.stroke();
1091
701
  },
1092
- [isPainting]
1093
- );
1094
- const handleMouseEnter = React.useCallback(
1095
- (event) => {
1096
- if (event.buttons === 1 && !isPainting) {
1097
- startPainting(event);
1098
- }
1099
- },
1100
- [isPainting, startPainting]
702
+ [isPainting, getEventPosition]
1101
703
  );
1102
704
  React.useEffect(() => {
1103
- const canvas = canvasRef.current;
1104
- if (!canvas) {
705
+ if (!canvasRefState) {
1105
706
  return;
1106
707
  }
1107
- canvas.addEventListener("mousedown", startPainting);
1108
- canvas.addEventListener("mouseup", stopPainting);
1109
- canvas.addEventListener("mousemove", paint);
1110
- canvas.addEventListener("mouseleave", stopPainting);
1111
- canvas.addEventListener("mouseenter", handleMouseEnter);
708
+ canvasRefState.addEventListener("mousedown", startPainting);
709
+ canvasRefState.addEventListener("mouseup", stopPainting);
710
+ canvasRefState.addEventListener("mousemove", paint);
711
+ canvasRefState.addEventListener("mouseleave", stopPainting);
712
+ canvasRefState.addEventListener("touchstart", startPainting);
713
+ canvasRefState.addEventListener("touchend", stopPainting);
714
+ canvasRefState.addEventListener("touchmove", paint);
715
+ canvasRefState.addEventListener("touchcancel", stopPainting);
1112
716
  return () => {
1113
- canvas.removeEventListener("mousedown", startPainting);
1114
- canvas.removeEventListener("mouseup", stopPainting);
1115
- canvas.removeEventListener("mousemove", paint);
1116
- canvas.removeEventListener("mouseleave", stopPainting);
1117
- canvas.removeEventListener("mouseenter", handleMouseEnter);
717
+ canvasRefState.removeEventListener("mousedown", startPainting);
718
+ canvasRefState.removeEventListener("mouseup", stopPainting);
719
+ canvasRefState.removeEventListener("mousemove", paint);
720
+ canvasRefState.removeEventListener("mouseleave", stopPainting);
721
+ canvasRefState.removeEventListener("touchstart", startPainting);
722
+ canvasRefState.removeEventListener("touchend", stopPainting);
723
+ canvasRefState.removeEventListener("touchmove", paint);
724
+ canvasRefState.removeEventListener("touchcancel", stopPainting);
1118
725
  };
1119
- }, [startPainting, stopPainting, paint, handleMouseEnter]);
726
+ }, [startPainting, stopPainting, paint, canvasRefState]);
1120
727
  const clear = () => {
1121
- const canvas = canvasRef.current;
1122
728
  const context = contextRef.current;
1123
- if (canvas && context) {
1124
- context.clearRect(0, 0, canvas.width, canvas.height);
1125
- const initialDataUrl = canvas.toDataURL();
729
+ if (canvasRefState && context) {
730
+ context.clearRect(0, 0, canvasRefState.width, canvasRefState.height);
731
+ const initialDataUrl = canvasRefState.toDataURL();
1126
732
  setHistory([initialDataUrl]);
1127
733
  setHistoryIndex(0);
1128
734
  onChange && onChange();
@@ -1143,15 +749,14 @@ function usePaint(paintProps = {}) {
1143
749
  }
1144
750
  };
1145
751
  const loadImage = (base64String) => {
1146
- const canvas = canvasRef.current;
1147
752
  const context = contextRef.current;
1148
- if (!canvas || !context) {
753
+ if (!canvasRefState || !context) {
1149
754
  return;
1150
755
  }
1151
756
  const img = new Image();
1152
757
  img.onload = () => {
1153
- context.clearRect(0, 0, canvas.width, canvas.height);
1154
- context.drawImage(img, 0, 0, canvas.width, canvas.height);
758
+ context.clearRect(0, 0, canvasRefState.width, canvasRefState.height);
759
+ context.drawImage(img, 0, 0, canvasRefState.width, canvasRefState.height);
1155
760
  saveState();
1156
761
  };
1157
762
  img.src = base64String;
@@ -1159,7 +764,7 @@ function usePaint(paintProps = {}) {
1159
764
  const getBase64String = (imageProps) => {
1160
765
  const props = { ...DEFAULT_DOWNLOAD_PROPS, ...imageProps };
1161
766
  const { fileExtendsion, transparent, backgroundColor, width, height } = props;
1162
- const originalCanvas = canvasRef.current;
767
+ const originalCanvas = canvasRefState;
1163
768
  if (!originalCanvas) {
1164
769
  return;
1165
770
  }
@@ -1179,7 +784,7 @@ function usePaint(paintProps = {}) {
1179
784
  const download = (downloadProps) => {
1180
785
  const props = { ...DEFAULT_DOWNLOAD_PROPS, ...downloadProps };
1181
786
  const { fileName, fileExtendsion, transparent, backgroundColor, width, height } = props;
1182
- const originalCanvas = canvasRef.current;
787
+ const originalCanvas = canvasRefState;
1183
788
  if (!originalCanvas) {
1184
789
  return;
1185
790
  }
@@ -1199,27 +804,49 @@ function usePaint(paintProps = {}) {
1199
804
  link.click();
1200
805
  }
1201
806
  };
807
+ const isCanvasBlank = () => {
808
+ if (!canvasRefState) {
809
+ return true;
810
+ }
811
+ const { width, height } = canvasRefState;
812
+ const ctx = canvasRefState.getContext("2d");
813
+ if (!ctx) {
814
+ console.error("2D context not available");
815
+ return true;
816
+ }
817
+ const imageData = ctx.getImageData(0, 0, width, height);
818
+ const { data } = imageData;
819
+ for (let i = 0; i < data.length; i += 4) {
820
+ if (data[i + 3] !== 0) {
821
+ return false;
822
+ }
823
+ }
824
+ return true;
825
+ };
1202
826
  return {
1203
827
  clear,
1204
828
  undo,
1205
829
  redo,
1206
830
  loadImage,
1207
831
  download,
1208
- canvasRef,
1209
- getBase64String
832
+ getBase64String,
833
+ isCanvasBlank,
834
+ setCanvasRefState,
835
+ canvasRefState
1210
836
  };
1211
837
  }
1212
838
 
839
+ const testSignatureBase64Data = "data:image/png;base64,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";
840
+
1213
841
  exports.Attachment = Attachment;
1214
842
  exports.DataTable = DataTable;
1215
843
  exports.FormDatePicker = FormDatePicker;
1216
844
  exports.FormSegmentGroup = FormSegmentGroup;
1217
- exports.FormSignature = FormSignature;
1218
845
  exports.FormTextField = FormTextField;
1219
846
  exports.StepIndicator = StepIndicator;
1220
847
  exports.resize = resize;
848
+ exports.testSignatureBase64Data = testSignatureBase64Data;
1221
849
  exports.useCamera = useCamera;
1222
- exports.useFormSignature = useFormSignature;
1223
- exports.usePaint = usePaint;
850
+ exports.useCanvasPaint = useCanvasPaint;
1224
851
  exports.useTable = useTable;
1225
852
  //# sourceMappingURL=index.cjs.js.map