Skip to content

feat(document-auto-capture): match legacy desktop UI and fix distance detection#643

Open
Barnabas A Nsoh (ayinloya) wants to merge 116 commits into
mainfrom
document-autocapture-old-design
Open

feat(document-auto-capture): match legacy desktop UI and fix distance detection#643
Barnabas A Nsoh (ayinloya) wants to merge 116 commits into
mainfrom
document-autocapture-old-design

Conversation

@ayinloya

@ayinloya Barnabas A Nsoh (ayinloya) commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

User description

Summary

Redesigns the desktop layout of <document-auto-capture> to mirror the legacy <document-capture> element, and fixes desktop distance detection so a card that fills the visible frame is recognized as close enough.

UI (desktop)

  • Title, simple bordered video area, instruction/feedback text, and the legacy concentric-circle capture button.
  • Optional back/close nav buttons (light styling) and gallery upload button.
  • Border color reflects detection state (gray → amber detecting → green stable/capturing).
  • Auto-capture detection logic (useCardDetection) is unchanged structurally — only the desktop visual shell differs from the mobile fullscreen view.

Distance detection fix

Previously the desktop view reported "Move document closer" even when the card filled the visible frame.

  • ROI now equals the visible video box on desktop (minus a 4% corner margin) instead of the fixed 64px inset carried over from the mobile overlay. On a ≤480px desktop box that inset shrank the invisible ROI to ~75% of the box, so a full-looking card measured as too far. Now the bordered box the user sees is the detection region.
  • Fill metric prefers the validated card outline, falling back to the combined-contour bbox then presence-edge bbox only when no outline is found. This avoids the face/background below the card inflating the measurement (which risked premature capture).
  • Per-device fill thresholds via the settings object: desktop 78/98, mobile 75/95 (mobile behavior unchanged).

Misc

  • Defaults the example app to auto-capture enabled for easier testing.

Test plan

  • Desktop: card filling the bordered box advances to capture (no stuck "Move closer").
  • Desktop: a small/distant card shows "Move document closer".
  • Auto-capture fires only after distance + blur/glare/stability pass.
  • Manual capture button and gallery upload work.
  • Mobile fullscreen behavior unchanged.

🤖 Generated with Claude Code


PR Type

Enhancement, Bug fix


Description

  • Redesign desktop auto-capture UI to match legacy document-capture layout

  • Fix desktop distance detection by using visible video box as ROI

  • Add per-device fill thresholds and skip grid check on desktop

  • Default example app to auto-capture enabled


Diagram Walkthrough

flowchart LR
  A["Desktop Video Box"] -- "ROI = visible box (4% margin)" --> B["useCardDetection"]
  B -- "skipGridCheck=true" --> C["Fill Metric"]
  C -- "Prefer card outline" --> D["Distance Guidance"]
  D -- "minFill 78% / maxFill 98%" --> E["Capture Decision"]
  F["DesktopCaptureButton"] -- "progress ring" --> E
Loading

File Walkthrough

Relevant files
Configuration changes
main.js
Default auto-capture to enabled in example                             

example/main.js

  • Changed default auto-capture selection from disabled to enabled for
    easier testing
+2/-2     
Enhancement
DocumentAutoCapture.tsx
Desktop layout redesign with legacy-style UI components   

packages/web-components/lib/components/document/src/document-auto-capture/DocumentAutoCapture.tsx

  • Added minFillPercent and maxFillPercent to device-specific settings
    (desktop 78/98, mobile 75/95)
  • Lowered desktop blurThreshold from 130 to 60
  • Added DesktopCaptureButton component with SVG concentric-circle design
    and progress ring
  • Added full desktop layout branch with bordered video, nav buttons,
    title, feedback text, and capture button
  • Passed skipGridCheck option to useCardDetection for non-mobile devices
  • Added theme-color and title props to the inner component
+349/-1 
Bug fix
useCardDetection.ts
Fix distance detection and add desktop ROI/fill logic       

