@nodii/onboarding 0.1.0-dev.0 → 0.1.0
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/README.md +78 -0
- package/dist/chunk-AZE3NPSY.js +186 -0
- package/dist/chunk-AZE3NPSY.js.map +1 -0
- package/dist/{chunk-BQCTDU5V.js → chunk-BMQINH6O.js} +89 -15
- package/dist/chunk-BMQINH6O.js.map +1 -0
- package/dist/{chunk-34BQX2KR.js → chunk-F75ZJERM.js} +41 -6
- package/dist/chunk-F75ZJERM.js.map +1 -0
- package/dist/chunk-FIRSA7EH.js +3 -0
- package/dist/{chunk-ZDY2I6KY.js.map → chunk-FIRSA7EH.js.map} +1 -1
- package/dist/{chunk-SWMIIUXR.js → chunk-IPAKPLIF.js} +590 -92
- package/dist/chunk-IPAKPLIF.js.map +1 -0
- package/dist/chunk-JFDQZ3AC.js +3 -0
- package/dist/chunk-JFDQZ3AC.js.map +1 -0
- package/dist/{chunk-4SWOVHZ2.js → chunk-KQTS47FC.js} +129 -17
- package/dist/chunk-KQTS47FC.js.map +1 -0
- package/dist/chunk-LVJM4CTG.js +306 -0
- package/dist/chunk-LVJM4CTG.js.map +1 -0
- package/dist/chunk-SEKNVHD3.js +59 -0
- package/dist/chunk-SEKNVHD3.js.map +1 -0
- package/dist/chunk-SIMLMQPT.js +37 -0
- package/dist/chunk-SIMLMQPT.js.map +1 -0
- package/dist/chunk-U56GQITG.js +79 -0
- package/dist/chunk-U56GQITG.js.map +1 -0
- package/dist/{chunk-AFCJLUPK.js → chunk-U6AXKGYQ.js} +14 -5
- package/dist/chunk-U6AXKGYQ.js.map +1 -0
- package/dist/{chunk-AW7W3HAC.js → chunk-XJTJPBJB.js} +40 -3
- package/dist/chunk-XJTJPBJB.js.map +1 -0
- package/dist/client-CqE2dF9A.d.ts +86 -0
- package/dist/consent/index.d.ts +59 -0
- package/dist/consent/index.js +7 -0
- package/dist/consent/index.js.map +1 -0
- package/dist/controller-BQb62D0N.d.ts +177 -0
- package/dist/dynamic/index.d.ts +57 -6
- package/dist/dynamic/index.js +4 -2
- package/dist/errors-vJkye4a0.d.ts +110 -0
- package/dist/form/index.d.ts +2 -2
- package/dist/form/index.js +2 -2
- package/dist/index-Dqfa890U.d.ts +83 -0
- package/dist/index.d.ts +12 -6
- package/dist/index.js +12 -8
- package/dist/{model-IEyDI54w.d.ts → model-ESLSEbi0.d.ts} +199 -46
- package/dist/model-mnjAEtKe.d.ts +253 -0
- package/dist/render-DC7P2BGQ.js +5 -0
- package/dist/render-DC7P2BGQ.js.map +1 -0
- package/dist/schema-BrXb9gnh.d.ts +267 -0
- package/dist/{signup-client-Bl6eUrxR.d.ts → signup-client-BL5DfarJ.d.ts} +152 -19
- package/dist/spec/index.d.ts +10 -81
- package/dist/spec/index.js +3 -2
- package/dist/submit/index.d.ts +7 -71
- package/dist/submit/index.js +3 -3
- package/dist/viewer/index.d.ts +4 -0
- package/dist/viewer/index.js +5 -0
- package/dist/viewer/index.js.map +1 -0
- package/dist/widget/index.d.ts +50 -7
- package/dist/widget/index.js +9 -7
- package/package.json +21 -2
- package/dist/chunk-34BQX2KR.js.map +0 -1
- package/dist/chunk-4SWOVHZ2.js.map +0 -1
- package/dist/chunk-AFCJLUPK.js.map +0 -1
- package/dist/chunk-AW7W3HAC.js.map +0 -1
- package/dist/chunk-BIFANV7M.js +0 -22
- package/dist/chunk-BIFANV7M.js.map +0 -1
- package/dist/chunk-BQCTDU5V.js.map +0 -1
- package/dist/chunk-SWMIIUXR.js.map +0 -1
- package/dist/chunk-ZDY2I6KY.js +0 -3
- package/dist/schema-TfyBU6JW.d.ts +0 -107
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod/v3';
|
|
2
|
-
import { T as TerminalStage } from './model-
|
|
3
|
-
import {
|
|
2
|
+
import { T as TerminalStage } from './model-ESLSEbi0.js';
|
|
3
|
+
import { e as ConsentSubmitDocument } from './controller-BQb62D0N.js';
|
|
4
|
+
import { C as ContactFormValues } from './schema-BrXb9gnh.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Submit client for POST /api/v1/public/onboarding/leads.
|
|
@@ -42,7 +43,7 @@ interface LeadsSubmitOptions {
|
|
|
42
43
|
* fresh token (recommended — tokens are single-use; a fixed string on a
|
|
43
44
|
* retried request risks 403 after the first attempt consumed it).
|
|
44
45
|
*/
|
|
45
|
-
botToken
|
|
46
|
+
botToken?: BotTokenSource;
|
|
46
47
|
/**
|
|
47
48
|
* Stable idempotency key for this submission. Generate ONCE with
|
|
48
49
|
* `generateIdempotencyKey()` and pass the same key for retries.
|
|
@@ -116,7 +117,7 @@ declare function submitLead(values: ContactFormValues, options: LeadsSubmitOptio
|
|
|
116
117
|
* Contract per the LOCKED hub REST interface (PublicOnboardingSubmitRequest):
|
|
117
118
|
* - Body: { specVersion, answers, selectedServices?, botToken,
|
|
118
119
|
* consent:{tosAccepted:true, privacyAccepted:true},
|
|
119
|
-
* credentials:{email,
|
|
120
|
+
* credentials:{email, displayName?}, organisationName?, subdomain }
|
|
120
121
|
* additionalProperties: false — validated STRICTLY client-side before
|
|
121
122
|
* any fetch (unknown keys are rejected, not stripped).
|
|
122
123
|
* - Idempotency-Key header REQUIRED (same D538 discipline as leads:
|
|
@@ -134,61 +135,177 @@ declare function submitLead(values: ContactFormValues, options: LeadsSubmitOptio
|
|
|
134
135
|
* (/leads tolerates body-less 2xx because its only signal IS the status.)
|
|
135
136
|
*/
|
|
136
137
|
|
|
138
|
+
/**
|
|
139
|
+
* STRICT wire schema for ONE element of the D543 §4 consent.documents array.
|
|
140
|
+
* `accepted` is const-true (an unaccepted doc is never sent — the consent
|
|
141
|
+
* controller omits it), and `evidence` carries only the gate-relevant flags.
|
|
142
|
+
*/
|
|
143
|
+
declare const consentSubmitDocumentSchema: z.ZodObject<{
|
|
144
|
+
legalDocumentId: z.ZodString;
|
|
145
|
+
versionNo: z.ZodNumber;
|
|
146
|
+
accepted: z.ZodLiteral<true>;
|
|
147
|
+
evidence: z.ZodObject<{
|
|
148
|
+
scrolled_to_end: z.ZodOptional<z.ZodBoolean>;
|
|
149
|
+
opened: z.ZodOptional<z.ZodBoolean>;
|
|
150
|
+
}, "strict", z.ZodTypeAny, {
|
|
151
|
+
opened?: boolean | undefined;
|
|
152
|
+
scrolled_to_end?: boolean | undefined;
|
|
153
|
+
}, {
|
|
154
|
+
opened?: boolean | undefined;
|
|
155
|
+
scrolled_to_end?: boolean | undefined;
|
|
156
|
+
}>;
|
|
157
|
+
}, "strict", z.ZodTypeAny, {
|
|
158
|
+
legalDocumentId: string;
|
|
159
|
+
versionNo: number;
|
|
160
|
+
accepted: true;
|
|
161
|
+
evidence: {
|
|
162
|
+
opened?: boolean | undefined;
|
|
163
|
+
scrolled_to_end?: boolean | undefined;
|
|
164
|
+
};
|
|
165
|
+
}, {
|
|
166
|
+
legalDocumentId: string;
|
|
167
|
+
versionNo: number;
|
|
168
|
+
accepted: true;
|
|
169
|
+
evidence: {
|
|
170
|
+
opened?: boolean | undefined;
|
|
171
|
+
scrolled_to_end?: boolean | undefined;
|
|
172
|
+
};
|
|
173
|
+
}>;
|
|
137
174
|
/**
|
|
138
175
|
* STRICT wire schema — mirrors PublicOnboardingSubmitRequest exactly
|
|
139
|
-
* (additionalProperties: false; consent booleans are const-true;
|
|
140
|
-
*
|
|
176
|
+
* (additionalProperties: false; consent booleans are const-true; passwordless
|
|
177
|
+
* per D1010, with the workspace subdomain required by D836).
|
|
178
|
+
*
|
|
179
|
+
* D543 §4: `consent` extends from booleans to a per-document array. The
|
|
180
|
+
* `documents` array is AUTHORITATIVE (the server re-validates it); the
|
|
181
|
+
* `tosAccepted`/`privacyAccepted` booleans are kept as a DERIVED convenience
|
|
182
|
+
* (D543 "kept as a derived convenience only"). `documents` is OPTIONAL on the
|
|
183
|
+
* wire for backward-compat — a pre-ConsentPack onboarder serves no consentPack
|
|
184
|
+
* and submits the booleans alone (D543 "pre-ConsentPack submits still parse").
|
|
141
185
|
*/
|
|
142
186
|
declare const signupWireSchema: z.ZodObject<{
|
|
143
187
|
specVersion: z.ZodString;
|
|
144
188
|
answers: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
145
189
|
selectedServices: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
146
|
-
botToken: z.ZodString
|
|
190
|
+
botToken: z.ZodOptional<z.ZodString>;
|
|
147
191
|
consent: z.ZodObject<{
|
|
148
192
|
tosAccepted: z.ZodLiteral<true>;
|
|
149
193
|
privacyAccepted: z.ZodLiteral<true>;
|
|
194
|
+
documents: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
195
|
+
legalDocumentId: z.ZodString;
|
|
196
|
+
versionNo: z.ZodNumber;
|
|
197
|
+
accepted: z.ZodLiteral<true>;
|
|
198
|
+
evidence: z.ZodObject<{
|
|
199
|
+
scrolled_to_end: z.ZodOptional<z.ZodBoolean>;
|
|
200
|
+
opened: z.ZodOptional<z.ZodBoolean>;
|
|
201
|
+
}, "strict", z.ZodTypeAny, {
|
|
202
|
+
opened?: boolean | undefined;
|
|
203
|
+
scrolled_to_end?: boolean | undefined;
|
|
204
|
+
}, {
|
|
205
|
+
opened?: boolean | undefined;
|
|
206
|
+
scrolled_to_end?: boolean | undefined;
|
|
207
|
+
}>;
|
|
208
|
+
}, "strict", z.ZodTypeAny, {
|
|
209
|
+
legalDocumentId: string;
|
|
210
|
+
versionNo: number;
|
|
211
|
+
accepted: true;
|
|
212
|
+
evidence: {
|
|
213
|
+
opened?: boolean | undefined;
|
|
214
|
+
scrolled_to_end?: boolean | undefined;
|
|
215
|
+
};
|
|
216
|
+
}, {
|
|
217
|
+
legalDocumentId: string;
|
|
218
|
+
versionNo: number;
|
|
219
|
+
accepted: true;
|
|
220
|
+
evidence: {
|
|
221
|
+
opened?: boolean | undefined;
|
|
222
|
+
scrolled_to_end?: boolean | undefined;
|
|
223
|
+
};
|
|
224
|
+
}>, "many">>;
|
|
150
225
|
}, "strict", z.ZodTypeAny, {
|
|
151
226
|
tosAccepted: true;
|
|
152
227
|
privacyAccepted: true;
|
|
228
|
+
documents?: {
|
|
229
|
+
legalDocumentId: string;
|
|
230
|
+
versionNo: number;
|
|
231
|
+
accepted: true;
|
|
232
|
+
evidence: {
|
|
233
|
+
opened?: boolean | undefined;
|
|
234
|
+
scrolled_to_end?: boolean | undefined;
|
|
235
|
+
};
|
|
236
|
+
}[] | undefined;
|
|
153
237
|
}, {
|
|
154
238
|
tosAccepted: true;
|
|
155
239
|
privacyAccepted: true;
|
|
240
|
+
documents?: {
|
|
241
|
+
legalDocumentId: string;
|
|
242
|
+
versionNo: number;
|
|
243
|
+
accepted: true;
|
|
244
|
+
evidence: {
|
|
245
|
+
opened?: boolean | undefined;
|
|
246
|
+
scrolled_to_end?: boolean | undefined;
|
|
247
|
+
};
|
|
248
|
+
}[] | undefined;
|
|
156
249
|
}>;
|
|
157
250
|
credentials: z.ZodObject<{
|
|
158
251
|
email: z.ZodString;
|
|
159
|
-
|
|
252
|
+
displayName: z.ZodOptional<z.ZodString>;
|
|
160
253
|
}, "strict", z.ZodTypeAny, {
|
|
161
254
|
email: string;
|
|
162
|
-
|
|
255
|
+
displayName?: string | undefined;
|
|
163
256
|
}, {
|
|
164
257
|
email: string;
|
|
165
|
-
|
|
258
|
+
displayName?: string | undefined;
|
|
166
259
|
}>;
|
|
260
|
+
organisationName: z.ZodOptional<z.ZodString>;
|
|
261
|
+
subdomain: z.ZodString;
|
|
167
262
|
}, "strict", z.ZodTypeAny, {
|
|
168
|
-
botToken: string;
|
|
169
263
|
specVersion: string;
|
|
170
264
|
credentials: {
|
|
171
265
|
email: string;
|
|
172
|
-
|
|
266
|
+
displayName?: string | undefined;
|
|
173
267
|
};
|
|
268
|
+
subdomain: string;
|
|
174
269
|
answers: Record<string, unknown>;
|
|
175
270
|
consent: {
|
|
176
271
|
tosAccepted: true;
|
|
177
272
|
privacyAccepted: true;
|
|
273
|
+
documents?: {
|
|
274
|
+
legalDocumentId: string;
|
|
275
|
+
versionNo: number;
|
|
276
|
+
accepted: true;
|
|
277
|
+
evidence: {
|
|
278
|
+
opened?: boolean | undefined;
|
|
279
|
+
scrolled_to_end?: boolean | undefined;
|
|
280
|
+
};
|
|
281
|
+
}[] | undefined;
|
|
178
282
|
};
|
|
283
|
+
botToken?: string | undefined;
|
|
284
|
+
organisationName?: string | undefined;
|
|
179
285
|
selectedServices?: string[] | undefined;
|
|
180
286
|
}, {
|
|
181
|
-
botToken: string;
|
|
182
287
|
specVersion: string;
|
|
183
288
|
credentials: {
|
|
184
289
|
email: string;
|
|
185
|
-
|
|
290
|
+
displayName?: string | undefined;
|
|
186
291
|
};
|
|
292
|
+
subdomain: string;
|
|
187
293
|
answers: Record<string, unknown>;
|
|
188
294
|
consent: {
|
|
189
295
|
tosAccepted: true;
|
|
190
296
|
privacyAccepted: true;
|
|
297
|
+
documents?: {
|
|
298
|
+
legalDocumentId: string;
|
|
299
|
+
versionNo: number;
|
|
300
|
+
accepted: true;
|
|
301
|
+
evidence: {
|
|
302
|
+
opened?: boolean | undefined;
|
|
303
|
+
scrolled_to_end?: boolean | undefined;
|
|
304
|
+
};
|
|
305
|
+
}[] | undefined;
|
|
191
306
|
};
|
|
307
|
+
botToken?: string | undefined;
|
|
308
|
+
organisationName?: string | undefined;
|
|
192
309
|
selectedServices?: string[] | undefined;
|
|
193
310
|
}>;
|
|
194
311
|
type SignupWirePayload = z.infer<typeof signupWireSchema>;
|
|
@@ -197,14 +314,22 @@ interface SignupSubmitBody {
|
|
|
197
314
|
specVersion: string;
|
|
198
315
|
answers: Record<string, unknown>;
|
|
199
316
|
selectedServices?: string[];
|
|
317
|
+
/**
|
|
318
|
+
* D543 §4 consent. `documents` (the per-doc array) is authoritative when
|
|
319
|
+
* present; the booleans are the derived convenience. `documents` is omitted
|
|
320
|
+
* for a pre-ConsentPack onboarder (backward-compat).
|
|
321
|
+
*/
|
|
200
322
|
consent: {
|
|
201
323
|
tosAccepted: true;
|
|
202
324
|
privacyAccepted: true;
|
|
325
|
+
documents?: ConsentSubmitDocument[];
|
|
203
326
|
};
|
|
204
327
|
credentials: {
|
|
205
328
|
email: string;
|
|
206
|
-
|
|
329
|
+
displayName?: string;
|
|
207
330
|
};
|
|
331
|
+
organisationName?: string;
|
|
332
|
+
subdomain: string;
|
|
208
333
|
}
|
|
209
334
|
interface SignupSubmitOptions {
|
|
210
335
|
baseUrl: string;
|
|
@@ -214,7 +339,7 @@ interface SignupSubmitOptions {
|
|
|
214
339
|
* string on a retried request risks 403 after the first attempt consumed
|
|
215
340
|
* it — pass a provider for retry-safe recovery.
|
|
216
341
|
*/
|
|
217
|
-
botToken
|
|
342
|
+
botToken?: BotTokenSource;
|
|
218
343
|
/** Stable idempotency key — same discipline as submitLead. */
|
|
219
344
|
idempotencyKey: string;
|
|
220
345
|
fetch?: typeof globalThis.fetch;
|
|
@@ -247,13 +372,21 @@ declare function computeSignupFingerprint(body: SignupSubmitBody): string;
|
|
|
247
372
|
* throws (reCAPTCHA unreachable) on any attempt
|
|
248
373
|
* @throws {OnboardingSpecStaleError} on 409 with code:"spec_stale" (caller
|
|
249
374
|
* refetches spec); carries the server's currentSpecVersion
|
|
250
|
-
* @throws {
|
|
375
|
+
* @throws {OnboardingConsentStaleError} on 409 with code:"consent_stale"
|
|
376
|
+
* (D543 §4 — a required legal doc changed; caller refetches spec + requires
|
|
377
|
+
* re-acceptance of the changed docs, NEVER auto-accepts); carries
|
|
378
|
+
* staleDocuments
|
|
379
|
+
* @throws {OnboardingConsentIncompleteError} on 400 with
|
|
380
|
+
* code:"consent_incomplete" (D543 §4 — server found a required doc missing/
|
|
381
|
+
* unaccepted/evidence-insufficient)
|
|
382
|
+
* @throws {OnboardingConflictError} on a 409 that is NOT spec_stale/consent_stale
|
|
251
383
|
* @throws {OnboardingRateLimitError} on 429
|
|
252
|
-
* @throws {OnboardingValidationError} on 422 (server re-validation)
|
|
384
|
+
* @throws {OnboardingValidationError} on 422 (server re-validation) or a
|
|
385
|
+
* generic 400 that is NOT consent_incomplete
|
|
253
386
|
* @throws {OnboardingServerError} on 5xx after retries, or a 2xx without
|
|
254
387
|
* the required {accepted:true, terminalStage} body
|
|
255
388
|
* @throws {OnboardingNetworkError} on network failure OR timeout after retries
|
|
256
389
|
*/
|
|
257
390
|
declare function submitSignup(body: SignupSubmitBody, options: SignupSubmitOptions): Promise<SignupSubmitResult>;
|
|
258
391
|
|
|
259
|
-
export { type BotTokenSource as B, type LeadsSubmitOptions as L, type SignupSubmitBody as S, type LeadsSubmitResult as a, type SignupSubmitOptions as b, type SignupSubmitResult as c, type SignupWirePayload as d, computePayloadFingerprint as e, computeSignupFingerprint as f,
|
|
392
|
+
export { type BotTokenSource as B, type LeadsSubmitOptions as L, type SignupSubmitBody as S, type LeadsSubmitResult as a, type SignupSubmitOptions as b, type SignupSubmitResult as c, type SignupWirePayload as d, computePayloadFingerprint as e, computeSignupFingerprint as f, consentSubmitDocumentSchema as g, generateIdempotencyKey as h, submitLead as i, submitSignup as j, resolveBotToken as r, signupWireSchema as s };
|
package/dist/spec/index.d.ts
CHANGED
|
@@ -1,88 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
1
|
+
export { F as FIELD_KEY_PATTERN, O as OnboarderTier, a as OnboardingSpec, P as PiiClass, S as SpecField, b as SpecStage, c as SpecStep, T as TerminalStage, o as onboardingSpecSchema, s as specFieldSchema, d as specStepSchema, v as validateOnboardingSpec } from '../model-ESLSEbi0.js';
|
|
2
|
+
export { A as ACCEPTANCE_LEVELS, a as AcceptanceLevel, C as ConsentDocType, b as ConsentDocument, c as ConsentPack, D as DOC_TYPES, d as acceptanceLevelSchema, e as consentDocKey, f as consentDocumentSchema, g as consentPackSchema } from '../model-mnjAEtKe.js';
|
|
3
|
+
export { O as OnboardingSpecCache, S as SpecFetchOptions, a as SpecFieldDiff, d as defaultSpecCache, b as diffSpecFields, f as fetchOnboardingSpec } from '../client-CqE2dF9A.js';
|
|
3
4
|
import 'zod/v3';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* - The onboarder is derived SERVER-side from the request Host (D536) —
|
|
9
|
-
* it is NOT sent by the client. The `onboarder` value here is purely the
|
|
10
|
-
* CLIENT-side cache key (D540 §3: "cache key (onboarder, specVersion)").
|
|
11
|
-
* - The spec response is validated against the LOCKED D540 shape before
|
|
12
|
-
* it is returned; a malformed spec throws OnboardingSpecInvalidError.
|
|
13
|
-
* - Cache semantics: every successful fetch is stored under
|
|
14
|
-
* (onboarder, specVersion) and as the onboarder's "latest". The versioned
|
|
15
|
-
* entries let the 409 spec_stale flow diff the previously-served version
|
|
16
|
-
* against the refetched one (see `diffSpecFields` + the signup widget's
|
|
17
|
-
* handleSpecStale, which reads the cached prior version before refetching).
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* In-memory spec cache keyed by (onboarder, specVersion), with a "latest"
|
|
22
|
-
* pointer per onboarder. Purely client-side; no TTL — the reject-stale
|
|
23
|
-
* policy (409 spec_stale on submit) is the authoritative staleness signal,
|
|
24
|
-
* and a refetch overwrites "latest".
|
|
25
|
-
*/
|
|
26
|
-
declare class OnboardingSpecCache {
|
|
27
|
-
private readonly byVersion;
|
|
28
|
-
private readonly latest;
|
|
29
|
-
/**
|
|
30
|
-
* Collision-proof composite key. Uses JSON.stringify of the tuple so an
|
|
31
|
-
* onboarder or version containing the delimiter can never alias another
|
|
32
|
-
* entry — and, critically, contains NO control characters (an earlier
|
|
33
|
-
* NUL-separator made git treat this whole file as binary/undiffable).
|
|
34
|
-
*/
|
|
35
|
-
private static versionKey;
|
|
36
|
-
get(onboarder: string, specVersion: string): OnboardingSpec | undefined;
|
|
37
|
-
getLatest(onboarder: string): OnboardingSpec | undefined;
|
|
38
|
-
set(onboarder: string, spec: OnboardingSpec): void;
|
|
39
|
-
clear(): void;
|
|
40
|
-
}
|
|
41
|
-
/** Module-level default cache (one per page). Injectable for tests/apps. */
|
|
42
|
-
declare const defaultSpecCache: OnboardingSpecCache;
|
|
43
|
-
/**
|
|
44
|
-
* Diff two spec versions' signup field sets — used by the 409 spec_stale
|
|
45
|
-
* flow to tell the user WHAT changed. Compares by field key across all
|
|
46
|
-
* signup steps.
|
|
47
|
-
*/
|
|
48
|
-
interface SpecFieldDiff {
|
|
49
|
-
added: string[];
|
|
50
|
-
removed: string[];
|
|
51
|
-
changed: string[];
|
|
6
|
+
interface PinStateResult {
|
|
7
|
+
pin: string;
|
|
8
|
+
stateIso: string | null;
|
|
52
9
|
}
|
|
53
|
-
declare function
|
|
54
|
-
interface SpecFetchOptions {
|
|
10
|
+
declare function fetchPinState(options: {
|
|
55
11
|
baseUrl: string;
|
|
56
|
-
|
|
57
|
-
* Client-side cache key ONLY (never transmitted; trust is host-derived
|
|
58
|
-
* per D536). Use the onboarder slug/id your embed is configured with.
|
|
59
|
-
*/
|
|
60
|
-
onboarder: string;
|
|
61
|
-
/** Custom fetch implementation (defaults to globalThis.fetch). */
|
|
12
|
+
pin: string;
|
|
62
13
|
fetch?: typeof globalThis.fetch;
|
|
63
|
-
/** Cache to read/write (defaults to the module-level cache). */
|
|
64
|
-
cache?: OnboardingSpecCache;
|
|
65
|
-
/**
|
|
66
|
-
* Request timeout in ms (default 15s). A stalled intake aborts with
|
|
67
|
-
* OnboardingNetworkError so the boot doesn't hang on "Loading signup form…".
|
|
68
|
-
*/
|
|
69
14
|
timeoutMs?: number;
|
|
70
|
-
|
|
71
|
-
* When true, return the cached "latest" for this onboarder if present
|
|
72
|
-
* WITHOUT a network round-trip. Default false (spec fetches are cheap
|
|
73
|
-
* and the server bumps specVersion on any change). The signup widget's
|
|
74
|
-
* boot passes preferCached:true so a remount reuses the loaded spec.
|
|
75
|
-
*/
|
|
76
|
-
preferCached?: boolean;
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Fetch (and validate, and cache) the onboarding spec.
|
|
80
|
-
*
|
|
81
|
-
* @throws {OnboardingSpecInvalidError} response does not match D540 §1
|
|
82
|
-
* @throws {OnboardingRateLimitError} on 429
|
|
83
|
-
* @throws {OnboardingServerError} on any other non-2xx status
|
|
84
|
-
* @throws {OnboardingNetworkError} on network failure OR timeout
|
|
85
|
-
*/
|
|
86
|
-
declare function fetchOnboardingSpec(options: SpecFetchOptions): Promise<OnboardingSpec>;
|
|
15
|
+
}): Promise<PinStateResult>;
|
|
87
16
|
|
|
88
|
-
export {
|
|
17
|
+
export { type PinStateResult, fetchPinState };
|
package/dist/spec/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { FIELD_KEY_PATTERN, OnboardingSpecCache, defaultSpecCache, diffSpecFields, fetchOnboardingSpec, onboardingSpecSchema, specFieldSchema, specStepSchema, validateOnboardingSpec } from '../chunk-
|
|
2
|
-
|
|
1
|
+
export { FIELD_KEY_PATTERN, OnboardingSpecCache, defaultSpecCache, diffSpecFields, fetchOnboardingSpec, fetchPinState, onboardingSpecSchema, specFieldSchema, specStepSchema, validateOnboardingSpec } from '../chunk-F75ZJERM.js';
|
|
2
|
+
export { ACCEPTANCE_LEVELS, DOC_TYPES, acceptanceLevelSchema, consentDocKey, consentDocumentSchema, consentPackSchema } from '../chunk-U56GQITG.js';
|
|
3
|
+
import '../chunk-XJTJPBJB.js';
|
|
3
4
|
//# sourceMappingURL=index.js.map
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
package/dist/submit/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
export { B as BotTokenSource, L as LeadsSubmitOptions, a as LeadsSubmitResult, S as SignupSubmitBody, b as SignupSubmitOptions, c as SignupSubmitResult, d as SignupWirePayload, e as computePayloadFingerprint, f as computeSignupFingerprint, g as generateIdempotencyKey, r as resolveBotToken, s as signupWireSchema,
|
|
1
|
+
export { B as BotTokenSource, L as LeadsSubmitOptions, a as LeadsSubmitResult, S as SignupSubmitBody, b as SignupSubmitOptions, c as SignupSubmitResult, d as SignupWirePayload, e as computePayloadFingerprint, f as computeSignupFingerprint, g as consentSubmitDocumentSchema, h as generateIdempotencyKey, r as resolveBotToken, s as signupWireSchema, i as submitLead, j as submitSignup } from '../signup-client-BL5DfarJ.js';
|
|
2
|
+
export { O as OnboardingBotChallengeError, a as OnboardingConflictError, b as OnboardingConsentIncompleteError, c as OnboardingConsentStaleError, d as OnboardingError, e as OnboardingErrorKind, f as OnboardingNetworkError, g as OnboardingRateLimitError, h as OnboardingServerError, i as OnboardingSpecInvalidError, j as OnboardingSpecStaleError, k as OnboardingSubdomainTakenError, l as OnboardingValidationError, S as StaleConsentDocument } from '../errors-vJkye4a0.js';
|
|
2
3
|
import 'zod/v3';
|
|
3
|
-
import '../model-
|
|
4
|
-
import '../
|
|
4
|
+
import '../model-ESLSEbi0.js';
|
|
5
|
+
import '../controller-BQb62D0N.js';
|
|
6
|
+
import '../model-mnjAEtKe.js';
|
|
7
|
+
import '../schema-BrXb9gnh.js';
|
|
5
8
|
|
|
6
9
|
/**
|
|
7
10
|
* Shared HTTP helper: fetch bounded by a timeout via AbortController.
|
|
@@ -36,71 +39,4 @@ declare function fetchWithTimeout(url: string, options?: TimeoutFetchOptions): P
|
|
|
36
39
|
*/
|
|
37
40
|
declare function withTimeout<T>(op: Promise<T>, timeoutMs: number, onTimeout: () => Error): Promise<T>;
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
* Error taxonomy for the onboarding submit client.
|
|
41
|
-
*
|
|
42
|
-
* Maps HTTP status codes and server error bodies to typed errors:
|
|
43
|
-
* 403 bot_challenge_failed → OnboardingBotChallengeError
|
|
44
|
-
* 409 spec_stale (SUBMIT) → OnboardingSpecStaleError (submit endpoint only,
|
|
45
|
-
* body { error:true, code:"spec_stale",
|
|
46
|
-
* currentSpecVersion })
|
|
47
|
-
* 409 (other / LEADS) → OnboardingConflictError (generic conflict)
|
|
48
|
-
* 429 → OnboardingRateLimitError
|
|
49
|
-
* 5xx → OnboardingServerError (retryable)
|
|
50
|
-
* network / timeout → OnboardingNetworkError
|
|
51
|
-
*/
|
|
52
|
-
type OnboardingErrorKind = "bot_challenge_failed" | "spec_stale" | "spec_invalid" | "conflict" | "rate_limited" | "server_error" | "network_error" | "validation_error";
|
|
53
|
-
declare class OnboardingError extends Error {
|
|
54
|
-
readonly kind: OnboardingErrorKind;
|
|
55
|
-
readonly statusCode: number | null;
|
|
56
|
-
constructor(kind: OnboardingErrorKind, message: string, statusCode?: number | null);
|
|
57
|
-
}
|
|
58
|
-
declare class OnboardingBotChallengeError extends OnboardingError {
|
|
59
|
-
constructor(message?: string);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* A 409 that is NOT spec_stale. On the /leads path there is no spec_stale
|
|
63
|
-
* concept (the payload carries no specVersion); on /submit, a 409 that
|
|
64
|
-
* lacks `code:"spec_stale"` also lands here. Distinct from
|
|
65
|
-
* OnboardingSpecStaleError so headless consumers switching on `kind` get the
|
|
66
|
-
* correct diagnosis (a generic conflict, e.g. a D538 same-key concurrent
|
|
67
|
-
* race) rather than a "form has been updated, refresh" recovery message.
|
|
68
|
-
*/
|
|
69
|
-
declare class OnboardingConflictError extends OnboardingError {
|
|
70
|
-
constructor(statusCode?: number, message?: string);
|
|
71
|
-
}
|
|
72
|
-
declare class OnboardingRateLimitError extends OnboardingError {
|
|
73
|
-
readonly retryAfterSeconds: number | null;
|
|
74
|
-
constructor(retryAfterSeconds?: number | null);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* A /submit 409 whose body carries `code:"spec_stale"` (D540 reject-stale).
|
|
78
|
-
* The PINNED body shape (confirmed against the crm intake) is exactly:
|
|
79
|
-
* { error: true, code: "spec_stale", currentSpecVersion: string }
|
|
80
|
-
* The version is read ONLY from `currentSpecVersion` — no field hedging.
|
|
81
|
-
* Submit-endpoint only; /leads 409s are OnboardingConflictError.
|
|
82
|
-
*/
|
|
83
|
-
declare class OnboardingSpecStaleError extends OnboardingError {
|
|
84
|
-
readonly currentSpecVersion: string;
|
|
85
|
-
constructor(currentSpecVersion: string);
|
|
86
|
-
}
|
|
87
|
-
declare class OnboardingServerError extends OnboardingError {
|
|
88
|
-
constructor(statusCode: number, message?: string);
|
|
89
|
-
}
|
|
90
|
-
declare class OnboardingNetworkError extends OnboardingError {
|
|
91
|
-
constructor(cause?: unknown);
|
|
92
|
-
}
|
|
93
|
-
declare class OnboardingValidationError extends OnboardingError {
|
|
94
|
-
constructor(message: string);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* The spec endpoint returned a body that does not conform to the LOCKED
|
|
98
|
-
* D540 §1 response shape. This is a server-side contract violation — the
|
|
99
|
-
* SDK refuses to render a form from a malformed spec (a half-parsed spec
|
|
100
|
-
* could silently drop required fields).
|
|
101
|
-
*/
|
|
102
|
-
declare class OnboardingSpecInvalidError extends OnboardingError {
|
|
103
|
-
constructor(detail: string);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export { DEFAULT_REQUEST_TIMEOUT_MS, OnboardingBotChallengeError, OnboardingConflictError, OnboardingError, type OnboardingErrorKind, OnboardingNetworkError, OnboardingRateLimitError, OnboardingServerError, OnboardingSpecInvalidError, OnboardingSpecStaleError, OnboardingValidationError, fetchWithTimeout, withTimeout };
|
|
42
|
+
export { DEFAULT_REQUEST_TIMEOUT_MS, fetchWithTimeout, withTimeout };
|
package/dist/submit/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '../chunk-Z4PA6C2Z.js';
|
|
2
|
-
export { computePayloadFingerprint, computeSignupFingerprint, generateIdempotencyKey, resolveBotToken, signupWireSchema, submitLead, submitSignup } from '../chunk-
|
|
3
|
-
import '../chunk-
|
|
4
|
-
export { DEFAULT_REQUEST_TIMEOUT_MS, OnboardingBotChallengeError, OnboardingConflictError, OnboardingError, OnboardingNetworkError, OnboardingRateLimitError, OnboardingServerError, OnboardingSpecInvalidError, OnboardingSpecStaleError, OnboardingValidationError, fetchWithTimeout, withTimeout } from '../chunk-
|
|
2
|
+
export { computePayloadFingerprint, computeSignupFingerprint, consentSubmitDocumentSchema, generateIdempotencyKey, resolveBotToken, signupWireSchema, submitLead, submitSignup } from '../chunk-BMQINH6O.js';
|
|
3
|
+
import '../chunk-SIMLMQPT.js';
|
|
4
|
+
export { DEFAULT_REQUEST_TIMEOUT_MS, OnboardingBotChallengeError, OnboardingConflictError, OnboardingConsentIncompleteError, OnboardingConsentStaleError, OnboardingError, OnboardingNetworkError, OnboardingRateLimitError, OnboardingServerError, OnboardingSpecInvalidError, OnboardingSpecStaleError, OnboardingSubdomainTakenError, OnboardingValidationError, fetchWithTimeout, withTimeout } from '../chunk-XJTJPBJB.js';
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
package/dist/widget/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { a as OnboardingSpec } from '../model-
|
|
2
|
-
import { OnboardingSpecCache } from '../
|
|
3
|
-
import { c as SignupSubmitResult } from '../signup-client-
|
|
1
|
+
import { a as OnboardingSpec } from '../model-ESLSEbi0.js';
|
|
2
|
+
import { O as OnboardingSpecCache } from '../client-CqE2dF9A.js';
|
|
3
|
+
import { c as SignupSubmitResult } from '../signup-client-BL5DfarJ.js';
|
|
4
|
+
import { _ as ___viewer_render_js } from '../index-Dqfa890U.js';
|
|
5
|
+
import { C as ConsentController, c as ConsentState } from '../controller-BQb62D0N.js';
|
|
4
6
|
import 'zod/v3';
|
|
5
|
-
import '../schema-
|
|
7
|
+
import '../schema-BrXb9gnh.js';
|
|
8
|
+
import '../model-mnjAEtKe.js';
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Default vanilla-TS contact form widget.
|
|
@@ -40,7 +43,7 @@ interface ContactFormMountOptions {
|
|
|
40
43
|
* reCAPTCHA v3 site key. Obtained from the spec endpoint (D540 §1)
|
|
41
44
|
* or passed directly in Phase 1 before spec-fetch is wired.
|
|
42
45
|
*/
|
|
43
|
-
siteKey
|
|
46
|
+
siteKey?: string;
|
|
44
47
|
/**
|
|
45
48
|
* Which form to render. Phase 1 supports "contact" only.
|
|
46
49
|
* Phase 2 will add "signup" (dynamic stepper from spec).
|
|
@@ -162,7 +165,7 @@ declare function mountSignupForm(host: HTMLElement, options: SignupFormMountOpti
|
|
|
162
165
|
* The widget scopes all styles under `.nodii-onboarding-widget` to avoid
|
|
163
166
|
* leaking into the host page.
|
|
164
167
|
*/
|
|
165
|
-
declare const DEFAULT_WIDGET_CSS = "\n.nodii-onboarding-widget {\n --_font: var(--nodii-onboarding-font-family, system-ui, -apple-system, sans-serif);\n --_primary: var(--nodii-onboarding-primary-color, #2563eb);\n --_primary-hover: var(--nodii-onboarding-primary-hover, #1d4ed8);\n --_error: var(--nodii-onboarding-error-color, #dc2626);\n --_border: var(--nodii-onboarding-border-color, #d1d5db);\n --_input-bg: var(--nodii-onboarding-input-bg, #fff);\n --_label: var(--nodii-onboarding-label-color, #374151);\n --_radius: var(--nodii-onboarding-radius, 6px);\n --_spacing: var(--nodii-onboarding-spacing, 16px);\n\n font-family: var(--_font);\n box-sizing: border-box;\n}\n\n.nodii-onboarding-widget *,\n.nodii-onboarding-widget *::before,\n.nodii-onboarding-widget *::after {\n box-sizing: inherit;\n}\n\n.nodii-onboarding-field {\n display: flex;\n flex-direction: column;\n gap: calc(var(--_spacing) * 0.25);\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--_label);\n}\n\n.nodii-onboarding-label.required::after {\n content: \" *\";\n color: var(--_error);\n}\n\n.nodii-onboarding-input,\n.nodii-onboarding-textarea {\n width: 100%;\n padding: calc(var(--_spacing) * 0.5) calc(var(--_spacing) * 0.75);\n border: 1px solid var(--_border);\n border-radius: var(--_radius);\n background: var(--_input-bg);\n font-family: var(--_font);\n font-size: 1rem;\n line-height: 1.5;\n outline: none;\n transition: border-color 0.15s ease;\n}\n\n.nodii-onboarding-input:focus,\n.nodii-onboarding-textarea:focus {\n border-color: var(--_primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_primary) 20%, transparent);\n}\n\n.nodii-onboarding-input.has-error,\n.nodii-onboarding-textarea.has-error {\n border-color: var(--_error);\n}\n\n.nodii-onboarding-textarea {\n min-height: 100px;\n resize: vertical;\n}\n\n.nodii-onboarding-field-error {\n font-size: 0.75rem;\n color: var(--_error);\n margin-top: 2px;\n}\n\n.nodii-onboarding-server-error {\n padding: calc(var(--_spacing) * 0.75);\n border-radius: var(--_radius);\n background: color-mix(in srgb, var(--_error) 8%, transparent);\n border: 1px solid color-mix(in srgb, var(--_error) 30%, transparent);\n color: var(--_error);\n font-size: 0.875rem;\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-success {\n padding: var(--_spacing);\n border-radius: var(--_radius);\n background: #f0fdf4;\n border: 1px solid #bbf7d0;\n color: #15803d;\n font-size: 0.9375rem;\n text-align: center;\n}\n\n.nodii-onboarding-submit-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n padding: calc(var(--_spacing) * 0.625) var(--_spacing);\n background: var(--_primary);\n color: #fff;\n border: none;\n border-radius: var(--_radius);\n font-family: var(--_font);\n font-size: 1rem;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n\n.nodii-onboarding-submit-btn:hover:not(:disabled) {\n background: var(--_primary-hover);\n}\n\n.nodii-onboarding-submit-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.nodii-onboarding-spinner {\n display: inline-block;\n width: 1em;\n height: 1em;\n border: 2px solid rgba(255,255,255,0.4);\n border-top-color: #fff;\n border-radius: 50%;\n animation: nodii-spin 0.6s linear infinite;\n margin-right: 0.5em;\n}\n\n@keyframes nodii-spin {\n to { transform: rotate(360deg); }\n}\n\n.nodii-onboarding-recaptcha-notice {\n font-size: 0.7rem;\n color: #6b7280;\n margin-top: calc(var(--_spacing) * 0.5);\n text-align: center;\n}\n\n.nodii-onboarding-recaptcha-notice a {\n color: inherit;\n}\n\n/* \u2500\u2500 dynamic stepper (signup form) \u2500\u2500 */\n\n.nodii-onboarding-steps {\n display: flex;\n gap: calc(var(--_spacing) * 0.5);\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-step-dot {\n flex: 1;\n height: 4px;\n border-radius: 2px;\n background: var(--_border);\n}\n\n.nodii-onboarding-step-dot.active {\n background: var(--_primary);\n}\n\n.nodii-onboarding-stage-title {\n font-size: 1.0625rem;\n font-weight: 600;\n color: var(--_label);\n margin: 0 0 var(--_spacing) 0;\n}\n\n.nodii-onboarding-nav {\n display: flex;\n gap: calc(var(--_spacing) * 0.5);\n margin-top: var(--_spacing);\n}\n\n.nodii-onboarding-back-btn {\n padding: calc(var(--_spacing) * 0.625) var(--_spacing);\n background: transparent;\n color: var(--_label);\n border: 1px solid var(--_border);\n border-radius: var(--_radius);\n font-family: var(--_font);\n font-size: 1rem;\n cursor: pointer;\n}\n\n.nodii-onboarding-stale-banner {\n padding: calc(var(--_spacing) * 0.75);\n border-radius: var(--_radius);\n background: #fffbeb;\n border: 1px solid #fcd34d;\n color: #92400e;\n font-size: 0.875rem;\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-consent-row {\n display: flex;\n align-items: flex-start;\n gap: calc(var(--_spacing) * 0.5);\n margin-bottom: calc(var(--_spacing) * 0.5);\n font-size: 0.875rem;\n color: var(--_label);\n}\n\n.nodii-onboarding-consent-row input[type=\"checkbox\"] {\n margin-top: 3px;\n}\n\n.nodii-onboarding-account-section {\n border-top: 1px solid var(--_border);\n margin-top: var(--_spacing);\n padding-top: var(--_spacing);\n}\n\n.nodii-onboarding-loading {\n padding: var(--_spacing);\n text-align: center;\n color: var(--_label);\n}\n";
|
|
168
|
+
declare const DEFAULT_WIDGET_CSS = "\n.nodii-onboarding-widget {\n --_font: var(--nodii-onboarding-font-family, system-ui, -apple-system, sans-serif);\n --_primary: var(--nodii-onboarding-primary-color, #2563eb);\n --_primary-hover: var(--nodii-onboarding-primary-hover, #1d4ed8);\n --_error: var(--nodii-onboarding-error-color, #dc2626);\n --_border: var(--nodii-onboarding-border-color, #d1d5db);\n --_input-bg: var(--nodii-onboarding-input-bg, #fff);\n --_label: var(--nodii-onboarding-label-color, #374151);\n --_radius: var(--nodii-onboarding-radius, 6px);\n --_spacing: var(--nodii-onboarding-spacing, 16px);\n\n font-family: var(--_font);\n box-sizing: border-box;\n}\n\n.nodii-onboarding-widget *,\n.nodii-onboarding-widget *::before,\n.nodii-onboarding-widget *::after {\n box-sizing: inherit;\n}\n\n.nodii-onboarding-field {\n display: flex;\n flex-direction: column;\n gap: calc(var(--_spacing) * 0.25);\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--_label);\n}\n\n.nodii-onboarding-label.required::after {\n content: \" *\";\n color: var(--_error);\n}\n\n.nodii-onboarding-input,\n.nodii-onboarding-textarea {\n width: 100%;\n padding: calc(var(--_spacing) * 0.5) calc(var(--_spacing) * 0.75);\n border: 1px solid var(--_border);\n border-radius: var(--_radius);\n background: var(--_input-bg);\n font-family: var(--_font);\n font-size: 1rem;\n line-height: 1.5;\n outline: none;\n transition: border-color 0.15s ease;\n}\n\n.nodii-onboarding-input:focus,\n.nodii-onboarding-textarea:focus {\n border-color: var(--_primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_primary) 20%, transparent);\n}\n\n.nodii-onboarding-input.has-error,\n.nodii-onboarding-textarea.has-error {\n border-color: var(--_error);\n}\n\n.nodii-onboarding-textarea {\n min-height: 100px;\n resize: vertical;\n}\n\n.nodii-onboarding-field-error {\n font-size: 0.75rem;\n color: var(--_error);\n margin-top: 2px;\n}\n\n.nodii-onboarding-server-error {\n padding: calc(var(--_spacing) * 0.75);\n border-radius: var(--_radius);\n background: color-mix(in srgb, var(--_error) 8%, transparent);\n border: 1px solid color-mix(in srgb, var(--_error) 30%, transparent);\n color: var(--_error);\n font-size: 0.875rem;\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-success {\n padding: var(--_spacing);\n border-radius: var(--_radius);\n background: #f0fdf4;\n border: 1px solid #bbf7d0;\n color: #15803d;\n font-size: 0.9375rem;\n text-align: center;\n}\n\n.nodii-onboarding-submit-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n padding: calc(var(--_spacing) * 0.625) var(--_spacing);\n background: var(--_primary);\n color: #fff;\n border: none;\n border-radius: var(--_radius);\n font-family: var(--_font);\n font-size: 1rem;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n\n.nodii-onboarding-submit-btn:hover:not(:disabled) {\n background: var(--_primary-hover);\n}\n\n.nodii-onboarding-submit-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.nodii-onboarding-spinner {\n display: inline-block;\n width: 1em;\n height: 1em;\n border: 2px solid rgba(255,255,255,0.4);\n border-top-color: #fff;\n border-radius: 50%;\n animation: nodii-spin 0.6s linear infinite;\n margin-right: 0.5em;\n}\n\n@keyframes nodii-spin {\n to { transform: rotate(360deg); }\n}\n\n.nodii-onboarding-recaptcha-notice {\n font-size: 0.7rem;\n color: #6b7280;\n margin-top: calc(var(--_spacing) * 0.5);\n text-align: center;\n}\n\n.nodii-onboarding-recaptcha-notice a {\n color: inherit;\n}\n\n/* \u2500\u2500 dynamic stepper (signup form) \u2500\u2500 */\n\n.nodii-onboarding-steps {\n display: flex;\n gap: calc(var(--_spacing) * 0.5);\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-step-dot {\n flex: 1;\n height: 4px;\n border-radius: 2px;\n background: var(--_border);\n}\n\n.nodii-onboarding-step-dot.active {\n background: var(--_primary);\n}\n\n.nodii-onboarding-stage-title {\n font-size: 1.0625rem;\n font-weight: 600;\n color: var(--_label);\n margin: 0 0 var(--_spacing) 0;\n}\n\n.nodii-onboarding-nav {\n display: flex;\n gap: calc(var(--_spacing) * 0.5);\n margin-top: var(--_spacing);\n}\n\n.nodii-onboarding-back-btn {\n padding: calc(var(--_spacing) * 0.625) var(--_spacing);\n background: transparent;\n color: var(--_label);\n border: 1px solid var(--_border);\n border-radius: var(--_radius);\n font-family: var(--_font);\n font-size: 1rem;\n cursor: pointer;\n}\n\n.nodii-onboarding-stale-banner {\n padding: calc(var(--_spacing) * 0.75);\n border-radius: var(--_radius);\n background: #fffbeb;\n border: 1px solid #fcd34d;\n color: #92400e;\n font-size: 0.875rem;\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-consent-row {\n display: flex;\n align-items: flex-start;\n gap: calc(var(--_spacing) * 0.5);\n margin-bottom: calc(var(--_spacing) * 0.5);\n font-size: 0.875rem;\n color: var(--_label);\n}\n\n.nodii-onboarding-consent-row input[type=\"checkbox\"] {\n margin-top: 3px;\n}\n\n.nodii-onboarding-account-section {\n border-top: 1px solid var(--_border);\n margin-top: var(--_spacing);\n padding-top: var(--_spacing);\n}\n\n.nodii-onboarding-loading {\n padding: var(--_spacing);\n text-align: center;\n color: var(--_label);\n}\n\n/* \u2500\u2500 D543 ConsentPack step (full-width, generous spacing) \u2500\u2500 */\n\n.nodii-onboarding-consent-stage {\n /* Full-bleed within the widget host \u2014 consent cards may span the page. */\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: calc(var(--_spacing) * 2);\n margin: calc(var(--_spacing) * 1.5) 0;\n}\n\n.nodii-onboarding-consent-intro {\n font-size: 0.9375rem;\n color: var(--_label);\n margin: 0 0 calc(var(--_spacing) * 0.5) 0;\n line-height: 1.6;\n}\n\n.nodii-onboarding-consent-card {\n width: 100%;\n border: 1px solid var(--_border);\n border-radius: var(--_radius);\n background: var(--_input-bg);\n padding: calc(var(--_spacing) * 1.5);\n display: flex;\n flex-direction: column;\n gap: var(--_spacing);\n}\n\n.nodii-onboarding-consent-card.is-stale {\n border-color: #fcd34d;\n background: #fffbeb;\n}\n\n.nodii-onboarding-consent-card.has-error {\n border-color: var(--_error);\n}\n\n.nodii-onboarding-consent-title {\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--_label);\n margin: 0;\n}\n\n.nodii-onboarding-consent-stale-tag {\n font-size: 0.8125rem;\n font-weight: 500;\n color: #92400e;\n}\n\n.nodii-onboarding-consent-gate {\n width: 100%;\n}\n\n.nodii-onboarding-consent-scrollbox {\n width: 100%;\n height: 360px;\n overflow-y: auto;\n border: 1px solid var(--_border);\n border-radius: var(--_radius);\n background: #fff;\n position: relative;\n}\n\n.nodii-onboarding-consent-scrollbox:focus {\n outline: none;\n border-color: var(--_primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_primary) 20%, transparent);\n}\n\n/* Inline, same-origin document content (no iframe). Rendered by the default\n viewer: sanitized HTML/markdown, escaped plain text, or PDF.js canvases. */\n.nodii-onboarding-consent-doc-body {\n padding: var(--_spacing);\n font-size: 0.9375rem;\n line-height: 1.7;\n color: var(--_label);\n word-break: break-word;\n}\n\n.nodii-onboarding-consent-doc-body:not(.nodii-consent-pdf) {\n white-space: pre-wrap;\n}\n\n.nodii-onboarding-consent-doc-loading {\n padding: var(--_spacing);\n color: #6b7280;\n font-size: 0.875rem;\n}\n\n.nodii-consent-pdf {\n display: flex;\n flex-direction: column;\n gap: var(--_spacing);\n white-space: normal;\n}\n\n.nodii-consent-pdf-page {\n max-width: 100%;\n height: auto;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n}\n\n.nodii-onboarding-consent-note {\n font-size: 0.8125rem;\n color: #6b7280;\n margin: calc(var(--_spacing) * 0.5) 0 0 0;\n}\n\n/* A gated doc that could not be rendered inline: the gate stays unsatisfiable\n (accept disabled); we surface a clear error + Retry. NO click-to-satisfy. */\n.nodii-onboarding-consent-unrenderable {\n display: flex;\n flex-direction: column;\n gap: calc(var(--_spacing) * 0.5);\n padding: var(--_spacing);\n border: 1px solid color-mix(in srgb, var(--_error) 30%, transparent);\n border-radius: var(--_radius);\n background: color-mix(in srgb, var(--_error) 6%, transparent);\n}\n\n.nodii-onboarding-consent-retry {\n align-self: flex-start;\n padding: calc(var(--_spacing) * 0.5) var(--_spacing);\n background: transparent;\n color: var(--_primary);\n border: 1px solid var(--_primary);\n border-radius: var(--_radius);\n font-family: var(--_font);\n font-size: 0.875rem;\n cursor: pointer;\n}\n\n.nodii-onboarding-consent-open-row,\n.nodii-onboarding-consent-preview-row {\n display: flex;\n}\n\n.nodii-onboarding-consent-open {\n display: inline-flex;\n align-items: center;\n padding: calc(var(--_spacing) * 0.625) var(--_spacing);\n border: 1px solid var(--_primary);\n border-radius: var(--_radius);\n color: var(--_primary);\n text-decoration: none;\n font-size: 0.9375rem;\n font-weight: 500;\n}\n\n.nodii-onboarding-consent-open:hover {\n background: color-mix(in srgb, var(--_primary) 8%, transparent);\n}\n\n.nodii-onboarding-consent-preview {\n font-size: 0.875rem;\n color: var(--_primary);\n}\n\n.nodii-onboarding-consent-accept-row {\n display: flex;\n align-items: flex-start;\n gap: calc(var(--_spacing) * 0.5);\n}\n\n.nodii-onboarding-consent-accept {\n margin-top: 3px;\n width: 1.125rem;\n height: 1.125rem;\n}\n\n.nodii-onboarding-consent-accept:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.nodii-onboarding-consent-accept-label {\n font-size: 0.9375rem;\n color: var(--_label);\n line-height: 1.5;\n}\n\n.nodii-onboarding-consent-required {\n color: var(--_error);\n}\n";
|
|
166
169
|
/**
|
|
167
170
|
* Inject the default widget CSS once into the document head.
|
|
168
171
|
* Idempotent — will not add a duplicate style tag.
|
|
@@ -189,6 +192,46 @@ declare function cssEscape(value: string): string;
|
|
|
189
192
|
/** Build a safe `#id` selector with the id CSS-escaped. */
|
|
190
193
|
declare function idSelector(id: string): string;
|
|
191
194
|
|
|
195
|
+
/** Render-time options for the default consent step. */
|
|
196
|
+
interface ConsentStepRenderOptions {
|
|
197
|
+
/** Injectable fetch for doc-content load (defaults to global). */
|
|
198
|
+
fetch?: typeof globalThis.fetch;
|
|
199
|
+
timeoutMs?: number;
|
|
200
|
+
/**
|
|
201
|
+
* Injectable viewer-module importer (defaults to the real dynamic
|
|
202
|
+
* `import("../viewer/render.js")`). Exposed so a consumer can control code-
|
|
203
|
+
* splitting AND so tests can drive the module-load-FAILURE branch WITHOUT
|
|
204
|
+
* `mock.module` (which leaks across bun tests). Must resolve to an object
|
|
205
|
+
* exposing `renderConsentDocument`; rejecting simulates a chunk-load failure.
|
|
206
|
+
*/
|
|
207
|
+
importViewer?: () => Promise<typeof ___viewer_render_js>;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Turn a consent doc's stable key into a DOM-id-safe token. `doc_type` is a
|
|
211
|
+
* fixed enum (safe); a custom key arrives as `custom:<key>` — the `:` and any
|
|
212
|
+
* residual metachar are replaced so the raw token is valid inside an id AND
|
|
213
|
+
* inside a `#id` selector. (The key is already `[A-Za-z0-9_-]+` past the `:`
|
|
214
|
+
* per model.ts; this only neutralizes the `custom:` prefix separator.)
|
|
215
|
+
*/
|
|
216
|
+
declare function consentDocElementId(key: string): string;
|
|
217
|
+
/**
|
|
218
|
+
* Render (or re-render) the consent stage into a host container from the given
|
|
219
|
+
* consent state. Full re-render (the doc set is small); disabled/checked/error
|
|
220
|
+
* state is refreshed in place via updateConsentStep so scroll position and
|
|
221
|
+
* inline doc content are not lost on unrelated state changes.
|
|
222
|
+
*/
|
|
223
|
+
declare function renderConsentStep(host: HTMLElement, control: ConsentController, state: ConsentState, staleKeys?: string[], opts?: ConsentStepRenderOptions): void;
|
|
224
|
+
/**
|
|
225
|
+
* Refresh the consent cards' disabled/checked/error state in place (no full
|
|
226
|
+
* re-render) — called on every stepper state change so gate unlocks and
|
|
227
|
+
* live-clearing errors reflect immediately without losing scroll position or
|
|
228
|
+
* re-fetching inline doc content.
|
|
229
|
+
*/
|
|
230
|
+
declare function updateConsentStep(host: HTMLElement, state: ConsentState, consentErrors: Array<{
|
|
231
|
+
path: string;
|
|
232
|
+
message: string;
|
|
233
|
+
}>): void;
|
|
234
|
+
|
|
192
235
|
type WidgetMountOptions = ContactFormMountOptions | SignupFormMountOptions;
|
|
193
236
|
declare const OnboardingWidget: {
|
|
194
237
|
/**
|
|
@@ -216,4 +259,4 @@ declare const OnboardingWidget: {
|
|
|
216
259
|
readonly mount: (el: HTMLElement, options: WidgetMountOptions) => MountedWidget;
|
|
217
260
|
};
|
|
218
261
|
|
|
219
|
-
export { type ContactFormMountOptions, DEFAULT_WIDGET_CSS, type MountedWidget, OnboardingWidget, type SignupFormMountOptions, type WidgetMountOptions, cssEscape, idSelector, injectWidgetStyles, mountContactForm, mountSignupForm };
|
|
262
|
+
export { type ConsentStepRenderOptions, type ContactFormMountOptions, DEFAULT_WIDGET_CSS, type MountedWidget, OnboardingWidget, type SignupFormMountOptions, type WidgetMountOptions, consentDocElementId, cssEscape, idSelector, injectWidgetStyles, mountContactForm, mountSignupForm, renderConsentStep, updateConsentStep };
|
package/dist/widget/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
export { DEFAULT_WIDGET_CSS, OnboardingWidget, cssEscape, idSelector, injectWidgetStyles, mountContactForm, mountSignupForm } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
4
|
-
import '../chunk-
|
|
5
|
-
import '../chunk-
|
|
6
|
-
import '../chunk-
|
|
7
|
-
import '../chunk-
|
|
1
|
+
export { DEFAULT_WIDGET_CSS, OnboardingWidget, consentDocElementId, cssEscape, idSelector, injectWidgetStyles, mountContactForm, mountSignupForm, renderConsentStep, updateConsentStep } from '../chunk-IPAKPLIF.js';
|
|
2
|
+
import '../chunk-U6AXKGYQ.js';
|
|
3
|
+
import '../chunk-F75ZJERM.js';
|
|
4
|
+
import '../chunk-KQTS47FC.js';
|
|
5
|
+
import '../chunk-AZE3NPSY.js';
|
|
6
|
+
import '../chunk-U56GQITG.js';
|
|
7
|
+
import '../chunk-BMQINH6O.js';
|
|
8
|
+
import '../chunk-SIMLMQPT.js';
|
|
9
|
+
import '../chunk-XJTJPBJB.js';
|
|
8
10
|
import '../chunk-7NS7ENJV.js';
|
|
9
11
|
//# sourceMappingURL=index.js.map
|
|
10
12
|
//# sourceMappingURL=index.js.map
|