@arkyc/widget 1.0.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 +85 -0
- package/dist/ArkycWidget.d.mts +50 -0
- package/dist/ArkycWidget.d.mts.map +1 -0
- package/dist/ArkycWidget.mjs +80 -0
- package/dist/ArkycWidget.mjs.map +1 -0
- package/dist/WidgetHandler.d.mts +24 -0
- package/dist/WidgetHandler.d.mts.map +1 -0
- package/dist/WidgetHandler.mjs +28 -0
- package/dist/WidgetHandler.mjs.map +1 -0
- package/dist/_virtual/_virtual_arkyc-theme-css.mjs +4 -0
- package/dist/arkyc-widget.iife.global.js +670 -0
- package/dist/arkyc-widget.iife.global.js.map +1 -0
- package/dist/capture.d.mts +73 -0
- package/dist/capture.d.mts.map +1 -0
- package/dist/capture.mjs +126 -0
- package/dist/capture.mjs.map +1 -0
- package/dist/client.d.mts +152 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +120 -0
- package/dist/client.mjs.map +1 -0
- package/dist/controller.d.mts +126 -0
- package/dist/controller.d.mts.map +1 -0
- package/dist/controller.mjs +582 -0
- package/dist/controller.mjs.map +1 -0
- package/dist/countries.mjs +967 -0
- package/dist/countries.mjs.map +1 -0
- package/dist/device.mjs +17 -0
- package/dist/device.mjs.map +1 -0
- package/dist/document.d.mts +108 -0
- package/dist/document.d.mts.map +1 -0
- package/dist/document.mjs +227 -0
- package/dist/document.mjs.map +1 -0
- package/dist/face.d.mts +82 -0
- package/dist/face.d.mts.map +1 -0
- package/dist/face.mjs +230 -0
- package/dist/face.mjs.map +1 -0
- package/dist/flow.d.mts +74 -0
- package/dist/flow.d.mts.map +1 -0
- package/dist/flow.mjs +132 -0
- package/dist/flow.mjs.map +1 -0
- package/dist/index.d.mts +19 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +16 -0
- package/dist/index.mjs.map +1 -0
- package/dist/qr.mjs +22 -0
- package/dist/qr.mjs.map +1 -0
- package/dist/realtime.d.mts +29 -0
- package/dist/realtime.d.mts.map +1 -0
- package/dist/realtime.mjs +107 -0
- package/dist/realtime.mjs.map +1 -0
- package/dist/theme.d.mts +42 -0
- package/dist/theme.d.mts.map +1 -0
- package/dist/theme.mjs +77 -0
- package/dist/theme.mjs.map +1 -0
- package/dist/types.d.mts +153 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/ui.mjs +931 -0
- package/dist/ui.mjs.map +1 -0
- package/package.json +43 -0
package/dist/ui.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.mjs","names":[],"sources":["../src/ui.ts"],"sourcesContent":["import type {\n DocumentType,\n LivenessChallenge,\n ProjectBranding,\n VerificationDecision,\n VerificationStatus,\n WidgetStep,\n} from '@arkyc/types'\n\nimport { Camera } from './capture'\nimport type { Facing } from './capture'\nimport {\n createDefaultDocumentAnalyzer,\n DEFAULT_DOCUMENT_TUNING,\n documentGuidance,\n type DocRect,\n type DocumentAnalyzer,\n type DocumentTuning,\n} from './document'\nimport {\n createDefaultFaceAnalyzer,\n DEFAULT_TUNING,\n isSelfieReady,\n makeChallengeDetector,\n type FaceAnalyzer,\n type FaceTuning,\n} from './face'\nimport { Theme } from './theme'\nimport { countries } from './countries'\n\n/** High-level events the view raises back to the controller. */\nexport interface ViewHandlers {\n onClose(): void\n onStart(): void\n onDocumentSelected(type: DocumentType, country: string): void\n /** A capture screen produced an image (or `null` when skipped in demo mode). */\n onImage(blob: Blob | null): void\n /**\n * Active liveness finished: the recorded video (or `null`), the performed\n * sequence, and a still selfie frame grabbed from the live video (or `null`).\n */\n onActiveLiveness(video: Blob | null, performed: LivenessChallenge[], selfie?: Blob | null): void\n /** The result screen was acknowledged (\"Done\"). */\n onAcknowledge(): void\n /** The user chose to continue the verification on another device (handoff). */\n onUsePhone(): void\n /** The user chose to keep verifying on this (desktop) device instead of handing off. */\n onContinueHere(): void\n}\n\n/** Per-render data the view needs for the current step. */\nexport interface ViewState {\n step: WidgetStep\n documentType: DocumentType | null\n decision?: VerificationDecision | null\n /** The session status (drives the close-only terminal notice). */\n status?: VerificationStatus\n /** Render the result as a close-only notice (session was already terminal on load). */\n terminalNotice?: boolean\n statusLabel?: string\n errorMessage?: string\n /** Show a \"Skip\" affordance on capture screens (demo / mock-driver flows). */\n allowSkip?: boolean\n /** The challenge sequence to prompt for the active-liveness screen. */\n livenessChallenges?: LivenessChallenge[]\n /**\n * Capture model demands a live camera (`capture_model === 'active'`). When set,\n * the active-liveness screen must NOT offer a manual/file fallback on\n * unsupported devices — it shows an \"unsupported device\" message instead.\n */\n requireLiveCamera?: boolean\n /**\n * The session runs the active flow (resolved liveness is `active`). Document\n * capture is then strict: detection-gated auto-capture only — no manual capture\n * button, no permissive brightness/upload fallback that could bypass detection.\n */\n strictCapture?: boolean\n /** Offer a \"Continue on your phone\" affordance on the welcome screen (handoff). */\n handoffAvailable?: boolean\n}\n\nconst DOCUMENT_LABELS: Record<DocumentType, string> = {\n passport: 'Passport',\n id_card: 'ID Card',\n drivers_license: \"Driver's License\",\n residence_permit: 'Residence Permit',\n}\n\nconst CHALLENGE_LABELS: Record<LivenessChallenge, string> = {\n turn_left: 'Slowly turn your head to the left, and hold',\n turn_right: 'Slowly turn your head to the right, and hold',\n blink: 'Blink slowly',\n smile: 'Smile, and hold it',\n nod: 'Slowly nod your head',\n move_closer: 'Slowly move closer to the camera',\n}\n\ninterface Notice {\n cls: string\n icon: string\n title: string\n copy: string\n}\n\n/** Fallback notice for an expired/unknown terminal session. */\nconst EXPIRED_NOTICE: Notice = {\n cls: 'warn',\n icon: '⏳',\n title: 'Link expired',\n copy: 'This verification link has expired.',\n}\n\n/** Close-only notice copy for a session that was already terminal on load. */\nconst TERMINAL_NOTICE: Partial<Record<VerificationStatus, Notice>> = {\n approved: { cls: 'ok', icon: '✓', title: 'Already complete', copy: 'This verification has already been completed.' },\n rejected: { cls: 'ok', icon: '✓', title: 'Already complete', copy: 'This verification has already been completed.' },\n requires_review: {\n cls: 'ok',\n icon: '✓',\n title: 'Already complete',\n copy: 'This verification has already been submitted and is being reviewed.',\n },\n expired: EXPIRED_NOTICE,\n cancelled: { cls: 'warn', icon: '⏳', title: 'Cancelled', copy: 'This verification was cancelled.' },\n}\n\nconst SVG = (body: string) =>\n `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${body}</svg>`\n\n/** Per-challenge directional cue icons, animated via CSS over the preview. */\nconst CUE_ICONS: Record<LivenessChallenge, string> = {\n turn_right: SVG('<path d=\"M5 12h14M13 6l6 6-6 6\"/>'),\n turn_left: SVG('<path d=\"M19 12H5M11 6l-6 6 6 6\"/>'),\n nod: SVG('<path d=\"M12 5v14M6 13l6 6 6-6\"/>'),\n move_closer: SVG('<circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v3M12 19v3M2 12h3M19 12h3\"/>'),\n blink: SVG('<path d=\"M2 12s4-7 10-7 10 7 10 7-4 7-10 7S2 12 2 12z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>'),\n smile: SVG('<path d=\"M8 14s1.5 2 4 2 4-2 4-2\"/><path d=\"M9 9h.01M15 9h.01\"/>'),\n}\n\nconst CHECK_ICON = SVG('<path d=\"M20 6 9 17l-5-5\"/>')\n\n/** Larger line-art illustration used to dress the informative / lead-in screens. */\nconst ART = (body: string) =>\n `<svg viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${body}</svg>`\n\n/** Per-screen decorative illustrations, keyed by step (plus a welcome hero). */\nconst STEP_ART: Partial<Record<WidgetStep | 'welcome', string>> = {\n // Shield with a check — trust / \"verify your identity\".\n welcome: ART(\n '<path d=\"M32 7 52 14v14c0 12.5-8.2 21.6-20 25.6C20.2 49.6 12 40.5 12 28V14z\"/><path d=\"M23 30.5l6.2 6.2L41 24.5\"/>',\n ),\n // ID card with a portrait + text lines.\n front_capture: ART(\n '<rect x=\"7\" y=\"15\" width=\"50\" height=\"34\" rx=\"5\"/><circle cx=\"22\" cy=\"28\" r=\"5\"/><path d=\"M14 42c1-5 5-7 8-7s7 2 8 7\"/><path d=\"M38 27h12M38 34h12M38 41h8\"/>',\n ),\n // ID card flipped: magnetic stripe + MRZ lines.\n back_capture: ART(\n '<rect x=\"7\" y=\"15\" width=\"50\" height=\"34\" rx=\"5\"/><rect x=\"7\" y=\"20\" width=\"50\" height=\"6\" fill=\"currentColor\" stroke=\"none\" opacity=\".18\"/><path d=\"M14 34h36M14 41h24\"/>',\n ),\n // A person centred in a camera viewfinder (corner brackets).\n selfie_capture: ART(\n '<path d=\"M10 20v-6a4 4 0 0 1 4-4h6\"/><path d=\"M44 10h6a4 4 0 0 1 4 4v6\"/><path d=\"M54 44v6a4 4 0 0 1-4 4h-6\"/><path d=\"M20 54h-6a4 4 0 0 1-4-4v-6\"/><circle cx=\"32\" cy=\"27\" r=\"8\"/><path d=\"M19 50c0-7 6-11 13-11s13 4 13 11\"/>',\n ),\n // A smiling face with turn-your-head arrows on each side.\n active_liveness: ART(\n '<circle cx=\"32\" cy=\"30\" r=\"13\"/><circle cx=\"27\" cy=\"27\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"37\" cy=\"27\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\"/><path d=\"M26 34c2 2.5 10 2.5 12 0\"/><path d=\"M13 30H6M10 26l-4 4 4 4\"/><path d=\"M51 30h7M54 26l4 4-4 4\"/>',\n ),\n}\n\n/** Handles for driving the circular preview overlay (ring + cue + success check). */\ninterface FaceStage {\n stage: HTMLElement\n /** 0–1 fill of the progress ring. */\n setProgress(p: number): void\n /** Visual state: searching, holding (green), or completed (check). */\n setState(state: 'wait' | 'good' | 'done'): void\n /** Show a challenge cue icon (or clear it with `null`). */\n setCue(challenge: LivenessChallenge | null): void\n}\n\n/** Handles for driving the document preview overlay (bracket frame + scan line). */\ninterface DocStage {\n stage: HTMLElement\n /** Tint the frame for the current capture quality. */\n setQuality(quality: 'wait' | 'good' | 'bad'): void\n /** Flag whether a document is currently detected (brightens the fixed guide). */\n setFrame(rect: DocRect | null): void\n}\n\n/** Handles for driving the liveness step-progress dots. */\ninterface StepDots {\n el: HTMLElement\n /** Mark the given step index as the active one. */\n setActive(index: number): void\n /** Mark the given step index as completed. */\n markDone(index: number): void\n}\n\ninterface ElProps {\n class?: string\n text?: string\n html?: string\n type?: string\n src?: string\n accept?: string\n placeholder?: string\n value?: string\n [attr: string]: string | undefined\n}\n\n/**\n * Renders the widget's screens into a host element. DOM- and camera-injectable\n * so it can run under a fake DOM in tests. The view owns capture-screen camera\n * mechanics and raises only high-level events to the controller.\n */\nexport class WidgetView {\n private readonly root: HTMLElement\n private readonly body: HTMLElement\n private readonly footer: HTMLElement\n /** The `<style>` carrying the theme's CSS vars; swapped on runtime re-brand. */\n private readonly styleEl: HTMLElement\n /** The header brand group (logo/name/title); rebuilt on runtime re-brand. */\n private readonly brandEl: HTMLElement\n private readonly camera: Camera\n private readonly analyzer: FaceAnalyzer | null\n private readonly tuning: FaceTuning\n private readonly docAnalyzer: DocumentAnalyzer | null\n private readonly docTuning: DocumentTuning\n /** Interval ids for live quality/recording timers, cleared on re-render. */\n private timers: ReturnType<typeof setInterval>[] = []\n /** Extra teardown run on each re-render (cancels in-flight detection loops). */\n private cleanups: (() => void)[] = []\n\n constructor(\n private readonly doc: Document,\n private theme: Theme,\n private readonly handlers: ViewHandlers,\n nav: Navigator = globalThis.navigator,\n analyzer: FaceAnalyzer | null = createDefaultFaceAnalyzer(),\n tuning: FaceTuning = DEFAULT_TUNING,\n docAnalyzer: DocumentAnalyzer | null = createDefaultDocumentAnalyzer(),\n docTuning: DocumentTuning = DEFAULT_DOCUMENT_TUNING,\n ) {\n this.camera = new Camera(doc, nav)\n this.analyzer = analyzer\n this.tuning = tuning\n this.docAnalyzer = docAnalyzer\n this.docTuning = docTuning\n this.root = this.el('div', { class: 'arkyc-root' })\n\n this.styleEl = this.el('style', { text: theme.stylesheet() })\n this.root.appendChild(this.styleEl)\n\n const card = this.el('div', { class: 'arkyc-card' })\n const header = this.el('div', { class: 'arkyc-header' })\n this.brandEl = this.el('div', { class: 'arkyc-brand' })\n this.fillBrand()\n header.appendChild(this.brandEl)\n const close = this.el('button', {\n class: 'arkyc-close',\n html: '×',\n 'aria-label': 'Close',\n })\n close.addEventListener('click', () => this.handlers.onClose())\n header.appendChild(close)\n\n this.body = this.el('div', { class: 'arkyc-body' })\n this.footer = this.el('div', { class: 'arkyc-footer' })\n\n card.appendChild(header)\n card.appendChild(this.body)\n card.appendChild(this.footer)\n this.root.appendChild(card)\n }\n\n /**\n * Populate the header brand group from the current theme: the project logo\n * and/or name when branding is shown, otherwise a neutral title.\n */\n private fillBrand(): void {\n this.clear(this.brandEl)\n const lastTenMins = Date.now() - Math.floor(Math.random() * (10 * 60 * 1000))\n\n if (this.theme.showBranding && (this.theme.logoUrl || this.theme.name)) {\n if (this.theme.logoUrl)\n this.brandEl.appendChild(\n this.el('img', {\n class: 'arkyc-logo',\n src: this.theme.logoUrl + '?stamp=' + lastTenMins,\n }),\n )\n if (this.theme.name)\n this.brandEl.appendChild(this.el('span', { class: 'arkyc-brand-name', text: this.theme.name }))\n } else {\n this.brandEl.appendChild(this.el('p', { class: 'arkyc-title', text: 'Verify your identity' }))\n }\n }\n\n /**\n * Re-theme the widget at runtime from project branding (resolved server-side):\n * swap the CSS-variable stylesheet (colours/radius) and rebuild the header\n * brand (logo/name). Cascades to every already-rendered element via the vars.\n */\n applyBranding(branding: ProjectBranding | null): void {\n this.theme = new Theme(branding)\n this.styleEl.textContent = this.theme.stylesheet()\n this.fillBrand()\n }\n\n /**\n * The widget's root element — append this to the overlay / container.\n */\n get element(): HTMLElement {\n return this.root\n }\n\n /**\n * Whether live camera capture is available (drives the active-liveness branch).\n */\n get cameraSupported(): boolean {\n return this.camera.supported\n }\n\n /**\n * Release any active camera stream and clear live timers.\n */\n destroy(): void {\n this.timers.forEach((id) => clearInterval(id))\n this.timers = []\n this.cleanups.forEach((fn) => fn())\n this.cleanups = []\n this.camera.stop()\n }\n\n /**\n * Render the screen for the given state.\n *\n * @param state\n * @returns\n */\n render(state: ViewState): void {\n this.destroy()\n this.clear(this.body)\n this.clear(this.footer)\n this.root.classList.remove('arkyc-handoff')\n\n switch (state.step) {\n case 'welcome':\n return this.renderWelcome(state.handoffAvailable)\n case 'document_selection':\n return this.renderDocumentSelection()\n case 'front_capture':\n return this.renderCapture('Front of document', 'environment', state.allowSkip, false, state.strictCapture)\n case 'back_capture':\n return this.renderCapture('Back of document', 'environment', state.allowSkip, false, state.strictCapture)\n case 'selfie_capture':\n return this.renderCapture('Take a selfie', 'user', state.allowSkip, true, state.strictCapture)\n case 'active_liveness':\n return this.renderActiveLiveness(state.livenessChallenges ?? [], state.allowSkip, state.requireLiveCamera)\n case 'ocr_processing':\n return this.renderProcessing('Reading your document…')\n case 'passive_liveness':\n return this.renderProcessing('Checking liveness…')\n case 'face_match':\n return this.renderProcessing('Matching your face…')\n case 'processing':\n return this.renderProcessing(state.statusLabel ?? 'Finalising verification…')\n case 'result':\n return this.renderResult(state.decision ?? null, state.errorMessage, {\n terminal: state.terminalNotice,\n status: state.status,\n })\n }\n }\n\n /** Prepend a decorative illustration for the given screen, when one exists. */\n private appendArt(key: WidgetStep | 'welcome'): void {\n const art = STEP_ART[key]\n if (art) this.body.appendChild(this.el('div', { class: 'arkyc-illus', html: art }))\n }\n\n private renderWelcome(handoffAvailable?: boolean): void {\n this.appendArt('welcome')\n this.body.appendChild(this.el('h2', { class: 'arkyc-h', text: 'Verify your identity' }))\n this.body.appendChild(\n this.el('p', {\n class: 'arkyc-p',\n text: 'You will need a government-issued ID and a moment to take a selfie. Your data is processed securely.',\n }),\n )\n this.footer.appendChild(this.button('Get started', () => this.handlers.onStart()))\n if (handoffAvailable) {\n this.footer.appendChild(\n this.button('Continue on your phone', () => this.handlers.onUsePhone(), 'arkyc-btn-ghost'),\n )\n }\n }\n\n /** A neutral connecting screen shown while the widget bootstraps the session. */\n renderLoading(label = 'Loading…'): void {\n this.destroy()\n this.clear(this.body)\n this.clear(this.footer)\n this.root.classList.remove('arkyc-handoff')\n this.renderProcessing(label)\n }\n\n /**\n * An interstitial that tells the user what the next step is, with a single\n * Continue button — so each step starts deliberately rather than the camera\n * springing to life unannounced.\n */\n renderInstruction(step: WidgetStep, title: string, body: string, cta: string, onContinue: () => void): void {\n this.destroy()\n this.clear(this.body)\n this.clear(this.footer)\n this.root.classList.remove('arkyc-handoff')\n this.appendArt(step)\n this.body.appendChild(this.el('h2', { class: 'arkyc-h', text: title }))\n this.body.appendChild(this.el('p', { class: 'arkyc-p', text: body }))\n this.footer.appendChild(this.button(cta, onContinue))\n }\n\n /**\n * Show the cross-device handoff QR: the user scans it to resume this same\n * session on their phone. The widget then waits for the other device to finish.\n * `allowContinueHere` offers an escape hatch to keep verifying on this device.\n */\n renderHandoff(qrSvg: string, allowContinueHere: boolean): void {\n this.destroy()\n this.clear(this.body)\n this.clear(this.footer)\n // Keep the QR prominent (edge-to-edge in fullscreen) rather than a small dialog.\n this.root.classList.add('arkyc-handoff')\n this.body.appendChild(this.el('h2', { class: 'arkyc-h', text: 'Continue on your phone' }))\n this.body.appendChild(\n this.el('p', { class: 'arkyc-p', text: 'Scan this code with your phone camera to finish verifying there.' }),\n )\n this.body.appendChild(this.el('div', { class: 'arkyc-qr', html: qrSvg }))\n const waiting = this.el('div', { class: 'arkyc-handoff-wait' })\n waiting.appendChild(this.el('div', { class: 'arkyc-spinner sm' }))\n waiting.appendChild(this.el('span', { text: 'Waiting for your phone…' }))\n this.body.appendChild(waiting)\n if (allowContinueHere) {\n this.footer.appendChild(\n this.button('Continue on this device', () => this.handlers.onContinueHere(), 'arkyc-btn-ghost'),\n )\n }\n }\n\n private renderDocumentSelection(): void {\n this.body.appendChild(this.el('h2', { class: 'arkyc-h', text: 'Select your document' }))\n const country = this.el('select', {\n class: 'arkyc-btn arkyc-btn-ghost arkyc-text-center',\n name: 'country',\n autocomplete: 'country',\n 'aria-label': 'Country',\n }) as HTMLSelectElement\n\n const placeholder = this.el('option', {\n value: '',\n selected: 'selected',\n })\n\n placeholder.textContent = 'Country'\n\n country.appendChild(placeholder)\n\n countries.forEach(({ name, iso2, flag }) => {\n const option = this.el('option', { value: iso2 }) as HTMLOptionElement\n option.textContent = `${flag} ${name}`\n country.appendChild(option)\n })\n\n const choices = this.el('div', { class: 'arkyc-choices' })\n\n choices.appendChild(country)\n ;(Object.keys(DOCUMENT_LABELS) as DocumentType[]).forEach((type) => {\n const btn = this.button(DOCUMENT_LABELS[type], () =>\n this.handlers.onDocumentSelected(type, (country.value || '').trim().toUpperCase()),\n )\n btn.classList.add('arkyc-btn-ghost')\n choices.appendChild(btn)\n })\n this.body.appendChild(choices)\n }\n\n private renderCapture(title: string, facing: Facing, allowSkip?: boolean, selfie = false, strict = false): void {\n // Documents in the active flow are strict: detection-gated only (no manual\n // bypass). Selfies are always pure auto, so strictness only changes documents.\n const strictDoc = strict && !selfie\n this.body.appendChild(this.el('h2', { class: 'arkyc-h', text: title }))\n this.body.appendChild(this.el('p', { class: 'arkyc-p', text: 'Position it clearly in frame, then capture.' }))\n\n const fileInput = this.el('input', {\n type: 'file',\n accept: 'image/*',\n class: 'arkyc-hidden',\n }) as HTMLInputElement\n fileInput.addEventListener('change', () => this.handlers.onImage(Camera.fileFromInput(fileInput)))\n this.body.appendChild(fileInput)\n\n if (this.camera.supported) {\n const video = this.el('video', {\n class: `arkyc-preview${selfie ? ' selfie' : ''}`,\n }) as HTMLVideoElement\n\n // Wrap the preview in its animated overlay (circular ring for selfies,\n // bracket frame for documents).\n const face = selfie ? this.buildFaceStage(video) : null\n const doc = selfie ? null : this.buildDocStage(video)\n const mount = face?.stage ?? doc!.stage\n this.body.appendChild(mount)\n\n // Live guidance hint (quality for documents, framing for selfies).\n const hint = this.el('p', { class: 'arkyc-p arkyc-hint' }) as HTMLParagraphElement\n this.body.appendChild(hint)\n\n // After a capture, wait for an explicit \"Continue\" so the user can review\n // and get ready for the next step — never auto-advance. Swap the live\n // preview for a still of the captured frame: this shows exactly what was\n // captured and removes the overlay (brackets / scan line / ring) entirely,\n // rather than leaving a stopped (black) video with animations still running.\n const confirmCapture = (blob: Blob | null) => {\n this.destroy() // stop the camera + detection timers\n if (blob) {\n const url = URL.createObjectURL(blob)\n const still = this.el('img', {\n class: `arkyc-preview${selfie ? ' selfie' : ''}`,\n src: url,\n }) as HTMLImageElement\n mount.replaceWith(still)\n this.cleanups.push(() => URL.revokeObjectURL(url))\n } else {\n mount.classList.add('arkyc-hidden')\n }\n this.clear(this.footer)\n hint.textContent = '✓ Captured'\n this.footer.appendChild(this.button('Continue', () => this.handlers.onImage(blob)))\n const retake = this.button('Retake', () => {\n this.destroy()\n this.clear(this.body)\n this.clear(this.footer)\n this.renderCapture(title, facing, allowSkip, selfie, strict)\n })\n retake.classList.add('arkyc-btn-ghost')\n this.footer.appendChild(retake)\n }\n\n const onCapture = () => void this.camera.grabFrame(video).then(confirmCapture)\n\n void this.camera.start(video, facing).catch(() => {\n mount.classList.add('arkyc-hidden')\n if (strictDoc) {\n // Strict document capture: no file fallback — a live camera is required.\n hint.textContent = 'Camera access is required to scan your document. Please allow access and try again.'\n return\n }\n // Camera denied/unavailable — fall back to the file input.\n fileInput.click()\n })\n\n if (selfie) {\n // Pure auto-capture: face detection grabs the frame when the user is\n // framed. The manual button only appears if the detector can't load.\n this.runSelfieAutoCapture(video, hint, onCapture, face!)\n } else {\n this.runDocumentAutoCapture(video, hint, doc!, strictDoc, onCapture)\n // Passive model only: a manual capture button as a reliable override.\n // The active flow is detection-gated — no manual bypass.\n if (!strictDoc) this.footer.appendChild(this.button('Capture', onCapture))\n }\n } else if (strictDoc) {\n // Strict document capture with no camera — surface as unsupported.\n this.body.appendChild(this.el('div', { class: 'arkyc-badge err', html: '!' }))\n this.body.appendChild(\n this.el('p', {\n class: 'arkyc-p',\n text: 'This step needs a working camera to scan your document. Please retry on a device with a camera.',\n }),\n )\n } else {\n const upload = this.button('Upload photo', () => fileInput.click())\n this.footer.appendChild(upload)\n }\n\n if (allowSkip) {\n const skip = this.button('Skip (demo)', () => this.handlers.onImage(null))\n skip.classList.add('arkyc-btn-ghost')\n this.footer.appendChild(skip)\n }\n }\n\n /**\n * Run `cb` once the live camera feed appears (the video has frames). The\n * detection model may still be downloading at that point, so callers use this\n * to replace the \"starting camera\" hint with a neutral one.\n *\n * @param video\n * @param cb\n */\n private onCameraLive(video: HTMLVideoElement, cb: () => void): void {\n if ((video.readyState ?? 0) >= 2) {\n cb()\n return\n }\n video.addEventListener('playing', cb, { once: true })\n }\n\n /**\n * Document capture: detect a real, well-framed, in-focus document (edge\n * projection) and auto-grab only once it's been held steady. Falls back to the\n * brightness/glare heuristic when the detector can't run.\n *\n * @param video\n * @returns\n */\n private runDocumentAutoCapture(\n video: HTMLVideoElement,\n hint: HTMLElement,\n doc: DocStage,\n strict: boolean,\n capture: () => void,\n ): void {\n // In strict mode the permissive brightness heuristic is disabled — it can't\n // tell a document from a well-lit blank frame, which would defeat detection.\n const onNoDetector = () => {\n if (strict) {\n hint.textContent = 'Document scanning isn’t available on this device.'\n return\n }\n this.runDocumentBrightnessCapture(video, hint, doc, capture)\n }\n\n const analyzer = this.docAnalyzer\n if (!analyzer) return onNoDetector()\n\n hint.textContent = 'Starting camera…'\n let cancelled = false\n let modelReady = false\n this.cleanups.push(() => {\n cancelled = true\n })\n // The camera feed appears before the document scanner model finishes loading;\n // once the video is live, stop implying the camera is still starting.\n this.onCameraLive(video, () => {\n if (!cancelled && !modelReady) hint.textContent = 'Getting ready…'\n })\n void analyzer.ready().then((ok) => {\n modelReady = true\n if (cancelled) return\n if (!ok) {\n onNoDetector()\n return\n }\n let goodStreak = 0\n // Smooth the noisiest geometry signals (fill/edge strength) across frames so a\n // single jittery edge-projection read doesn't flip the hint to \"move closer\"\n // and reset the streak. Exponential moving average; null until the first frame.\n let fillEma: number | null = null\n let edgeEma: number | null = null\n const ema = (prev: number | null, next: number) => (prev == null ? next : prev * 0.6 + next * 0.4)\n const timer = setInterval(() => {\n const sample = analyzer.analyze(video)\n if (!sample) return\n fillEma = ema(fillEma, sample.fill)\n edgeEma = ema(edgeEma, sample.edgeStrength)\n const smoothed = { ...sample, fill: fillEma, edgeStrength: edgeEma }\n const { ready, hint: message } = documentGuidance(smoothed, this.docTuning)\n hint.textContent = message\n doc.setFrame(sample.present ? sample.rect : null)\n doc.setQuality(ready ? 'good' : sample.present ? 'wait' : 'bad')\n // Soft reset: a single off frame nudges the streak down rather than zeroing\n // it, so transient detector noise doesn't perpetually restart the hold.\n goodStreak = ready ? goodStreak + 1 : Math.max(0, goodStreak - 1)\n // Auto-capture once a framed, focused document has held for ~1.25s.\n if (goodStreak >= this.docTuning.hold) {\n clearInterval(timer)\n doc.setQuality('good')\n capture()\n }\n }, 250)\n this.timers.push(timer)\n })\n }\n\n /**\n * Coarse fallback: brightness/glare heuristic, used when detection can't run.\n *\n * @param video\n * @param hint\n * @param doc\n */\n private runDocumentBrightnessCapture(\n video: HTMLVideoElement,\n hint: HTMLElement,\n doc: DocStage,\n capture: () => void,\n ): void {\n let goodStreak = 0\n const timer = setInterval(() => {\n const quality = this.camera.sampleQuality(video)\n if (!quality) return\n if (quality.tooDark) {\n hint.textContent = 'Too dark — find better lighting'\n goodStreak = 0\n doc.setQuality('bad')\n } else if (quality.glare) {\n hint.textContent = 'Reduce glare on the document'\n goodStreak = 0\n doc.setQuality('bad')\n } else {\n hint.textContent = 'Looks good — hold steady'\n goodStreak += 1\n doc.setQuality('good')\n }\n // Auto-capture a steady document after ~1.5s of good quality.\n if (goodStreak >= 5) {\n clearInterval(timer)\n capture()\n }\n }, 300)\n this.timers.push(timer)\n }\n\n /**\n * Selfie capture: when face detection is available, auto-grab once a centred\n * face is held steady. Falls back to a brightness hint (manual capture) when\n * the detector can't load (unsupported browser / offline / test host).\n *\n * @param video\n * @param hint\n * @param capture\n * @returns\n */\n private runSelfieAutoCapture(video: HTMLVideoElement, hint: HTMLElement, capture: () => void, face: FaceStage): void {\n const analyzer = this.analyzer\n const addManualCapture = () => this.footer.appendChild(this.button('Capture', capture))\n if (!analyzer) {\n // No detector available — fall back to a manual capture button.\n hint.textContent = 'Center your face, then capture'\n addManualCapture()\n return\n }\n hint.textContent = 'Starting camera…'\n let cancelled = false\n let modelReady = false\n this.cleanups.push(() => {\n cancelled = true\n })\n // The camera feed appears before the detection model (MediaPipe WASM, lazily\n // fetched from a CDN) finishes loading. Once the video is live, stop implying\n // the camera is still starting.\n this.onCameraLive(video, () => {\n if (!cancelled && !modelReady) hint.textContent = 'Getting ready…'\n })\n void analyzer.ready().then((ok) => {\n modelReady = true\n if (cancelled) return\n if (!ok) {\n // Detector failed to load — guide with brightness and offer manual capture.\n hint.textContent = 'Center your face, then capture'\n addManualCapture()\n return\n }\n const need = 4\n let streak = 0\n const timer = setInterval(() => {\n const sample = analyzer.analyze(video)\n if (!sample || !sample.present) {\n hint.textContent = 'Position your face in the circle'\n streak = 0\n face.setState('wait')\n face.setProgress(0)\n return\n }\n if (isSelfieReady(sample, this.tuning)) {\n hint.textContent = 'Hold still…'\n streak += 1\n face.setState('good')\n face.setProgress(streak / need)\n } else {\n hint.textContent = sample.scale <= this.tuning.selfieMinScale ? 'Move a little closer' : 'Center your face'\n streak = 0\n face.setState('wait')\n face.setProgress(0)\n }\n if (streak >= need) {\n clearInterval(timer)\n face.setState('done')\n face.setProgress(1)\n capture()\n }\n }, 180)\n this.timers.push(timer)\n })\n }\n\n /**\n * Guided active-liveness screen: live front-camera preview, a recorded video,\n * and a sequence of challenge prompts the user advances through. The performed\n * sequence (the prompts shown, in order) is submitted for the driver to verify.\n *\n * @param video\n * @returns\n */\n private renderActiveLiveness(\n challenges: LivenessChallenge[],\n allowSkip?: boolean,\n requireLiveCamera?: boolean,\n ): void {\n this.body.appendChild(this.el('h2', { class: 'arkyc-h', text: 'Liveness check' }))\n const prompt = this.el('p', {\n class: 'arkyc-p',\n text: 'Follow the on-screen prompts. Keep your face centred in the circle.',\n })\n this.body.appendChild(prompt)\n\n const fileFallback = !this.camera.supported || !this.camera.canRecord\n\n if (fileFallback) {\n if (requireLiveCamera) {\n // capture_model = active: a live camera is mandatory. Do NOT offer a\n // manual \"I did it\" path — surface the device as unsupported instead.\n this.body.appendChild(this.el('div', { class: 'arkyc-badge err', html: '!' }))\n prompt.textContent =\n 'This check needs camera access on a supported device. Please retry on a device with a working camera.'\n if (allowSkip) {\n const skip = this.button('Skip (demo)', () => this.handlers.onActiveLiveness(null, challenges))\n skip.classList.add('arkyc-btn-ghost')\n this.footer.appendChild(skip)\n }\n return\n }\n // No camera/recorder — let the user finish (or skip) without a video.\n const finish = this.button('I performed the steps', () => this.handlers.onActiveLiveness(null, challenges))\n this.footer.appendChild(finish)\n if (allowSkip) {\n const skip = this.button('Skip (demo)', () => this.handlers.onActiveLiveness(null, challenges))\n skip.classList.add('arkyc-btn-ghost')\n this.footer.appendChild(skip)\n }\n return\n }\n\n const video = this.el('video', { class: 'arkyc-preview selfie' }) as HTMLVideoElement\n const face = this.buildFaceStage(video)\n const dots = this.buildDots(challenges.length)\n if (challenges.length > 1) this.body.appendChild(dots.el)\n this.body.appendChild(face.stage)\n\n let recording: { stop(): Promise<Blob> } | null = null\n let index = 0\n // The challenges the user actually completed, in order (detected or advanced).\n const performed: LivenessChallenge[] = []\n let detector = makeChallengeDetector(challenges[0] ?? 'blink', this.tuning)\n\n const showPrompt = (done = false) => {\n const challenge = challenges[index]\n if (!challenge) {\n prompt.textContent = 'Hold still…'\n return\n }\n prompt.textContent = done\n ? `✓ ${CHALLENGE_LABELS[challenge]}`\n : `Step ${index + 1} of ${challenges.length}: ${CHALLENGE_LABELS[challenge]}`\n }\n\n // Arm the overlay for the current challenge: show its cue, reset the ring,\n // and highlight the active step dot.\n const armChallenge = () => {\n face.setCue(challenges[index] ?? null)\n face.setState('wait')\n face.setProgress(0)\n dots.setActive(index)\n }\n\n const finish = () => {\n advance.setAttribute('disabled', 'true')\n // Grab a still selfie from the live video before stopping the recorder, so\n // active liveness yields a face image for review + face matching.\n void this.camera\n .grabFrame(video)\n .then((selfie) =>\n Promise.resolve(recording?.stop() ?? Promise.resolve(null)).then((blob) =>\n this.handlers.onActiveLiveness(blob, performed, selfie),\n ),\n )\n }\n\n const advanceStep = () => {\n if (index >= challenges.length) return\n const current = challenges[index]\n if (current) performed.push(current)\n dots.markDone(index)\n index += 1\n if (index >= challenges.length) {\n finish()\n return\n }\n detector = makeChallengeDetector(challenges[index]!, this.tuning)\n showPrompt()\n armChallenge()\n if (index === challenges.length - 1) advance.textContent = 'Finish'\n }\n\n // Manual advance is only revealed as a fallback when detection can't run.\n const advance = this.button('Next', () => advanceStep())\n if (challenges.length <= 1) advance.textContent = 'Finish'\n let manualShown = false\n const showManualAdvance = () => {\n if (manualShown) return\n manualShown = true\n this.footer.appendChild(advance)\n }\n\n void this.camera\n .start(video, 'user')\n .then((stream) => {\n recording = this.camera.recordStart(stream)\n showPrompt()\n armChallenge()\n\n // Real detection when available: auto-advance only when the prompted\n // challenge is actually performed. Reveals the manual button if the\n // detector is absent or fails to load.\n const analyzer = this.analyzer\n if (!analyzer) {\n showManualAdvance()\n return\n }\n let cancelled = false\n this.cleanups.push(() => {\n cancelled = true\n })\n void analyzer.ready().then((ok) => {\n if (cancelled) return\n if (!ok) {\n showManualAdvance()\n return\n }\n // While the success check is held, pause detection so the next cue\n // doesn't flash in before the user sees the confirmation.\n let flashing = false\n const timer = setInterval(() => {\n if (index >= challenges.length) {\n clearInterval(timer)\n return\n }\n if (flashing) return\n const sample = analyzer.analyze(video)\n if (!sample) return\n const hit = detector.feed(sample)\n face.setProgress(detector.progress)\n if (hit) {\n face.setState('done')\n showPrompt(true)\n flashing = true\n const to = setTimeout(() => {\n flashing = false\n advanceStep()\n }, 650)\n this.cleanups.push(() => clearTimeout(to))\n } else {\n face.setState(detector.progress > 0 ? 'good' : 'wait')\n }\n }, 160)\n this.timers.push(timer)\n })\n })\n .catch(() => {\n face.stage.classList.add('arkyc-hidden')\n if (requireLiveCamera) {\n // Mandatory live camera was denied — require a retry, don't fall back.\n prompt.textContent = 'Camera access is required to continue. Please allow access and try again.'\n return\n }\n this.handlers.onActiveLiveness(null, challenges)\n })\n\n if (allowSkip) {\n const skip = this.button('Skip (demo)', () => this.handlers.onActiveLiveness(null, challenges))\n skip.classList.add('arkyc-btn-ghost')\n this.footer.appendChild(skip)\n }\n }\n\n /**\n * Build the circular selfie/liveness preview overlay: an SVG progress ring, a\n * gesture-cue layer, and a success checkmark — driven via the returned handles.\n *\n * @param video\n * @returns\n */\n private buildFaceStage(video: HTMLVideoElement): FaceStage {\n const stage = this.el('div', { class: 'arkyc-stage' })\n stage.setAttribute('data-state', 'wait')\n stage.appendChild(video)\n\n const ring = this.el('div', {\n class: 'arkyc-ring',\n html: '<svg viewBox=\"0 0 100 100\"><circle class=\"arkyc-ring-track\" cx=\"50\" cy=\"50\" r=\"46\"/><circle class=\"arkyc-ring-arc\" cx=\"50\" cy=\"50\" r=\"46\"/></svg>',\n })\n stage.appendChild(ring)\n const cue = this.el('div', { class: 'arkyc-cue' })\n stage.appendChild(cue)\n stage.appendChild(this.el('div', { class: 'arkyc-check', html: CHECK_ICON }))\n\n const arc = ring.querySelector('.arkyc-ring-arc') as SVGCircleElement | null\n const circumference = 2 * Math.PI * 46\n if (arc) {\n arc.style.strokeDasharray = String(circumference)\n arc.style.strokeDashoffset = String(circumference)\n }\n\n return {\n stage,\n setProgress: (p) => {\n if (arc) arc.style.strokeDashoffset = String(circumference * (1 - Math.max(0, Math.min(1, p))))\n },\n setState: (state) => stage.setAttribute('data-state', state),\n setCue: (challenge) => {\n cue.className = 'arkyc-cue' + (challenge ? ` show arkyc-cue-${challenge}` : '')\n cue.innerHTML = challenge ? CUE_ICONS[challenge] : ''\n },\n }\n }\n\n /**\n * Build the liveness step-progress dots (one per challenge).\n *\n * @param video\n * @param hint\n * @param doc\n */\n private buildDots(count: number): StepDots {\n const el = this.el('div', { class: 'arkyc-dots' })\n const dots: HTMLElement[] = []\n for (let i = 0; i < count; i += 1) {\n const dot = this.el('div', { class: 'arkyc-dot' })\n dots.push(dot)\n el.appendChild(dot)\n }\n return {\n el,\n setActive: (index) =>\n dots.forEach((d, i) => d.classList.toggle('active', i === index && !d.classList.contains('done'))),\n markDone: (index) => {\n const d = dots[index]\n if (d) {\n d.classList.remove('active')\n d.classList.add('done')\n }\n },\n }\n }\n\n /**\n * Build the document preview overlay: a fixed card-shaped alignment guide\n * (corner brackets + border) with an animated scan line. The guide is a target,\n * not a tracker — it stays put so the user aligns the card to it; detection only\n * tints it for quality and brightens it once a document is in view.\n *\n * @param video\n * @returns\n */\n private buildDocStage(video: HTMLVideoElement): DocStage {\n const stage = this.el('div', { class: 'arkyc-doc' })\n stage.setAttribute('data-q', 'wait')\n stage.appendChild(video)\n const frame = this.el('div', { class: 'arkyc-doc-frame' })\n for (const corner of ['tl', 'tr', 'bl', 'br']) {\n frame.appendChild(this.el('span', { class: `arkyc-corner ${corner}` }))\n }\n frame.appendChild(this.el('div', { class: 'arkyc-scan' }))\n stage.appendChild(frame)\n return {\n stage,\n setQuality: (quality) => stage.setAttribute('data-q', quality),\n // The guide never moves; a detected document only brightens it as feedback.\n setFrame: (rect) => stage.setAttribute('data-detected', rect ? 'true' : 'false'),\n }\n }\n\n private renderProcessing(label: string): void {\n this.body.appendChild(this.el('div', { class: 'arkyc-spinner' }))\n this.body.appendChild(this.el('p', { class: 'arkyc-p', text: label }))\n }\n\n private renderResult(\n decision: VerificationDecision | null,\n errorMessage?: string,\n opts: { terminal?: boolean; status?: VerificationStatus } = {},\n ): void {\n if (errorMessage) {\n this.body.appendChild(this.el('div', { class: 'arkyc-badge err', html: '!' }))\n this.body.appendChild(this.el('h2', { class: 'arkyc-h', text: 'Something went wrong' }))\n this.body.appendChild(this.el('p', { class: 'arkyc-p', text: errorMessage }))\n } else if (opts.terminal) {\n // The session was already finished/expired when this device opened it (e.g.\n // a stale handoff link). Show a notice, not the live result — and only Close.\n const n = TERMINAL_NOTICE[opts.status ?? 'expired'] ?? EXPIRED_NOTICE\n this.body.appendChild(this.el('div', { class: `arkyc-badge ${n.cls}`, text: n.icon }))\n this.body.appendChild(this.el('h2', { class: 'arkyc-h', text: n.title }))\n this.body.appendChild(this.el('p', { class: 'arkyc-p', text: n.copy }))\n this.footer.appendChild(this.button('Close', () => this.handlers.onClose()))\n return\n } else {\n const map = {\n approved: {\n cls: 'ok',\n icon: '✓',\n title: 'Verified',\n copy: 'Your identity has been verified.',\n },\n requires_review: {\n cls: 'warn',\n icon: '⏳',\n title: 'Under review',\n copy: 'Your verification is being reviewed. We will be in touch shortly.',\n },\n rejected: {\n cls: 'err',\n icon: '✕',\n title: 'Not verified',\n copy: 'We could not verify your identity. Please try again.',\n },\n } as const\n const r = map[decision ?? 'requires_review'] ?? map.requires_review\n this.body.appendChild(this.el('div', { class: `arkyc-badge ${r.cls}`, text: r.icon }))\n this.body.appendChild(this.el('h2', { class: 'arkyc-h', text: r.title }))\n this.body.appendChild(this.el('p', { class: 'arkyc-p', text: r.copy }))\n }\n this.footer.appendChild(this.button('Done', () => this.handlers.onAcknowledge()))\n }\n\n private button(label: string, onClick: () => void, extraClass?: string): HTMLButtonElement {\n const cls = extraClass ? `arkyc-btn ${extraClass}` : 'arkyc-btn'\n const btn = this.el('button', { class: cls, text: label }) as HTMLButtonElement\n // Guard against accidental double-clicks: a button fires once, then disables\n // and shows an inline loader while its (usually async) handler runs. The next\n // screen re-renders a fresh button, so this only spans the in-flight gap.\n let fired = false\n btn.addEventListener('click', () => {\n if (fired) return\n fired = true\n btn.setAttribute('disabled', 'true')\n btn.classList.add('arkyc-busy')\n onClick()\n })\n return btn\n }\n\n private clear(node: HTMLElement): void {\n while (node.firstChild) node.removeChild(node.firstChild)\n }\n\n private el<T extends HTMLElement = HTMLElement>(tag: string, props: ElProps = {}): T {\n const node = this.doc.createElement(tag) as T\n for (const [key, value] of Object.entries(props)) {\n if (value == null) continue\n if (key === 'class') node.className = value\n else if (key === 'text') node.textContent = value\n else if (key === 'html') node.innerHTML = value\n else if (key === 'value' || key === 'src' || key === 'type' || key === 'accept' || key === 'placeholder') {\n ;(node as unknown as Record<string, string>)[key] = value\n } else node.setAttribute(key, value)\n }\n return node\n }\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arkyc/widget",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Embeddable, framework-agnostic Arkyc identity-verification widget",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.mjs",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.mts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.mts",
|
|
13
|
+
"import": "./dist/index.mjs"
|
|
14
|
+
},
|
|
15
|
+
"./standalone": "./dist/arkyc-widget.iife.global.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"qrcode-generator": "^1.4.4",
|
|
22
|
+
"@arkyc/types": "^1.0.0"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"firebase": "^11.0.0",
|
|
26
|
+
"pusher-js": "^8.0.0"
|
|
27
|
+
},
|
|
28
|
+
"peerDependenciesMeta": {
|
|
29
|
+
"firebase": {
|
|
30
|
+
"optional": true
|
|
31
|
+
},
|
|
32
|
+
"pusher-js": {
|
|
33
|
+
"optional": true
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build:standalone": "tsdown -c tsdown.iife.ts",
|
|
38
|
+
"typecheck": "tsc --noEmit",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"lint": "eslint src",
|
|
41
|
+
"clean": "rm -rf dist"
|
|
42
|
+
}
|
|
43
|
+
}
|