@kwik-id/sdk-web 0.1.0-alpha.4 → 0.1.0-alpha.7

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.
@@ -46043,7 +46043,7 @@ function usePresence(present) {
46043
46043
  const prevPresentRef = reactExports.useRef(present);
46044
46044
  const prevAnimationNameRef = reactExports.useRef("none");
46045
46045
  const initialState = present ? "mounted" : "unmounted";
46046
- const [state, send2] = useStateMachine(initialState, {
46046
+ const [state, send] = useStateMachine(initialState, {
46047
46047
  mounted: {
46048
46048
  UNMOUNT: "unmounted",
46049
46049
  ANIMATION_OUT: "unmountSuspended"
@@ -46068,20 +46068,20 @@ function usePresence(present) {
46068
46068
  const prevAnimationName = prevAnimationNameRef.current;
46069
46069
  const currentAnimationName = getAnimationName(styles2);
46070
46070
  if (present) {
46071
- send2("MOUNT");
46071
+ send("MOUNT");
46072
46072
  } else if (currentAnimationName === "none" || styles2?.display === "none") {
46073
- send2("UNMOUNT");
46073
+ send("UNMOUNT");
46074
46074
  } else {
46075
46075
  const isAnimating = prevAnimationName !== currentAnimationName;
46076
46076
  if (wasPresent && isAnimating) {
46077
- send2("ANIMATION_OUT");
46077
+ send("ANIMATION_OUT");
46078
46078
  } else {
46079
- send2("UNMOUNT");
46079
+ send("UNMOUNT");
46080
46080
  }
46081
46081
  }
46082
46082
  prevPresentRef.current = present;
46083
46083
  }
46084
- }, [present, send2]);
46084
+ }, [present, send]);
46085
46085
  useLayoutEffect2(() => {
46086
46086
  if (node) {
46087
46087
  let timeoutId;
@@ -46090,7 +46090,7 @@ function usePresence(present) {
46090
46090
  const currentAnimationName = getAnimationName(stylesRef.current);
46091
46091
  const isCurrentAnimation = currentAnimationName.includes(CSS.escape(event.animationName));
46092
46092
  if (event.target === node && isCurrentAnimation) {
46093
- send2("ANIMATION_END");
46093
+ send("ANIMATION_END");
46094
46094
  if (!prevPresentRef.current) {
46095
46095
  const currentFillMode = node.style.animationFillMode;
46096
46096
  node.style.animationFillMode = "forwards";
@@ -46117,9 +46117,9 @@ function usePresence(present) {
46117
46117
  node.removeEventListener("animationend", handleAnimationEnd);
46118
46118
  };
46119
46119
  } else {
46120
- send2("ANIMATION_END");
46120
+ send("ANIMATION_END");
46121
46121
  }
46122
- }, [node, send2]);
46122
+ }, [node, send]);
46123
46123
  return {
46124
46124
  isPresent: ["mounted", "unmountSuspended"].includes(state),
46125
46125
  ref: reactExports.useCallback((node2) => {
@@ -53054,50 +53054,106 @@ reactExports.createContext({
53054
53054
  size: "default",
53055
53055
  variant: "default"
53056
53056
  });
53057
- let _worker = null;
53058
- let _idCounter = 0;
53059
- const _pending = /* @__PURE__ */ new Map();
53060
- function getWorker() {
53061
- if (_worker) return _worker;
53062
- _worker = new Worker(new URL(
53063
- /* @vite-ignore */
53064
- "/assets/image-processor.worker-CzywSQ7p.js",
53065
- import.meta.url
53066
- ), {
53067
- type: "module"
53068
- });
53069
- _worker.onmessage = ({ data: data2 }) => {
53070
- const { id: id2, ...result } = data2;
53071
- const p = _pending.get(id2);
53072
- if (!p) return;
53073
- _pending.delete(id2);
53074
- p.resolve(result);
53057
+ const MIN_LUMINANCE = 50;
53058
+ const MAX_LUMINANCE = 220;
53059
+ const MIN_BLUR_VARIANCE = 0;
53060
+ function checkLuminance(imageData) {
53061
+ const data2 = imageData.data;
53062
+ let totalLuminance = 0;
53063
+ const pixelCount = data2.length / 4;
53064
+ for (let i = 0; i < data2.length; i += 4) {
53065
+ const r2 = data2[i];
53066
+ const g = data2[i + 1];
53067
+ const b = data2[i + 2];
53068
+ totalLuminance += 0.299 * r2 + 0.587 * g + 0.114 * b;
53069
+ }
53070
+ const avgLuminance = totalLuminance / pixelCount;
53071
+ const score = Math.min(100, avgLuminance / 255 * 100);
53072
+ if (avgLuminance < MIN_LUMINANCE) {
53073
+ return {
53074
+ score,
53075
+ isAcceptable: false,
53076
+ message: "Image is too dark. Please ensure better lighting."
53077
+ };
53078
+ }
53079
+ if (avgLuminance > MAX_LUMINANCE) {
53080
+ return {
53081
+ score,
53082
+ isAcceptable: false,
53083
+ message: "Image is too bright. Please reduce exposure or lighting."
53084
+ };
53085
+ }
53086
+ return {
53087
+ score,
53088
+ isAcceptable: true
53075
53089
  };
53076
- _worker.onerror = (e) => {
53077
- const err = new Error(e.message ?? "Worker error");
53078
- for (const [id2, p] of _pending) {
53079
- _pending.delete(id2);
53080
- p.reject(err);
53090
+ }
53091
+ function checkBlur(imageData) {
53092
+ const { width: width2, height: height2, data: data2 } = imageData;
53093
+ const grayscale = new Float32Array(width2 * height2);
53094
+ for (let i = 0; i < data2.length; i += 4) {
53095
+ const idx = i / 4;
53096
+ grayscale[idx] = 0.299 * data2[i] + 0.587 * data2[i + 1] + 0.114 * data2[i + 2];
53097
+ }
53098
+ const laplacian = new Float32Array(width2 * height2);
53099
+ for (let y = 1; y < height2 - 1; y++) {
53100
+ for (let x = 1; x < width2 - 1; x++) {
53101
+ const idx = y * width2 + x;
53102
+ const value2 = grayscale[idx - width2] + // top
53103
+ grayscale[idx - 1] + // left
53104
+ -4 * grayscale[idx] + // center
53105
+ grayscale[idx + 1] + // right
53106
+ grayscale[idx + width2];
53107
+ laplacian[idx] = value2;
53108
+ }
53109
+ }
53110
+ let sum2 = 0;
53111
+ let sumSq = 0;
53112
+ let count2 = 0;
53113
+ for (let y = 1; y < height2 - 1; y++) {
53114
+ for (let x = 1; x < width2 - 1; x++) {
53115
+ const idx = y * width2 + x;
53116
+ const val2 = laplacian[idx];
53117
+ sum2 += val2;
53118
+ sumSq += val2 * val2;
53119
+ count2++;
53081
53120
  }
53082
- _worker = null;
53121
+ }
53122
+ const mean = sum2 / count2;
53123
+ const variance = sumSq / count2 - mean * mean;
53124
+ const score = Math.min(100, variance / 500 * 100);
53125
+ if (variance < MIN_BLUR_VARIANCE) {
53126
+ return {
53127
+ score,
53128
+ isAcceptable: false,
53129
+ message: "Image is too blurry. Please hold the camera steady."
53130
+ };
53131
+ }
53132
+ return {
53133
+ score,
53134
+ isAcceptable: true
53083
53135
  };
53084
- return _worker;
53085
53136
  }
53086
- function send(msg, transfers = []) {
53087
- const id2 = `wp-${++_idCounter}`;
53088
- return new Promise((resolve, reject) => {
53089
- _pending.set(id2, { resolve, reject });
53090
- try {
53091
- getWorker().postMessage({ id: id2, ...msg }, transfers);
53092
- } catch (e) {
53093
- _pending.delete(id2);
53094
- reject(e instanceof Error ? e : new Error(String(e)));
53137
+ function analyzeImageQuality(imageData) {
53138
+ const luminance = checkLuminance(imageData);
53139
+ const blur = checkBlur(imageData);
53140
+ const overallScore = (luminance.score + blur.score) / 2;
53141
+ const isAcceptable = luminance.isAcceptable && blur.isAcceptable;
53142
+ let message;
53143
+ if (!luminance.isAcceptable) {
53144
+ message = luminance.message;
53145
+ } else if (!blur.isAcceptable) {
53146
+ message = blur.message;
53147
+ }
53148
+ return {
53149
+ luminance,
53150
+ blur,
53151
+ overall: {
53152
+ score: overallScore,
53153
+ isAcceptable,
53154
+ message
53095
53155
  }
53096
- });
53097
- }
53098
- async function analyzeQualityOffThread(data2, width2, height2) {
53099
- const buffer = data2.buffer.slice(data2.byteOffset, data2.byteOffset + data2.byteLength);
53100
- return send({ type: "analyze-quality", buffer, width: width2, height: height2 }, [buffer]);
53156
+ };
53101
53157
  }
53102
53158
  function CameraCapture({ type, onCapture, onCancel }) {
53103
53159
  const [stream, setStream] = reactExports.useState(null);
@@ -53136,11 +53192,7 @@ function CameraCapture({ type, onCapture, onCancel }) {
53136
53192
  const imageData = ctx.getImageData(0, 0, SAMPLE_W, SAMPLE_H);
53137
53193
  qualityPendingRef.current = true;
53138
53194
  try {
53139
- const result = await analyzeQualityOffThread(
53140
- imageData.data,
53141
- SAMPLE_W,
53142
- SAMPLE_H
53143
- );
53195
+ const result = analyzeImageQuality(imageData);
53144
53196
  setQualityStatus({
53145
53197
  isAcceptable: result.overall.isAcceptable,
53146
53198
  message: result.overall.message || null,