qapture2 0.2.1 → 0.2.3
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/dist/bin/init.cjs +3 -3
- package/dist/{chunk-OPZF4IVW.js → chunk-BE3H3FKR.js} +232 -41
- package/dist/{chunk-CJQHPDT7.cjs → chunk-PC6LNG5Y.cjs} +231 -40
- package/dist/index.cjs +4 -4
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/next.cjs +4 -4
- package/dist/next.js +1 -1
- package/dist/standalone.cjs +2 -2
- package/dist/standalone.js +1 -1
- package/package.json +2 -2
package/dist/bin/init.cjs
CHANGED
|
@@ -819,10 +819,10 @@ function genConfigText(opts) {
|
|
|
819
819
|
const hintsComment = frameworkHints.length > 0 ? ` *
|
|
820
820
|
* Auto-detected stack:
|
|
821
821
|
${frameworkHints.map((h) => ` * \u2022 ${h}`).join("\n")}` : "";
|
|
822
|
-
const typeImport = isTypeScript ? `import type { QaConfig } from '
|
|
822
|
+
const typeImport = isTypeScript ? `import type { QaConfig } from 'qapture2';
|
|
823
823
|
|
|
824
824
|
` : `// @ts-check
|
|
825
|
-
/** @type {import('
|
|
825
|
+
/** @type {import('qapture2').QaConfig} */
|
|
826
826
|
`;
|
|
827
827
|
const typeAnnotation = isTypeScript ? ": QaConfig" : "";
|
|
828
828
|
const exportStatement = `export default config;
|
|
@@ -1073,7 +1073,7 @@ ${DIVIDER}
|
|
|
1073
1073
|
Mount the widget near your app root:
|
|
1074
1074
|
${DIVIDER}
|
|
1075
1075
|
|
|
1076
|
-
import { Qapture } from '
|
|
1076
|
+
import { Qapture } from 'qapture2';
|
|
1077
1077
|
import config from './${configFile.replace(/\.[jt]s$/, "")}';
|
|
1078
1078
|
|
|
1079
1079
|
// Render once near your app root:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useEffect, Component, useState, useCallback, useReducer, useContext,
|
|
1
|
+
import React, { createContext, useEffect, Component, useState, useCallback, useRef, useReducer, useContext, useLayoutEffect } from 'react';
|
|
2
2
|
import ReactDOM from 'react-dom/client';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -1563,28 +1563,165 @@ function Icon({
|
|
|
1563
1563
|
function renderSvgElement(tag, attrs, key) {
|
|
1564
1564
|
return React.createElement(tag, { key, ...attrs });
|
|
1565
1565
|
}
|
|
1566
|
+
function isCoarsePointer() {
|
|
1567
|
+
if (typeof window === "undefined") return false;
|
|
1568
|
+
try {
|
|
1569
|
+
if (window.matchMedia && window.matchMedia("(pointer: coarse)").matches) return true;
|
|
1570
|
+
} catch {
|
|
1571
|
+
}
|
|
1572
|
+
return typeof navigator !== "undefined" && (navigator.maxTouchPoints || 0) > 0;
|
|
1573
|
+
}
|
|
1574
|
+
function useCoarsePointer() {
|
|
1575
|
+
const [coarse, setCoarse] = useState(() => isCoarsePointer());
|
|
1576
|
+
useEffect(() => {
|
|
1577
|
+
if (typeof window === "undefined" || !window.matchMedia) return;
|
|
1578
|
+
const mq = window.matchMedia("(pointer: coarse)");
|
|
1579
|
+
const on = () => setCoarse(isCoarsePointer());
|
|
1580
|
+
if (mq.addEventListener) mq.addEventListener("change", on);
|
|
1581
|
+
else if (mq.addListener) mq.addListener(on);
|
|
1582
|
+
return () => {
|
|
1583
|
+
if (mq.removeEventListener) mq.removeEventListener("change", on);
|
|
1584
|
+
else if (mq.removeListener) mq.removeListener(on);
|
|
1585
|
+
};
|
|
1586
|
+
}, []);
|
|
1587
|
+
return coarse;
|
|
1588
|
+
}
|
|
1589
|
+
var DEFAULT_LEFT = "calc(1.25rem + env(safe-area-inset-left))";
|
|
1590
|
+
var DEFAULT_BOTTOM = "calc(5rem + env(safe-area-inset-bottom))";
|
|
1591
|
+
var FAB_SIZE_PX = 56;
|
|
1592
|
+
var EDGE_MARGIN = 12;
|
|
1593
|
+
var DRAG_THRESHOLD = 8;
|
|
1594
|
+
var FAB_POS_KEY = "qapture:fabpos";
|
|
1595
|
+
function isFabPos(v) {
|
|
1596
|
+
if (!v || typeof v !== "object") return false;
|
|
1597
|
+
const o = v;
|
|
1598
|
+
return typeof o.left === "number" && Number.isFinite(o.left) && typeof o.bottom === "number" && Number.isFinite(o.bottom);
|
|
1599
|
+
}
|
|
1600
|
+
function loadFabPos() {
|
|
1601
|
+
if (typeof window === "undefined") return null;
|
|
1602
|
+
try {
|
|
1603
|
+
const raw = window.localStorage.getItem(FAB_POS_KEY);
|
|
1604
|
+
if (!raw) return null;
|
|
1605
|
+
const parsed = JSON.parse(raw);
|
|
1606
|
+
return isFabPos(parsed) ? parsed : null;
|
|
1607
|
+
} catch {
|
|
1608
|
+
return null;
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
function saveFabPos(pos) {
|
|
1612
|
+
if (typeof window === "undefined") return;
|
|
1613
|
+
try {
|
|
1614
|
+
window.localStorage.setItem(FAB_POS_KEY, JSON.stringify(pos));
|
|
1615
|
+
} catch {
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
function clampNum(v, lo, hi) {
|
|
1619
|
+
return Math.min(Math.max(v, lo), hi);
|
|
1620
|
+
}
|
|
1621
|
+
function clampFabPos(p, w = FAB_SIZE_PX, h = FAB_SIZE_PX) {
|
|
1622
|
+
if (typeof window === "undefined") return p;
|
|
1623
|
+
const maxLeft = Math.max(EDGE_MARGIN, window.innerWidth - w - EDGE_MARGIN);
|
|
1624
|
+
const maxBottom = Math.max(EDGE_MARGIN, window.innerHeight - h - EDGE_MARGIN);
|
|
1625
|
+
return {
|
|
1626
|
+
left: clampNum(p.left, EDGE_MARGIN, maxLeft),
|
|
1627
|
+
bottom: clampNum(p.bottom, EDGE_MARGIN, maxBottom)
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1566
1630
|
function QaFab() {
|
|
1567
1631
|
const { isOpen, setIsOpen, notes, captureActive, theme } = useQa();
|
|
1632
|
+
const coarse = useCoarsePointer();
|
|
1633
|
+
const [pos, setPos] = useState(() => loadFabPos());
|
|
1634
|
+
const dragRef = useRef(null);
|
|
1635
|
+
const didDragRef = useRef(false);
|
|
1568
1636
|
if (captureActive) return null;
|
|
1637
|
+
const onPointerDown = (e) => {
|
|
1638
|
+
if (dragRef.current) return;
|
|
1639
|
+
didDragRef.current = false;
|
|
1640
|
+
const target = e.currentTarget;
|
|
1641
|
+
const rect = target.getBoundingClientRect();
|
|
1642
|
+
dragRef.current = {
|
|
1643
|
+
pointerId: e.pointerId,
|
|
1644
|
+
startX: e.clientX,
|
|
1645
|
+
startY: e.clientY,
|
|
1646
|
+
startLeft: rect.left,
|
|
1647
|
+
startBottom: window.innerHeight - rect.bottom,
|
|
1648
|
+
width: rect.width,
|
|
1649
|
+
height: rect.height,
|
|
1650
|
+
dragging: false
|
|
1651
|
+
};
|
|
1652
|
+
try {
|
|
1653
|
+
target.setPointerCapture(e.pointerId);
|
|
1654
|
+
} catch {
|
|
1655
|
+
}
|
|
1656
|
+
};
|
|
1657
|
+
const onPointerMove = (e) => {
|
|
1658
|
+
const d = dragRef.current;
|
|
1659
|
+
if (!d || d.pointerId !== e.pointerId) return;
|
|
1660
|
+
const dx = e.clientX - d.startX;
|
|
1661
|
+
const dy = e.clientY - d.startY;
|
|
1662
|
+
if (!d.dragging) {
|
|
1663
|
+
if (Math.hypot(dx, dy) < DRAG_THRESHOLD) return;
|
|
1664
|
+
d.dragging = true;
|
|
1665
|
+
}
|
|
1666
|
+
setPos(clampFabPos({ left: d.startLeft + dx, bottom: d.startBottom - dy }, d.width, d.height));
|
|
1667
|
+
};
|
|
1668
|
+
const endDrag = (e) => {
|
|
1669
|
+
const d = dragRef.current;
|
|
1670
|
+
if (!d || d.pointerId !== e.pointerId) return null;
|
|
1671
|
+
try {
|
|
1672
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
1673
|
+
} catch {
|
|
1674
|
+
}
|
|
1675
|
+
dragRef.current = null;
|
|
1676
|
+
return d;
|
|
1677
|
+
};
|
|
1678
|
+
const onPointerUp = (e) => {
|
|
1679
|
+
const d = endDrag(e);
|
|
1680
|
+
if (!d) return;
|
|
1681
|
+
if (d.dragging) {
|
|
1682
|
+
const dx = e.clientX - d.startX;
|
|
1683
|
+
const dy = e.clientY - d.startY;
|
|
1684
|
+
const next = clampFabPos({ left: d.startLeft + dx, bottom: d.startBottom - dy }, d.width, d.height);
|
|
1685
|
+
setPos(next);
|
|
1686
|
+
saveFabPos(next);
|
|
1687
|
+
didDragRef.current = true;
|
|
1688
|
+
}
|
|
1689
|
+
};
|
|
1690
|
+
const onPointerCancel = (e) => {
|
|
1691
|
+
endDrag(e);
|
|
1692
|
+
};
|
|
1693
|
+
const handleClick = () => {
|
|
1694
|
+
if (didDragRef.current) {
|
|
1695
|
+
didDragRef.current = false;
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
setIsOpen(!isOpen);
|
|
1699
|
+
};
|
|
1700
|
+
const applied = coarse && pos ? clampFabPos(pos) : null;
|
|
1701
|
+
const fabStyle = {
|
|
1702
|
+
left: applied ? `${applied.left}px` : DEFAULT_LEFT,
|
|
1703
|
+
bottom: applied ? `${applied.bottom}px` : DEFAULT_BOTTOM,
|
|
1704
|
+
width: "3.5rem",
|
|
1705
|
+
height: "3.5rem",
|
|
1706
|
+
backgroundImage: `linear-gradient(135deg, ${theme.primary}, ${theme.accent})`,
|
|
1707
|
+
boxShadow: "0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04), 0 0 0 2px rgba(255,255,255,0.7)",
|
|
1708
|
+
zIndex: 9990
|
|
1709
|
+
};
|
|
1569
1710
|
return /* @__PURE__ */ jsxs(
|
|
1570
1711
|
"button",
|
|
1571
1712
|
{
|
|
1572
1713
|
type: "button",
|
|
1573
1714
|
"data-qa-overlay": "true",
|
|
1574
1715
|
dir: "ltr",
|
|
1575
|
-
onClick:
|
|
1716
|
+
onClick: handleClick,
|
|
1717
|
+
onPointerDown: coarse ? onPointerDown : void 0,
|
|
1718
|
+
onPointerMove: coarse ? onPointerMove : void 0,
|
|
1719
|
+
onPointerUp: coarse ? onPointerUp : void 0,
|
|
1720
|
+
onPointerCancel: coarse ? onPointerCancel : void 0,
|
|
1576
1721
|
"aria-label": "Qapture \u2014 testing notes",
|
|
1577
1722
|
title: "Qapture",
|
|
1578
|
-
className:
|
|
1579
|
-
style:
|
|
1580
|
-
left: "calc(1.25rem + env(safe-area-inset-left))",
|
|
1581
|
-
bottom: "calc(5rem + env(safe-area-inset-bottom))",
|
|
1582
|
-
width: "3.5rem",
|
|
1583
|
-
height: "3.5rem",
|
|
1584
|
-
backgroundImage: `linear-gradient(135deg, ${theme.primary}, ${theme.accent})`,
|
|
1585
|
-
boxShadow: "0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04), 0 0 0 2px rgba(255,255,255,0.7)",
|
|
1586
|
-
zIndex: 9990
|
|
1587
|
-
},
|
|
1723
|
+
className: `qa-fixed qa-flex qa-items-center qa-justify-center qa-rounded-full qa-text-white qa-print-hidden qa-fab-btn${coarse ? " qa-touch-none" : ""}`,
|
|
1724
|
+
style: fabStyle,
|
|
1588
1725
|
children: [
|
|
1589
1726
|
!isOpen && /* @__PURE__ */ jsx(
|
|
1590
1727
|
"span",
|
|
@@ -2547,6 +2684,20 @@ function panelReducer(state, action) {
|
|
|
2547
2684
|
return state;
|
|
2548
2685
|
}
|
|
2549
2686
|
}
|
|
2687
|
+
var KEYBOARD_OVERLAP_THRESHOLD = 120;
|
|
2688
|
+
var KEYBOARD_LIFT_GAP = 12;
|
|
2689
|
+
var NON_TEXT_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
2690
|
+
"checkbox",
|
|
2691
|
+
"radio",
|
|
2692
|
+
"range",
|
|
2693
|
+
"button",
|
|
2694
|
+
"submit",
|
|
2695
|
+
"reset",
|
|
2696
|
+
"color",
|
|
2697
|
+
"file",
|
|
2698
|
+
"image"
|
|
2699
|
+
]);
|
|
2700
|
+
var PANEL_TRANSITION_WITH_LIFT = "opacity 200ms cubic-bezier(0.4,0,0.2,1), transform 200ms cubic-bezier(0.4,0,0.2,1), bottom 200ms cubic-bezier(0.4,0,0.2,1)";
|
|
2550
2701
|
function QaPanel() {
|
|
2551
2702
|
const {
|
|
2552
2703
|
isOpen,
|
|
@@ -2612,6 +2763,61 @@ function QaPanel() {
|
|
|
2612
2763
|
mql.addListener(handleChange);
|
|
2613
2764
|
return () => mql.removeListener(handleChange);
|
|
2614
2765
|
}, []);
|
|
2766
|
+
const coarse = useCoarsePointer();
|
|
2767
|
+
const panelRef = useRef(null);
|
|
2768
|
+
const [keyboardLift, setKeyboardLift] = useState(0);
|
|
2769
|
+
const computeKeyboardLift = useCallback(() => {
|
|
2770
|
+
try {
|
|
2771
|
+
if (!coarse || isIpadLandscape) return 0;
|
|
2772
|
+
if (typeof window === "undefined") return 0;
|
|
2773
|
+
const vv = window.visualViewport;
|
|
2774
|
+
if (!vv) return 0;
|
|
2775
|
+
const overlap = Math.max(0, window.innerHeight - vv.height - vv.offsetTop);
|
|
2776
|
+
if (overlap <= KEYBOARD_OVERLAP_THRESHOLD) return 0;
|
|
2777
|
+
const panel = panelRef.current;
|
|
2778
|
+
if (!panel) return 0;
|
|
2779
|
+
const root = panel.getRootNode();
|
|
2780
|
+
const active = root.activeElement;
|
|
2781
|
+
if (!active || !panel.contains(active)) return 0;
|
|
2782
|
+
const tag = active.tagName;
|
|
2783
|
+
if (tag === "TEXTAREA") return Math.round(overlap) + KEYBOARD_LIFT_GAP;
|
|
2784
|
+
if (tag === "INPUT" && !NON_TEXT_INPUT_TYPES.has(active.type)) {
|
|
2785
|
+
return Math.round(overlap) + KEYBOARD_LIFT_GAP;
|
|
2786
|
+
}
|
|
2787
|
+
return 0;
|
|
2788
|
+
} catch {
|
|
2789
|
+
return 0;
|
|
2790
|
+
}
|
|
2791
|
+
}, [coarse, isIpadLandscape]);
|
|
2792
|
+
useEffect(() => {
|
|
2793
|
+
if (!coarse) return void 0;
|
|
2794
|
+
if (typeof window === "undefined" || typeof document === "undefined") return void 0;
|
|
2795
|
+
const vv = window.visualViewport;
|
|
2796
|
+
if (!vv) return void 0;
|
|
2797
|
+
let closeTimer;
|
|
2798
|
+
const recompute = () => setKeyboardLift(computeKeyboardLift());
|
|
2799
|
+
const recomputeSoon = () => {
|
|
2800
|
+
if (closeTimer !== void 0) clearTimeout(closeTimer);
|
|
2801
|
+
closeTimer = setTimeout(recompute, 80);
|
|
2802
|
+
};
|
|
2803
|
+
recompute();
|
|
2804
|
+
vv.addEventListener("resize", recompute);
|
|
2805
|
+
vv.addEventListener("scroll", recompute);
|
|
2806
|
+
document.addEventListener("focusin", recompute);
|
|
2807
|
+
document.addEventListener("focusout", recomputeSoon);
|
|
2808
|
+
return () => {
|
|
2809
|
+
if (closeTimer !== void 0) clearTimeout(closeTimer);
|
|
2810
|
+
vv.removeEventListener("resize", recompute);
|
|
2811
|
+
vv.removeEventListener("scroll", recompute);
|
|
2812
|
+
document.removeEventListener("focusin", recompute);
|
|
2813
|
+
document.removeEventListener("focusout", recomputeSoon);
|
|
2814
|
+
};
|
|
2815
|
+
}, [coarse, computeKeyboardLift]);
|
|
2816
|
+
useEffect(() => {
|
|
2817
|
+
if (!isOpen) setKeyboardLift(0);
|
|
2818
|
+
}, [isOpen]);
|
|
2819
|
+
const keyboardLiftActive = coarse && !isIpadLandscape;
|
|
2820
|
+
const appliedKeyboardLift = keyboardLiftActive ? keyboardLift : 0;
|
|
2615
2821
|
if (phase === "hidden") return null;
|
|
2616
2822
|
const openNaming = () => {
|
|
2617
2823
|
setFilename(todayName());
|
|
@@ -2622,9 +2828,12 @@ function QaPanel() {
|
|
|
2622
2828
|
void exportZip(filename);
|
|
2623
2829
|
};
|
|
2624
2830
|
const namingCoverage = naming ? computeCoverage(journey, guideChecked) : null;
|
|
2831
|
+
const restBottomRem = dir === "rtl" ? "9rem" : "8.75rem";
|
|
2832
|
+
const panelBottom = isIpadLandscape ? "0" : appliedKeyboardLift > 0 ? `calc(${restBottomRem} + env(safe-area-inset-bottom) + ${appliedKeyboardLift}px)` : `calc(${restBottomRem} + env(safe-area-inset-bottom))`;
|
|
2625
2833
|
return /* @__PURE__ */ jsxs(
|
|
2626
2834
|
"div",
|
|
2627
2835
|
{
|
|
2836
|
+
ref: panelRef,
|
|
2628
2837
|
"data-qa-overlay": "true",
|
|
2629
2838
|
dir,
|
|
2630
2839
|
onTransitionEnd: handleTransitionEnd,
|
|
@@ -2635,7 +2844,7 @@ function QaPanel() {
|
|
|
2635
2844
|
left: isIpadLandscape ? "auto" : "calc(1rem + env(safe-area-inset-left))",
|
|
2636
2845
|
right: isIpadLandscape ? "0" : void 0,
|
|
2637
2846
|
top: isIpadLandscape ? "0" : void 0,
|
|
2638
|
-
bottom:
|
|
2847
|
+
bottom: panelBottom,
|
|
2639
2848
|
height: isIpadLandscape ? "100dvh" : void 0,
|
|
2640
2849
|
width: isIpadLandscape ? "min(92vw, 420px)" : void 0,
|
|
2641
2850
|
// qa-max-h-74vh (class) would otherwise cap the sheet well short of
|
|
@@ -2645,7 +2854,12 @@ function QaPanel() {
|
|
|
2645
2854
|
background: theme.surface,
|
|
2646
2855
|
borderColor: `${theme.primary}22`,
|
|
2647
2856
|
fontFamily: lang === "ar" ? "'Tajawal', sans-serif" : "'Nunito', system-ui, sans-serif",
|
|
2648
|
-
zIndex: 9990
|
|
2857
|
+
zIndex: 9990,
|
|
2858
|
+
// Keyboard-avoidance lift (coarse/touch only — see effect above).
|
|
2859
|
+
// undefined ⇒ !keyboardLiftActive, so desktop and the iPad-landscape
|
|
2860
|
+
// side-sheet render this property exactly as before (the class's own
|
|
2861
|
+
// opacity/transform transition applies, untouched).
|
|
2862
|
+
transition: keyboardLiftActive ? PANEL_TRANSITION_WITH_LIFT : void 0
|
|
2649
2863
|
},
|
|
2650
2864
|
children: [
|
|
2651
2865
|
/* @__PURE__ */ jsxs(
|
|
@@ -3029,29 +3243,6 @@ function getStableSelector(el) {
|
|
|
3029
3243
|
}
|
|
3030
3244
|
return nthOfTypePath(el);
|
|
3031
3245
|
}
|
|
3032
|
-
function isCoarsePointer() {
|
|
3033
|
-
if (typeof window === "undefined") return false;
|
|
3034
|
-
try {
|
|
3035
|
-
if (window.matchMedia && window.matchMedia("(pointer: coarse)").matches) return true;
|
|
3036
|
-
} catch {
|
|
3037
|
-
}
|
|
3038
|
-
return typeof navigator !== "undefined" && (navigator.maxTouchPoints || 0) > 0;
|
|
3039
|
-
}
|
|
3040
|
-
function useCoarsePointer() {
|
|
3041
|
-
const [coarse, setCoarse] = useState(() => isCoarsePointer());
|
|
3042
|
-
useEffect(() => {
|
|
3043
|
-
if (typeof window === "undefined" || !window.matchMedia) return;
|
|
3044
|
-
const mq = window.matchMedia("(pointer: coarse)");
|
|
3045
|
-
const on = () => setCoarse(isCoarsePointer());
|
|
3046
|
-
if (mq.addEventListener) mq.addEventListener("change", on);
|
|
3047
|
-
else if (mq.addListener) mq.addListener(on);
|
|
3048
|
-
return () => {
|
|
3049
|
-
if (mq.removeEventListener) mq.removeEventListener("change", on);
|
|
3050
|
-
else if (mq.removeListener) mq.removeListener(on);
|
|
3051
|
-
};
|
|
3052
|
-
}, []);
|
|
3053
|
-
return coarse;
|
|
3054
|
-
}
|
|
3055
3246
|
|
|
3056
3247
|
// src/lib/scrollLock.ts
|
|
3057
3248
|
var locked = false;
|
|
@@ -3073,7 +3264,7 @@ function unlockPageScroll() {
|
|
|
3073
3264
|
if (document.body) document.body.style.overflow = prevBodyOverflow;
|
|
3074
3265
|
locked = false;
|
|
3075
3266
|
}
|
|
3076
|
-
var
|
|
3267
|
+
var DRAG_THRESHOLD2 = 6;
|
|
3077
3268
|
var TOUCH_DRAG_THRESHOLD = 12;
|
|
3078
3269
|
var MIN_REGION_SIZE = 8;
|
|
3079
3270
|
var REGION_HANDLES = [
|
|
@@ -3196,7 +3387,7 @@ function CaptureMode() {
|
|
|
3196
3387
|
activePointerId.current = null;
|
|
3197
3388
|
const d = dragRef.current;
|
|
3198
3389
|
dragRef.current = null;
|
|
3199
|
-
const threshold = pointerKind.current === "mouse" ?
|
|
3390
|
+
const threshold = pointerKind.current === "mouse" ? DRAG_THRESHOLD2 : TOUCH_DRAG_THRESHOLD;
|
|
3200
3391
|
const moved = d !== null && Math.hypot(e.clientX - d.x0, e.clientY - d.y0) > threshold;
|
|
3201
3392
|
scrollSnap.current = { x: window.scrollX, y: window.scrollY };
|
|
3202
3393
|
if (moved && d) {
|
|
@@ -3819,5 +4010,5 @@ function Qapture({ config }) {
|
|
|
3819
4010
|
}
|
|
3820
4011
|
|
|
3821
4012
|
export { Qapture, initQaStudio };
|
|
3822
|
-
//# sourceMappingURL=chunk-
|
|
3823
|
-
//# sourceMappingURL=chunk-
|
|
4013
|
+
//# sourceMappingURL=chunk-BE3H3FKR.js.map
|
|
4014
|
+
//# sourceMappingURL=chunk-BE3H3FKR.js.map
|
|
@@ -1570,28 +1570,165 @@ function Icon({
|
|
|
1570
1570
|
function renderSvgElement(tag, attrs, key) {
|
|
1571
1571
|
return React__default.default.createElement(tag, { key, ...attrs });
|
|
1572
1572
|
}
|
|
1573
|
+
function isCoarsePointer() {
|
|
1574
|
+
if (typeof window === "undefined") return false;
|
|
1575
|
+
try {
|
|
1576
|
+
if (window.matchMedia && window.matchMedia("(pointer: coarse)").matches) return true;
|
|
1577
|
+
} catch {
|
|
1578
|
+
}
|
|
1579
|
+
return typeof navigator !== "undefined" && (navigator.maxTouchPoints || 0) > 0;
|
|
1580
|
+
}
|
|
1581
|
+
function useCoarsePointer() {
|
|
1582
|
+
const [coarse, setCoarse] = React.useState(() => isCoarsePointer());
|
|
1583
|
+
React.useEffect(() => {
|
|
1584
|
+
if (typeof window === "undefined" || !window.matchMedia) return;
|
|
1585
|
+
const mq = window.matchMedia("(pointer: coarse)");
|
|
1586
|
+
const on = () => setCoarse(isCoarsePointer());
|
|
1587
|
+
if (mq.addEventListener) mq.addEventListener("change", on);
|
|
1588
|
+
else if (mq.addListener) mq.addListener(on);
|
|
1589
|
+
return () => {
|
|
1590
|
+
if (mq.removeEventListener) mq.removeEventListener("change", on);
|
|
1591
|
+
else if (mq.removeListener) mq.removeListener(on);
|
|
1592
|
+
};
|
|
1593
|
+
}, []);
|
|
1594
|
+
return coarse;
|
|
1595
|
+
}
|
|
1596
|
+
var DEFAULT_LEFT = "calc(1.25rem + env(safe-area-inset-left))";
|
|
1597
|
+
var DEFAULT_BOTTOM = "calc(5rem + env(safe-area-inset-bottom))";
|
|
1598
|
+
var FAB_SIZE_PX = 56;
|
|
1599
|
+
var EDGE_MARGIN = 12;
|
|
1600
|
+
var DRAG_THRESHOLD = 8;
|
|
1601
|
+
var FAB_POS_KEY = "qapture:fabpos";
|
|
1602
|
+
function isFabPos(v) {
|
|
1603
|
+
if (!v || typeof v !== "object") return false;
|
|
1604
|
+
const o = v;
|
|
1605
|
+
return typeof o.left === "number" && Number.isFinite(o.left) && typeof o.bottom === "number" && Number.isFinite(o.bottom);
|
|
1606
|
+
}
|
|
1607
|
+
function loadFabPos() {
|
|
1608
|
+
if (typeof window === "undefined") return null;
|
|
1609
|
+
try {
|
|
1610
|
+
const raw = window.localStorage.getItem(FAB_POS_KEY);
|
|
1611
|
+
if (!raw) return null;
|
|
1612
|
+
const parsed = JSON.parse(raw);
|
|
1613
|
+
return isFabPos(parsed) ? parsed : null;
|
|
1614
|
+
} catch {
|
|
1615
|
+
return null;
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
function saveFabPos(pos) {
|
|
1619
|
+
if (typeof window === "undefined") return;
|
|
1620
|
+
try {
|
|
1621
|
+
window.localStorage.setItem(FAB_POS_KEY, JSON.stringify(pos));
|
|
1622
|
+
} catch {
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
function clampNum(v, lo, hi) {
|
|
1626
|
+
return Math.min(Math.max(v, lo), hi);
|
|
1627
|
+
}
|
|
1628
|
+
function clampFabPos(p, w = FAB_SIZE_PX, h = FAB_SIZE_PX) {
|
|
1629
|
+
if (typeof window === "undefined") return p;
|
|
1630
|
+
const maxLeft = Math.max(EDGE_MARGIN, window.innerWidth - w - EDGE_MARGIN);
|
|
1631
|
+
const maxBottom = Math.max(EDGE_MARGIN, window.innerHeight - h - EDGE_MARGIN);
|
|
1632
|
+
return {
|
|
1633
|
+
left: clampNum(p.left, EDGE_MARGIN, maxLeft),
|
|
1634
|
+
bottom: clampNum(p.bottom, EDGE_MARGIN, maxBottom)
|
|
1635
|
+
};
|
|
1636
|
+
}
|
|
1573
1637
|
function QaFab() {
|
|
1574
1638
|
const { isOpen, setIsOpen, notes, captureActive, theme } = useQa();
|
|
1639
|
+
const coarse = useCoarsePointer();
|
|
1640
|
+
const [pos, setPos] = React.useState(() => loadFabPos());
|
|
1641
|
+
const dragRef = React.useRef(null);
|
|
1642
|
+
const didDragRef = React.useRef(false);
|
|
1575
1643
|
if (captureActive) return null;
|
|
1644
|
+
const onPointerDown = (e) => {
|
|
1645
|
+
if (dragRef.current) return;
|
|
1646
|
+
didDragRef.current = false;
|
|
1647
|
+
const target = e.currentTarget;
|
|
1648
|
+
const rect = target.getBoundingClientRect();
|
|
1649
|
+
dragRef.current = {
|
|
1650
|
+
pointerId: e.pointerId,
|
|
1651
|
+
startX: e.clientX,
|
|
1652
|
+
startY: e.clientY,
|
|
1653
|
+
startLeft: rect.left,
|
|
1654
|
+
startBottom: window.innerHeight - rect.bottom,
|
|
1655
|
+
width: rect.width,
|
|
1656
|
+
height: rect.height,
|
|
1657
|
+
dragging: false
|
|
1658
|
+
};
|
|
1659
|
+
try {
|
|
1660
|
+
target.setPointerCapture(e.pointerId);
|
|
1661
|
+
} catch {
|
|
1662
|
+
}
|
|
1663
|
+
};
|
|
1664
|
+
const onPointerMove = (e) => {
|
|
1665
|
+
const d = dragRef.current;
|
|
1666
|
+
if (!d || d.pointerId !== e.pointerId) return;
|
|
1667
|
+
const dx = e.clientX - d.startX;
|
|
1668
|
+
const dy = e.clientY - d.startY;
|
|
1669
|
+
if (!d.dragging) {
|
|
1670
|
+
if (Math.hypot(dx, dy) < DRAG_THRESHOLD) return;
|
|
1671
|
+
d.dragging = true;
|
|
1672
|
+
}
|
|
1673
|
+
setPos(clampFabPos({ left: d.startLeft + dx, bottom: d.startBottom - dy }, d.width, d.height));
|
|
1674
|
+
};
|
|
1675
|
+
const endDrag = (e) => {
|
|
1676
|
+
const d = dragRef.current;
|
|
1677
|
+
if (!d || d.pointerId !== e.pointerId) return null;
|
|
1678
|
+
try {
|
|
1679
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
1680
|
+
} catch {
|
|
1681
|
+
}
|
|
1682
|
+
dragRef.current = null;
|
|
1683
|
+
return d;
|
|
1684
|
+
};
|
|
1685
|
+
const onPointerUp = (e) => {
|
|
1686
|
+
const d = endDrag(e);
|
|
1687
|
+
if (!d) return;
|
|
1688
|
+
if (d.dragging) {
|
|
1689
|
+
const dx = e.clientX - d.startX;
|
|
1690
|
+
const dy = e.clientY - d.startY;
|
|
1691
|
+
const next = clampFabPos({ left: d.startLeft + dx, bottom: d.startBottom - dy }, d.width, d.height);
|
|
1692
|
+
setPos(next);
|
|
1693
|
+
saveFabPos(next);
|
|
1694
|
+
didDragRef.current = true;
|
|
1695
|
+
}
|
|
1696
|
+
};
|
|
1697
|
+
const onPointerCancel = (e) => {
|
|
1698
|
+
endDrag(e);
|
|
1699
|
+
};
|
|
1700
|
+
const handleClick = () => {
|
|
1701
|
+
if (didDragRef.current) {
|
|
1702
|
+
didDragRef.current = false;
|
|
1703
|
+
return;
|
|
1704
|
+
}
|
|
1705
|
+
setIsOpen(!isOpen);
|
|
1706
|
+
};
|
|
1707
|
+
const applied = coarse && pos ? clampFabPos(pos) : null;
|
|
1708
|
+
const fabStyle = {
|
|
1709
|
+
left: applied ? `${applied.left}px` : DEFAULT_LEFT,
|
|
1710
|
+
bottom: applied ? `${applied.bottom}px` : DEFAULT_BOTTOM,
|
|
1711
|
+
width: "3.5rem",
|
|
1712
|
+
height: "3.5rem",
|
|
1713
|
+
backgroundImage: `linear-gradient(135deg, ${theme.primary}, ${theme.accent})`,
|
|
1714
|
+
boxShadow: "0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04), 0 0 0 2px rgba(255,255,255,0.7)",
|
|
1715
|
+
zIndex: 9990
|
|
1716
|
+
};
|
|
1576
1717
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1577
1718
|
"button",
|
|
1578
1719
|
{
|
|
1579
1720
|
type: "button",
|
|
1580
1721
|
"data-qa-overlay": "true",
|
|
1581
1722
|
dir: "ltr",
|
|
1582
|
-
onClick:
|
|
1723
|
+
onClick: handleClick,
|
|
1724
|
+
onPointerDown: coarse ? onPointerDown : void 0,
|
|
1725
|
+
onPointerMove: coarse ? onPointerMove : void 0,
|
|
1726
|
+
onPointerUp: coarse ? onPointerUp : void 0,
|
|
1727
|
+
onPointerCancel: coarse ? onPointerCancel : void 0,
|
|
1583
1728
|
"aria-label": "Qapture \u2014 testing notes",
|
|
1584
1729
|
title: "Qapture",
|
|
1585
|
-
className:
|
|
1586
|
-
style:
|
|
1587
|
-
left: "calc(1.25rem + env(safe-area-inset-left))",
|
|
1588
|
-
bottom: "calc(5rem + env(safe-area-inset-bottom))",
|
|
1589
|
-
width: "3.5rem",
|
|
1590
|
-
height: "3.5rem",
|
|
1591
|
-
backgroundImage: `linear-gradient(135deg, ${theme.primary}, ${theme.accent})`,
|
|
1592
|
-
boxShadow: "0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04), 0 0 0 2px rgba(255,255,255,0.7)",
|
|
1593
|
-
zIndex: 9990
|
|
1594
|
-
},
|
|
1730
|
+
className: `qa-fixed qa-flex qa-items-center qa-justify-center qa-rounded-full qa-text-white qa-print-hidden qa-fab-btn${coarse ? " qa-touch-none" : ""}`,
|
|
1731
|
+
style: fabStyle,
|
|
1595
1732
|
children: [
|
|
1596
1733
|
!isOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1597
1734
|
"span",
|
|
@@ -2554,6 +2691,20 @@ function panelReducer(state, action) {
|
|
|
2554
2691
|
return state;
|
|
2555
2692
|
}
|
|
2556
2693
|
}
|
|
2694
|
+
var KEYBOARD_OVERLAP_THRESHOLD = 120;
|
|
2695
|
+
var KEYBOARD_LIFT_GAP = 12;
|
|
2696
|
+
var NON_TEXT_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
2697
|
+
"checkbox",
|
|
2698
|
+
"radio",
|
|
2699
|
+
"range",
|
|
2700
|
+
"button",
|
|
2701
|
+
"submit",
|
|
2702
|
+
"reset",
|
|
2703
|
+
"color",
|
|
2704
|
+
"file",
|
|
2705
|
+
"image"
|
|
2706
|
+
]);
|
|
2707
|
+
var PANEL_TRANSITION_WITH_LIFT = "opacity 200ms cubic-bezier(0.4,0,0.2,1), transform 200ms cubic-bezier(0.4,0,0.2,1), bottom 200ms cubic-bezier(0.4,0,0.2,1)";
|
|
2557
2708
|
function QaPanel() {
|
|
2558
2709
|
const {
|
|
2559
2710
|
isOpen,
|
|
@@ -2619,6 +2770,61 @@ function QaPanel() {
|
|
|
2619
2770
|
mql.addListener(handleChange);
|
|
2620
2771
|
return () => mql.removeListener(handleChange);
|
|
2621
2772
|
}, []);
|
|
2773
|
+
const coarse = useCoarsePointer();
|
|
2774
|
+
const panelRef = React.useRef(null);
|
|
2775
|
+
const [keyboardLift, setKeyboardLift] = React.useState(0);
|
|
2776
|
+
const computeKeyboardLift = React.useCallback(() => {
|
|
2777
|
+
try {
|
|
2778
|
+
if (!coarse || isIpadLandscape) return 0;
|
|
2779
|
+
if (typeof window === "undefined") return 0;
|
|
2780
|
+
const vv = window.visualViewport;
|
|
2781
|
+
if (!vv) return 0;
|
|
2782
|
+
const overlap = Math.max(0, window.innerHeight - vv.height - vv.offsetTop);
|
|
2783
|
+
if (overlap <= KEYBOARD_OVERLAP_THRESHOLD) return 0;
|
|
2784
|
+
const panel = panelRef.current;
|
|
2785
|
+
if (!panel) return 0;
|
|
2786
|
+
const root = panel.getRootNode();
|
|
2787
|
+
const active = root.activeElement;
|
|
2788
|
+
if (!active || !panel.contains(active)) return 0;
|
|
2789
|
+
const tag = active.tagName;
|
|
2790
|
+
if (tag === "TEXTAREA") return Math.round(overlap) + KEYBOARD_LIFT_GAP;
|
|
2791
|
+
if (tag === "INPUT" && !NON_TEXT_INPUT_TYPES.has(active.type)) {
|
|
2792
|
+
return Math.round(overlap) + KEYBOARD_LIFT_GAP;
|
|
2793
|
+
}
|
|
2794
|
+
return 0;
|
|
2795
|
+
} catch {
|
|
2796
|
+
return 0;
|
|
2797
|
+
}
|
|
2798
|
+
}, [coarse, isIpadLandscape]);
|
|
2799
|
+
React.useEffect(() => {
|
|
2800
|
+
if (!coarse) return void 0;
|
|
2801
|
+
if (typeof window === "undefined" || typeof document === "undefined") return void 0;
|
|
2802
|
+
const vv = window.visualViewport;
|
|
2803
|
+
if (!vv) return void 0;
|
|
2804
|
+
let closeTimer;
|
|
2805
|
+
const recompute = () => setKeyboardLift(computeKeyboardLift());
|
|
2806
|
+
const recomputeSoon = () => {
|
|
2807
|
+
if (closeTimer !== void 0) clearTimeout(closeTimer);
|
|
2808
|
+
closeTimer = setTimeout(recompute, 80);
|
|
2809
|
+
};
|
|
2810
|
+
recompute();
|
|
2811
|
+
vv.addEventListener("resize", recompute);
|
|
2812
|
+
vv.addEventListener("scroll", recompute);
|
|
2813
|
+
document.addEventListener("focusin", recompute);
|
|
2814
|
+
document.addEventListener("focusout", recomputeSoon);
|
|
2815
|
+
return () => {
|
|
2816
|
+
if (closeTimer !== void 0) clearTimeout(closeTimer);
|
|
2817
|
+
vv.removeEventListener("resize", recompute);
|
|
2818
|
+
vv.removeEventListener("scroll", recompute);
|
|
2819
|
+
document.removeEventListener("focusin", recompute);
|
|
2820
|
+
document.removeEventListener("focusout", recomputeSoon);
|
|
2821
|
+
};
|
|
2822
|
+
}, [coarse, computeKeyboardLift]);
|
|
2823
|
+
React.useEffect(() => {
|
|
2824
|
+
if (!isOpen) setKeyboardLift(0);
|
|
2825
|
+
}, [isOpen]);
|
|
2826
|
+
const keyboardLiftActive = coarse && !isIpadLandscape;
|
|
2827
|
+
const appliedKeyboardLift = keyboardLiftActive ? keyboardLift : 0;
|
|
2622
2828
|
if (phase === "hidden") return null;
|
|
2623
2829
|
const openNaming = () => {
|
|
2624
2830
|
setFilename(todayName());
|
|
@@ -2629,9 +2835,12 @@ function QaPanel() {
|
|
|
2629
2835
|
void exportZip(filename);
|
|
2630
2836
|
};
|
|
2631
2837
|
const namingCoverage = naming ? computeCoverage(journey, guideChecked) : null;
|
|
2838
|
+
const restBottomRem = dir === "rtl" ? "9rem" : "8.75rem";
|
|
2839
|
+
const panelBottom = isIpadLandscape ? "0" : appliedKeyboardLift > 0 ? `calc(${restBottomRem} + env(safe-area-inset-bottom) + ${appliedKeyboardLift}px)` : `calc(${restBottomRem} + env(safe-area-inset-bottom))`;
|
|
2632
2840
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2633
2841
|
"div",
|
|
2634
2842
|
{
|
|
2843
|
+
ref: panelRef,
|
|
2635
2844
|
"data-qa-overlay": "true",
|
|
2636
2845
|
dir,
|
|
2637
2846
|
onTransitionEnd: handleTransitionEnd,
|
|
@@ -2642,7 +2851,7 @@ function QaPanel() {
|
|
|
2642
2851
|
left: isIpadLandscape ? "auto" : "calc(1rem + env(safe-area-inset-left))",
|
|
2643
2852
|
right: isIpadLandscape ? "0" : void 0,
|
|
2644
2853
|
top: isIpadLandscape ? "0" : void 0,
|
|
2645
|
-
bottom:
|
|
2854
|
+
bottom: panelBottom,
|
|
2646
2855
|
height: isIpadLandscape ? "100dvh" : void 0,
|
|
2647
2856
|
width: isIpadLandscape ? "min(92vw, 420px)" : void 0,
|
|
2648
2857
|
// qa-max-h-74vh (class) would otherwise cap the sheet well short of
|
|
@@ -2652,7 +2861,12 @@ function QaPanel() {
|
|
|
2652
2861
|
background: theme.surface,
|
|
2653
2862
|
borderColor: `${theme.primary}22`,
|
|
2654
2863
|
fontFamily: lang === "ar" ? "'Tajawal', sans-serif" : "'Nunito', system-ui, sans-serif",
|
|
2655
|
-
zIndex: 9990
|
|
2864
|
+
zIndex: 9990,
|
|
2865
|
+
// Keyboard-avoidance lift (coarse/touch only — see effect above).
|
|
2866
|
+
// undefined ⇒ !keyboardLiftActive, so desktop and the iPad-landscape
|
|
2867
|
+
// side-sheet render this property exactly as before (the class's own
|
|
2868
|
+
// opacity/transform transition applies, untouched).
|
|
2869
|
+
transition: keyboardLiftActive ? PANEL_TRANSITION_WITH_LIFT : void 0
|
|
2656
2870
|
},
|
|
2657
2871
|
children: [
|
|
2658
2872
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -3036,29 +3250,6 @@ function getStableSelector(el) {
|
|
|
3036
3250
|
}
|
|
3037
3251
|
return nthOfTypePath(el);
|
|
3038
3252
|
}
|
|
3039
|
-
function isCoarsePointer() {
|
|
3040
|
-
if (typeof window === "undefined") return false;
|
|
3041
|
-
try {
|
|
3042
|
-
if (window.matchMedia && window.matchMedia("(pointer: coarse)").matches) return true;
|
|
3043
|
-
} catch {
|
|
3044
|
-
}
|
|
3045
|
-
return typeof navigator !== "undefined" && (navigator.maxTouchPoints || 0) > 0;
|
|
3046
|
-
}
|
|
3047
|
-
function useCoarsePointer() {
|
|
3048
|
-
const [coarse, setCoarse] = React.useState(() => isCoarsePointer());
|
|
3049
|
-
React.useEffect(() => {
|
|
3050
|
-
if (typeof window === "undefined" || !window.matchMedia) return;
|
|
3051
|
-
const mq = window.matchMedia("(pointer: coarse)");
|
|
3052
|
-
const on = () => setCoarse(isCoarsePointer());
|
|
3053
|
-
if (mq.addEventListener) mq.addEventListener("change", on);
|
|
3054
|
-
else if (mq.addListener) mq.addListener(on);
|
|
3055
|
-
return () => {
|
|
3056
|
-
if (mq.removeEventListener) mq.removeEventListener("change", on);
|
|
3057
|
-
else if (mq.removeListener) mq.removeListener(on);
|
|
3058
|
-
};
|
|
3059
|
-
}, []);
|
|
3060
|
-
return coarse;
|
|
3061
|
-
}
|
|
3062
3253
|
|
|
3063
3254
|
// src/lib/scrollLock.ts
|
|
3064
3255
|
var locked = false;
|
|
@@ -3080,7 +3271,7 @@ function unlockPageScroll() {
|
|
|
3080
3271
|
if (document.body) document.body.style.overflow = prevBodyOverflow;
|
|
3081
3272
|
locked = false;
|
|
3082
3273
|
}
|
|
3083
|
-
var
|
|
3274
|
+
var DRAG_THRESHOLD2 = 6;
|
|
3084
3275
|
var TOUCH_DRAG_THRESHOLD = 12;
|
|
3085
3276
|
var MIN_REGION_SIZE = 8;
|
|
3086
3277
|
var REGION_HANDLES = [
|
|
@@ -3203,7 +3394,7 @@ function CaptureMode() {
|
|
|
3203
3394
|
activePointerId.current = null;
|
|
3204
3395
|
const d = dragRef.current;
|
|
3205
3396
|
dragRef.current = null;
|
|
3206
|
-
const threshold = pointerKind.current === "mouse" ?
|
|
3397
|
+
const threshold = pointerKind.current === "mouse" ? DRAG_THRESHOLD2 : TOUCH_DRAG_THRESHOLD;
|
|
3207
3398
|
const moved = d !== null && Math.hypot(e.clientX - d.x0, e.clientY - d.y0) > threshold;
|
|
3208
3399
|
scrollSnap.current = { x: window.scrollX, y: window.scrollY };
|
|
3209
3400
|
if (moved && d) {
|
|
@@ -3827,5 +4018,5 @@ function Qapture({ config }) {
|
|
|
3827
4018
|
|
|
3828
4019
|
exports.Qapture = Qapture;
|
|
3829
4020
|
exports.initQaStudio = initQaStudio;
|
|
3830
|
-
//# sourceMappingURL=chunk-
|
|
3831
|
-
//# sourceMappingURL=chunk-
|
|
4021
|
+
//# sourceMappingURL=chunk-PC6LNG5Y.cjs.map
|
|
4022
|
+
//# sourceMappingURL=chunk-PC6LNG5Y.cjs.map
|
package/dist/index.cjs
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkPC6LNG5Y_cjs = require('./chunk-PC6LNG5Y.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
Object.defineProperty(exports, "QaStudio", {
|
|
8
8
|
enumerable: true,
|
|
9
|
-
get: function () { return
|
|
9
|
+
get: function () { return chunkPC6LNG5Y_cjs.Qapture; }
|
|
10
10
|
});
|
|
11
11
|
Object.defineProperty(exports, "Qapture", {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
13
|
+
get: function () { return chunkPC6LNG5Y_cjs.Qapture; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, "initQaStudio", {
|
|
16
16
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
17
|
+
get: function () { return chunkPC6LNG5Y_cjs.initQaStudio; }
|
|
18
18
|
});
|
|
19
19
|
//# sourceMappingURL=index.cjs.map
|
|
20
20
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.cts
CHANGED
|
@@ -165,11 +165,11 @@ declare function initQaStudio(config?: QaConfig): {
|
|
|
165
165
|
* (destroy + remount if needed).
|
|
166
166
|
*
|
|
167
167
|
* Usage (Next.js App Router):
|
|
168
|
-
* import { Qapture } from '
|
|
168
|
+
* import { Qapture } from 'qapture2/next'; // adds 'use client' banner
|
|
169
169
|
* <Qapture config={qaConfig} />
|
|
170
170
|
*
|
|
171
171
|
* Usage (any React app):
|
|
172
|
-
* import { Qapture } from '
|
|
172
|
+
* import { Qapture } from 'qapture2';
|
|
173
173
|
* <Qapture config={qaConfig} />
|
|
174
174
|
*/
|
|
175
175
|
declare function Qapture({ config }: {
|
package/dist/index.d.ts
CHANGED
|
@@ -165,11 +165,11 @@ declare function initQaStudio(config?: QaConfig): {
|
|
|
165
165
|
* (destroy + remount if needed).
|
|
166
166
|
*
|
|
167
167
|
* Usage (Next.js App Router):
|
|
168
|
-
* import { Qapture } from '
|
|
168
|
+
* import { Qapture } from 'qapture2/next'; // adds 'use client' banner
|
|
169
169
|
* <Qapture config={qaConfig} />
|
|
170
170
|
*
|
|
171
171
|
* Usage (any React app):
|
|
172
|
-
* import { Qapture } from '
|
|
172
|
+
* import { Qapture } from 'qapture2';
|
|
173
173
|
* <Qapture config={qaConfig} />
|
|
174
174
|
*/
|
|
175
175
|
declare function Qapture({ config }: {
|
package/dist/index.js
CHANGED
package/dist/next.cjs
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunkPC6LNG5Y_cjs = require('./chunk-PC6LNG5Y.cjs');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, "QaStudio", {
|
|
9
9
|
enumerable: true,
|
|
10
|
-
get: function () { return
|
|
10
|
+
get: function () { return chunkPC6LNG5Y_cjs.Qapture; }
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "Qapture", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunkPC6LNG5Y_cjs.Qapture; }
|
|
15
15
|
});
|
|
16
16
|
Object.defineProperty(exports, "initQaStudio", {
|
|
17
17
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunkPC6LNG5Y_cjs.initQaStudio; }
|
|
19
19
|
});
|
|
20
20
|
//# sourceMappingURL=next.cjs.map
|
|
21
21
|
//# sourceMappingURL=next.cjs.map
|
package/dist/next.js
CHANGED
package/dist/standalone.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkPC6LNG5Y_cjs = require('./chunk-PC6LNG5Y.cjs');
|
|
4
4
|
|
|
5
5
|
// src/standalone.ts
|
|
6
6
|
if (typeof window !== "undefined" && typeof customElements !== "undefined" && !customElements.get("qapture-widget")) {
|
|
@@ -33,7 +33,7 @@ if (typeof window !== "undefined" && typeof customElements !== "undefined" && !c
|
|
|
33
33
|
|
|
34
34
|
Object.defineProperty(exports, "initQaStudio", {
|
|
35
35
|
enumerable: true,
|
|
36
|
-
get: function () { return
|
|
36
|
+
get: function () { return chunkPC6LNG5Y_cjs.initQaStudio; }
|
|
37
37
|
});
|
|
38
38
|
//# sourceMappingURL=standalone.cjs.map
|
|
39
39
|
//# sourceMappingURL=standalone.cjs.map
|
package/dist/standalone.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qapture2",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Drop-in, AI-aware in-browser QA capture widget. A tester annotates the live app (element/region + auto-screenshot + note), tracks a graded testing journey, and exports a ZIP your own coding agent reads. Ships zero AI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"./package.json": "./package.json"
|
|
56
56
|
},
|
|
57
57
|
"bin": {
|
|
58
|
-
"qapture2": "
|
|
58
|
+
"qapture2": "dist/bin/init.cjs"
|
|
59
59
|
},
|
|
60
60
|
"repository": {
|
|
61
61
|
"type": "git",
|