@archbase/components 3.0.25 → 4.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 (168) hide show
  1. package/dist/buttons/ArchbaseSpeedDial.d.ts +59 -0
  2. package/dist/buttons/index.d.ts +2 -0
  3. package/dist/charts/ArchbaseArcGauge.d.ts +55 -0
  4. package/dist/charts/ArchbaseGantt.d.ts +70 -0
  5. package/dist/charts/ArchbaseLinearGauge.d.ts +55 -0
  6. package/dist/charts/ArchbaseResourceTimeline.d.ts +61 -0
  7. package/dist/charts/ArchbaseSparkline.d.ts +45 -0
  8. package/dist/charts/index.d.ts +10 -0
  9. package/dist/containers/ArchbaseExpansionPanel.d.ts +60 -0
  10. package/dist/containers/ArchbaseFloatingPanel.d.ts +91 -0
  11. package/dist/containers/index.d.ts +4 -0
  12. package/dist/datagrid/export/ArchbaseDataGridExcelExport.d.ts +67 -0
  13. package/dist/datagrid/export/index.d.ts +2 -0
  14. package/dist/datagrid/index.d.ts +1 -0
  15. package/dist/display/ArchbaseAnimationWrapper.d.ts +73 -0
  16. package/dist/display/ArchbaseBarcodeGenerator.d.ts +50 -0
  17. package/dist/display/ArchbaseCarousel.d.ts +100 -0
  18. package/dist/display/ArchbaseCodeViewer.d.ts +63 -0
  19. package/dist/display/ArchbaseDiffViewer.d.ts +41 -0
  20. package/dist/display/ArchbaseJsonTree.d.ts +34 -0
  21. package/dist/display/ArchbaseLightbox.d.ts +89 -0
  22. package/dist/display/ArchbaseMarquee.d.ts +46 -0
  23. package/dist/display/ArchbasePhotoAlbum.d.ts +58 -0
  24. package/dist/display/ArchbaseQRCode.d.ts +44 -0
  25. package/dist/display/ArchbaseTooltipRich.d.ts +82 -0
  26. package/dist/display/ArchbaseVirtualList.d.ts +116 -0
  27. package/dist/display/index.d.ts +24 -0
  28. package/dist/editors/ArchbaseAIPromptInput.d.ts +69 -0
  29. package/dist/editors/ArchbaseAsyncMultiSelect.d.ts +1 -1
  30. package/dist/editors/ArchbaseAsyncSelect.d.ts +1 -1
  31. package/dist/editors/ArchbaseBarcodeScanner.d.ts +63 -0
  32. package/dist/editors/ArchbaseCepInput.d.ts +26 -0
  33. package/dist/editors/ArchbaseColorGradientPicker.d.ts +80 -0
  34. package/dist/editors/ArchbaseCpfCnpjInput.d.ts +21 -0
  35. package/dist/editors/ArchbaseCurrencyInput.d.ts +25 -0
  36. package/dist/editors/ArchbaseDualListbox.d.ts +61 -0
  37. package/dist/editors/ArchbaseInPlaceEditor.d.ts +67 -0
  38. package/dist/editors/ArchbaseLightGrid.d.ts +56 -0
  39. package/dist/editors/ArchbaseMentionInput.d.ts +75 -0
  40. package/dist/editors/ArchbaseMultiEmail.d.ts +53 -0
  41. package/dist/editors/ArchbaseMultiViewCalendar.d.ts +47 -0
  42. package/dist/editors/ArchbaseNumberStepper.d.ts +66 -0
  43. package/dist/editors/ArchbaseOTPInput.d.ts +27 -0
  44. package/dist/editors/ArchbasePhoneInput.d.ts +52 -0
  45. package/dist/editors/ArchbaseRangeSlider.d.ts +22 -0
  46. package/dist/editors/ArchbaseSignaturePad.d.ts +60 -0
  47. package/dist/editors/ArchbaseSpeechToTextInput.d.ts +106 -0
  48. package/dist/editors/ArchbaseSpreadsheet.d.ts +56 -0
  49. package/dist/editors/ArchbaseTagInput.d.ts +55 -0
  50. package/dist/editors/index.d.ts +40 -0
  51. package/dist/feedback/ArchbaseChunkProgressBar.d.ts +35 -0
  52. package/dist/feedback/ArchbaseRipple.d.ts +43 -0
  53. package/dist/feedback/ArchbaseSkeleton.d.ts +115 -0
  54. package/dist/feedback/index.d.ts +6 -0
  55. package/dist/filters/ArchbaseColumnSelector.d.ts +38 -0
  56. package/dist/filters/index.d.ts +2 -0
  57. package/dist/forms/ArchbaseFieldArray.d.ts +80 -0
  58. package/dist/forms/ArchbaseFormWizard.d.ts +73 -0
  59. package/dist/forms/ArchbaseStepper.d.ts +51 -0
  60. package/dist/forms/index.d.ts +8 -0
  61. package/dist/forms/useArchbaseFormWizard.d.ts +74 -0
  62. package/dist/hooks/index.d.ts +2 -0
  63. package/dist/hooks/useArchbaseConfirm.d.ts +59 -0
  64. package/dist/image/editor/index.d.ts +43 -4
  65. package/dist/image/index.d.ts +1 -0
  66. package/dist/index.css +1 -1
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.js +22510 -13820
  69. package/dist/list/ArchbaseTreeList.d.ts +76 -0
  70. package/dist/list/index.d.ts +2 -0
  71. package/dist/navigation/ArchbaseActionSheet.d.ts +70 -0
  72. package/dist/navigation/ArchbaseAppBar.d.ts +63 -0
  73. package/dist/navigation/ArchbaseBottomNavigation.d.ts +61 -0
  74. package/dist/navigation/ArchbaseContextMenu.d.ts +76 -0
  75. package/dist/navigation/ArchbaseKeyboardShortcuts.d.ts +85 -0
  76. package/dist/navigation/ArchbaseSpotlight.d.ts +69 -0
  77. package/dist/navigation/index.d.ts +12 -0
  78. package/dist/notification/ArchbaseNotificationCenter.d.ts +56 -0
  79. package/dist/notification/index.d.ts +2 -0
  80. package/dist/onboarding/ArchbaseOnboardingTour.d.ts +27 -76
  81. package/dist/viewers/ArchbaseDocViewer.d.ts +40 -0
  82. package/dist/viewers/ArchbasePdfBuilder.d.ts +53 -0
  83. package/dist/viewers/ArchbaseXmlViewer.d.ts +36 -0
  84. package/dist/viewers/index.d.ts +6 -0
  85. package/package.json +41 -18
  86. package/src/buttons/ArchbaseSpeedDial.tsx +282 -0
  87. package/src/buttons/index.ts +3 -0
  88. package/src/charts/ArchbaseArcGauge.tsx +325 -0
  89. package/src/charts/ArchbaseGantt.tsx +494 -0
  90. package/src/charts/ArchbaseLinearGauge.tsx +288 -0
  91. package/src/charts/ArchbaseResourceTimeline.tsx +433 -0
  92. package/src/charts/ArchbaseSparkline.tsx +193 -0
  93. package/src/charts/index.ts +20 -1
  94. package/src/containers/ArchbaseExpansionPanel.tsx +208 -0
  95. package/src/containers/ArchbaseFloatingPanel.tsx +448 -0
  96. package/src/containers/index.ts +17 -0
  97. package/src/datagrid/components/pagination/grid-pagination.tsx +2 -2
  98. package/src/datagrid/export/ArchbaseDataGridExcelExport.tsx +293 -0
  99. package/src/datagrid/export/index.ts +8 -0
  100. package/src/datagrid/index.tsx +2 -0
  101. package/src/display/ArchbaseAnimationWrapper.tsx +272 -0
  102. package/src/display/ArchbaseBarcodeGenerator.tsx +303 -0
  103. package/src/display/ArchbaseCarousel.tsx +679 -0
  104. package/src/display/ArchbaseCodeViewer.tsx +271 -0
  105. package/src/display/ArchbaseDiffViewer.tsx +108 -0
  106. package/src/display/ArchbaseJsonTree.tsx +150 -0
  107. package/src/display/ArchbaseLightbox.tsx +279 -0
  108. package/src/display/ArchbaseMarquee.tsx +268 -0
  109. package/src/display/ArchbasePhotoAlbum.tsx +415 -0
  110. package/src/display/ArchbaseQRCode.tsx +137 -0
  111. package/src/display/ArchbaseTooltipRich.tsx +317 -0
  112. package/src/display/ArchbaseVirtualList.tsx +618 -0
  113. package/src/display/index.ts +94 -1
  114. package/src/editors/ArchbaseAIPromptInput.tsx +432 -0
  115. package/src/editors/ArchbaseBarcodeScanner.tsx +570 -0
  116. package/src/editors/ArchbaseCepInput.tsx +173 -0
  117. package/src/editors/ArchbaseColorGradientPicker.tsx +460 -0
  118. package/src/editors/ArchbaseCpfCnpjInput.tsx +193 -0
  119. package/src/editors/ArchbaseCurrencyInput.tsx +100 -0
  120. package/src/editors/ArchbaseDualListbox.tsx +671 -0
  121. package/src/editors/ArchbaseInPlaceEditor.tsx +406 -0
  122. package/src/editors/ArchbaseLightGrid.tsx +538 -0
  123. package/src/editors/ArchbaseMentionInput.tsx +384 -0
  124. package/src/editors/ArchbaseMultiEmail.tsx +367 -0
  125. package/src/editors/ArchbaseMultiViewCalendar.tsx +439 -0
  126. package/src/editors/ArchbaseNumberStepper.tsx +219 -0
  127. package/src/editors/ArchbaseOTPInput.tsx +133 -0
  128. package/src/editors/ArchbaseOperationHoursEditor.tsx +1 -1
  129. package/src/editors/ArchbasePhoneInput.tsx +355 -0
  130. package/src/editors/ArchbaseRangeSlider.tsx +109 -0
  131. package/src/editors/ArchbaseSignaturePad.tsx +425 -0
  132. package/src/editors/ArchbaseSpeechToTextInput.tsx +444 -0
  133. package/src/editors/ArchbaseSpreadsheet.tsx +388 -0
  134. package/src/editors/ArchbaseTagInput.tsx +326 -0
  135. package/src/editors/index.tsx +92 -0
  136. package/src/feedback/ArchbaseChunkProgressBar.tsx +156 -0
  137. package/src/feedback/ArchbaseRipple.tsx +278 -0
  138. package/src/feedback/ArchbaseSkeleton.tsx +419 -0
  139. package/src/feedback/index.ts +22 -1
  140. package/src/filters/ArchbaseColumnSelector.tsx +268 -0
  141. package/src/filters/index.ts +2 -0
  142. package/src/forms/ArchbaseFieldArray.tsx +305 -0
  143. package/src/forms/ArchbaseFormWizard.tsx +284 -0
  144. package/src/forms/ArchbaseStepper.tsx +137 -0
  145. package/src/forms/index.ts +24 -2
  146. package/src/forms/useArchbaseFormWizard.ts +283 -0
  147. package/src/hooks/index.ts +12 -0
  148. package/src/hooks/useArchbaseConfirm.ts +293 -0
  149. package/src/image/editor/functions/image-processing.ts +5 -0
  150. package/src/image/editor/index.tsx +305 -391
  151. package/src/image/index.ts +1 -0
  152. package/src/index.ts +3 -0
  153. package/src/list/ArchbaseTreeList.tsx +422 -0
  154. package/src/list/index.ts +3 -0
  155. package/src/navigation/ArchbaseActionSheet.tsx +301 -0
  156. package/src/navigation/ArchbaseAppBar.tsx +233 -0
  157. package/src/navigation/ArchbaseBottomNavigation.tsx +243 -0
  158. package/src/navigation/ArchbaseContextMenu.tsx +298 -0
  159. package/src/navigation/ArchbaseKeyboardShortcuts.tsx +472 -0
  160. package/src/navigation/ArchbaseSpotlight.tsx +483 -0
  161. package/src/navigation/index.ts +48 -1
  162. package/src/notification/ArchbaseNotificationCenter.tsx +502 -0
  163. package/src/notification/index.ts +2 -0
  164. package/src/onboarding/ArchbaseOnboardingTour.tsx +229 -102
  165. package/src/viewers/ArchbaseDocViewer.tsx +584 -0
  166. package/src/viewers/ArchbasePdfBuilder.tsx +291 -0
  167. package/src/viewers/ArchbaseXmlViewer.tsx +142 -0
  168. package/src/viewers/index.ts +12 -0