packages/web-components/lib/components/document/src/document-auto-capture/hooks/useCardDetection.ts

  • Added skipGridCheck option to bypass grid-cell validation on desktop
  • When skipGridCheck is true, ROI equals the visible video box with 4%
    margin instead of fixed 64px inset
  • Reordered fill metric fallback: card outline → combined contour bbox →
    presence edges
  • Extended synthetic contour fallback to id-card documents with 15%
    expansion factor
  • Made fill thresholds configurable via settings.minFillPercent /
    settings.maxFillPercent
  • Increased CAPTURE_MISS_TOLERANCE from 8 to 20 and default fill
    constants from 65/90 to 75/95
  • Raised fillRatio threshold for valid card outline from 0.65 to 0.75
  • Disabled off-guide detection when skipGridCheck is active
+84/-32 


Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • …deploy-preview (#586)
    
    * feat: add manual workflow_dispatch trigger with skip_tests option to deploy-preview
    
    * feat: add manual workflow_dispatch trigger with skip_tests option to deploy-preview
    
    * fix: remove unnecessary if condition from share-preview-url step
    
    * refactor: rename step id set_dest_dir_hosted_web to set_dest_dir_embed for clarity
    
    * feat: add manual workflow_dispatch trigger to destroy-preview with safe branch handling
    
    * chore: limit preview comment step to pull_request events
    
    * fix: use safe inputs expression for skip_tests across all trigger types
    …oup across 1 directory (#582)
    
    chore(deps-dev): bump vite in the npm_and_yarn group across 1 directory
    
    Bumps the npm_and_yarn group with 1 update in the / directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).
    
    
    Updates `vite` from 7.2.2 to 7.3.2
    - [Release notes](https://github.com/vitejs/vite/releases)
    - [Changelog](https://github.com/vitejs/vite/blob/v7.3.2/packages/vite/CHANGELOG.md)
    - [Commits](https://github.com/vitejs/vite/commits/v7.3.2/packages/vite)
    
    ---
    updated-dependencies:
    - dependency-name: vite
      dependency-version: 7.3.2
      dependency-type: direct:development
      dependency-group: npm_and_yarn
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Barnabas A Nsoh <banasco@gmail.com>
    The new Preact-based component was missing shadow DOM, which caused
    Cypress tests to fail when looking for .back-button in the shadow root.
    The original JS component used attachShadow() but preact-custom-element
    defaults to no shadow DOM. Adding { shadow: true } option fixes the test.
    The embed tests expect an element with id="take-photo" in the document
    capture instructions component. The new Preact component was missing
    this ID, causing test failures.
    * feat(web-components): update Navigation to match new design
    
    - Replace circular colored icon buttons with minimal 40x40px semi-transparent buttons
    - Use simple white arrow icon for back button (no text label)
    - Use simple white X icon for close button
    - Add hover and focus-visible states
    - Move button labels to aria-label for accessibility
    - Update stories with dark background to visualize white icons
    
    * Update navigation to Figma tokens and parent-controlled padding
    
    * Fix dependency
    
    * fix(web-components): address PR review comments on Navigation
    
    * fix(web-components): improve Navigation hover performance and story visibility
    
    * fix(web-components): add appearance resets and decouple theme-color to icon
    …ated
    
    Side-mounted capture/gallery buttons were keyed on useLandscapeUi, which stays true for landscape doc types (id-card, passport) even on desktop where rotation is suppressed. Switch to shouldRotateUi so the bottom row renders the buttons whenever the UI isn't actually rotated.
    Add https local host for mobile testing
    Show guide throughout capture
    Add focusMode continuous as constraints
    Comment out 4k resolution
    * feat(web-components): new document capture instructions screen
    
    * fix(web-components): enable shadow DOM for DocumentCaptureInstructions
    
    The new Preact-based component was missing shadow DOM, which caused
    Cypress tests to fail when looking for .back-button in the shadow root.
    The original JS component used attachShadow() but preact-custom-element
    defaults to no shadow DOM. Adding { shadow: true } option fixes the test.
    
    * fix(web-components): add take-photo id to start button for test compat
    
    The embed tests expect an element with id="take-photo" in the document
    capture instructions component. The new Preact component was missing
    this ID, causing test failures.
    Barnabas A Nsoh (ayinloya) and others added 26 commits June 8, 2026 23:51
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    * fix(doc-auto-capture): address PR #602 review comments
    
    - A4: clamp autoCaptureTimeout to documented 3000-30000ms range
    
    - A5: guard ResizeObserver for environments where it is undefined
    
    - A6: HeroLottie now destroy()s before flipping hasError
    
    - A7: drop selected attr on controlled <select> in previews route
    
    - B1: replace contrived useCamera reduce-chain with for-of fallback
    
    - B2: gate dev console.info telemetry behind ?debug URL flag
    
    - B3: extract safeDelete helper for OpenCV Mat cleanup
    
    - B4: friendlier user-facing feedback strings (no raw ratios/percentages)
    
    - B5: comment opencvLoader's typeof window guard as SSR-only
    
    - C1/C2: explicit prop types for CaptureButton/TuningPanel (FunctionComponent)
    
    - C3: relax eslint import/extensions tsx rule with rationale comment
    
    - D1: flip sync-roi-to-guide default to false to match README
    
    - D2: drop theme-color attribute from props/observedAttributes/README/theme
    
    * refactor await in loop to recursive function
    
    * fix(doc-auto-capture): restore sync-roi-to-guide default to true
    
    Reverts the D1 portion of the previous PR-602 fix-up commit. Flipping the default to false changed runtime behaviour for every consumer that relied on the implicit default; keep the legacy guide-synced ROI as default and document it in the README.
    
    * fix(doc-auto-capture): recover from rotation re-encode failure in capture loop
    
    Add .catch to the Promise.all rotation path so a canvas 2d context
    failure resets isCapturingRef and returns to IDLE instead of permanently
    freezing the detection loop.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    * fix(doc-auto-capture): restart rAF loop after rotation encode failure
    
    The `.catch` handler on the `Promise.all` rotation path reset
    `isCapturingRef` and set state to IDLE, but left the detection loop
    dead. The `finally` block runs synchronously (while `isCapturingRef` is
    still `true`), so no `requestAnimationFrame` was ever requeued after the
    async rejection settled. The loop will now restart when a rotation
    encode failure is caught.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    * perf(doc-auto-capture): downscale video to 640px before OpenCV processing
    
    All CV ops (GaussianBlur, Canny, findContours, Laplacian, etc.) now run
    on a 640px-wide canvas instead of the native camera resolution (~1920px).
    This reduces the pixel count ~9× and should bring per-frame processing
    time under 10ms on mid-range devices.
    
    The full-res canvas is kept for the captured image — only the detection
    pipeline is downscaled. Detected contour coords are scaled back to
    full-res before being stored in latestCardRectRef so capture cropping
    remains accurate.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    * style: lint fix
    
    * fix(doc-auto-capture): address prfectionist and copilot review comments
    
    - safeDelete: wrap each m.delete() in try/catch so one bad mat doesn't
      abort cleanup of the remaining mats in the array
    - DocumentCaptureInstructions: guard cleanup animation.destroy() with
      try/catch since handleError may have already destroyed it
    - useCamera tryConstraints: thread lastError through recursive calls so
      the final rejection preserves the real DOMException (e.g.
      NotAllowedError) instead of swapping it for a generic message
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    * fix(doc-auto-capture): address two Copilot review comments
    
    - Reset stabilityRef and bestFrameRef in rotation .catch so a failed
      re-encode doesn't leave the stability counter at threshold, which
      would immediately re-trigger auto-capture on the next frame and spin
      in a failure/retry loop
    - Guard downscaled canvas setup against video.videoWidth === 0 (common
      early in startup) and null getContext return, both of which would
      propagate NaN into all downstream ROI math and throw in the hot loop
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    * style: lint fix
    
    * fix(doc-auto-capture): scale CV kernels with downscale factor to prevent false distance prompts
    
    Fixed-size kernels (5×5 Gaussian, 3×3 morphological close) become
    proportionally larger as the processing resolution decreases. At 640px
    (1/3 of 1920px), background texture gaps that were wider than the kernel
    at full resolution are now narrower, causing edge bridging that produces
    false large-rectangle contours and triggering "Move document further away"
    incorrectly.
    
    Kernel size and closing iterations are now computed from dsScale so the
    physical blur radius and bridging distance stay constant relative to the
    scene content regardless of PROCESS_WIDTH.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    * fix(doc-auto-capture): reject ROI-filling contours to prevent background false positives
    
    Background patterns (carpet, tile, wood grain) can form large rectangles
    that pass aspect-ratio and rectangularity checks and win the largest-area
    selection, triggering false "Move document further away" prompts.
    
    A real card at correct distance leaves visible space on at least 2 sides
    of the ROI; a background rectangle fills all 4 walls simultaneously.
    Contours whose bounding rect touches 3+ ROI walls (within a 4% margin)
    are now rejected during selection.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    * fix(doc-auto-capture): reject background contours via perimeter compression ratio
    
    Background texture (carpet, concrete) forms long jagged edge paths that
    approxPolyDP collapses dramatically to 4 vertices — original perimeter is
    4–10× the approximated polygon perimeter. A real card border is already
    near-rectangular before approximation, giving a ratio of 1.0–2.0.
    
    Contours with peri/approxPeri >= 3.5 are now rejected during selection,
    stopping textured backgrounds from triggering false "Move document
    further away" prompts even when no card is in frame.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    * fix(doc-auto-capture): reject background contours via polygon-side edge support
    
    Previous fixes (wall-hug, perimeter compression) don't catch compact
    background structures (shadows, tile seams, uniform-texture rectangles)
    that already have a near-rectangular edge path before approxPolyDP.
    
    Add a background-normalised edge support check: sample presenceEdges
    along each of the 4 approx-polygon sides (84 points total) and compare
    the hit fraction to the ambient edge density of the whole ROI. A real
    card border aligns its polygon sides with physical card edges → hit
    ratio 5–15× above background. Background "rectangles" have side density
    ≈ background density → ratio ~1×. Threshold: 2.5× relative or 45%
    absolute (for very plain backgrounds).
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    * fix(doc-auto-capture): run contour detection at full resolution
    
    The 640px downscale (2004999) collapsed the card border to a ~1px line
    that Canny/findContours could only recover when the card was large in
    frame. Distance feedback is gated on a validated contour, so detection
    silently failed: no "move closer/further", eventually "Align document in
    frame". Every fix since piled on rejection heuristics that also rejected
    the real, now-faint border.
    
    Run the contour pass at native resolution on a crop of just the guide-box
    ROI (cheap — the ROI is a fraction of the frame and the pass is gated
    behind the presence/grid check). Keep the cheap gates (presence, texture,
    grid, blur, glare) on the 640px canvas. Relax the contour gates back to
    the pre-regression set (4 corners + fill-ratio + angles + aspect +
    wall-hug), dropping the perimeter-compression and edge-support gates that
    fought the real border. Distance metrics now divide by the ROI area in
    their own coordinate space (full-res for the contour, 640px for the
    presence-edge fallback).
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    
    ---------
    
    Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
    …-old-design
    
    Pull latest #602 (incl. #654 review fixes) into #643. Resolved the one
    conflict in useCardDetection.ts: kept #643's detection tuning
    (syncRoiToGuide=false, fillRatio>0.75, aspectTol + guide-based minArea)
    and adopted #602's dsRoiArea fix for the 640px presence-map fill metric.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    On desktop, a card filling the visible box was silently rejected by the
    ROI wall-hug gate before the max-fill gate could say "Move document
    further away", leaving users stuck on "Align document in frame" - and
    deadlocking discovery when no document-type is provided, since the
    discovery timeout only advances on valid contours.
    
    Desktop-only changes (gated on skipGridCheck / Desktop defaults):
    - Treat a quad that fails ONLY the wall-hug check as a "too close"
      signal: show "Move document further away" in both CAPTURE and
      DISCOVERY phases instead of the dead-end alignment prompt.
    - Relax the wall-hug rejection from 3 to 4 simultaneous wall touches;
      3 touches is common for legitimate off-center hand-held cards.
    - Lower desktop minFillPercent from 78 to 70 (area), widening the
      effective capture band from ~78-90% to ~70-90% fill.
    - Fix a stale comment claiming desktop fill thresholds are 85/99.
    - Expose minFillPercent/maxFillPercent sliders in the debug-only
      TuningPanel for empirical tuning.
    
    Mobile behaviour is unchanged.
    
    https://claude.ai/code/session_011mDeM9KWiDTC5NR8RPynRx
    … detection
    
    After widening the desktop capture band (8a9c180), a document-free scene
    could still auto-capture: the id-card synthetic fallback builds a "card"
    from the combined bbox of ALL significant contours (face, furniture,
    window frames), whose aspect/area easily pass its gates. The synthetic
    then activates fill gating, sails through blur/glare/stability, and
    captures the whole ROI - the review screen shows a room, not a document.
    
    Restore the fallback to its documented purpose - bridging finger/glare
    contour dropouts of a card that WAS being detected - by requiring a
    genuine 4-corner card validation within the last SYNTH_BRIDGE_MAX_FRAMES
    (15 frames, ~0.5s at 30fps). Pristine/reset state is Infinity, so empty
    scenes never synthesize; resetCapture re-arms the window so it cannot
    leak across retakes.
    
    Book-doc (passport/greenbook) fallback is untouched; mobile behaviour is
    unchanged (the recency term only tightens an already desktop-only path).
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    The recency gate (e29fae6) over-corrected: fingers permanently crossing
    a card edge - the normal way to hold a card to a webcam - can prevent a
    clean 4-corner quad from EVER forming, so the bridge window never opens
    and a well-positioned card stalls on "Align document in frame".
    
    Make the synthetic eligible when EITHER a real card was detected within
    the bridge window OR the scene passes the 7/9 grid-coverage bar that
    mobile enforces for every capture (passingCells is already computed on
    desktop; only its gating was skipped). A hand-held card filling the box
    lights up the whole 3x3 grid, while the document-free scene that
    previously auto-captured leaves blank wall cells.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    The capture components enable their tuning panel and verbose telemetry
    when their own window.location.search contains `debug` — but the embed
    iframe src never carried the host page's query string, so `?debug` on an
    integrating page (e.g. the previews app) silently did nothing.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    …closer"
    
    A card pushed too close overflows the ROI: its outer edges leave the
    frame, so no 4-corner quad forms and the wall-hug too-close signal never
    fires (it needs a complete quad). Only inner-content contours remain,
    clipped at the ROI walls. The synthetic fallback then either fails its
    aspect check (clipped bbox is too wide) - "Align document in frame" - or
    forms from the content cluster whose bbox underestimates the card -
    fill < min - "Move document closer". Both prompts push the user the
    wrong way.
    
    Detect the overflow directly: combined contour bbox clipped at 2+ ROI
    walls with capture-grade (7/9) grid coverage. On overflow, suppress the
    synthetic (a capture would clip the card's edges anyway) and show
    "Move document further away" in both CAPTURE and DISCOVERY no-contour
    paths. A genuinely far card keeps its small centered bbox and still
    gets "Move document closer". Desktop-only (skipGridCheck-gated).
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    The overflow heuristic (412935b) counted ANY 2+ ROI wall touches of the
    combined contour bbox as "card overflows the box". But the hand holding
    the card is a significant contour too - fingers intrude from one side or
    corner, dragging the bbox to adjacent walls at a perfectly good distance,
    suppressing the synthetic and showing a false "Move document further
    away". Require an OPPOSITE wall pair (left+right or top+bottom): a card
    overflowing the box spans the ROI along an axis; a hand does not.
    
    Also expose the active detection ROI (clamped, mapped back to the video
    element's CSS box) from useCardDetection in debug mode, and outline it
    in the desktop layout when ?debug is set, so wall-hug/overflow/fill
    issues can be judged against what the camera actually analyses.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    The panel rendered edge density / texture / blur / glare but never
    docFill (no row for it) and kept the 3x3 grid densities in a hidden div,
    so the two signals that drive the desktop fill + coverage gates were
    invisible during tuning. Add a Doc Fill row, unhide the grid row, and
    stash docFillPercent in a ref so the per-frame quality payload (emitted
    after the contour block, where the value is out of scope) reports the
    live fill at the moment of capture.
    
    Debug-only; no behaviour change.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Each gate's setDebugInfo call replaced the whole object, so the panel
    only ever showed the subset the current frame's early-return path
    emitted - docFill blanked on the "Align document in frame" path, grid
    blanked on the move-closer/blur paths, etc. Route all emits through a
    mergeDebugInfo helper so the last-known docFill / grid / blur / glare
    stay visible together. Debug-only.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Replace the hand-rolled back/close <button> pairs in both the desktop and
    mobile layouts with the shared <smileid-navigation> custom element, the
    same component used by the selfie capture screens. This brings localised
    aria labels (navigation.back / navigation.closeVerificationFrame), RTL
    arrow flipping, and consistent focus styling for free, and drops the
    duplicated SVG markup and the now-unused roundControlButtonStyle /
    desktopNavBtnStyle objects.
    
    The element's navigation.back / navigation.close events are bridged to
    the existing onBack / onClose host-event dispatchers via a ref + effect
    (mirroring SmartSelfieCapture). Per-layout chrome is set through the
    element's CSS custom properties: dark-on-light pills for the desktop
    card, translucent-white-on-dark for the fullscreen mobile camera.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    and  doc auto-capture screen: replace the hand-rolled back <button> +
    BackArrowIcon with the shared <smileid-navigation hide-close> element,
    bridging its navigation.back event to handleBack via a ref + effect.
    Brings the localised back label and RTL arrow flip for free; the .back-nav
    class now only positions the element (the circle/hover/focus live in the
    element's own shadow DOM). Both document capture surfaces now use the
    same navigation component.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    The desktop shutter (DesktopCaptureButton) rendered unconditionally and
    was only disabled on SUCCESS, so it was always tappable regardless of
    captureMode and the auto-capture timeout had no effect on it — unlike
    mobile, which gates its manual control on showManualButton.
    
    Render the desktop shutter only when showManualButton is true: shown for
    manualCaptureOnly, after the autoCaptureTimeout fallback fires in
    autoCapture, or on CV load failure; never in autoCaptureOnly. Auto-capture
    state is already conveyed by the video border, so the button is hidden
    (not just disabled) while unavailable.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Bump the manual-fallback timeout default from 10s to 20s so users get
    more time for auto-capture to succeed before the manual shutter appears.
    
    The effective default for the document flow is DocumentAutoCapture's
    `auto-capture-timeout` prop default (and the invalid-input fallback
    constant), which always override useCardDetection's own default — update
    both, plus the hook default for direct callers, the README, and the
    Storybook arg. Integrators can still override per the 3000–30000ms clamp.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Wrap document-type, auto-capture, and auto-capture-timeout attribute
    values in escAttr() with double quotes, matching the escaping already
    applied to the other forwarded attributes.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    - DocumentCaptureScreens: validate auto-capture-timeout as a positive number
      before interpolating into innerHTML (omit otherwise), with double quotes
    - README: fix broken ./AGENTS.md link and correct the OpenCV runtime URL/CSP
      origin to web-models.smileidentity.com to match opencvLoader
    - useCardDetection: gate the remaining MANUAL-capture and [ROI] debug logs
      behind IS_DEBUG_MODE
    - add Cypress e2e asserting auto-capture-enabled flips the live-capture element
      between <document-auto-capture> and legacy <document-capture>
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Base automatically changed from document-auto-capture-rework to main June 17, 2026 14:28
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    5 participants