@facesmash/sdk 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 +236 -0
- package/dist/index.cjs +658 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +192 -0
- package/dist/index.d.ts +192 -0
- package/dist/index.js +621 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +1068 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +292 -0
- package/dist/react.d.ts +292 -0
- package/dist/react.js +1024 -0
- package/dist/react.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/detection.ts","../src/core/matching.ts","../src/core/types.ts","../src/core/client.ts","../src/index.ts","../src/react/FaceSmashProvider.tsx","../src/react/FaceLogin.tsx","../src/react/FaceRegister.tsx","../src/react/hooks.ts"],"names":["tf","faceapi","faceapi2","PocketBase","error","createContext","useRef","useState","useCallback","useEffect","jsx","useContext","result","Fragment","jsxs"],"mappings":"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","file":"react.cjs","sourcesContent":["import * as faceapi from '@vladmandic/face-api';\nimport type { ResolvedConfig, FaceAnalysis, HeadPose, FaceSizeCheck, LightingAnalysis, Point } from './types';\n\nlet modelsLoaded = false;\n\n// ─── Model Loading ──────────────────────────────────────────\n\nexport async function loadModels(\n config: ResolvedConfig,\n onProgress?: (progress: number) => void\n): Promise<boolean> {\n if (modelsLoaded) {\n onProgress?.(100);\n return true;\n }\n\n try {\n // Initialize TF.js backend (runtime APIs not fully typed)\n try {\n const tf = faceapi.tf as any;\n if (tf) {\n await tf.setBackend('webgl');\n await tf.ready();\n if (tf.env().flagRegistry?.CANVAS2D_WILL_READ_FREQUENTLY) {\n tf.env().set('CANVAS2D_WILL_READ_FREQUENTLY', true);\n }\n if (tf.env().flagRegistry?.WEBGL_EXP_CONV) {\n tf.env().set('WEBGL_EXP_CONV', true);\n }\n if (config.debug) {\n console.log(`[FaceSmash] TF.js backend: ${tf.getBackend()}`);\n }\n }\n } catch {\n // Non-fatal: webgl may not be available\n }\n\n onProgress?.(10);\n\n // Load models in parallel\n await Promise.all([\n faceapi.nets.ssdMobilenetv1.loadFromUri(config.modelUrl),\n faceapi.nets.tinyFaceDetector.loadFromUri(config.modelUrl),\n faceapi.nets.faceLandmark68Net.loadFromUri(config.modelUrl),\n faceapi.nets.faceRecognitionNet.loadFromUri(config.modelUrl),\n faceapi.nets.faceExpressionNet.loadFromUri(config.modelUrl),\n ]);\n\n modelsLoaded = true;\n onProgress?.(100);\n\n if (config.debug) {\n console.log('[FaceSmash] Models loaded successfully');\n }\n\n return true;\n } catch (error) {\n if (config.debug) {\n console.error('[FaceSmash] Failed to load models:', error);\n }\n return false;\n }\n}\n\nexport function areModelsLoaded(): boolean {\n return modelsLoaded;\n}\n\n// ─── Detection Options ──────────────────────────────────────\n\nexport function getSsdOptions(minConfidence: number) {\n return new faceapi.SsdMobilenetv1Options({ minConfidence });\n}\n\nexport function getTinyOptions() {\n return new faceapi.TinyFaceDetectorOptions({ inputSize: 224, scoreThreshold: 0.4 });\n}\n\n// ─── Face Descriptor Extraction ─────────────────────────────\n\nexport async function extractDescriptor(\n input: string | HTMLVideoElement | HTMLCanvasElement | HTMLImageElement,\n config: ResolvedConfig\n): Promise<Float32Array | null> {\n try {\n const media = typeof input === 'string' ? await faceapi.fetchImage(input) : input;\n\n // SSD primary\n let detection = await faceapi\n .detectSingleFace(media, getSsdOptions(config.minDetectionConfidence))\n .withFaceLandmarks()\n .withFaceDescriptor();\n\n // Tiny fallback\n if (!detection) {\n detection = await faceapi\n .detectSingleFace(media, getTinyOptions())\n .withFaceLandmarks()\n .withFaceDescriptor();\n }\n\n return detection?.descriptor ?? null;\n } catch (error) {\n if (config.debug) {\n console.error('[FaceSmash] Descriptor extraction failed:', error);\n }\n return null;\n }\n}\n\n// ─── Full Face Quality Analysis ─────────────────────────────\n\nexport async function analyzeFace(\n imageData: string,\n config: ResolvedConfig\n): Promise<FaceAnalysis | null> {\n try {\n const img = await faceapi.fetchImage(imageData);\n\n let detection = await faceapi\n .detectSingleFace(img, getSsdOptions(config.minDetectionConfidence))\n .withFaceLandmarks()\n .withFaceDescriptor();\n\n if (!detection) {\n detection = await faceapi\n .detectSingleFace(img, getTinyOptions())\n .withFaceLandmarks()\n .withFaceDescriptor();\n }\n\n if (!detection) return null;\n\n const headPose = estimateHeadPose(detection.landmarks, detection.detection.box);\n const imgWidth = img.width || 640;\n const imgHeight = img.height || 480;\n const faceSizeCheck = validateFaceSize(detection.detection.box, imgWidth, imgHeight);\n\n if (!faceSizeCheck.isValid) {\n return {\n descriptor: detection.descriptor,\n normalizedDescriptor: normalizeDescriptor(detection.descriptor),\n confidence: detection.detection.score,\n qualityScore: 0,\n lightingScore: 0,\n headPose,\n faceSizeCheck,\n eyeAspectRatio: 0,\n rejectionReason: faceSizeCheck.reason,\n };\n }\n\n const { avgEAR } = getEyeAspectRatios(detection.landmarks);\n\n let lightingAnalysis: LightingAnalysis;\n try {\n lightingAnalysis = analyzeLighting(detection, img);\n } catch {\n lightingAnalysis = {\n score: 0.5, brightness: 0.5, contrast: 0.5, evenness: 0.5,\n conditions: { tooDark: false, tooBright: false, uneven: false, optimal: false },\n };\n }\n\n // Quality score calculation\n let qualityScore = Math.min(detection.detection.score, 1.0);\n qualityScore *= (0.7 + lightingAnalysis.score * 0.3);\n\n const faceArea = detection.detection.box.width * detection.detection.box.height;\n const imageArea = 640 * 640;\n const sizeRatio = Math.min(faceArea / imageArea, 0.3) / 0.3;\n qualityScore *= (0.8 + sizeRatio * 0.2);\n\n if (!headPose.isFrontal) {\n const anglePenalty = Math.max(0.5, 1 - (Math.abs(headPose.yaw) + Math.abs(headPose.pitch)) * 0.3);\n qualityScore *= anglePenalty;\n }\n\n qualityScore = Math.max(0, Math.min(1, qualityScore));\n\n return {\n descriptor: detection.descriptor,\n normalizedDescriptor: normalizeDescriptor(detection.descriptor),\n confidence: detection.detection.score,\n qualityScore,\n lightingScore: lightingAnalysis.score,\n headPose,\n faceSizeCheck,\n eyeAspectRatio: avgEAR,\n };\n } catch (error) {\n if (config.debug) {\n console.error('[FaceSmash] Face analysis failed:', error);\n }\n return null;\n }\n}\n\n// ─── Multi-Image Processing ─────────────────────────────────\n\nexport async function processImages(\n images: string[],\n config: ResolvedConfig\n): Promise<Float32Array | null> {\n if (images.length === 1) {\n return extractDescriptor(images[0], config);\n }\n\n const descriptors: Float32Array[] = [];\n for (const image of images) {\n const d = await extractDescriptor(image, config);\n if (d) descriptors.push(d);\n }\n\n if (descriptors.length === 0) return null;\n\n // Average descriptors\n const avg = new Float32Array(descriptors[0].length);\n for (let i = 0; i < avg.length; i++) {\n let sum = 0;\n for (const d of descriptors) sum += d[i];\n avg[i] = sum / descriptors.length;\n }\n\n return avg;\n}\n\n// ─── Helpers ────────────────────────────────────────────────\n\nfunction euclidean(a: Point, b: Point): number {\n return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);\n}\n\nfunction calculateEAR(eye: Point[]): number {\n if (eye.length < 6) return 0.3;\n const v1 = euclidean(eye[1], eye[5]);\n const v2 = euclidean(eye[2], eye[4]);\n const h = euclidean(eye[0], eye[3]);\n return h === 0 ? 0 : (v1 + v2) / (2 * h);\n}\n\nfunction getEyeAspectRatios(landmarks: faceapi.FaceLandmarks68) {\n const leftEAR = calculateEAR(landmarks.getLeftEye());\n const rightEAR = calculateEAR(landmarks.getRightEye());\n return { leftEAR, rightEAR, avgEAR: (leftEAR + rightEAR) / 2 };\n}\n\nexport function estimateHeadPose(landmarks: faceapi.FaceLandmarks68, box: faceapi.Box): HeadPose {\n const nose = landmarks.getNose();\n const jaw = landmarks.getJawOutline();\n const noseTip = nose[3];\n const faceCenterX = box.x + box.width / 2;\n const faceCenterY = box.y + box.height / 2;\n const yaw = (noseTip.x - faceCenterX) / (box.width / 2);\n const pitch = (noseTip.y - faceCenterY) / (box.height / 2);\n const jawLeft = jaw[0];\n const jawRight = jaw[jaw.length - 1];\n const roll = Math.atan2(jawRight.y - jawLeft.y, jawRight.x - jawLeft.x);\n const isFrontal = Math.abs(yaw) < 0.35 && Math.abs(pitch) < 0.4 && Math.abs(roll) < 0.25;\n return { yaw, pitch, roll, isFrontal };\n}\n\nexport function validateFaceSize(\n box: faceapi.Box,\n frameWidth = 640,\n frameHeight = 480\n): FaceSizeCheck {\n const ratio = (box.width * box.height) / (frameWidth * frameHeight);\n if (ratio < 0.02) return { isValid: false, ratio, reason: 'Face too far from camera' };\n if (ratio > 0.65) return { isValid: false, ratio, reason: 'Face too close to camera' };\n if (box.width < 80 || box.height < 80) return { isValid: false, ratio, reason: 'Face too small for reliable recognition' };\n return { isValid: true, ratio };\n}\n\nexport function normalizeDescriptor(descriptor: Float32Array): Float32Array {\n let norm = 0;\n for (let i = 0; i < descriptor.length; i++) norm += descriptor[i] ** 2;\n norm = Math.sqrt(norm);\n if (norm === 0) return descriptor;\n const normalized = new Float32Array(descriptor.length);\n for (let i = 0; i < descriptor.length; i++) normalized[i] = descriptor[i] / norm;\n return normalized;\n}\n\nfunction analyzeLighting(\n detection: faceapi.WithFaceLandmarks<faceapi.WithFaceDescriptor<faceapi.WithFaceDetection<{ detection: faceapi.FaceDetection }>>>,\n imageElement: HTMLImageElement | HTMLCanvasElement\n): LightingAnalysis {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('Cannot get canvas context');\n\n canvas.width = imageElement.width || 640;\n canvas.height = imageElement.height || 640;\n\n if (imageElement instanceof HTMLImageElement) {\n ctx.drawImage(imageElement, 0, 0, canvas.width, canvas.height);\n } else {\n ctx.drawImage(imageElement, 0, 0);\n }\n\n const faceBox = detection.detection.box;\n const faceImageData = ctx.getImageData(\n Math.max(0, faceBox.x - 20),\n Math.max(0, faceBox.y - 20),\n Math.min(canvas.width - faceBox.x, faceBox.width + 40),\n Math.min(canvas.height - faceBox.y, faceBox.height + 40)\n );\n\n const pixels = faceImageData.data;\n let totalBrightness = 0;\n const brightnessValues: number[] = [];\n\n for (let i = 0; i < pixels.length; i += 4) {\n const brightness = (pixels[i] + pixels[i + 1] + pixels[i + 2]) / 3;\n totalBrightness += brightness;\n brightnessValues.push(brightness);\n }\n\n const avgBrightness = totalBrightness / (pixels.length / 4);\n const variance = brightnessValues.reduce((acc, val) => acc + (val - avgBrightness) ** 2, 0) / brightnessValues.length;\n const contrast = Math.sqrt(variance);\n const evenness = Math.max(0, 1 - contrast / 128);\n\n const tooDark = avgBrightness < 80;\n const tooBright = avgBrightness > 200;\n const uneven = evenness < 0.6;\n const optimal = !tooDark && !tooBright && !uneven;\n\n let score = 0.5;\n if (optimal) score = 0.9;\n else if (tooDark) score = Math.max(0.2, avgBrightness / 160);\n else if (tooBright) score = Math.max(0.2, (255 - avgBrightness) / 110);\n else if (uneven) score = Math.max(0.3, evenness);\n\n return {\n score,\n brightness: avgBrightness / 255,\n contrast: Math.min(contrast / 64, 1),\n evenness,\n conditions: { tooDark, tooBright, uneven, optimal },\n };\n}\n","import * as faceapi from '@vladmandic/face-api';\nimport type { MatchResult, MultiTemplateMatchResult, ResolvedConfig } from './types';\n\n/** Calculate cosine similarity between two face descriptors (1 - euclidean distance) */\nexport function calculateSimilarity(d1: Float32Array, d2: Float32Array): number {\n return 1 - faceapi.euclideanDistance(d1, d2);\n}\n\n/** Check if two face descriptors match */\nexport function facesMatch(\n d1: Float32Array,\n d2: Float32Array,\n threshold = 0.45\n): boolean {\n return calculateSimilarity(d1, d2) >= threshold;\n}\n\n/**\n * Enhanced face matching with adaptive threshold.\n * Adjusts threshold based on lighting conditions and user confidence boost.\n */\nexport function enhancedMatch(\n descriptor1: Float32Array,\n descriptor2: Float32Array,\n baseThreshold = 0.45,\n confidenceBoost = 0,\n lightingScore = 0.5\n): MatchResult {\n if (descriptor1.length !== descriptor2.length) {\n return { isMatch: false, similarity: 0, adaptedThreshold: baseThreshold };\n }\n\n const similarity = calculateSimilarity(descriptor1, descriptor2);\n\n let adaptedThreshold = baseThreshold;\n\n // More lenient in poor lighting\n if (lightingScore < 0.4) {\n adaptedThreshold = Math.max(0.35, adaptedThreshold - 0.05);\n } else if (lightingScore > 0.8) {\n adaptedThreshold = Math.min(0.6, adaptedThreshold + 0.02);\n }\n\n // Confidence boost for experienced users\n adaptedThreshold = Math.max(0.35, adaptedThreshold - confidenceBoost * 0.05);\n\n return {\n isMatch: similarity >= adaptedThreshold,\n similarity,\n adaptedThreshold,\n };\n}\n\n/** Match a face descriptor against multiple stored templates */\nexport function multiTemplateMatch(\n newDescriptor: Float32Array,\n templates: { descriptor: Float32Array; quality: number; weight: number }[],\n baseThreshold: number,\n lightingScore = 0.5\n): MultiTemplateMatchResult {\n if (templates.length === 0) {\n return { isMatch: false, bestSimilarity: 0, avgSimilarity: 0, matchCount: 0 };\n }\n\n let bestSimilarity = 0;\n let weightedSum = 0;\n let totalWeight = 0;\n let matchCount = 0;\n\n for (const template of templates) {\n if (!template.descriptor || template.descriptor.length === 0) continue;\n\n const result = enhancedMatch(\n newDescriptor,\n template.descriptor,\n baseThreshold,\n template.weight,\n lightingScore\n );\n\n if (result.similarity > bestSimilarity) {\n bestSimilarity = result.similarity;\n }\n\n const w = template.quality * template.weight;\n weightedSum += result.similarity * w;\n totalWeight += w;\n\n if (result.isMatch) matchCount++;\n }\n\n const avgSimilarity = totalWeight > 0 ? weightedSum / totalWeight : 0;\n const isMatch = bestSimilarity >= baseThreshold || (matchCount / templates.length) >= 0.6;\n\n return { isMatch, bestSimilarity, avgSimilarity, matchCount };\n}\n\n/** Calculate a learning weight based on scan quality */\nexport function calculateLearningWeight(\n qualityScore: number,\n lightingScore: number,\n confidence: number\n): number {\n let weight = 1.0;\n\n if (qualityScore > 0.8) weight *= 1.5;\n else if (qualityScore > 0.6) weight *= 1.2;\n else if (qualityScore < 0.4) weight *= 0.5;\n\n if (lightingScore > 0.7) weight *= 1.3;\n else if (lightingScore < 0.4) weight *= 0.7;\n\n if (confidence > 0.8) weight *= 1.2;\n else if (confidence < 0.5) weight *= 0.8;\n\n return Math.max(0.1, Math.min(weight, 3.0));\n}\n","/** Configuration for the FaceSmash client */\nexport interface FaceSmashConfig {\n /** PocketBase API URL (default: https://api.facesmash.app) */\n apiUrl?: string;\n /** URL to load face-api.js models from (default: jsdelivr CDN) */\n modelUrl?: string;\n /** Minimum confidence for SSD MobileNet face detection (default: 0.3) */\n minDetectionConfidence?: number;\n /** Similarity threshold for face matching (default: 0.45) */\n matchThreshold?: number;\n /** Minimum quality score to accept a face scan (default: 0.2) */\n minQualityScore?: number;\n /** Maximum face templates stored per user (default: 10) */\n maxTemplatesPerUser?: number;\n /** Enable debug logging (default: false) */\n debug?: boolean;\n}\n\n/** Resolved config with all defaults applied */\nexport interface ResolvedConfig {\n apiUrl: string;\n modelUrl: string;\n minDetectionConfidence: number;\n matchThreshold: number;\n minQualityScore: number;\n maxTemplatesPerUser: number;\n debug: boolean;\n}\n\nexport const DEFAULT_CONFIG: ResolvedConfig = {\n apiUrl: 'https://api.facesmash.app',\n modelUrl: 'https://cdn.jsdelivr.net/npm/@vladmandic/face-api/model',\n minDetectionConfidence: 0.3,\n matchThreshold: 0.45,\n minQualityScore: 0.2,\n maxTemplatesPerUser: 10,\n debug: false,\n};\n\nexport function resolveConfig(config?: FaceSmashConfig): ResolvedConfig {\n return { ...DEFAULT_CONFIG, ...config };\n}\n\n/** 2D point */\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** Head pose estimation */\nexport interface HeadPose {\n yaw: number;\n pitch: number;\n roll: number;\n isFrontal: boolean;\n}\n\n/** Face size validation result */\nexport interface FaceSizeCheck {\n isValid: boolean;\n ratio: number;\n reason?: string;\n}\n\n/** Lighting analysis */\nexport interface LightingAnalysis {\n score: number;\n brightness: number;\n contrast: number;\n evenness: number;\n conditions: {\n tooDark: boolean;\n tooBright: boolean;\n uneven: boolean;\n optimal: boolean;\n };\n}\n\n/** Full face analysis result */\nexport interface FaceAnalysis {\n descriptor: Float32Array;\n normalizedDescriptor: Float32Array;\n confidence: number;\n qualityScore: number;\n lightingScore: number;\n headPose: HeadPose;\n faceSizeCheck: FaceSizeCheck;\n eyeAspectRatio: number;\n rejectionReason?: string;\n}\n\n/** Face match result */\nexport interface MatchResult {\n isMatch: boolean;\n similarity: number;\n adaptedThreshold: number;\n}\n\n/** Multi-template match result */\nexport interface MultiTemplateMatchResult {\n isMatch: boolean;\n bestSimilarity: number;\n avgSimilarity: number;\n matchCount: number;\n}\n\n/** A stored face template */\nexport interface FaceTemplate {\n id: string;\n user_email: string;\n descriptor: number[];\n quality_score: number;\n created: string;\n}\n\n/** A user profile from PocketBase */\nexport interface UserProfile {\n id: string;\n name: string;\n email: string;\n face_embedding: number[];\n created: string;\n updated: string;\n}\n\n/** Login result */\nexport interface LoginResult {\n success: boolean;\n user?: UserProfile;\n similarity?: number;\n error?: string;\n}\n\n/** Registration result */\nexport interface RegisterResult {\n success: boolean;\n user?: UserProfile;\n error?: string;\n}\n\n/** Model loading progress callback */\nexport type OnProgress = (progress: number) => void;\n\n/** Event types emitted by the SDK */\nexport type FaceSmashEvent =\n | { type: 'models-loading'; progress: number }\n | { type: 'models-loaded' }\n | { type: 'models-error'; error: string }\n | { type: 'face-detected'; analysis: FaceAnalysis }\n | { type: 'face-lost' }\n | { type: 'login-start' }\n | { type: 'login-success'; user: UserProfile; similarity: number }\n | { type: 'login-failed'; error: string; bestSimilarity?: number }\n | { type: 'register-start' }\n | { type: 'register-success'; user: UserProfile }\n | { type: 'register-failed'; error: string };\n\nexport type FaceSmashEventListener = (event: FaceSmashEvent) => void;\n","import PocketBase from 'pocketbase';\nimport { loadModels, areModelsLoaded, analyzeFace, processImages } from './detection';\nimport { enhancedMatch, multiTemplateMatch, calculateLearningWeight } from './matching';\nimport type {\n FaceSmashConfig,\n ResolvedConfig,\n FaceSmashEvent,\n FaceSmashEventListener,\n FaceAnalysis,\n LoginResult,\n RegisterResult,\n UserProfile,\n OnProgress,\n} from './types';\nimport { resolveConfig } from './types';\n\nexport class FaceSmashClient {\n readonly config: ResolvedConfig;\n readonly pb: PocketBase;\n private listeners: FaceSmashEventListener[] = [];\n private _modelsLoaded = false;\n\n constructor(config?: FaceSmashConfig) {\n this.config = resolveConfig(config);\n this.pb = new PocketBase(this.config.apiUrl);\n this.pb.autoCancellation(false);\n }\n\n // ─── Event System ───────────────────────────────────────────\n\n on(listener: FaceSmashEventListener): () => void {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n private emit(event: FaceSmashEvent) {\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch {\n // Don't let listener errors break the SDK\n }\n }\n }\n\n // ─── Model Loading ──────────────────────────────────────────\n\n get isReady(): boolean {\n return this._modelsLoaded;\n }\n\n async init(onProgress?: OnProgress): Promise<boolean> {\n if (this._modelsLoaded) return true;\n\n this.emit({ type: 'models-loading', progress: 0 });\n\n const success = await loadModels(this.config, (progress) => {\n onProgress?.(progress);\n this.emit({ type: 'models-loading', progress });\n });\n\n if (success) {\n this._modelsLoaded = true;\n this.emit({ type: 'models-loaded' });\n } else {\n this.emit({ type: 'models-error', error: 'Failed to load face recognition models' });\n }\n\n return success;\n }\n\n // ─── Face Analysis ──────────────────────────────────────────\n\n async analyzeFace(imageData: string): Promise<FaceAnalysis | null> {\n this.ensureReady();\n const result = await analyzeFace(imageData, this.config);\n if (result) {\n this.emit({ type: 'face-detected', analysis: result });\n } else {\n this.emit({ type: 'face-lost' });\n }\n return result;\n }\n\n // ─── Login ──────────────────────────────────────────────────\n\n async login(images: string[]): Promise<LoginResult> {\n this.ensureReady();\n this.emit({ type: 'login-start' });\n\n try {\n // Analyze all images, pick the best\n let bestAnalysis: FaceAnalysis | null = null;\n for (const img of images) {\n const analysis = await analyzeFace(img, this.config);\n if (analysis && !analysis.rejectionReason) {\n if (!bestAnalysis || analysis.qualityScore > bestAnalysis.qualityScore) {\n bestAnalysis = analysis;\n }\n }\n }\n\n if (!bestAnalysis) {\n const error = 'No face detected in any image';\n this.emit({ type: 'login-failed', error });\n return { success: false, error };\n }\n\n if (bestAnalysis.qualityScore < this.config.minQualityScore) {\n const error = 'Face quality too low. Improve lighting and face the camera directly.';\n this.emit({ type: 'login-failed', error });\n return { success: false, error };\n }\n\n // Fetch all registered users\n const profiles = await this.pb.collection('user_profiles').getFullList();\n\n if (profiles.length === 0) {\n const error = 'No registered users found';\n this.emit({ type: 'login-failed', error });\n return { success: false, error };\n }\n\n let bestMatch = { user: null as UserProfile | null, similarity: 0 };\n\n for (const profile of profiles) {\n if (!profile.face_embedding) continue;\n\n const storedEmbedding = new Float32Array(profile.face_embedding as number[]);\n let matchResult = enhancedMatch(\n bestAnalysis.descriptor,\n storedEmbedding,\n this.config.matchThreshold,\n 0,\n bestAnalysis.lightingScore\n );\n\n // Try templates if available\n try {\n const templates = await this.pb.collection('face_templates').getList(1, 50, {\n filter: `user_email=\"${profile.email}\"`,\n sort: '-quality_score',\n });\n\n if (templates.items.length > 0) {\n const templateData = templates.items\n .filter((t: any) => t.descriptor && t.descriptor.length > 0)\n .map((t: any) => ({\n descriptor: new Float32Array(t.descriptor),\n quality: t.quality_score || 0.5,\n weight: 1,\n }));\n\n if (templateData.length > 0) {\n const multiResult = multiTemplateMatch(\n bestAnalysis.descriptor,\n templateData,\n this.config.matchThreshold,\n bestAnalysis.lightingScore\n );\n\n if (multiResult.bestSimilarity > matchResult.similarity) {\n matchResult = {\n isMatch: multiResult.isMatch,\n similarity: multiResult.bestSimilarity,\n adaptedThreshold: this.config.matchThreshold,\n };\n }\n }\n }\n } catch {\n // Template matching failed, use profile embedding result\n }\n\n const userProfile: UserProfile = {\n id: profile.id,\n name: profile.name as string,\n email: profile.email as string,\n face_embedding: profile.face_embedding as number[],\n created: profile.created as string,\n updated: profile.updated as string,\n };\n\n if (matchResult.similarity > bestMatch.similarity) {\n bestMatch = { user: userProfile, similarity: matchResult.similarity };\n }\n\n if (matchResult.isMatch) {\n // Store scan + update templates on successful login\n try {\n await this.storeLoginScan(userProfile, bestAnalysis);\n } catch {\n // Non-fatal\n }\n\n this.emit({\n type: 'login-success',\n user: userProfile,\n similarity: matchResult.similarity,\n });\n\n return { success: true, user: userProfile, similarity: matchResult.similarity };\n }\n }\n\n const error = bestMatch.similarity > 0.4\n ? 'Face partially matched but did not meet security threshold.'\n : 'Face not recognized.';\n\n this.emit({ type: 'login-failed', error, bestSimilarity: bestMatch.similarity });\n return { success: false, error, similarity: bestMatch.similarity };\n } catch (err) {\n const error = err instanceof Error ? err.message : 'Unknown error during login';\n this.emit({ type: 'login-failed', error });\n return { success: false, error };\n }\n }\n\n // ─── Registration ───────────────────────────────────────────\n\n async register(\n name: string,\n images: string[],\n email?: string\n ): Promise<RegisterResult> {\n this.ensureReady();\n this.emit({ type: 'register-start' });\n\n try {\n // Analyze best image\n let bestAnalysis: FaceAnalysis | null = null;\n let bestImageIdx = 0;\n\n for (let i = 0; i < images.length; i++) {\n const analysis = await analyzeFace(images[i], this.config);\n if (analysis && !analysis.rejectionReason) {\n if (!bestAnalysis || analysis.qualityScore > bestAnalysis.qualityScore) {\n bestAnalysis = analysis;\n bestImageIdx = i;\n }\n }\n }\n\n if (!bestAnalysis) {\n const error = 'No face detected in any image';\n this.emit({ type: 'register-failed', error });\n return { success: false, error };\n }\n\n if (bestAnalysis.qualityScore < this.config.minQualityScore) {\n const error = 'Face quality too low for registration.';\n this.emit({ type: 'register-failed', error });\n return { success: false, error };\n }\n\n // Check for duplicate users\n const existingProfiles = await this.pb.collection('user_profiles').getFullList();\n for (const profile of existingProfiles) {\n if (!profile.face_embedding) continue;\n const stored = new Float32Array(profile.face_embedding as number[]);\n if (stored.length !== bestAnalysis.descriptor.length) continue;\n const similarity = 1 - (await import('@vladmandic/face-api')).euclideanDistance(bestAnalysis.descriptor, stored);\n if (similarity >= 0.75) {\n const error = `This face is already registered to ${profile.name || profile.email}`;\n this.emit({ type: 'register-failed', error });\n return { success: false, error };\n }\n }\n\n // Create user profile\n const embeddingArray = Array.from(bestAnalysis.descriptor);\n const record = await this.pb.collection('user_profiles').create({\n name,\n email: email || `${name.toLowerCase().replace(/\\s+/g, '.')}@facesmash.app`,\n face_embedding: embeddingArray,\n });\n\n // Create initial face template\n await this.pb.collection('face_templates').create({\n user_email: record.email,\n descriptor: embeddingArray,\n quality_score: bestAnalysis.qualityScore,\n label: 'registration',\n });\n\n // Create face scan record\n await this.pb.collection('face_scans').create({\n user_email: record.email,\n face_embedding: JSON.stringify(embeddingArray),\n confidence: String(bestAnalysis.confidence),\n scan_type: 'registration',\n quality_score: String(bestAnalysis.qualityScore),\n });\n\n const user: UserProfile = {\n id: record.id,\n name: record.name as string,\n email: record.email as string,\n face_embedding: embeddingArray,\n created: record.created as string,\n updated: record.updated as string,\n };\n\n this.emit({ type: 'register-success', user });\n return { success: true, user };\n } catch (err) {\n const error = err instanceof Error ? err.message : 'Unknown error during registration';\n this.emit({ type: 'register-failed', error });\n return { success: false, error };\n }\n }\n\n // ─── Helpers ────────────────────────────────────────────────\n\n private ensureReady() {\n if (!areModelsLoaded()) {\n throw new Error(\n 'FaceSmash models not loaded. Call client.init() first.'\n );\n }\n }\n\n private async storeLoginScan(user: UserProfile, analysis: FaceAnalysis) {\n const embeddingArray = Array.from(analysis.descriptor);\n\n // Create sign-in log\n await this.pb.collection('sign_in_logs').create({\n user_email: user.email,\n success: true,\n });\n\n // Create face scan\n await this.pb.collection('face_scans').create({\n user_email: user.email,\n face_embedding: JSON.stringify(embeddingArray),\n confidence: String(analysis.confidence),\n scan_type: 'login',\n quality_score: String(analysis.qualityScore),\n });\n\n // Update user embedding with weighted average (adaptive learning)\n if (analysis.qualityScore > 0.5) {\n const weight = calculateLearningWeight(\n analysis.qualityScore,\n analysis.lightingScore,\n analysis.confidence\n );\n const learningRate = Math.min(weight * 0.1, 0.3);\n\n const current = new Float32Array(user.face_embedding);\n const updated = new Float32Array(current.length);\n for (let i = 0; i < current.length; i++) {\n updated[i] = current[i] * (1 - learningRate) + analysis.descriptor[i] * learningRate;\n }\n\n await this.pb.collection('user_profiles').update(user.id, {\n face_embedding: Array.from(updated),\n });\n }\n\n // Store template if quality is good\n if (analysis.qualityScore > 0.6) {\n const existing = await this.pb.collection('face_templates').getList(1, 50, {\n filter: `user_email=\"${user.email}\"`,\n sort: 'quality_score',\n });\n\n if (existing.items.length >= this.config.maxTemplatesPerUser) {\n await this.pb.collection('face_templates').delete(existing.items[0].id);\n }\n\n await this.pb.collection('face_templates').create({\n user_email: user.email,\n descriptor: embeddingArray,\n quality_score: analysis.qualityScore,\n label: 'auto',\n });\n }\n }\n}\n","// Core client\nimport { FaceSmashClient } from './core/client';\nexport { FaceSmashClient };\n\n// Detection utilities\nexport {\n loadModels,\n areModelsLoaded,\n extractDescriptor,\n analyzeFace,\n processImages,\n normalizeDescriptor,\n} from './core/detection';\n\n// Matching utilities\nexport {\n calculateSimilarity,\n facesMatch,\n enhancedMatch,\n multiTemplateMatch,\n calculateLearningWeight,\n} from './core/matching';\n\n// Types\nexport type {\n FaceSmashConfig,\n ResolvedConfig,\n FaceAnalysis,\n MatchResult,\n MultiTemplateMatchResult,\n LoginResult,\n RegisterResult,\n UserProfile,\n FaceTemplate,\n HeadPose,\n FaceSizeCheck,\n LightingAnalysis,\n OnProgress,\n FaceSmashEvent,\n FaceSmashEventListener,\n} from './core/types';\n\n// Convenience factory\nexport function createFaceSmash(config?: import('./core/types').FaceSmashConfig) {\n return new FaceSmashClient(config);\n}\n","import React, { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';\nimport type { ReactNode } from 'react';\nimport { FaceSmashClient } from '../core/client';\nimport type { FaceSmashConfig, FaceSmashEvent } from '../core/types';\n\ninterface FaceSmashContextValue {\n client: FaceSmashClient;\n isReady: boolean;\n isLoading: boolean;\n loadProgress: number;\n error: string | null;\n retryInit: () => void;\n}\n\nconst FaceSmashContext = createContext<FaceSmashContextValue | null>(null);\n\nexport interface FaceSmashProviderProps {\n children: ReactNode;\n /** SDK configuration */\n config?: FaceSmashConfig;\n /** Called when models finish loading */\n onReady?: () => void;\n /** Called on model loading error */\n onError?: (error: string) => void;\n /** Called for any SDK event */\n onEvent?: (event: FaceSmashEvent) => void;\n}\n\nexport function FaceSmashProvider({\n children,\n config,\n onReady,\n onError,\n onEvent,\n}: FaceSmashProviderProps) {\n const clientRef = useRef<FaceSmashClient | null>(null);\n if (!clientRef.current) {\n clientRef.current = new FaceSmashClient(config);\n }\n const client = clientRef.current;\n\n const [isReady, setIsReady] = useState(false);\n const [isLoading, setIsLoading] = useState(true);\n const [loadProgress, setLoadProgress] = useState(0);\n const [error, setError] = useState<string | null>(null);\n\n const initModels = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n setLoadProgress(0);\n\n const success = await client.init((progress) => {\n setLoadProgress(progress);\n });\n\n if (success) {\n setIsReady(true);\n setIsLoading(false);\n onReady?.();\n } else {\n const msg = 'Failed to load face recognition models';\n setError(msg);\n setIsLoading(false);\n onError?.(msg);\n }\n }, [client, onReady, onError]);\n\n useEffect(() => {\n initModels();\n }, [initModels]);\n\n // Forward events\n useEffect(() => {\n if (!onEvent) return;\n return client.on(onEvent);\n }, [client, onEvent]);\n\n const retryInit = useCallback(() => {\n initModels();\n }, [initModels]);\n\n return (\n <FaceSmashContext.Provider\n value={{ client, isReady, isLoading, loadProgress, error, retryInit }}\n >\n {children}\n </FaceSmashContext.Provider>\n );\n}\n\nexport function useFaceSmash(): FaceSmashContextValue {\n const ctx = useContext(FaceSmashContext);\n if (!ctx) {\n throw new Error('useFaceSmash must be used within a <FaceSmashProvider>');\n }\n return ctx;\n}\n","import React, { useRef, useState, useEffect, useCallback } from 'react';\nimport { useFaceSmash } from './FaceSmashProvider';\nimport type { LoginResult } from '../core/types';\n\nexport interface FaceLoginProps {\n /** Called with the login result when authentication completes */\n onResult: (result: LoginResult) => void;\n /** Number of images to capture for matching (default: 3) */\n captureCount?: number;\n /** Delay between captures in ms (default: 500) */\n captureDelay?: number;\n /** Auto-start scanning when component mounts (default: true) */\n autoStart?: boolean;\n /** Custom className for the container */\n className?: string;\n /** Custom overlay content rendered on top of the video */\n overlay?: React.ReactNode;\n /** Custom loading content */\n loadingContent?: React.ReactNode;\n /** Custom error content */\n errorContent?: (error: string, retry: () => void) => React.ReactNode;\n}\n\n/**\n * Drop-in face login component.\n * Renders a webcam feed, auto-detects a face, captures images, and authenticates.\n */\nexport function FaceLogin({\n onResult,\n captureCount = 3,\n captureDelay = 500,\n autoStart = true,\n className,\n overlay,\n loadingContent,\n errorContent,\n}: FaceLoginProps) {\n const { client, isReady, isLoading, error: initError } = useFaceSmash();\n const videoRef = useRef<HTMLVideoElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const streamRef = useRef<MediaStream | null>(null);\n\n const [cameraError, setCameraError] = useState<string | null>(null);\n const [isScanning, setIsScanning] = useState(false);\n const [status, setStatus] = useState<'loading' | 'ready' | 'scanning' | 'done' | 'error'>('loading');\n\n // Start camera\n const startCamera = useCallback(async () => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n video: { width: 640, height: 480, facingMode: 'user' },\n });\n streamRef.current = stream;\n if (videoRef.current) {\n videoRef.current.srcObject = stream;\n await videoRef.current.play();\n }\n setCameraError(null);\n } catch {\n setCameraError('Camera access denied or not available');\n setStatus('error');\n }\n }, []);\n\n // Stop camera\n const stopCamera = useCallback(() => {\n streamRef.current?.getTracks().forEach((t) => t.stop());\n streamRef.current = null;\n }, []);\n\n // Capture a frame as base64\n const captureFrame = useCallback((): string | null => {\n const video = videoRef.current;\n const canvas = canvasRef.current;\n if (!video || !canvas) return null;\n\n canvas.width = video.videoWidth || 640;\n canvas.height = video.videoHeight || 480;\n const ctx = canvas.getContext('2d');\n if (!ctx) return null;\n\n ctx.drawImage(video, 0, 0);\n return canvas.toDataURL('image/jpeg', 0.9);\n }, []);\n\n // Scan and authenticate\n const scan = useCallback(async () => {\n if (!isReady || isScanning) return;\n setIsScanning(true);\n setStatus('scanning');\n\n const images: string[] = [];\n for (let i = 0; i < captureCount; i++) {\n const frame = captureFrame();\n if (frame) images.push(frame);\n if (i < captureCount - 1) {\n await new Promise((r) => setTimeout(r, captureDelay));\n }\n }\n\n if (images.length === 0) {\n const result: LoginResult = { success: false, error: 'Failed to capture images from camera' };\n onResult(result);\n setIsScanning(false);\n setStatus('error');\n return;\n }\n\n const result = await client.login(images);\n onResult(result);\n setIsScanning(false);\n setStatus('done');\n }, [isReady, isScanning, captureCount, captureDelay, captureFrame, client, onResult]);\n\n // Initialize\n useEffect(() => {\n if (isReady) {\n startCamera();\n setStatus('ready');\n }\n return () => stopCamera();\n }, [isReady, startCamera, stopCamera]);\n\n // Auto-start scanning once camera is ready\n useEffect(() => {\n if (autoStart && status === 'ready' && !isScanning) {\n const timer = setTimeout(scan, 2000); // 2s delay to let user position face\n return () => clearTimeout(timer);\n }\n }, [autoStart, status, isScanning, scan]);\n\n const retry = useCallback(() => {\n setCameraError(null);\n setStatus('loading');\n startCamera().then(() => setStatus('ready'));\n }, [startCamera]);\n\n // Render\n const displayError = cameraError || initError;\n\n if (displayError && errorContent) {\n return <>{errorContent(displayError, retry)}</>;\n }\n\n if (isLoading && loadingContent) {\n return <>{loadingContent}</>;\n }\n\n return (\n <div className={className} style={{ position: 'relative' }}>\n <video\n ref={videoRef}\n autoPlay\n playsInline\n muted\n style={{\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n transform: 'scaleX(-1)',\n }}\n />\n <canvas ref={canvasRef} style={{ display: 'none' }} />\n {overlay}\n {displayError && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'rgba(0,0,0,0.8)',\n color: 'white',\n padding: '1rem',\n textAlign: 'center',\n }}\n >\n <div>\n <p>{displayError}</p>\n <button onClick={retry} style={{ marginTop: '0.5rem', cursor: 'pointer' }}>\n Retry\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n","import React, { useRef, useState, useEffect, useCallback } from 'react';\nimport { useFaceSmash } from './FaceSmashProvider';\nimport type { RegisterResult } from '../core/types';\n\nexport interface FaceRegisterProps {\n /** User's display name */\n name: string;\n /** Optional email */\n email?: string;\n /** Called with the registration result */\n onResult: (result: RegisterResult) => void;\n /** Number of images to capture (default: 3) */\n captureCount?: number;\n /** Delay between captures in ms (default: 500) */\n captureDelay?: number;\n /** Auto-start when component mounts (default: true) */\n autoStart?: boolean;\n /** Custom className for the container */\n className?: string;\n /** Custom overlay */\n overlay?: React.ReactNode;\n /** Custom loading content */\n loadingContent?: React.ReactNode;\n /** Custom error content */\n errorContent?: (error: string, retry: () => void) => React.ReactNode;\n}\n\n/**\n * Drop-in face registration component.\n * Renders a webcam feed, captures face images, and registers a new user.\n */\nexport function FaceRegister({\n name,\n email,\n onResult,\n captureCount = 3,\n captureDelay = 500,\n autoStart = true,\n className,\n overlay,\n loadingContent,\n errorContent,\n}: FaceRegisterProps) {\n const { client, isReady, isLoading, error: initError } = useFaceSmash();\n const videoRef = useRef<HTMLVideoElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const streamRef = useRef<MediaStream | null>(null);\n\n const [cameraError, setCameraError] = useState<string | null>(null);\n const [isCapturing, setIsCapturing] = useState(false);\n const [status, setStatus] = useState<'loading' | 'ready' | 'capturing' | 'done' | 'error'>('loading');\n\n const startCamera = useCallback(async () => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n video: { width: 640, height: 480, facingMode: 'user' },\n });\n streamRef.current = stream;\n if (videoRef.current) {\n videoRef.current.srcObject = stream;\n await videoRef.current.play();\n }\n setCameraError(null);\n } catch {\n setCameraError('Camera access denied or not available');\n setStatus('error');\n }\n }, []);\n\n const stopCamera = useCallback(() => {\n streamRef.current?.getTracks().forEach((t) => t.stop());\n streamRef.current = null;\n }, []);\n\n const captureFrame = useCallback((): string | null => {\n const video = videoRef.current;\n const canvas = canvasRef.current;\n if (!video || !canvas) return null;\n\n canvas.width = video.videoWidth || 640;\n canvas.height = video.videoHeight || 480;\n const ctx = canvas.getContext('2d');\n if (!ctx) return null;\n\n ctx.drawImage(video, 0, 0);\n return canvas.toDataURL('image/jpeg', 0.9);\n }, []);\n\n const capture = useCallback(async () => {\n if (!isReady || isCapturing) return;\n setIsCapturing(true);\n setStatus('capturing');\n\n const images: string[] = [];\n for (let i = 0; i < captureCount; i++) {\n const frame = captureFrame();\n if (frame) images.push(frame);\n if (i < captureCount - 1) {\n await new Promise((r) => setTimeout(r, captureDelay));\n }\n }\n\n if (images.length === 0) {\n const result: RegisterResult = { success: false, error: 'Failed to capture images' };\n onResult(result);\n setIsCapturing(false);\n setStatus('error');\n return;\n }\n\n const result = await client.register(name, images, email);\n onResult(result);\n setIsCapturing(false);\n setStatus('done');\n }, [isReady, isCapturing, captureCount, captureDelay, captureFrame, client, name, email, onResult]);\n\n useEffect(() => {\n if (isReady) {\n startCamera();\n setStatus('ready');\n }\n return () => stopCamera();\n }, [isReady, startCamera, stopCamera]);\n\n useEffect(() => {\n if (autoStart && status === 'ready' && !isCapturing) {\n const timer = setTimeout(capture, 2000);\n return () => clearTimeout(timer);\n }\n }, [autoStart, status, isCapturing, capture]);\n\n const retry = useCallback(() => {\n setCameraError(null);\n setStatus('loading');\n startCamera().then(() => setStatus('ready'));\n }, [startCamera]);\n\n const displayError = cameraError || initError;\n\n if (displayError && errorContent) {\n return <>{errorContent(displayError, retry)}</>;\n }\n\n if (isLoading && loadingContent) {\n return <>{loadingContent}</>;\n }\n\n return (\n <div className={className} style={{ position: 'relative' }}>\n <video\n ref={videoRef}\n autoPlay\n playsInline\n muted\n style={{\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n transform: 'scaleX(-1)',\n }}\n />\n <canvas ref={canvasRef} style={{ display: 'none' }} />\n {overlay}\n {displayError && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'rgba(0,0,0,0.8)',\n color: 'white',\n padding: '1rem',\n textAlign: 'center',\n }}\n >\n <div>\n <p>{displayError}</p>\n <button onClick={retry} style={{ marginTop: '0.5rem', cursor: 'pointer' }}>\n Retry\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n","import { useState, useCallback } from 'react';\nimport { useFaceSmash } from './FaceSmashProvider';\nimport type { LoginResult, RegisterResult, FaceAnalysis } from '../core/types';\n\n/** Hook for face login flow */\nexport function useFaceLogin() {\n const { client, isReady } = useFaceSmash();\n const [isScanning, setIsScanning] = useState(false);\n const [result, setResult] = useState<LoginResult | null>(null);\n\n const login = useCallback(\n async (images: string[]): Promise<LoginResult> => {\n if (!isReady) {\n return { success: false, error: 'Models not loaded yet' };\n }\n setIsScanning(true);\n setResult(null);\n\n const loginResult = await client.login(images);\n setResult(loginResult);\n setIsScanning(false);\n return loginResult;\n },\n [client, isReady]\n );\n\n const reset = useCallback(() => {\n setIsScanning(false);\n setResult(null);\n }, []);\n\n return { login, isScanning, result, reset, isReady };\n}\n\n/** Hook for face registration flow */\nexport function useFaceRegister() {\n const { client, isReady } = useFaceSmash();\n const [isRegistering, setIsRegistering] = useState(false);\n const [result, setResult] = useState<RegisterResult | null>(null);\n\n const register = useCallback(\n async (name: string, images: string[], email?: string): Promise<RegisterResult> => {\n if (!isReady) {\n return { success: false, error: 'Models not loaded yet' };\n }\n setIsRegistering(true);\n setResult(null);\n\n const regResult = await client.register(name, images, email);\n setResult(regResult);\n setIsRegistering(false);\n return regResult;\n },\n [client, isReady]\n );\n\n const reset = useCallback(() => {\n setIsRegistering(false);\n setResult(null);\n }, []);\n\n return { register, isRegistering, result, reset, isReady };\n}\n\n/** Hook for face analysis (quality scoring, detection) */\nexport function useFaceAnalysis() {\n const { client, isReady } = useFaceSmash();\n const [analysis, setAnalysis] = useState<FaceAnalysis | null>(null);\n const [isAnalyzing, setIsAnalyzing] = useState(false);\n\n const analyze = useCallback(\n async (imageData: string): Promise<FaceAnalysis | null> => {\n if (!isReady) return null;\n setIsAnalyzing(true);\n const result = await client.analyzeFace(imageData);\n setAnalysis(result);\n setIsAnalyzing(false);\n return result;\n },\n [client, isReady]\n );\n\n return { analyze, analysis, isAnalyzing, isReady };\n}\n"]}
|
package/dist/react.d.cts
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import PocketBase from 'pocketbase';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import React, { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
/** Configuration for the FaceSmash client */
|
|
6
|
+
interface FaceSmashConfig {
|
|
7
|
+
/** PocketBase API URL (default: https://api.facesmash.app) */
|
|
8
|
+
apiUrl?: string;
|
|
9
|
+
/** URL to load face-api.js models from (default: jsdelivr CDN) */
|
|
10
|
+
modelUrl?: string;
|
|
11
|
+
/** Minimum confidence for SSD MobileNet face detection (default: 0.3) */
|
|
12
|
+
minDetectionConfidence?: number;
|
|
13
|
+
/** Similarity threshold for face matching (default: 0.45) */
|
|
14
|
+
matchThreshold?: number;
|
|
15
|
+
/** Minimum quality score to accept a face scan (default: 0.2) */
|
|
16
|
+
minQualityScore?: number;
|
|
17
|
+
/** Maximum face templates stored per user (default: 10) */
|
|
18
|
+
maxTemplatesPerUser?: number;
|
|
19
|
+
/** Enable debug logging (default: false) */
|
|
20
|
+
debug?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/** Resolved config with all defaults applied */
|
|
23
|
+
interface ResolvedConfig {
|
|
24
|
+
apiUrl: string;
|
|
25
|
+
modelUrl: string;
|
|
26
|
+
minDetectionConfidence: number;
|
|
27
|
+
matchThreshold: number;
|
|
28
|
+
minQualityScore: number;
|
|
29
|
+
maxTemplatesPerUser: number;
|
|
30
|
+
debug: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** Head pose estimation */
|
|
33
|
+
interface HeadPose {
|
|
34
|
+
yaw: number;
|
|
35
|
+
pitch: number;
|
|
36
|
+
roll: number;
|
|
37
|
+
isFrontal: boolean;
|
|
38
|
+
}
|
|
39
|
+
/** Face size validation result */
|
|
40
|
+
interface FaceSizeCheck {
|
|
41
|
+
isValid: boolean;
|
|
42
|
+
ratio: number;
|
|
43
|
+
reason?: string;
|
|
44
|
+
}
|
|
45
|
+
/** Lighting analysis */
|
|
46
|
+
interface LightingAnalysis {
|
|
47
|
+
score: number;
|
|
48
|
+
brightness: number;
|
|
49
|
+
contrast: number;
|
|
50
|
+
evenness: number;
|
|
51
|
+
conditions: {
|
|
52
|
+
tooDark: boolean;
|
|
53
|
+
tooBright: boolean;
|
|
54
|
+
uneven: boolean;
|
|
55
|
+
optimal: boolean;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** Full face analysis result */
|
|
59
|
+
interface FaceAnalysis {
|
|
60
|
+
descriptor: Float32Array;
|
|
61
|
+
normalizedDescriptor: Float32Array;
|
|
62
|
+
confidence: number;
|
|
63
|
+
qualityScore: number;
|
|
64
|
+
lightingScore: number;
|
|
65
|
+
headPose: HeadPose;
|
|
66
|
+
faceSizeCheck: FaceSizeCheck;
|
|
67
|
+
eyeAspectRatio: number;
|
|
68
|
+
rejectionReason?: string;
|
|
69
|
+
}
|
|
70
|
+
/** Face match result */
|
|
71
|
+
interface MatchResult {
|
|
72
|
+
isMatch: boolean;
|
|
73
|
+
similarity: number;
|
|
74
|
+
adaptedThreshold: number;
|
|
75
|
+
}
|
|
76
|
+
/** Multi-template match result */
|
|
77
|
+
interface MultiTemplateMatchResult {
|
|
78
|
+
isMatch: boolean;
|
|
79
|
+
bestSimilarity: number;
|
|
80
|
+
avgSimilarity: number;
|
|
81
|
+
matchCount: number;
|
|
82
|
+
}
|
|
83
|
+
/** A stored face template */
|
|
84
|
+
interface FaceTemplate {
|
|
85
|
+
id: string;
|
|
86
|
+
user_email: string;
|
|
87
|
+
descriptor: number[];
|
|
88
|
+
quality_score: number;
|
|
89
|
+
created: string;
|
|
90
|
+
}
|
|
91
|
+
/** A user profile from PocketBase */
|
|
92
|
+
interface UserProfile {
|
|
93
|
+
id: string;
|
|
94
|
+
name: string;
|
|
95
|
+
email: string;
|
|
96
|
+
face_embedding: number[];
|
|
97
|
+
created: string;
|
|
98
|
+
updated: string;
|
|
99
|
+
}
|
|
100
|
+
/** Login result */
|
|
101
|
+
interface LoginResult {
|
|
102
|
+
success: boolean;
|
|
103
|
+
user?: UserProfile;
|
|
104
|
+
similarity?: number;
|
|
105
|
+
error?: string;
|
|
106
|
+
}
|
|
107
|
+
/** Registration result */
|
|
108
|
+
interface RegisterResult {
|
|
109
|
+
success: boolean;
|
|
110
|
+
user?: UserProfile;
|
|
111
|
+
error?: string;
|
|
112
|
+
}
|
|
113
|
+
/** Model loading progress callback */
|
|
114
|
+
type OnProgress = (progress: number) => void;
|
|
115
|
+
/** Event types emitted by the SDK */
|
|
116
|
+
type FaceSmashEvent = {
|
|
117
|
+
type: 'models-loading';
|
|
118
|
+
progress: number;
|
|
119
|
+
} | {
|
|
120
|
+
type: 'models-loaded';
|
|
121
|
+
} | {
|
|
122
|
+
type: 'models-error';
|
|
123
|
+
error: string;
|
|
124
|
+
} | {
|
|
125
|
+
type: 'face-detected';
|
|
126
|
+
analysis: FaceAnalysis;
|
|
127
|
+
} | {
|
|
128
|
+
type: 'face-lost';
|
|
129
|
+
} | {
|
|
130
|
+
type: 'login-start';
|
|
131
|
+
} | {
|
|
132
|
+
type: 'login-success';
|
|
133
|
+
user: UserProfile;
|
|
134
|
+
similarity: number;
|
|
135
|
+
} | {
|
|
136
|
+
type: 'login-failed';
|
|
137
|
+
error: string;
|
|
138
|
+
bestSimilarity?: number;
|
|
139
|
+
} | {
|
|
140
|
+
type: 'register-start';
|
|
141
|
+
} | {
|
|
142
|
+
type: 'register-success';
|
|
143
|
+
user: UserProfile;
|
|
144
|
+
} | {
|
|
145
|
+
type: 'register-failed';
|
|
146
|
+
error: string;
|
|
147
|
+
};
|
|
148
|
+
type FaceSmashEventListener = (event: FaceSmashEvent) => void;
|
|
149
|
+
|
|
150
|
+
declare class FaceSmashClient {
|
|
151
|
+
readonly config: ResolvedConfig;
|
|
152
|
+
readonly pb: PocketBase;
|
|
153
|
+
private listeners;
|
|
154
|
+
private _modelsLoaded;
|
|
155
|
+
constructor(config?: FaceSmashConfig);
|
|
156
|
+
on(listener: FaceSmashEventListener): () => void;
|
|
157
|
+
private emit;
|
|
158
|
+
get isReady(): boolean;
|
|
159
|
+
init(onProgress?: OnProgress): Promise<boolean>;
|
|
160
|
+
analyzeFace(imageData: string): Promise<FaceAnalysis | null>;
|
|
161
|
+
login(images: string[]): Promise<LoginResult>;
|
|
162
|
+
register(name: string, images: string[], email?: string): Promise<RegisterResult>;
|
|
163
|
+
private ensureReady;
|
|
164
|
+
private storeLoginScan;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
declare function loadModels(config: ResolvedConfig, onProgress?: (progress: number) => void): Promise<boolean>;
|
|
168
|
+
declare function areModelsLoaded(): boolean;
|
|
169
|
+
declare function extractDescriptor(input: string | HTMLVideoElement | HTMLCanvasElement | HTMLImageElement, config: ResolvedConfig): Promise<Float32Array | null>;
|
|
170
|
+
declare function analyzeFace(imageData: string, config: ResolvedConfig): Promise<FaceAnalysis | null>;
|
|
171
|
+
declare function processImages(images: string[], config: ResolvedConfig): Promise<Float32Array | null>;
|
|
172
|
+
declare function normalizeDescriptor(descriptor: Float32Array): Float32Array;
|
|
173
|
+
|
|
174
|
+
/** Calculate cosine similarity between two face descriptors (1 - euclidean distance) */
|
|
175
|
+
declare function calculateSimilarity(d1: Float32Array, d2: Float32Array): number;
|
|
176
|
+
/** Check if two face descriptors match */
|
|
177
|
+
declare function facesMatch(d1: Float32Array, d2: Float32Array, threshold?: number): boolean;
|
|
178
|
+
/**
|
|
179
|
+
* Enhanced face matching with adaptive threshold.
|
|
180
|
+
* Adjusts threshold based on lighting conditions and user confidence boost.
|
|
181
|
+
*/
|
|
182
|
+
declare function enhancedMatch(descriptor1: Float32Array, descriptor2: Float32Array, baseThreshold?: number, confidenceBoost?: number, lightingScore?: number): MatchResult;
|
|
183
|
+
/** Match a face descriptor against multiple stored templates */
|
|
184
|
+
declare function multiTemplateMatch(newDescriptor: Float32Array, templates: {
|
|
185
|
+
descriptor: Float32Array;
|
|
186
|
+
quality: number;
|
|
187
|
+
weight: number;
|
|
188
|
+
}[], baseThreshold: number, lightingScore?: number): MultiTemplateMatchResult;
|
|
189
|
+
/** Calculate a learning weight based on scan quality */
|
|
190
|
+
declare function calculateLearningWeight(qualityScore: number, lightingScore: number, confidence: number): number;
|
|
191
|
+
|
|
192
|
+
declare function createFaceSmash(config?: FaceSmashConfig): FaceSmashClient;
|
|
193
|
+
|
|
194
|
+
interface FaceSmashContextValue {
|
|
195
|
+
client: FaceSmashClient;
|
|
196
|
+
isReady: boolean;
|
|
197
|
+
isLoading: boolean;
|
|
198
|
+
loadProgress: number;
|
|
199
|
+
error: string | null;
|
|
200
|
+
retryInit: () => void;
|
|
201
|
+
}
|
|
202
|
+
interface FaceSmashProviderProps {
|
|
203
|
+
children: ReactNode;
|
|
204
|
+
/** SDK configuration */
|
|
205
|
+
config?: FaceSmashConfig;
|
|
206
|
+
/** Called when models finish loading */
|
|
207
|
+
onReady?: () => void;
|
|
208
|
+
/** Called on model loading error */
|
|
209
|
+
onError?: (error: string) => void;
|
|
210
|
+
/** Called for any SDK event */
|
|
211
|
+
onEvent?: (event: FaceSmashEvent) => void;
|
|
212
|
+
}
|
|
213
|
+
declare function FaceSmashProvider({ children, config, onReady, onError, onEvent, }: FaceSmashProviderProps): react_jsx_runtime.JSX.Element;
|
|
214
|
+
declare function useFaceSmash(): FaceSmashContextValue;
|
|
215
|
+
|
|
216
|
+
interface FaceLoginProps {
|
|
217
|
+
/** Called with the login result when authentication completes */
|
|
218
|
+
onResult: (result: LoginResult) => void;
|
|
219
|
+
/** Number of images to capture for matching (default: 3) */
|
|
220
|
+
captureCount?: number;
|
|
221
|
+
/** Delay between captures in ms (default: 500) */
|
|
222
|
+
captureDelay?: number;
|
|
223
|
+
/** Auto-start scanning when component mounts (default: true) */
|
|
224
|
+
autoStart?: boolean;
|
|
225
|
+
/** Custom className for the container */
|
|
226
|
+
className?: string;
|
|
227
|
+
/** Custom overlay content rendered on top of the video */
|
|
228
|
+
overlay?: React.ReactNode;
|
|
229
|
+
/** Custom loading content */
|
|
230
|
+
loadingContent?: React.ReactNode;
|
|
231
|
+
/** Custom error content */
|
|
232
|
+
errorContent?: (error: string, retry: () => void) => React.ReactNode;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Drop-in face login component.
|
|
236
|
+
* Renders a webcam feed, auto-detects a face, captures images, and authenticates.
|
|
237
|
+
*/
|
|
238
|
+
declare function FaceLogin({ onResult, captureCount, captureDelay, autoStart, className, overlay, loadingContent, errorContent, }: FaceLoginProps): react_jsx_runtime.JSX.Element;
|
|
239
|
+
|
|
240
|
+
interface FaceRegisterProps {
|
|
241
|
+
/** User's display name */
|
|
242
|
+
name: string;
|
|
243
|
+
/** Optional email */
|
|
244
|
+
email?: string;
|
|
245
|
+
/** Called with the registration result */
|
|
246
|
+
onResult: (result: RegisterResult) => void;
|
|
247
|
+
/** Number of images to capture (default: 3) */
|
|
248
|
+
captureCount?: number;
|
|
249
|
+
/** Delay between captures in ms (default: 500) */
|
|
250
|
+
captureDelay?: number;
|
|
251
|
+
/** Auto-start when component mounts (default: true) */
|
|
252
|
+
autoStart?: boolean;
|
|
253
|
+
/** Custom className for the container */
|
|
254
|
+
className?: string;
|
|
255
|
+
/** Custom overlay */
|
|
256
|
+
overlay?: React.ReactNode;
|
|
257
|
+
/** Custom loading content */
|
|
258
|
+
loadingContent?: React.ReactNode;
|
|
259
|
+
/** Custom error content */
|
|
260
|
+
errorContent?: (error: string, retry: () => void) => React.ReactNode;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Drop-in face registration component.
|
|
264
|
+
* Renders a webcam feed, captures face images, and registers a new user.
|
|
265
|
+
*/
|
|
266
|
+
declare function FaceRegister({ name, email, onResult, captureCount, captureDelay, autoStart, className, overlay, loadingContent, errorContent, }: FaceRegisterProps): react_jsx_runtime.JSX.Element;
|
|
267
|
+
|
|
268
|
+
/** Hook for face login flow */
|
|
269
|
+
declare function useFaceLogin(): {
|
|
270
|
+
login: (images: string[]) => Promise<LoginResult>;
|
|
271
|
+
isScanning: boolean;
|
|
272
|
+
result: LoginResult | null;
|
|
273
|
+
reset: () => void;
|
|
274
|
+
isReady: boolean;
|
|
275
|
+
};
|
|
276
|
+
/** Hook for face registration flow */
|
|
277
|
+
declare function useFaceRegister(): {
|
|
278
|
+
register: (name: string, images: string[], email?: string) => Promise<RegisterResult>;
|
|
279
|
+
isRegistering: boolean;
|
|
280
|
+
result: RegisterResult | null;
|
|
281
|
+
reset: () => void;
|
|
282
|
+
isReady: boolean;
|
|
283
|
+
};
|
|
284
|
+
/** Hook for face analysis (quality scoring, detection) */
|
|
285
|
+
declare function useFaceAnalysis(): {
|
|
286
|
+
analyze: (imageData: string) => Promise<FaceAnalysis | null>;
|
|
287
|
+
analysis: FaceAnalysis | null;
|
|
288
|
+
isAnalyzing: boolean;
|
|
289
|
+
isReady: boolean;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
export { type FaceAnalysis, FaceLogin, type FaceLoginProps, FaceRegister, type FaceRegisterProps, type FaceSizeCheck, FaceSmashClient, type FaceSmashConfig, type FaceSmashEvent, type FaceSmashEventListener, FaceSmashProvider, type FaceSmashProviderProps, type FaceTemplate, type HeadPose, type LightingAnalysis, type LoginResult, type MatchResult, type MultiTemplateMatchResult, type OnProgress, type RegisterResult, type ResolvedConfig, type UserProfile, analyzeFace, areModelsLoaded, calculateLearningWeight, calculateSimilarity, createFaceSmash, enhancedMatch, extractDescriptor, facesMatch, loadModels, multiTemplateMatch, normalizeDescriptor, processImages, useFaceAnalysis, useFaceLogin, useFaceRegister, useFaceSmash };
|