@@ -0,0 +1,425 @@
1
+ /**
2
+ * ArchbaseSignaturePad — captura de assinatura integrada ao DataSource (v1/v2).
3
+ * Armazena a assinatura como string base64 (data URL).
4
+ * @status stable
5
+ */
6
+ import React, { CSSProperties, useCallback, useEffect, useRef, useState } from 'react';
7
+ import SignatureCanvas from 'react-signature-canvas';
8
+ import { Box, Button, Group, Input, MantineSize, useMantineTheme, useComputedColorScheme } from '@mantine/core';
9
+ import { useForceUpdate } from '@mantine/hooks';
10
+ import { IconEraser, IconCheck } from '@tabler/icons-react';
11
+ import type { DataSourceEvent, IArchbaseDataSourceBase } from '@archbase/data';
12
+ import { DataSourceEventNames, useArchbaseDidUpdate, useArchbaseV1V2Compatibility } from '@archbase/data';
13
+ import { useValidationErrors } from '@archbase/core';
14
+
15
+ export interface ArchbaseSignaturePadProps<T, ID> {
16
+ /** Fonte de dados onde sera atribuido o valor da assinatura (V1 ou V2) */
17
+ dataSource?: IArchbaseDataSourceBase<T>;
18
+ /** Campo onde devera ser atribuido o valor da assinatura na fonte de dados */
19
+ dataField?: string;
20
+ /** Valor controlado (base64 data URL) */
21
+ value?: string;
22
+ /** Valor padrao (base64 data URL) */
23
+ defaultValue?: string;
24
+ /** Titulo do campo */
25
+ label?: string;
26
+ /** Descricao do campo */
27
+ description?: string;
28
+ /** Ultimo erro ocorrido */
29
+ error?: string;
30
+ /** Indicador se o preenchimento e obrigatorio */
31
+ required?: boolean;
32
+ /** Indicador se esta desabilitado */
33
+ disabled?: boolean;
34
+ /** Indicador se e somente leitura */
35
+ readOnly?: boolean;
36
+ /** Cor da caneta */
37
+ penColor?: string;
38
+ /** Cor de fundo do canvas */
39
+ backgroundColor?: string;
40
+ /** Largura do canvas */
41
+ width?: number;
42
+ /** Altura do canvas */
43
+ height?: number;
44
+ /** Exibir botao limpar */
45
+ showClearButton?: boolean;
46
+ /** Exibir botao confirmar */
47
+ showConfirmButton?: boolean;
48
+ /** Texto do botao limpar */
49
+ clearLabel?: string;
50
+ /** Texto do botao confirmar */
51
+ confirmLabel?: string;
52
+ /** Evento quando o valor muda (retorna base64 data URL) */
53
+ onChangeValue?: (value: string | undefined) => void;
54
+ /** Evento quando o foco entra */
55
+ onFocusEnter?: React.FocusEventHandler<any>;
56
+ /** Evento quando o foco sai */
57
+ onFocusExit?: React.FocusEventHandler<any>;
58
+ /** Evento quando o usuario confirma a assinatura */
59
+ onConfirm?: (value: string | undefined) => void;
60
+ /** Estilo do componente */
61
+ style?: CSSProperties;
62
+ /** Classe CSS */
63
+ className?: string;
64
+ /** Formato da imagem gerada */
65
+ imageFormat?: 'png' | 'jpeg' | 'svg';
66
+ /** Tamanho do componente */
67
+ size?: MantineSize;
68
+ }
69
+
70
+ function ArchbaseSignaturePadInner<T, ID>(
71
+ {
72
+ dataSource,
73
+ dataField,
74
+ value: valueProp,
75
+ defaultValue,
76
+ label,
77
+ description,
78
+ error,
79
+ required = false,
80
+ disabled = false,
81
+ readOnly = false,
82
+ penColor = 'black',
83
+ backgroundColor,
84
+ width = 400,
85
+ height = 200,
86
+ showClearButton = true,
87
+ showConfirmButton = false,
88
+ clearLabel = 'Limpar',
89
+ confirmLabel = 'Confirmar',
90
+ onChangeValue,
91
+ onFocusEnter,
92
+ onFocusExit,
93
+ onConfirm,
94
+ style,
95
+ className,
96
+ imageFormat = 'png',
97
+ size,
98
+ }: ArchbaseSignaturePadProps<T, ID>,
99
+ ) {
100
+ const theme = useMantineTheme();
101
+ const colorScheme = useComputedColorScheme('light');
102
+ const sigCanvasRef = useRef<SignatureCanvas | null>(null);
103
+ const containerRef = useRef<HTMLDivElement>(null);
104
+ const forceUpdate = useForceUpdate();
105
+
106
+ // Cor de fundo responsiva ao dark mode
107
+ const resolvedBackgroundColor =
108
+ backgroundColor ?? (colorScheme === 'dark' ? theme.colors.dark[6] : 'white');
109
+
110
+ // Hook de compatibilidade V1/V2
111
+ const v1v2Compatibility = useArchbaseV1V2Compatibility<string | undefined>(
112
+ 'ArchbaseSignaturePad',
113
+ dataSource,
114
+ dataField,
115
+ valueProp ?? defaultValue ?? undefined,
116
+ );
117
+
118
+ // Contexto de validacao
119
+ const validationContext = useValidationErrors();
120
+ const fieldKey = `${dataField}`;
121
+ const contextError = validationContext?.getError(fieldKey);
122
+
123
+ const [internalError, setInternalError] = useState<string | undefined>(error);
124
+ const [localValue, setLocalValue] = useState<string | undefined>(
125
+ valueProp ?? defaultValue ?? undefined,
126
+ );
127
+
128
+ // Atualizar erro externo
129
+ useEffect(() => {
130
+ if (error !== undefined && error !== internalError) {
131
+ setInternalError(error);
132
+ }
133
+ }, [error]);
134
+
135
+ // Carregar valor do datasource
136
+ const loadDataSourceFieldValue = useCallback(() => {
137
+ let initialValue: string | undefined = valueProp ?? defaultValue ?? undefined;
138
+
139
+ if (dataSource && dataField) {
140
+ const fieldVal = dataSource.getFieldValue(dataField);
141
+ initialValue = fieldVal || undefined;
142
+ }
143
+
144
+ setLocalValue(initialValue);
145
+ }, [dataSource, dataField, valueProp, defaultValue]);
146
+
147
+ const fieldChangedListener = useCallback(() => {
148
+ loadDataSourceFieldValue();
149
+ }, [loadDataSourceFieldValue]);
150
+
151
+ const dataSourceEvent = useCallback(
152
+ (event: DataSourceEvent<T>) => {
153
+ if (dataSource && dataField) {
154
+ if (
155
+ event.type === DataSourceEventNames.dataChanged ||
156
+ event.type === DataSourceEventNames.recordChanged ||
157
+ event.type === DataSourceEventNames.afterScroll ||
158
+ event.type === DataSourceEventNames.afterCancel ||
159
+ event.type === DataSourceEventNames.afterEdit
160
+ ) {
161
+ loadDataSourceFieldValue();
162
+ if (!v1v2Compatibility.isDataSourceV2) {
163
+ forceUpdate();
164
+ }
165
+ }
166
+
167
+ if (
168
+ event.type === DataSourceEventNames.onFieldError &&
169
+ event.fieldName === dataField
170
+ ) {
171
+ setInternalError(event.error);
172
+ validationContext?.setError(fieldKey, event.error);
173
+ }
174
+ }
175
+ },
176
+ [
177
+ v1v2Compatibility.isDataSourceV2,
178
+ dataSource,
179
+ dataField,
180
+ loadDataSourceFieldValue,
181
+ forceUpdate,
182
+ validationContext,
183
+ fieldKey,
184
+ ],
185
+ );
186
+
187
+ // Ref estavel para o callback
188
+ const dataSourceEventRef = useRef(dataSourceEvent);
189
+ useEffect(() => {
190
+ dataSourceEventRef.current = dataSourceEvent;
191
+ }, [dataSourceEvent]);
192
+
193
+ const stableDataSourceEvent = useCallback((event: DataSourceEvent<T>) => {
194
+ dataSourceEventRef.current(event);
195
+ }, []);
196
+
197
+ // Registrar listeners
198
+ useEffect(() => {
199
+ loadDataSourceFieldValue();
200
+ if (dataSource && dataField) {
201
+ const hasFieldListener =
202
+ typeof (dataSource as any).addFieldChangeListener === 'function';
203
+ dataSource.addListener(stableDataSourceEvent);
204
+ if (hasFieldListener) {
205
+ (dataSource as any).addFieldChangeListener(dataField, fieldChangedListener);
206
+ }
207
+
208
+ return () => {
209
+ dataSource.removeListener(stableDataSourceEvent);
210
+ if (hasFieldListener) {
211
+ (dataSource as any).removeFieldChangeListener(dataField, fieldChangedListener);
212
+ }
213
+ };
214
+ }
215
+ }, [dataSource, dataField, stableDataSourceEvent, fieldChangedListener]);
216
+
217
+ useArchbaseDidUpdate(() => {
218
+ loadDataSourceFieldValue();
219
+ }, []);
220
+
221
+ // Carregar imagem no canvas quando o valor muda
222
+ useEffect(() => {
223
+ const sigCanvas = sigCanvasRef.current;
224
+ if (!sigCanvas) return;
225
+
226
+ if (localValue && localValue.startsWith('data:')) {
227
+ sigCanvas.fromDataURL(localValue, {
228
+ width,
229
+ height,
230
+ ratio: 1,
231
+ });
232
+ } else if (!localValue) {
233
+ sigCanvas.clear();
234
+ }
235
+ }, [localValue, width, height]);
236
+
237
+ const getMimeType = (): string => {
238
+ switch (imageFormat) {
239
+ case 'jpeg':
240
+ return 'image/jpeg';
241
+ case 'svg':
242
+ return 'image/svg+xml';
243
+ case 'png':
244
+ default:
245
+ return 'image/png';
246
+ }
247
+ };
248
+
249
+ const getDataURL = (): string | undefined => {
250
+ const sigCanvas = sigCanvasRef.current;
251
+ if (!sigCanvas || sigCanvas.isEmpty()) {
252
+ return undefined;
253
+ }
254
+
255
+ if (imageFormat === 'svg') {
256
+ const dataUrl = sigCanvas.toDataURL('image/svg+xml');
257
+ return dataUrl;
258
+ }
259
+
260
+ return sigCanvas.toDataURL(getMimeType());
261
+ };
262
+
263
+ const handleStrokeEnd = () => {
264
+ if (disabled || isReadOnly()) return;
265
+
266
+ // Limpar erros ao interagir
267
+ const hasError = internalError || contextError;
268
+ if (hasError) {
269
+ setInternalError(undefined);
270
+ validationContext?.clearError(fieldKey);
271
+ }
272
+
273
+ const base64Value = getDataURL();
274
+ setLocalValue(base64Value);
275
+
276
+ // Salvar no datasource
277
+ if (
278
+ dataSource &&
279
+ !dataSource.isBrowsing() &&
280
+ dataField &&
281
+ dataSource.getFieldValue(dataField) !== base64Value
282
+ ) {
283
+ v1v2Compatibility.handleValueChange(base64Value);
284
+ }
285
+
286
+ if (onChangeValue) {
287
+ onChangeValue(base64Value);
288
+ }
289
+ };
290
+
291
+ const handleClear = () => {
292
+ if (disabled || isReadOnly()) return;
293
+
294
+ const sigCanvas = sigCanvasRef.current;
295
+ if (sigCanvas) {
296
+ sigCanvas.clear();
297
+ }
298
+
299
+ // Limpar erros
300
+ const hasError = internalError || contextError;
301
+ if (hasError) {
302
+ setInternalError(undefined);
303
+ validationContext?.clearError(fieldKey);
304
+ }
305
+
306
+ setLocalValue(undefined);
307
+
308
+ if (
309
+ dataSource &&
310
+ !dataSource.isBrowsing() &&
311
+ dataField
312
+ ) {
313
+ v1v2Compatibility.handleValueChange(undefined);
314
+ }
315
+
316
+ if (onChangeValue) {
317
+ onChangeValue(undefined);
318
+ }
319
+ };
320
+
321
+ const handleConfirm = () => {
322
+ const base64Value = getDataURL();
323
+ if (onConfirm) {
324
+ onConfirm(base64Value);
325
+ }
326
+ };
327
+
328
+ const isReadOnly = (): boolean => {
329
+ return readOnly || v1v2Compatibility.isReadOnly;
330
+ };
331
+
332
+ const handleFocusEnter = (event: React.FocusEvent<any>) => {
333
+ if (onFocusEnter) {
334
+ onFocusEnter(event);
335
+ }
336
+ };
337
+
338
+ const handleFocusExit = (event: React.FocusEvent<any>) => {
339
+ if (onFocusExit) {
340
+ onFocusExit(event);
341
+ }
342
+ };
343
+
344
+ const displayError = internalError || contextError;
345
+ const isDisabledOrReadOnly = disabled || isReadOnly();
346
+
347
+ return (
348
+ <Input.Wrapper
349
+ withAsterisk={required}
350
+ label={label}
351
+ description={description}
352
+ error={displayError}
353
+ size={size}
354
+ className={className}
355
+ style={style}
356
+ >
357
+ <Box
358
+ ref={containerRef}
359
+ onFocus={handleFocusEnter}
360
+ onBlur={handleFocusExit}
361
+ tabIndex={0}
362
+ style={{
363
+ border: `1px solid ${
364
+ displayError
365
+ ? theme.colors.red[6]
366
+ : colorScheme === 'dark'
367
+ ? theme.colors.dark[4]
368
+ : theme.colors.gray[4]
369
+ }`,
370
+ borderRadius: theme.radius.sm,
371
+ overflow: 'hidden',
372
+ width,
373
+ opacity: disabled ? 0.6 : 1,
374
+ cursor: isDisabledOrReadOnly ? 'not-allowed' : 'crosshair',
375
+ position: 'relative',
376
+ }}
377
+ >
378
+ <SignatureCanvas
379
+ ref={sigCanvasRef}
380
+ penColor={penColor}
381
+ backgroundColor={resolvedBackgroundColor}
382
+ canvasProps={{
383
+ width,
384
+ height,
385
+ style: {
386
+ display: 'block',
387
+ pointerEvents: isDisabledOrReadOnly ? 'none' : 'auto',
388
+ },
389
+ }}
390
+ onEnd={handleStrokeEnd}
391
+ />
392
+ </Box>
393
+ {(showClearButton || showConfirmButton) && (
394
+ <Group gap="xs" mt="xs">
395
+ {showClearButton && (
396
+ <Button
397
+ variant="light"
398
+ size="xs"
399
+ leftSection={<IconEraser size={16} />}
400
+ onClick={handleClear}
401
+ disabled={isDisabledOrReadOnly}
402
+ >
403
+ {clearLabel}
404
+ </Button>
405
+ )}
406
+ {showConfirmButton && (
407
+ <Button
408
+ variant="filled"
409
+ size="xs"
410
+ leftSection={<IconCheck size={16} />}
411
+ onClick={handleConfirm}
412
+ disabled={isDisabledOrReadOnly}
413
+ >
414
+ {confirmLabel}
415
+ </Button>
416
+ )}
417
+ </Group>
418
+ )}
419
+ </Input.Wrapper>
420
+ );
421
+ }
422
+
423
+ export const ArchbaseSignaturePad = React.memo(ArchbaseSignaturePadInner) as typeof ArchbaseSignaturePadInner;
424
+
425
+ (ArchbaseSignaturePad as any).displayName = 'ArchbaseSignaturePad';