@pallasoft/ps-file-components 1.5.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/dist/components/ps-document-scanner-loader.d.ts +1 -1
  2. package/dist/components/ps-document-scanner-sheet.d.ts +1 -1
  3. package/dist/components/ps-document-scanner-sheet.js +40 -110
  4. package/dist/components/ps-document-scanner.d.ts +1 -1
  5. package/dist/components/ps-document-scanner.js +2 -3
  6. package/dist/components/ps-file-delete-confirm.js +1 -1
  7. package/dist/components/ps-scan-camera-view.d.ts +2 -9
  8. package/dist/components/ps-scan-camera-view.js +3 -12
  9. package/dist/components/ps-scan-crop-editor.d.ts +4 -4
  10. package/dist/components/ps-scan-crop-editor.js +9 -9
  11. package/dist/components/ps-scan-permission-view.d.ts +2 -3
  12. package/dist/components/ps-scan-permission-view.js +2 -2
  13. package/dist/components/ps-scan-photo-button.d.ts +2 -3
  14. package/dist/components/ps-scan-photo-button.js +5 -5
  15. package/dist/components/ps-scan-preview.d.ts +12 -0
  16. package/dist/components/ps-scan-preview.js +10 -0
  17. package/dist/components/ps-scan-shutter.d.ts +1 -2
  18. package/dist/components/ps-scan-shutter.js +1 -1
  19. package/dist/components/ps-upload-modal.js +1 -1
  20. package/dist/constants/ps-document-scanner-labels.d.ts +5 -34
  21. package/dist/constants/ps-document-scanner-labels.js +5 -34
  22. package/dist/constants/ps-scan-chrome-classes.d.ts +0 -2
  23. package/dist/constants/ps-scan-chrome-classes.js +0 -2
  24. package/dist/constants/ps-scan-config.d.ts +24 -31
  25. package/dist/constants/ps-scan-config.js +24 -31
  26. package/dist/constants/ps-scan-step.d.ts +1 -1
  27. package/dist/constants/ps-scan-step.js +1 -1
  28. package/dist/esm/components/ps-document-scanner-sheet.js +41 -111
  29. package/dist/esm/components/ps-document-scanner.js +2 -3
  30. package/dist/esm/components/ps-file-delete-confirm.js +2 -2
  31. package/dist/esm/components/ps-scan-camera-view.js +3 -12
  32. package/dist/esm/components/ps-scan-crop-editor.js +9 -9
  33. package/dist/esm/components/ps-scan-permission-view.js +2 -2
  34. package/dist/esm/components/ps-scan-photo-button.js +5 -5
  35. package/dist/esm/components/ps-scan-preview.js +6 -0
  36. package/dist/esm/components/ps-scan-shutter.js +1 -1
  37. package/dist/esm/components/ps-upload-modal.js +2 -2
  38. package/dist/esm/constants/ps-document-scanner-labels.js +5 -34
  39. package/dist/esm/constants/ps-scan-chrome-classes.js +0 -2
  40. package/dist/esm/constants/ps-scan-config.js +24 -31
  41. package/dist/esm/constants/ps-scan-step.js +1 -1
  42. package/dist/esm/hooks/use-ps-scan-live-detection.js +17 -21
  43. package/dist/esm/hooks/use-ps-scan-photo.js +42 -0
  44. package/dist/esm/index.js +0 -2
  45. package/dist/esm/services/ps-scan-camera-service.js +2 -2
  46. package/dist/esm/services/ps-scan-canny-service.js +93 -0
  47. package/dist/esm/services/ps-scan-canvas-service.js +7 -1
  48. package/dist/esm/services/ps-scan-edge-service.js +73 -137
  49. package/dist/esm/services/ps-scan-file-name-service.js +2 -11
  50. package/dist/esm/services/ps-scan-geometry-service.js +36 -0
  51. package/dist/esm/services/ps-scan-hull-service.js +0 -39
  52. package/dist/esm/services/ps-scan-image-filter-service.js +0 -21
  53. package/dist/esm/services/ps-scan-morphology-service.js +44 -0
  54. package/dist/esm/services/ps-scan-pipeline-service.js +9 -19
  55. package/dist/esm/services/ps-scan-polygon-service.js +75 -0
  56. package/dist/esm/services/ps-scan-region-service.js +52 -0
  57. package/dist/esm/services/ps-scan-stability-service.js +9 -22
  58. package/dist/esm/services/ps-scan-warp-service.js +8 -2
  59. package/dist/esm/services/ps-scan-yield-service.js +5 -0
  60. package/dist/hooks/use-ps-scan-live-detection.d.ts +1 -1
  61. package/dist/hooks/use-ps-scan-live-detection.js +16 -20
  62. package/dist/hooks/use-ps-scan-photo.d.ts +9 -0
  63. package/dist/hooks/use-ps-scan-photo.js +46 -0
  64. package/dist/index.d.ts +0 -2
  65. package/dist/index.js +0 -2
  66. package/dist/models/ps-document-scanner-props.d.ts +0 -4
  67. package/dist/models/ps-document-scanner-sheet-props.d.ts +0 -4
  68. package/dist/models/ps-scan-gradient.d.ts +4 -0
  69. package/dist/models/ps-scan-live-detection.d.ts +0 -1
  70. package/dist/models/ps-scan-located.d.ts +5 -0
  71. package/dist/models/ps-scan-photo.d.ts +9 -0
  72. package/dist/models/ps-scan-region.d.ts +5 -0
  73. package/dist/models/ps-scan-result.d.ts +6 -0
  74. package/dist/models/ps-scan-stability.d.ts +0 -3
  75. package/dist/services/ps-scan-camera-service.js +2 -2
  76. package/dist/services/ps-scan-canny-service.d.ts +7 -0
  77. package/dist/services/ps-scan-canny-service.js +97 -0
  78. package/dist/services/ps-scan-canvas-service.js +7 -1
  79. package/dist/services/ps-scan-edge-service.d.ts +5 -5
  80. package/dist/services/ps-scan-edge-service.js +73 -137
  81. package/dist/services/ps-scan-file-name-service.d.ts +1 -3
  82. package/dist/services/ps-scan-file-name-service.js +2 -11
  83. package/dist/services/ps-scan-geometry-service.d.ts +2 -0
  84. package/dist/services/ps-scan-geometry-service.js +36 -0
  85. package/dist/services/ps-scan-hull-service.d.ts +0 -2
  86. package/dist/services/ps-scan-hull-service.js +0 -39
  87. package/dist/services/ps-scan-image-filter-service.d.ts +0 -1
  88. package/dist/services/ps-scan-image-filter-service.js +0 -21
  89. package/dist/services/ps-scan-morphology-service.d.ts +7 -0
  90. package/dist/services/ps-scan-morphology-service.js +48 -0
  91. package/dist/services/ps-scan-pipeline-service.d.ts +2 -5
  92. package/dist/services/ps-scan-pipeline-service.js +9 -19
  93. package/dist/services/ps-scan-polygon-service.d.ts +8 -0
  94. package/dist/services/ps-scan-polygon-service.js +79 -0
  95. package/dist/services/ps-scan-region-service.d.ts +4 -0
  96. package/dist/services/ps-scan-region-service.js +56 -0
  97. package/dist/services/ps-scan-stability-service.d.ts +1 -3
  98. package/dist/services/ps-scan-stability-service.js +9 -22
  99. package/dist/services/ps-scan-warp-service.d.ts +1 -1
  100. package/dist/services/ps-scan-warp-service.js +8 -2
  101. package/dist/services/ps-scan-yield-service.d.ts +3 -0
  102. package/dist/services/ps-scan-yield-service.js +9 -0
  103. package/package.json +3 -5
  104. package/dist/components/ps-scan-page-list.d.ts +0 -14
  105. package/dist/components/ps-scan-page-list.js +0 -22
  106. package/dist/components/ps-scan-page-stack.d.ts +0 -7
  107. package/dist/components/ps-scan-page-stack.js +0 -6
  108. package/dist/components/ps-scan-review.d.ts +0 -24
  109. package/dist/components/ps-scan-review.js +0 -37
  110. package/dist/constants/ps-scan-filter.d.ts +0 -7
  111. package/dist/constants/ps-scan-filter.js +0 -9
  112. package/dist/constants/ps-scan-output-format.d.ts +0 -5
  113. package/dist/constants/ps-scan-output-format.js +0 -7
  114. package/dist/esm/components/ps-scan-page-list.js +0 -18
  115. package/dist/esm/components/ps-scan-page-stack.js +0 -2
  116. package/dist/esm/components/ps-scan-review.js +0 -33
  117. package/dist/esm/constants/ps-scan-filter.js +0 -6
  118. package/dist/esm/constants/ps-scan-output-format.js +0 -4
  119. package/dist/esm/hooks/use-ps-scan-pages.js +0 -62
  120. package/dist/esm/hooks/use-ps-scan-previews.js +0 -57
  121. package/dist/esm/services/ps-scan-enhance-service.js +0 -97
  122. package/dist/esm/services/ps-scan-order-service.js +0 -13
  123. package/dist/esm/services/ps-scan-output-service.js +0 -24
  124. package/dist/esm/services/ps-scan-pdf-service.js +0 -56
  125. package/dist/hooks/use-ps-scan-pages.d.ts +0 -12
  126. package/dist/hooks/use-ps-scan-pages.js +0 -66
  127. package/dist/hooks/use-ps-scan-previews.d.ts +0 -2
  128. package/dist/hooks/use-ps-scan-previews.js +0 -61
  129. package/dist/models/ps-scan-added-page.d.ts +0 -5
  130. package/dist/models/ps-scan-levels.d.ts +0 -4
  131. package/dist/models/ps-scan-output-options.d.ts +0 -7
  132. package/dist/models/ps-scan-page.d.ts +0 -12
  133. package/dist/models/ps-scan-pdf-page.d.ts +0 -5
  134. package/dist/services/ps-scan-enhance-service.d.ts +0 -9
  135. package/dist/services/ps-scan-enhance-service.js +0 -101
  136. package/dist/services/ps-scan-order-service.d.ts +0 -4
  137. package/dist/services/ps-scan-order-service.js +0 -17
  138. package/dist/services/ps-scan-output-service.d.ts +0 -5
  139. package/dist/services/ps-scan-output-service.js +0 -28
  140. package/dist/services/ps-scan-pdf-service.d.ts +0 -5
  141. package/dist/services/ps-scan-pdf-service.js +0 -60
  142. /package/dist/esm/models/{ps-scan-added-page.js → ps-scan-gradient.js} +0 -0
  143. /package/dist/esm/models/{ps-scan-levels.js → ps-scan-located.js} +0 -0
  144. /package/dist/esm/models/{ps-scan-output-options.js → ps-scan-photo.js} +0 -0
  145. /package/dist/esm/models/{ps-scan-page.js → ps-scan-region.js} +0 -0
  146. /package/dist/esm/models/{ps-scan-pdf-page.js → ps-scan-result.js} +0 -0
  147. /package/dist/models/{ps-scan-added-page.js → ps-scan-gradient.js} +0 -0
  148. /package/dist/models/{ps-scan-levels.js → ps-scan-located.js} +0 -0
  149. /package/dist/models/{ps-scan-output-options.js → ps-scan-photo.js} +0 -0
  150. /package/dist/models/{ps-scan-page.js → ps-scan-region.js} +0 -0
  151. /package/dist/models/{ps-scan-pdf-page.js → ps-scan-result.js} +0 -0
