@incodetech/prizma-core-screens 0.2.24 → 0.2.26
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/DemoScreensConfigSheetScreen.js +1 -1
- package/dist/DocumentSignatureLayout.css +160 -0
- package/dist/DocumentSignatureReviewScreen.d.ts +88 -0
- package/dist/DocumentSignatureReviewScreen.js +274 -0
- package/dist/DocumentSignatureStrings.d.ts +82 -0
- package/dist/DocumentSignatureStrings.js +39 -0
- package/dist/ElectronicSignatureDrawScreen.d.ts +17 -2
- package/dist/ElectronicSignatureDrawScreen.js +60 -12
- package/dist/ElectronicSignatureLayout.css +32 -0
- package/dist/ElectronicSignatureStrings.d.ts +26 -1
- package/dist/FaceCaptureCapturingScreen.js +1 -1
- package/dist/IdCaptureStageScreen.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4 -0
- package/dist/styles.css +1 -0
- package/package.json +9 -3
- package/src/DemoScreensConfigSheetScreen.tsx +1 -1
- package/src/DocumentSignatureLayout.css +160 -0
- package/src/DocumentSignatureReviewScreen.tsx +517 -0
- package/src/DocumentSignatureStrings.ts +122 -0
- package/src/ElectronicSignatureDrawScreen.tsx +143 -19
- package/src/ElectronicSignatureLayout.css +32 -0
- package/src/ElectronicSignatureStrings.ts +28 -1
- package/src/FaceCaptureCapturingScreen.tsx +0 -1
- package/src/IdCaptureStageScreen.tsx +0 -1
- package/src/index.ts +18 -1
- package/src/styles.css +1 -0
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import React, { forwardRef } from 'react';
|
|
1
|
+
import React, { forwardRef, useEffect, useId, useState } from 'react';
|
|
2
|
+
import { PrizmaSegmentedControl } from '@incodetech/prizma-core-web/segmented-control';
|
|
2
3
|
import { PrizmaSignaturePad } from '@incodetech/prizma-core-web/signature-pad';
|
|
4
|
+
import { PrizmaSignaturePreview } from '@incodetech/prizma-core-web/signature-preview';
|
|
5
|
+
import { PrizmaTextField } from '@incodetech/prizma-core-web/text-field';
|
|
3
6
|
import { PrizmaFormScreen, type PrizmaFormScreenProps } from './FormScreen';
|
|
4
7
|
import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
|
|
5
8
|
import type {
|
|
6
9
|
ElectronicSignatureDrawState,
|
|
10
|
+
ElectronicSignatureMethod,
|
|
7
11
|
ElectronicSignatureStrings,
|
|
8
12
|
} from './ElectronicSignatureStrings';
|
|
9
13
|
import './ScreenLayout.css';
|
|
14
|
+
import './ElectronicSignatureLayout.css';
|
|
10
15
|
|
|
11
16
|
export interface ElectronicSignatureDrawScreenProps
|
|
12
17
|
extends Omit<
|
|
@@ -23,8 +28,22 @@ export interface ElectronicSignatureDrawScreenProps
|
|
|
23
28
|
> {
|
|
24
29
|
/** Module copy — this screen reads the `draw` slice. */
|
|
25
30
|
strings: ElectronicSignatureStrings;
|
|
26
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Which pose to render: `draw` (empty pad), `signed` (ink on the pad) or
|
|
33
|
+
* `type` (type mode, `typedName` in the field). Default `draw`.
|
|
34
|
+
*/
|
|
27
35
|
state?: ElectronicSignatureDrawState;
|
|
36
|
+
/**
|
|
37
|
+
* Draw or Type, when the host owns it. Left out, the screen keeps its own,
|
|
38
|
+
* starting from `state`. Only read when `strings.type` is supplied.
|
|
39
|
+
*/
|
|
40
|
+
method?: ElectronicSignatureMethod;
|
|
41
|
+
/** Called when the person switches between Draw and Type. */
|
|
42
|
+
onMethodChange?: (method: ElectronicSignatureMethod) => void;
|
|
43
|
+
/** The typed name, when the host owns it. Left out, the screen keeps its own. */
|
|
44
|
+
typedName?: string;
|
|
45
|
+
/** Called on every change to the typed name. */
|
|
46
|
+
onTypedNameChange?: (name: string) => void;
|
|
28
47
|
/**
|
|
29
48
|
* Core's own extension point for the drawing engine
|
|
30
49
|
* (`PrizmaSignaturePad.onCanvasReady`: "consumers wire their drawing engine
|
|
@@ -79,6 +98,10 @@ export const ElectronicSignatureDrawScreen = forwardRef<
|
|
|
79
98
|
{
|
|
80
99
|
strings,
|
|
81
100
|
state = 'draw',
|
|
101
|
+
method: methodProp,
|
|
102
|
+
onMethodChange,
|
|
103
|
+
typedName: typedNameProp,
|
|
104
|
+
onTypedNameChange,
|
|
82
105
|
onCanvasReady,
|
|
83
106
|
screenId = `electronic-signature-${state}`,
|
|
84
107
|
overrides,
|
|
@@ -88,16 +111,129 @@ export const ElectronicSignatureDrawScreen = forwardRef<
|
|
|
88
111
|
ref,
|
|
89
112
|
) => {
|
|
90
113
|
const signed = state === 'signed';
|
|
114
|
+
const alt = strings.type;
|
|
115
|
+
|
|
116
|
+
// Draw / Type: controlled when the host passes `method` / `typedName`,
|
|
117
|
+
// otherwise the screen holds them, starting from the pose.
|
|
118
|
+
const [ownMethod, setOwnMethod] = useState<ElectronicSignatureMethod>(
|
|
119
|
+
state === 'type' ? 'type' : 'draw',
|
|
120
|
+
);
|
|
121
|
+
const [ownName, setOwnName] = useState(state === 'type' ? typedNameProp ?? '' : '');
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
setOwnMethod(state === 'type' ? 'type' : 'draw');
|
|
124
|
+
}, [state]);
|
|
125
|
+
const method: ElectronicSignatureMethod = alt ? methodProp ?? ownMethod : 'draw';
|
|
126
|
+
const name = typedNameProp ?? ownName;
|
|
127
|
+
const typing = method === 'type';
|
|
128
|
+
const [padKey, setPadKey] = useState(0);
|
|
129
|
+
const panelId = useId();
|
|
130
|
+
|
|
131
|
+
const setName = (next: string) => {
|
|
132
|
+
if (typedNameProp === undefined) setOwnName(next);
|
|
133
|
+
onTypedNameChange?.(next);
|
|
134
|
+
};
|
|
135
|
+
// Switching clears what the other mode held, the Document Electronic
|
|
136
|
+
// Signature rule (Elena, 2026-11-12), so Done only turns on for the
|
|
137
|
+
// signature on screen. A fresh pad is a remount of Core's pad.
|
|
138
|
+
const switchMethod = (next: ElectronicSignatureMethod) => {
|
|
139
|
+
if (next === method) return;
|
|
140
|
+
setPadKey((k) => k + 1);
|
|
141
|
+
setName('');
|
|
142
|
+
if (methodProp === undefined) setOwnMethod(next);
|
|
143
|
+
onMethodChange?.(next);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const ready = typing ? name.trim().length > 1 : signed;
|
|
147
|
+
const title = typing && alt ? alt.title : strings.draw.title;
|
|
148
|
+
const subtitle = typing && alt ? alt.subtitle : strings.draw.subtitle;
|
|
149
|
+
|
|
150
|
+
const pad = (ghost: boolean) => (
|
|
151
|
+
<PrizmaSignaturePad
|
|
152
|
+
key={ghost ? 'ghost' : padKey}
|
|
153
|
+
isFilled={ghost ? false : signed}
|
|
154
|
+
/* Full-signature sub-type, not the initials one. */
|
|
155
|
+
isInitials={false}
|
|
156
|
+
placeholder={strings.draw.placeholder}
|
|
157
|
+
canvasLabel={strings.draw.canvasLabel}
|
|
158
|
+
clearLabel={strings.draw.clearLabel}
|
|
159
|
+
/* Clearing the canvas is a different flow from submitting it, so it
|
|
160
|
+
emits its own event rather than collapsing into the CTA
|
|
161
|
+
(DEVIATIONS #PI-10). */
|
|
162
|
+
onClear={ghost ? undefined : () => onAction?.({ type: 'secondary', screenId })}
|
|
163
|
+
onCanvasReady={ghost ? undefined : onCanvasReady}
|
|
164
|
+
/>
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
// No `type` copy: the pad-only screen the module shipped with.
|
|
168
|
+
const middle = !alt ? (
|
|
169
|
+
pad(false)
|
|
170
|
+
) : (
|
|
171
|
+
<div className="electronic-signature-method">
|
|
172
|
+
<PrizmaSegmentedControl
|
|
173
|
+
aria-label={alt.methodLabel}
|
|
174
|
+
value={method}
|
|
175
|
+
onValueChange={(v: string) => switchMethod(v === 'type' ? 'type' : 'draw')}
|
|
176
|
+
options={[
|
|
177
|
+
{ value: 'draw', label: alt.drawLabel, controls: !typing ? panelId : undefined },
|
|
178
|
+
{ value: 'type', label: alt.typeLabel, controls: typing ? panelId : undefined },
|
|
179
|
+
]}
|
|
180
|
+
/>
|
|
181
|
+
{!typing ? (
|
|
182
|
+
<div id={panelId} role="tabpanel" aria-label={alt.drawLabel} className="electronic-signature-method__body">
|
|
183
|
+
{pad(false)}
|
|
184
|
+
</div>
|
|
185
|
+
) : (
|
|
186
|
+
<div
|
|
187
|
+
id={panelId}
|
|
188
|
+
role="tabpanel"
|
|
189
|
+
aria-label={alt.typeLabel}
|
|
190
|
+
className="electronic-signature-method__body electronic-signature-method__body--type"
|
|
191
|
+
>
|
|
192
|
+
{/* An inert copy of the pad holds the Draw height, so the CTA does
|
|
193
|
+
not jump when the mode switches. Inert, not just hidden: its
|
|
194
|
+
Clear canvas button must stay out of focus and hit-testing. */}
|
|
195
|
+
<div className="electronic-signature-method__floor" aria-hidden="true" {...{ inert: '' }}>
|
|
196
|
+
{pad(true)}
|
|
197
|
+
</div>
|
|
198
|
+
<div className="electronic-signature-method__type">
|
|
199
|
+
{/* Set up for a name: the phone offers the person's own,
|
|
200
|
+
capitalises each word, does not autocorrect, Return submits. */}
|
|
201
|
+
<PrizmaTextField
|
|
202
|
+
label={alt.nameLabel}
|
|
203
|
+
value={name}
|
|
204
|
+
onValueChange={setName}
|
|
205
|
+
autoComplete="name"
|
|
206
|
+
autoCapitalize="words"
|
|
207
|
+
autoCorrect="off"
|
|
208
|
+
spellCheck={false}
|
|
209
|
+
enterKeyHint="done"
|
|
210
|
+
onKeyDown={(e) => {
|
|
211
|
+
if (e.key === 'Enter' && ready) {
|
|
212
|
+
e.preventDefault();
|
|
213
|
+
onAction?.({ type: 'cta', screenId });
|
|
214
|
+
}
|
|
215
|
+
}}
|
|
216
|
+
/>
|
|
217
|
+
<PrizmaSignaturePreview
|
|
218
|
+
label={alt.previewLabel}
|
|
219
|
+
name={name}
|
|
220
|
+
placeholder={alt.previewPlaceholder}
|
|
221
|
+
/>
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
)}
|
|
225
|
+
</div>
|
|
226
|
+
);
|
|
91
227
|
|
|
92
228
|
return (
|
|
93
229
|
<PrizmaFormScreen
|
|
94
230
|
ref={ref}
|
|
95
|
-
title={
|
|
96
|
-
subtitle={
|
|
231
|
+
title={title}
|
|
232
|
+
subtitle={subtitle}
|
|
97
233
|
ctaLabel={strings.draw.ctaLabel}
|
|
98
234
|
/* `eSign.draw` draws `Done` on Button/Primary/Surface/Disabled — there
|
|
99
|
-
is nothing to submit until the canvas has ink. */
|
|
100
|
-
ctaDisabled={!
|
|
235
|
+
is nothing to submit until the canvas has ink, or a name is typed. */
|
|
236
|
+
ctaDisabled={!ready}
|
|
101
237
|
verifiedLabel={strings.verifiedLabel}
|
|
102
238
|
navLabel={strings.navLabel}
|
|
103
239
|
screenId={screenId}
|
|
@@ -105,19 +241,7 @@ export const ElectronicSignatureDrawScreen = forwardRef<
|
|
|
105
241
|
onAction={onAction}
|
|
106
242
|
{...shell}
|
|
107
243
|
>
|
|
108
|
-
|
|
109
|
-
isFilled={signed}
|
|
110
|
-
/* Full-signature sub-type, not the initials one. */
|
|
111
|
-
isInitials={false}
|
|
112
|
-
placeholder={strings.draw.placeholder}
|
|
113
|
-
canvasLabel={strings.draw.canvasLabel}
|
|
114
|
-
clearLabel={strings.draw.clearLabel}
|
|
115
|
-
/* Clearing the canvas is a different flow from submitting it, so it
|
|
116
|
-
emits its own event rather than collapsing into the CTA
|
|
117
|
-
(DEVIATIONS #PI-10). */
|
|
118
|
-
onClear={() => onAction?.({ type: 'secondary', screenId })}
|
|
119
|
-
onCanvasReady={onCanvasReady}
|
|
120
|
-
/>
|
|
244
|
+
{middle}
|
|
121
245
|
</PrizmaFormScreen>
|
|
122
246
|
);
|
|
123
247
|
},
|
|
@@ -84,3 +84,35 @@
|
|
|
84
84
|
letter-spacing: var(--prizma-headline-h5-letter-spacing);
|
|
85
85
|
color: var(--prizma-text-body-800-primary);
|
|
86
86
|
}
|
|
87
|
+
|
|
88
|
+
/* ── Draw / Type (`strings.type` supplied) ───────────────────────────────────
|
|
89
|
+
* Core's Segmented control over the mode's body, the same composition as
|
|
90
|
+
* Document Electronic Signature's sheet (`.document-signature-sheet-body`):
|
|
91
|
+
* Spacing/8 between the control and the body, and between field and preview.
|
|
92
|
+
* Type mode keeps the Draw body's height: an inert copy of Core's pad shares
|
|
93
|
+
* the grid cell with the field + preview, so the CTA does not jump. */
|
|
94
|
+
.electronic-signature-method,
|
|
95
|
+
.electronic-signature-method__body,
|
|
96
|
+
.electronic-signature-method__type {
|
|
97
|
+
display: flex;
|
|
98
|
+
flex-direction: column;
|
|
99
|
+
gap: var(--prizma-spacing-8);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.electronic-signature-method__body--type {
|
|
103
|
+
display: grid;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.electronic-signature-method__body--type > * {
|
|
107
|
+
grid-area: 1 / 1;
|
|
108
|
+
min-width: 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.electronic-signature-method__floor {
|
|
112
|
+
visibility: hidden;
|
|
113
|
+
pointer-events: none;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.electronic-signature-method__type {
|
|
117
|
+
align-self: start;
|
|
118
|
+
}
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
* placeholder visible, both actions inert) and `eSign.signed` (ink on the
|
|
16
16
|
* canvas, Clear live, Done live). One screen, one Figma-drawn axis.
|
|
17
17
|
*/
|
|
18
|
-
export type ElectronicSignatureDrawState = 'draw' | 'signed';
|
|
18
|
+
export type ElectronicSignatureDrawState = 'draw' | 'signed' | 'type';
|
|
19
|
+
|
|
20
|
+
/** How the person signs: drawing on the pad, or typing their name. */
|
|
21
|
+
export type ElectronicSignatureMethod = 'draw' | 'type';
|
|
19
22
|
|
|
20
23
|
export interface ElectronicSignatureStrings {
|
|
21
24
|
/** "verified by" attribution copy for the footer tag. */
|
|
@@ -49,6 +52,30 @@ export interface ElectronicSignatureStrings {
|
|
|
49
52
|
ctaLabel: string;
|
|
50
53
|
};
|
|
51
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Draw / Type — the accessible alternative to the pad (Elena, 2026-11-13,
|
|
57
|
+
* the same switch as Document Electronic Signature's sheet). Optional: a
|
|
58
|
+
* host that leaves it out keeps the pad-only screen it shipped with.
|
|
59
|
+
*/
|
|
60
|
+
type?: {
|
|
61
|
+
/** Accessible name for the Draw / Type Segmented control — "Signature method". */
|
|
62
|
+
methodLabel: string;
|
|
63
|
+
/** Segmented control, the draw option — "Draw". */
|
|
64
|
+
drawLabel: string;
|
|
65
|
+
/** Segmented control, the type option — "Type". */
|
|
66
|
+
typeLabel: string;
|
|
67
|
+
/** H2 in type mode — "Type your name". */
|
|
68
|
+
title: string;
|
|
69
|
+
/** H5 in type mode — "Use your full name". */
|
|
70
|
+
subtitle: string;
|
|
71
|
+
/** Field label — "Full name". */
|
|
72
|
+
nameLabel: string;
|
|
73
|
+
/** Core's Signature preview label, under the field — "Preview". */
|
|
74
|
+
previewLabel: string;
|
|
75
|
+
/** Signature preview while the field is empty — "Your signature". */
|
|
76
|
+
previewPlaceholder: string;
|
|
77
|
+
};
|
|
78
|
+
|
|
52
79
|
/** `eSign.success` — the verdict, reported with no action. */
|
|
53
80
|
success: {
|
|
54
81
|
/** H2 — "Signed successfully!". */
|
|
@@ -154,7 +154,6 @@ export const FaceCaptureCapturingScreen = forwardRef<
|
|
|
154
154
|
extendTime && offer ? (
|
|
155
155
|
<PrizmaSnackbar
|
|
156
156
|
state="neutral"
|
|
157
|
-
isMultiline
|
|
158
157
|
// Assertive on purpose — see the live-region note in this file's
|
|
159
158
|
// header. The component default here would be `status`.
|
|
160
159
|
role="alert"
|
|
@@ -228,7 +228,6 @@ export const IdCaptureStageScreen = forwardRef<HTMLDivElement, IdCaptureStageScr
|
|
|
228
228
|
(extendTime && offer ? (
|
|
229
229
|
<PrizmaSnackbar
|
|
230
230
|
state="neutral"
|
|
231
|
-
isMultiline
|
|
232
231
|
// Assertive on purpose — a polite region can queue behind the
|
|
233
232
|
// stage's own state announcements and be read out after the 20 s
|
|
234
233
|
// has already run out. FaceCaptureCapturingScreen's header has the
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// from the `read-and-sign-in-one-screen` exploration
|
|
1
2
|
// @incodetech/prizma-core-screens — barrel.
|
|
2
3
|
//
|
|
3
4
|
// Foundation: shell, nav, capture overlay, and the seven screen archetypes
|
|
@@ -394,11 +395,27 @@ export { CurpResultScreen, type CurpResultScreenProps } from './CurpResultScreen
|
|
|
394
395
|
|
|
395
396
|
// ── Electronic Signature (wave 3) ────────────────────────────────────────────────
|
|
396
397
|
// Purple sections of the Electronic Signature Figma file (kUsDigsC8Mq1WobTewF0R6, page 5:13191).
|
|
397
|
-
export {
|
|
398
|
+
export {
|
|
399
|
+
type ElectronicSignatureDrawState,
|
|
400
|
+
type ElectronicSignatureMethod,
|
|
401
|
+
type ElectronicSignatureStrings,
|
|
402
|
+
} from './ElectronicSignatureStrings';
|
|
398
403
|
export { ElectronicSignatureDrawScreen, type ElectronicSignatureDrawScreenProps } from './ElectronicSignatureDrawScreen';
|
|
399
404
|
export { ElectronicSignatureErrorScreen, type ElectronicSignatureErrorScreenProps } from './ElectronicSignatureErrorScreen';
|
|
400
405
|
export { ElectronicSignatureReviewScreen, type ElectronicSignatureReviewScreenProps } from './ElectronicSignatureReviewScreen';
|
|
401
406
|
export { ElectronicSignatureSuccessScreen, type ElectronicSignatureSuccessScreenProps } from './ElectronicSignatureSuccessScreen';
|
|
407
|
+
// Document Electronic Signature: from the `read-and-sign-in-one-screen` exploration.
|
|
408
|
+
export {
|
|
409
|
+
documentSignatureResultStrings,
|
|
410
|
+
type DocumentSignatureState,
|
|
411
|
+
type DocumentSignatureStrings,
|
|
412
|
+
} from './DocumentSignatureStrings';
|
|
413
|
+
export {
|
|
414
|
+
DocumentSignatureReviewScreen,
|
|
415
|
+
type DocumentSignatureDocument,
|
|
416
|
+
type DocumentSignatureReviewScreenProps,
|
|
417
|
+
type DocumentSignatureSignature,
|
|
418
|
+
} from './DocumentSignatureReviewScreen';
|
|
402
419
|
|
|
403
420
|
// ── Qualified Signature (wave 3) ────────────────────────────────────────────────
|
|
404
421
|
// Purple sections of the Qualified Signature Figma file (XO9YGKlEsGUyag8CGbSUsi, page 6086:28669).
|
package/src/styles.css
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
@import './DemoScreensLayout.css';
|
|
19
19
|
@import './DigitalIdProvidersLayout.css';
|
|
20
20
|
@import './DocumentCaptureLayout.css';
|
|
21
|
+
@import './DocumentSignatureLayout.css';
|
|
21
22
|
@import './EkycLayout.css';
|
|
22
23
|
@import './ElectronicSignatureLayout.css';
|
|
23
24
|
@import './FaceCaptureLayout.css';
|