@@ -1,23 +1,19 @@
1
1
  export declare const PsDocumentScannerLabels: {
2
- readonly addPage: "Add page";
3
2
  readonly allowCamera: "Allow camera";
4
- readonly auto: "Auto";
5
- readonly autoCapture: "Capture automatically when the page is steady";
6
3
  readonly autoDetect: "Detect edges";
7
4
  readonly busyBody: "Another app is using the camera. Close it, then try again.";
8
5
  readonly busyTitle: "Your camera is busy";
9
6
  readonly cameraStarting: "Starting camera";
10
7
  readonly capture: "Take photo";
11
8
  readonly choosePhoto: "Choose a photo instead";
12
- readonly choosePhotos: "Choose photos";
13
9
  readonly close: "Close scanner";
10
+ readonly continue: "Continue";
14
11
  readonly cornerBottomLeft: "Bottom left corner";
15
12
  readonly cornerBottomRight: "Bottom right corner";
16
13
  readonly cornerTopLeft: "Top left corner";
17
14
  readonly cornerTopRight: "Top right corner";
18
15
  readonly cropHint: "Drag the corners to the edges of the page.";
19
16
  readonly cropTitle: "Adjust corners";
20
- readonly deletePage: "Delete";
21
17
  readonly deniedAndroid1: "Tap the icon to the left of the address bar.";
22
18
  readonly deniedAndroid2: "Open Permissions, then Camera.";
23
19
  readonly deniedAndroid3: "Choose Allow, then come back and tap Try again.";
@@ -29,52 +25,27 @@ export declare const PsDocumentScannerLabels: {
29
25
  readonly deniedIos2: "Set Camera to Allow.";
30
26
  readonly deniedIos3: "Come back and tap Try again.";
31
27
  readonly deniedTitle: "Camera access is off";
32
- readonly done: "Done";
33
- readonly dragPage: "Drag {page} to reorder";
34
- readonly editCrop: "Crop";
35
28
  readonly edgesFound: "Page edges found.";
36
29
  readonly edgesNotFound: "Edges not found. Drag the corners to the page.";
37
- readonly filterColour: "Colour";
38
- readonly filterDocument: "Document";
39
- readonly filterGreyscale: "Greyscale";
40
- readonly filterOriginal: "Original";
41
- readonly filters: "Filter";
42
- readonly finish: "Upload {count} pages";
43
- readonly finishOne: "Upload 1 page";
44
- readonly finishing: "Preparing your scan";
45
30
  readonly hintFind: "Point your camera at a document";
46
31
  readonly hintFound: "Document found";
47
- readonly hintHold: "Hold steady";
48
32
  readonly insecureBody: "The camera only works on a secure (https) page. You can still choose a photo.";
49
33
  readonly insecureTitle: "Camera not available here";
50
- readonly keepScan: "Keep scan";
51
- readonly maxPages: "You reached the page limit.";
52
- readonly nextPage: "Next page";
53
- readonly page: "Page";
54
- readonly pageAdded: "Page {position} added.";
55
- readonly pageDeleted: "Page deleted.";
56
- readonly pageMoved: "{page} moved to position {position} of {count}.";
57
- readonly pageOf: "{position} of {count}";
58
- readonly pages: "Pages";
59
34
  readonly platformAndroid: "Android";
60
35
  readonly platformDesktop: "Computer";
61
36
  readonly platformIos: "iPhone";
62
- readonly previousPage: "Previous page";
37
+ readonly preparing: "Preparing your scan";
38
+ readonly previewAlt: "Your flattened scan";
39
+ readonly previewTitle: "Your scan";
63
40
  readonly primerBody: "The camera is only used while the scanner is open. Nothing is saved until you upload.";
64
41
  readonly primerTitle: "Allow camera access to scan your documents";
65
42
  readonly processFailed: "The scan could not be prepared. Try again.";
66
- readonly reorderCancelled: "{page} stays where it was.";
67
- readonly reorderDropped: "{page} dropped at {position} of {count}.";
68
- readonly reorderInstructions: "Press space to lift a page, the arrow keys to move it and space to drop it.";
69
- readonly reorderLifted: "{page} lifted from {position} of {count}.";
70
- readonly reorderMoved: "{page} is now {position} of {count}.";
71
43
  readonly retake: "Retake";
72
- readonly rotate: "Rotate";
73
44
  readonly title: "Scan document";
74
45
  readonly torchOff: "Turn flash off";
75
46
  readonly torchOn: "Turn flash on";
76
47
  readonly tryAgain: "Try again";
77
48
  readonly unavailableBody: "This device has no camera the browser can use. Choose a photo of the page instead.";
78
49
  readonly unavailableTitle: "No camera found";
79
- readonly viewPages: "Review {count} pages";
50
+ readonly useScan: "Use scan";
80
51
  };
@@ -2,25 +2,21 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsDocumentScannerLabels = void 0;
4
4
  exports.PsDocumentScannerLabels = {
5
- addPage: 'Add page',
6
5
  allowCamera: 'Allow camera',
7
- auto: 'Auto',
8
- autoCapture: 'Capture automatically when the page is steady',
9
6
  autoDetect: 'Detect edges',
10
7
  busyBody: 'Another app is using the camera. Close it, then try again.',
11
8
  busyTitle: 'Your camera is busy',
12
9
  cameraStarting: 'Starting camera',
13
10
  capture: 'Take photo',
14
11
  choosePhoto: 'Choose a photo instead',
15
- choosePhotos: 'Choose photos',
16
12
  close: 'Close scanner',
13
+ continue: 'Continue',
17
14
  cornerBottomLeft: 'Bottom left corner',
18
15
  cornerBottomRight: 'Bottom right corner',
19
16
  cornerTopLeft: 'Top left corner',
20
17
  cornerTopRight: 'Top right corner',
21
18
  cropHint: 'Drag the corners to the edges of the page.',
22
19
  cropTitle: 'Adjust corners',
23
- deletePage: 'Delete',
24
20
  deniedAndroid1: 'Tap the icon to the left of the address bar.',
25
21
  deniedAndroid2: 'Open Permissions, then Camera.',
26
22
  deniedAndroid3: 'Choose Allow, then come back and tap Try again.',
@@ -32,52 +28,27 @@ exports.PsDocumentScannerLabels = {
32
28
  deniedIos2: 'Set Camera to Allow.',
33
29
  deniedIos3: 'Come back and tap Try again.',
34
30
  deniedTitle: 'Camera access is off',
35
- done: 'Done',
36
- dragPage: 'Drag {page} to reorder',
37
- editCrop: 'Crop',
38
31
  edgesFound: 'Page edges found.',
39
32
  edgesNotFound: 'Edges not found. Drag the corners to the page.',
40
- filterColour: 'Colour',
41
- filterDocument: 'Document',
42
- filterGreyscale: 'Greyscale',
43
- filterOriginal: 'Original',
44
- filters: 'Filter',
45
- finish: 'Upload {count} pages',
46
- finishOne: 'Upload 1 page',
47
- finishing: 'Preparing your scan',
48
33
  hintFind: 'Point your camera at a document',
49
34
  hintFound: 'Document found',
50
- hintHold: 'Hold steady',
51
35
  insecureBody: 'The camera only works on a secure (https) page. You can still choose a photo.',
52
36
  insecureTitle: 'Camera not available here',
53
- keepScan: 'Keep scan',
54
- maxPages: 'You reached the page limit.',
55
- nextPage: 'Next page',
56
- page: 'Page',
57
- pageAdded: 'Page {position} added.',
58
- pageDeleted: 'Page deleted.',
59
- pageMoved: '{page} moved to position {position} of {count}.',
60
- pageOf: '{position} of {count}',
61
- pages: 'Pages',
62
37
  platformAndroid: 'Android',
63
38
  platformDesktop: 'Computer',
64
39
  platformIos: 'iPhone',
65
- previousPage: 'Previous page',
40
+ preparing: 'Preparing your scan',
41
+ previewAlt: 'Your flattened scan',
42
+ previewTitle: 'Your scan',
66
43
  primerBody: 'The camera is only used while the scanner is open. Nothing is saved until you upload.',
67
44
  primerTitle: 'Allow camera access to scan your documents',
68
45
  processFailed: 'The scan could not be prepared. Try again.',
69
- reorderCancelled: '{page} stays where it was.',
70
- reorderDropped: '{page} dropped at {position} of {count}.',
71
- reorderInstructions: 'Press space to lift a page, the arrow keys to move it and space to drop it.',
72
- reorderLifted: '{page} lifted from {position} of {count}.',
73
- reorderMoved: '{page} is now {position} of {count}.',
74
46
  retake: 'Retake',
75
- rotate: 'Rotate',
76
47
  title: 'Scan document',
77
48
  torchOff: 'Turn flash off',
78
49
  torchOn: 'Turn flash on',
79
50
  tryAgain: 'Try again',
80
51
  unavailableBody: 'This device has no camera the browser can use. Choose a photo of the page instead.',
81
52
  unavailableTitle: 'No camera found',
82
- viewPages: 'Review {count} pages',
53
+ useScan: 'Use scan',
83
54
  };
@@ -3,10 +3,8 @@ export declare const PsScanChromeClasses: {
3
3
  readonly buttonLarge: "ps-control-large ps-control-padding-large";
4
4
  readonly buttonPrimary: "border-primary bg-primary text-[color:var(--ps-color-primary-contrast)] hover:border-primary-dark hover:bg-primary-dark";
5
5
  readonly buttonQuiet: "border-white/15 bg-white/10 text-white hover:border-white/25 hover:bg-white/20";
6
- readonly chip: "ps-focus-ring ps-control inline-flex min-w-0 items-center justify-center rounded-ps-control px-2 text-sm font-semibold transition";
7
6
  readonly icon: "ps-focus-ring ps-control ps-control-square inline-flex shrink-0 items-center justify-center rounded-ps-control text-white transition disabled:pointer-events-none disabled:opacity-40";
8
7
  readonly iconOff: "bg-black/45 backdrop-blur-md hover:bg-white/20";
9
8
  readonly iconOn: "bg-white text-black hover:bg-white/90";
10
9
  readonly pill: "pointer-events-none rounded-ps-pill bg-black/55 px-3.5 py-1.5 text-sm font-medium text-white backdrop-blur-md";
11
- readonly tool: "ps-focus-ring flex min-h-14 min-w-16 flex-col items-center justify-center gap-1 rounded-ps-control px-2 text-xs font-medium text-white/80 transition hover:bg-white/10 hover:text-white disabled:pointer-events-none disabled:opacity-40";
12
10
  };
@@ -6,10 +6,8 @@ exports.PsScanChromeClasses = {
6
6
  buttonLarge: 'ps-control-large ps-control-padding-large',
7
7
  buttonPrimary: 'border-primary bg-primary text-[color:var(--ps-color-primary-contrast)] hover:border-primary-dark hover:bg-primary-dark',
8
8
  buttonQuiet: 'border-white/15 bg-white/10 text-white hover:border-white/25 hover:bg-white/20',
9
- chip: 'ps-focus-ring ps-control inline-flex min-w-0 items-center justify-center rounded-ps-control px-2 text-sm font-semibold transition',
10
9
  icon: 'ps-focus-ring ps-control ps-control-square inline-flex shrink-0 items-center justify-center rounded-ps-control text-white transition disabled:pointer-events-none disabled:opacity-40',
11
10
  iconOff: 'bg-black/45 backdrop-blur-md hover:bg-white/20',
12
11
  iconOn: 'bg-white text-black hover:bg-white/90',
13
12
  pill: 'pointer-events-none rounded-ps-pill bg-black/55 px-3.5 py-1.5 text-sm font-medium text-white backdrop-blur-md',
14
- tool: 'ps-focus-ring flex min-h-14 min-w-16 flex-col items-center justify-center gap-1 rounded-ps-control px-2 text-xs font-medium text-white/80 transition hover:bg-white/10 hover:text-white disabled:pointer-events-none disabled:opacity-40',
15
13
  };
@@ -1,48 +1,41 @@
1
1
  export declare const PsScanConfig: {
2
- readonly adaptiveRatio: 0.92;
3
- readonly adaptiveWindowDivisor: 16;
4
- readonly adaptiveWindowMin: 15;
5
- readonly autoCaptureMs: 1000;
6
2
  readonly cameraPermission: "camera";
7
- readonly capturedJpegQuality: 0.92;
3
+ readonly cannyHighPercentile: 0.9;
4
+ readonly cannyLowRatio: 0.45;
5
+ readonly cannyMinHigh: 12;
6
+ readonly capturedJpegQuality: 0.97;
7
+ readonly closeRadii: readonly [1, 2, 4];
8
8
  readonly cornerNudge: 0.005;
9
9
  readonly cornerNudgeLarge: 0.025;
10
- readonly decodeMaxDimension: 3000;
10
+ readonly decodeMaxPixels: 16000000;
11
11
  readonly defaultFileName: "scan";
12
- readonly defaultJpegQuality: 0.82;
13
- readonly defaultMaxDimension: 2000;
14
- readonly defaultMaxPages: 30;
15
- readonly detectDilations: 2;
16
- readonly detectInset: 3;
17
- readonly detectMaxDimension: 320;
18
- readonly detectMinAreaRatio: 0.12;
19
- readonly detectMaxAreaRatio: 0.995;
20
- readonly detectMinEdgeStrength: 24;
21
- readonly detectMinHullFill: 0.85;
22
- readonly detectPercentile: 0.98;
23
- readonly detectRelativeStrength: 0.3;
12
+ readonly defaultJpegQuality: 0.92;
13
+ readonly defaultMaxDimension: 4000;
14
+ readonly detectBorderMargin: 3;
15
+ readonly detectExpand: 0.3;
16
+ readonly detectMaxAngle: 140;
17
+ readonly detectMaxAreaRatio: 0.95;
18
+ readonly detectMaxDimension: 480;
19
+ readonly detectMinAngle: 40;
20
+ readonly detectMinAreaRatio: 0.1;
21
+ readonly detectMinQuadFill: 0.88;
22
+ readonly detectMinSideRatio: 0.06;
24
23
  readonly guideArm: 36;
25
24
  readonly guideArmRatio: 0.18;
26
25
  readonly guideAspect: 0.72;
27
26
  readonly guideHeightRatio: 0.58;
28
27
  readonly guideLift: 0.03;
29
28
  readonly guideWidthRatio: 0.76;
30
- readonly hullCandidateLimit: 18;
31
- readonly levelHighPercentile: 0.99;
32
- readonly levelLowPercentile: 0.01;
33
- readonly liveDetectIntervalMs: 160;
34
- readonly liveDetectMaxDimension: 240;
35
- readonly liveMissLimit: 2;
36
- readonly liveRearmMovement: 0.08;
37
- readonly liveSmoothing: 0.5;
38
- readonly liveStillMovement: 0.02;
29
+ readonly liveDeadzone: 0.006;
30
+ readonly liveDetectIntervalMs: 200;
31
+ readonly liveDetectMaxDimension: 280;
32
+ readonly liveMissLimit: 3;
33
+ readonly liveSmoothing: 0.45;
39
34
  readonly loupeOffset: 72;
40
35
  readonly loupeSize: 112;
41
36
  readonly loupeZoom: 2.5;
42
37
  readonly minCornerGap: 0.02;
43
- readonly pdfDpi: 150;
44
- readonly pdfPointsPerInch: 72;
45
- readonly previewDebounceMs: 120;
46
- readonly previewMaxDimension: 1400;
38
+ readonly polygonEpsilons: readonly [0.008, 0.012, 0.018, 0.026, 0.036, 0.05, 0.07];
47
39
  readonly torchConstraint: "torch";
40
+ readonly warpChunkPixels: 400000;
48
41
  };
@@ -2,50 +2,43 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsScanConfig = void 0;
4
4
  exports.PsScanConfig = {
5
- adaptiveRatio: 0.92,
6
- adaptiveWindowDivisor: 16,
7
- adaptiveWindowMin: 15,
8
- autoCaptureMs: 1000,
9
5
  cameraPermission: 'camera',
10
- capturedJpegQuality: 0.92,
6
+ cannyHighPercentile: 0.9,
7
+ cannyLowRatio: 0.45,
8
+ cannyMinHigh: 12,
9
+ capturedJpegQuality: 0.97,
10
+ closeRadii: [1, 2, 4],
11
11
  cornerNudge: 0.005,
12
12
  cornerNudgeLarge: 0.025,
13
- decodeMaxDimension: 3000,
13
+ decodeMaxPixels: 16000000,
14
14
  defaultFileName: 'scan',
15
- defaultJpegQuality: 0.82,
16
- defaultMaxDimension: 2000,
17
- defaultMaxPages: 30,
18
- detectDilations: 2,
19
- detectInset: 3,
20
- detectMaxDimension: 320,
21
- detectMinAreaRatio: 0.12,
22
- detectMaxAreaRatio: 0.995,
23
- detectMinEdgeStrength: 24,
24
- detectMinHullFill: 0.85,
25
- detectPercentile: 0.98,
26
- detectRelativeStrength: 0.3,
15
+ defaultJpegQuality: 0.92,
16
+ defaultMaxDimension: 4000,
17
+ detectBorderMargin: 3,
18
+ detectExpand: 0.3,
19
+ detectMaxAngle: 140,
20
+ detectMaxAreaRatio: 0.95,
21
+ detectMaxDimension: 480,
22
+ detectMinAngle: 40,
23
+ detectMinAreaRatio: 0.1,
24
+ detectMinQuadFill: 0.88,
25
+ detectMinSideRatio: 0.06,
27
26
  guideArm: 36,
28
27
  guideArmRatio: 0.18,
29
28
  guideAspect: 0.72,
30
29
  guideHeightRatio: 0.58,
31
30
  guideLift: 0.03,
32
31
  guideWidthRatio: 0.76,
33
- hullCandidateLimit: 18,
34
- levelHighPercentile: 0.99,
35
- levelLowPercentile: 0.01,
36
- liveDetectIntervalMs: 160,
37
- liveDetectMaxDimension: 240,
38
- liveMissLimit: 2,
39
- liveRearmMovement: 0.08,
40
- liveSmoothing: 0.5,
41
- liveStillMovement: 0.02,
32
+ liveDeadzone: 0.006,
33
+ liveDetectIntervalMs: 200,
34
+ liveDetectMaxDimension: 280,
35
+ liveMissLimit: 3,
36
+ liveSmoothing: 0.45,
42
37
  loupeOffset: 72,
43
38
  loupeSize: 112,
44
39
  loupeZoom: 2.5,
45
40
  minCornerGap: 0.02,
46
- pdfDpi: 150,
47
- pdfPointsPerInch: 72,
48
- previewDebounceMs: 120,
49
- previewMaxDimension: 1400,
41
+ polygonEpsilons: [0.008, 0.012, 0.018, 0.026, 0.036, 0.05, 0.07],
50
42
  torchConstraint: 'torch',
43
+ warpChunkPixels: 400000,
51
44
  };
@@ -1,6 +1,6 @@
1
1
  export declare const PsScanStep: {
2
2
  readonly Camera: "camera";
3
3
  readonly Crop: "crop";
4
- readonly Review: "review";
4
+ readonly Preview: "preview";
5
5
  };
6
6
  export type PsScanStep = (typeof PsScanStep)[keyof typeof PsScanStep];
@@ -4,5 +4,5 @@ exports.PsScanStep = void 0;
4
4
  exports.PsScanStep = {
5
5
  Camera: 'camera',
6
6
  Crop: 'crop',
7
- Review: 'review',
7
+ Preview: 'preview',
8
8
  };
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback, useRef, useState } from 'react';
2
+ import { useEffect, useRef, useState } from 'react';
3
3
  import { PsLayer, usePsLayerZIndex, usePsRestoreFocus, usePsScrollLock, usePsViewport, } from '@pallasoft/ps-core-components';
4
4
  import { PallasoftViewportTier, PallasoftZIndex } from '@pallasoft/ps-design-system';
5
5
  import { PsIconKey } from '@pallasoft/ps-icons';
@@ -9,81 +9,52 @@ import { PsScanStep } from '../constants/ps-scan-step';
9
9
  import { usePsFocusTrap } from '../hooks/use-ps-focus-trap';
10
10
  import { usePsScanCamera } from '../hooks/use-ps-scan-camera';
11
11
  import { usePsScanLiveDetection } from '../hooks/use-ps-scan-live-detection';
12
- import { usePsScanPages } from '../hooks/use-ps-scan-pages';
13
- import { usePsScanPreviews } from '../hooks/use-ps-scan-previews';
14
- import { PsScanOutputService } from '../services/ps-scan-output-service';
12
+ import { usePsScanPhoto } from '../hooks/use-ps-scan-photo';
13
+ import { PsScanFileNameService } from '../services/ps-scan-file-name-service';
15
14
  import { PsScanPipelineService } from '../services/ps-scan-pipeline-service';
16
- import { PsScanTemplateService } from '../services/ps-scan-template-service';
17
15
  import { PsScanCameraView } from './ps-scan-camera-view';
18
16
  import { PsScanCropEditor } from './ps-scan-crop-editor';
19
17
  import { PsScanIconButton } from './ps-scan-icon-button';
20
18
  import { PsScanPermissionView } from './ps-scan-permission-view';
21
- import { PsScanReview } from './ps-scan-review';
22
- export const PsDocumentScannerSheet = ({ fileName, isAutoCapture, jpegQuality, labels, maxDimension, maxPages, onClose, onComplete, outputFormat, }) => {
19
+ import { PsScanPreview } from './ps-scan-preview';
20
+ export const PsDocumentScannerSheet = ({ fileName, jpegQuality, labels, maxDimension, onClose, onComplete, }) => {
23
21
  const tier = usePsViewport();
24
22
  const zIndex = usePsLayerZIndex(PallasoftZIndex.Modal);
25
23
  const content = useRef(null);
26
- const { add, move, pages, remove, replace, setCorners, update } = usePsScanPages();
24
+ const { clear, detectAgain, load, photo, setCorners } = usePsScanPhoto();
27
25
  const [step, setStep] = useState(PsScanStep.Camera);
28
- const [cropReturn, setCropReturn] = useState(PsScanStep.Camera);
29
- const [activeId, setActiveId] = useState('');
30
- const [retakeId, setRetakeId] = useState('');
26
+ const [result, setResult] = useState(null);
31
27
  const [announcement, setAnnouncement] = useState('');
32
28
  const [error, setError] = useState('');
33
- const [isBusy, setIsBusy] = useState(false);
34
29
  const [isCapturing, setIsCapturing] = useState(false);
35
- const [isAuto, setIsAuto] = useState(isAutoCapture);
36
30
  const [flashKey, setFlashKey] = useState(0);
37
31
  const camera = usePsScanCamera(step === PsScanStep.Camera);
38
32
  const isReady = camera.status === PsScanCameraStatus.Ready;
39
- const isFull = pages.length >= maxPages;
40
- const previews = usePsScanPreviews(pages);
41
- const page = pages.find((item) => item.id === activeId);
42
- const lastPage = pages[pages.length - 1];
43
33
  const isDesktop = tier === PallasoftViewportTier.Desktop;
44
34
  const isCameraStep = step === PsScanStep.Camera;
45
35
  const showsCamera = isReady || camera.status === PsScanCameraStatus.Starting;
36
+ const detection = usePsScanLiveDetection(camera.videoRef, isCameraStep && isReady);
46
37
  usePsScrollLock(true);
47
38
  usePsRestoreFocus(true);
48
39
  usePsFocusTrap(content, true, onClose);
40
+ useEffect(() => () => {
41
+ if (result !== null)
42
+ URL.revokeObjectURL(result.url);
43
+ }, [result]);
49
44
  const edgeMessage = (isDetected) => isDetected ? labels.edgesFound : labels.edgesNotFound;
50
- const addFiles = async (files, after) => {
45
+ const accept = async (source) => {
51
46
  setError('');
52
47
  try {
53
- const images = files.filter((file) => file.type === '' || file.type.startsWith('image/'));
54
- if (retakeId !== '' && images.length > 0) {
55
- const added = await replace(retakeId, images[0]);
56
- setActiveId(retakeId);
57
- setRetakeId('');
58
- setStep(PsScanStep.Crop);
59
- setAnnouncement(edgeMessage(added.isDetected));
60
- return;
61
- }
62
- const room = Math.max(0, maxPages - pages.length);
63
- if (images.length > room)
64
- setError(labels.maxPages);
65
- const added = await add(images.slice(0, room));
66
- if (added.length === 0)
67
- return;
68
- const position = pages.length + added.length;
69
- setActiveId(added[added.length - 1].page.id);
70
- setAnnouncement(PsScanTemplateService.fill(labels.pageAdded, { position }));
71
- if (after === null)
72
- return;
73
- if (added.length === 1) {
74
- setCropReturn(after);
75
- setStep(PsScanStep.Crop);
76
- setAnnouncement(edgeMessage(added[0].isDetected));
77
- }
78
- else
79
- setStep(PsScanStep.Review);
48
+ const added = await load(source);
49
+ setAnnouncement(edgeMessage(added.isDetected));
50
+ setStep(PsScanStep.Crop);
80
51
  }
81
52
  catch {
82
53
  setError(labels.processFailed);
83
54
  }
84
55
  };
85
- const capture = async (isAutomatic) => {
86
- if (isCapturing || isFull)
56
+ const capture = async () => {
57
+ if (isCapturing)
87
58
  return;
88
59
  setIsCapturing(true);
89
60
  try {
@@ -91,92 +62,51 @@ export const PsDocumentScannerSheet = ({ fileName, isAutoCapture, jpegQuality, l
91
62
  if (blob === null)
92
63
  return;
93
64
  setFlashKey((current) => current + 1);
94
- await addFiles([blob], isAutomatic && retakeId === '' ? null : PsScanStep.Camera);
65
+ await accept(blob);
95
66
  }
96
67
  finally {
97
68
  setIsCapturing(false);
98
69
  }
99
70
  };
100
- const detection = usePsScanLiveDetection(camera.videoRef, isCameraStep && isReady, isAuto, () => capture(true));
101
- const autoDetect = async () => {
102
- if (page === undefined)
103
- return;
104
- const prepared = await PsScanPipelineService.prepare(page.source);
105
- setCorners(page.id, prepared.corners);
106
- setAnnouncement(edgeMessage(prepared.isDetected));
107
- };
108
- const keep = () => setStep(cropReturn === PsScanStep.Camera && !isFull ? PsScanStep.Camera : PsScanStep.Review);
71
+ const autoDetect = async () => setAnnouncement(edgeMessage(await detectAgain()));
109
72
  const retake = () => {
110
- if (page === undefined)
111
- return;
112
- if (step === PsScanStep.Review)
113
- setCropReturn(PsScanStep.Review);
114
- setRetakeId(page.id);
115
- setStep(PsScanStep.Camera);
116
- };
117
- const openCamera = () => {
118
- setRetakeId('');
119
- setCropReturn(PsScanStep.Camera);
73
+ clear();
74
+ setResult(null);
75
+ setError('');
120
76
  setStep(PsScanStep.Camera);
121
77
  };
122
- const openReview = () => {
123
- if (pages.length === 0)
124
- return;
125
- setRetakeId('');
126
- if (page === undefined)
127
- setActiveId(lastPage.id);
128
- setStep(PsScanStep.Review);
129
- };
130
- const editCrop = () => {
131
- setCropReturn(PsScanStep.Review);
78
+ const adjust = () => {
79
+ setResult(null);
80
+ setError('');
132
81
  setStep(PsScanStep.Crop);
133
82
  };
134
- const deletePage = () => {
135
- if (page === undefined)
83
+ const flatten = async () => {
84
+ if (photo === null)
136
85
  return;
137
- const index = pages.findIndex((item) => item.id === page.id);
138
- const rest = pages.filter((item) => item.id !== page.id);
139
- remove(page.id);
140
- setAnnouncement(labels.pageDeleted);
141
- if (rest.length === 0) {
142
- setActiveId('');
143
- openCamera();
144
- }
145
- else
146
- setActiveId(rest[Math.min(index, rest.length - 1)].id);
147
- };
148
- const finish = async () => {
149
- setIsBusy(true);
86
+ setResult(null);
150
87
  setError('');
88
+ setStep(PsScanStep.Preview);
151
89
  try {
152
- const files = await PsScanOutputService.build(pages, {
153
- fileName,
154
- format: outputFormat,
155
- jpegQuality,
156
- maxDimension,
157
- });
158
- onComplete(files);
159
- onClose();
90
+ const rendered = await PsScanPipelineService.render(photo.source, photo.corners, maxDimension, jpegQuality);
91
+ setResult({ ...rendered, url: URL.createObjectURL(rendered.blob) });
160
92
  }
161
93
  catch {
162
94
  setError(labels.processFailed);
163
- setIsBusy(false);
164
95
  }
165
96
  };
166
- const moveTo = useCallback((from, to) => {
167
- move(from, to);
168
- setAnnouncement(PsScanTemplateService.fill(labels.pageMoved, {
169
- count: pages.length,
170
- page: `${labels.page} ${from + 1}`,
171
- position: to + 1,
172
- }));
173
- }, [move, pages.length, labels]);
174
- const fromLibrary = (files) => addFiles(files, PsScanStep.Review);
97
+ const use = () => {
98
+ if (result === null)
99
+ return;
100
+ onComplete([
101
+ new File([result.blob], PsScanFileNameService.build(fileName), { type: 'image/jpeg' }),
102
+ ]);
103
+ onClose();
104
+ };
175
105
  if (typeof document === 'undefined')
176
106
  return null;
177
107
  return createPortal(_jsx("div", { "aria-label": labels.title, "aria-modal": 'true', className: isDesktop
178
108
  ? 'fixed inset-0 flex items-center justify-center bg-black/70 p-6 backdrop-blur-sm animate-ps-fade-in'
179
109
  : 'fixed inset-0 bg-black animate-ps-fade-in', role: 'dialog', style: { zIndex }, children: _jsx(PsLayer, { zIndex: zIndex, children: _jsxs("div", { className: isDesktop
180
110
  ? 'relative h-[min(52rem,calc(100dvh-3rem))] w-[min(76rem,calc(100vw-3rem))] overflow-hidden rounded-2xl bg-black text-white shadow-2xl ring-1 ring-white/10 animate-ps-scale-in'
181
- : 'relative h-full overflow-hidden bg-black text-white', ref: content, children: [_jsx("p", { "aria-live": 'polite', className: 'sr-only', role: 'status', children: announcement }), isCameraStep && showsCamera ? (_jsx(PsScanCameraView, { canTorch: camera.canTorch, detection: detection, flashKey: flashKey, isAuto: isAuto, isBusy: isCapturing, isFull: isFull, isMultiple: maxPages > 1, isReady: isReady, isTorchOn: camera.isTorchOn, labels: labels, lastPreview: lastPage === undefined ? undefined : previews[lastPage.id], onCapture: () => capture(false), onClose: onClose, onDone: openReview, onFiles: fromLibrary, onToggleAuto: () => setIsAuto((current) => !current), onToggleTorch: camera.toggleTorch, pageCount: pages.length, videoRef: camera.videoRef, videoTarget: camera.attachVideo })) : null, isCameraStep && !showsCamera ? (_jsxs(_Fragment, { children: [_jsx(PsScanPermissionView, { isMultiple: maxPages > 1, labels: labels, onAllow: camera.allow, onFiles: fromLibrary, status: camera.status }), _jsx("div", { className: 'absolute left-4 top-[max(1rem,env(safe-area-inset-top))] flex gap-2', children: _jsx(PsScanIconButton, { iconKey: PsIconKey.Close, label: labels.close, onClick: onClose }) }), pages.length > 0 ? (_jsx("div", { className: 'absolute right-4 top-[max(1rem,env(safe-area-inset-top))]', children: _jsx(PsScanIconButton, { iconKey: PsIconKey.Check, label: PsScanTemplateService.fill(labels.viewPages, { count: pages.length }), onClick: openReview }) })) : null] })) : null, step === PsScanStep.Crop && page !== undefined ? (_jsx(PsScanCropEditor, { labels: labels, onAutoDetect: autoDetect, onChange: (corners) => setCorners(page.id, corners), onKeep: keep, onRetake: retake, page: page })) : null, step === PsScanStep.Review && page !== undefined ? (_jsx(PsScanReview, { canAddPage: !isFull, error: error, isBusy: isBusy, labels: labels, onAddPage: openCamera, onClose: onClose, onDelete: deletePage, onEditCrop: editCrop, onFilter: (filter) => update(page.id, { filter }), onFinish: finish, onMove: moveTo, onRetake: retake, onRotate: () => update(page.id, { rotation: (page.rotation + 90) % 360 }), onSelect: setActiveId, page: page, pages: pages, previews: previews })) : null, isCameraStep && error !== '' ? (_jsx("p", { className: 'absolute inset-x-4 bottom-36 mx-auto max-w-sm rounded-ps-control bg-danger px-3 py-2 text-center text-sm text-white', role: 'alert', children: error })) : null] }) }) }), document.body);
111
+ : 'relative h-full overflow-hidden bg-black text-white', ref: content, children: [_jsx("p", { "aria-live": 'polite', className: 'sr-only', role: 'status', children: announcement }), isCameraStep && showsCamera ? (_jsx(PsScanCameraView, { canTorch: camera.canTorch, detection: detection, flashKey: flashKey, isBusy: isCapturing, isReady: isReady, isTorchOn: camera.isTorchOn, labels: labels, onCapture: capture, onClose: onClose, onFile: accept, onToggleTorch: camera.toggleTorch, videoRef: camera.videoRef, videoTarget: camera.attachVideo })) : null, isCameraStep && !showsCamera ? (_jsxs(_Fragment, { children: [_jsx(PsScanPermissionView, { labels: labels, onAllow: camera.allow, onFile: accept, status: camera.status }), _jsx("div", { className: 'absolute left-4 top-[max(1rem,env(safe-area-inset-top))] flex gap-2', children: _jsx(PsScanIconButton, { iconKey: PsIconKey.Close, label: labels.close, onClick: onClose }) })] })) : null, step === PsScanStep.Crop && photo !== null ? (_jsx(PsScanCropEditor, { labels: labels, onAutoDetect: autoDetect, onChange: setCorners, onContinue: flatten, onRetake: retake, photo: photo })) : null, step === PsScanStep.Preview ? (_jsx(PsScanPreview, { error: error, labels: labels, onAdjust: adjust, onRetake: retake, onUse: use, result: result })) : null, isCameraStep && error !== '' ? (_jsx("p", { className: 'absolute inset-x-4 bottom-36 mx-auto max-w-sm rounded-ps-control bg-danger px-3 py-2 text-center text-sm text-white', role: 'alert', children: error })) : null] }) }) }), document.body);
182
112
  };
@@ -3,11 +3,10 @@ import { Suspense } from 'react';
3
3
  import { usePsHydrated } from '@pallasoft/ps-core-components';
4
4
  import { PsDocumentScannerLabels } from '../constants/ps-document-scanner-labels';
5
5
  import { PsScanConfig } from '../constants/ps-scan-config';
6
- import { PsScanOutputFormat } from '../constants/ps-scan-output-format';
7
6
  import { PsDocumentScannerLoader } from './ps-document-scanner-loader';
8
- export const PsDocumentScanner = ({ fileName = PsScanConfig.defaultFileName, isAutoCapture = false, isOpen, jpegQuality = PsScanConfig.defaultJpegQuality, labels, maxDimension = PsScanConfig.defaultMaxDimension, maxPages = PsScanConfig.defaultMaxPages, onClose, onComplete, outputFormat = PsScanOutputFormat.Pdf, }) => {
7
+ export const PsDocumentScanner = ({ fileName = PsScanConfig.defaultFileName, isOpen, jpegQuality = PsScanConfig.defaultJpegQuality, labels, maxDimension = PsScanConfig.defaultMaxDimension, onClose, onComplete, }) => {
9
8
  const isHydrated = usePsHydrated();
10
9
  if (!isOpen || !isHydrated)
11
10
  return null;
12
- return (_jsx(Suspense, { fallback: null, children: _jsx(PsDocumentScannerLoader, { fileName: fileName, isAutoCapture: isAutoCapture, jpegQuality: jpegQuality, labels: { ...PsDocumentScannerLabels, ...labels }, maxDimension: maxDimension, maxPages: maxPages, onClose: onClose, onComplete: onComplete, outputFormat: outputFormat }) }));
11
+ return (_jsx(Suspense, { fallback: null, children: _jsx(PsDocumentScannerLoader, { fileName: fileName, jpegQuality: jpegQuality, labels: { ...PsDocumentScannerLabels, ...labels }, maxDimension: maxDimension, onClose: onClose, onComplete: onComplete }) }));
13
12
  };
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { PsButton } from '@pallasoft/ps-core-components';
3
3
  import { PsModal } from '@pallasoft/ps-popovers';
4
- export const PsFileDeleteConfirm = ({ fileName, isDeleting, isOpen, labels, onCancel, onConfirm, }) => (_jsx(PsModal, { eyebrow: fileName, isOpen: isOpen, onClose: onCancel, size: 'sm', title: labels.deleteConfirm, children: _jsxs("div", { className: 'flex flex-col gap-5', children: [_jsxs("p", { className: 'text-sm text-ink/70', children: [_jsx("span", { className: 'font-medium text-ink', children: fileName }), " ", labels.deleteConfirmBody] }), _jsxs("div", { className: 'flex justify-end gap-2 border-t border-line pt-4', children: [_jsx(PsButton, { disabled: isDeleting, onClick: onCancel, type: 'button', variant: 'ghost', children: labels.deleteCancel }), _jsx(PsButton, { isLoading: isDeleting, onClick: onConfirm, type: 'button', variant: 'danger', children: labels.delete })] })] }) }));
4
+ export const PsFileDeleteConfirm = ({ fileName, isDeleting, isOpen, labels, onCancel, onConfirm, }) => (_jsx(PsModal, { eyebrow: fileName, footer: _jsxs(_Fragment, { children: [_jsx(PsButton, { disabled: isDeleting, onClick: onCancel, type: 'button', variant: 'surface', children: labels.deleteCancel }), _jsx(PsButton, { isLoading: isDeleting, onClick: onConfirm, type: 'button', variant: 'danger', children: labels.delete })] }), isOpen: isOpen, onClose: onCancel, size: 'sm', title: labels.deleteConfirm, children: _jsxs("p", { className: 'text-sm text-ink/70', children: [_jsx("span", { className: 'font-medium text-ink', children: fileName }), " ", labels.deleteConfirmBody] }) }));