@hunterchen/canvas 0.8.0 → 0.9.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.
Files changed (39) hide show
  1. package/dist/components/canvas/backgrounds.js +67 -38
  2. package/dist/components/canvas/backgrounds.js.map +1 -1
  3. package/dist/components/canvas/canvas.js +451 -387
  4. package/dist/components/canvas/canvas.js.map +1 -1
  5. package/dist/components/canvas/component.js +108 -174
  6. package/dist/components/canvas/component.js.map +1 -1
  7. package/dist/components/canvas/draggable.js +168 -151
  8. package/dist/components/canvas/draggable.js.map +1 -1
  9. package/dist/components/canvas/navbar/index.js +164 -142
  10. package/dist/components/canvas/navbar/index.js.map +1 -1
  11. package/dist/components/canvas/navbar/single-button.js +176 -149
  12. package/dist/components/canvas/navbar/single-button.js.map +1 -1
  13. package/dist/components/canvas/toolbar.js +121 -82
  14. package/dist/components/canvas/toolbar.js.map +1 -1
  15. package/dist/components/canvas/wrapper.js +127 -99
  16. package/dist/components/canvas/wrapper.js.map +1 -1
  17. package/dist/contexts/CanvasContext.js +25 -17
  18. package/dist/contexts/CanvasContext.js.map +1 -1
  19. package/dist/contexts/PerformanceContext.js +51 -50
  20. package/dist/contexts/PerformanceContext.js.map +1 -1
  21. package/dist/hooks/usePerformanceMode.js +36 -37
  22. package/dist/hooks/usePerformanceMode.js.map +1 -1
  23. package/dist/hooks/useWindowDimensions.js +22 -18
  24. package/dist/hooks/useWindowDimensions.js.map +1 -1
  25. package/dist/index.js +17 -21
  26. package/dist/lib/canvas.js +65 -72
  27. package/dist/lib/canvas.js.map +1 -1
  28. package/dist/lib/constants.js +78 -92
  29. package/dist/lib/constants.js.map +1 -1
  30. package/dist/lib/utils.js +10 -5
  31. package/dist/lib/utils.js.map +1 -1
  32. package/dist/utils/performance.js +18 -23
  33. package/dist/utils/performance.js.map +1 -1
  34. package/package.json +7 -21
  35. package/dist/components/canvas/offest.js +0 -12
  36. package/dist/components/canvas/offest.js.map +0 -1
  37. package/dist/index.js.map +0 -1
  38. package/dist/types/index.js +0 -6
  39. package/dist/types/index.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../../src/components/canvas/toolbar.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"toolbar.js","names":[],"sources":["../../../src/components/canvas/toolbar.tsx"],"sourcesContent":["import { type Point, useTransform, motion } from \"framer-motion\";\nimport { useEffect, useState, useMemo } from \"react\";\nimport { useCanvasContext } from \"../../contexts/CanvasContext\";\nimport {\n TOOLBAR_OPACITY_POS_EPS,\n TOOLBAR_OPACITY_SCALE_EPS,\n} from \"../../lib/constants\";\nimport { cn } from \"../../lib/utils\";\nimport type { ToolbarConfig, ToolbarPosition } from \"../../types\";\n\ntype ToolbarProps = {\n homeCoordinates?: Point;\n config?: ToolbarConfig;\n};\n\nconst positionStyles: Record<ToolbarPosition, string> = {\n \"top-left\": \"left-4 top-6 sm:top-4\",\n \"top-right\": \"right-4 top-6 sm:top-4\",\n \"bottom-left\": \"left-4 bottom-6 sm:bottom-4\",\n \"bottom-right\": \"right-4 bottom-6 sm:bottom-4\",\n};\n\nconst Toolbar = ({\n homeCoordinates = { x: 0, y: 0 },\n config = {},\n}: ToolbarProps) => {\n const { x, y, scale } = useCanvasContext();\n const [hasMounted, setHasMounted] = useState(false);\n\n const {\n display = \"both\",\n position = \"top-left\",\n disableAutoHide = false,\n className,\n coordinatesClassName,\n scaleClassName,\n separatorClassName,\n style,\n coordinatesStyle,\n scaleStyle,\n separator = \"|\",\n separatorGap,\n coordinatesFormat,\n scaleFormat,\n } = config;\n\n const separatorStyle: React.CSSProperties | undefined = separatorGap\n ? {\n marginInline:\n typeof separatorGap === \"number\" ? `${separatorGap}px` : separatorGap,\n }\n : undefined;\n\n useEffect(() => {\n setHasMounted(true);\n }, []);\n\n // numeric MotionValues\n const rawDx = useTransform(\n [x, scale],\n ([lx, ls]) => -((lx as number) / (ls as number)) + homeCoordinates.x\n );\n const rawDy = useTransform(\n [y, scale],\n ([ly, ls]) => -((ly as number) / (ls as number)) + homeCoordinates.y\n );\n\n // formatted MotionValues for default display\n const displayX = useTransform(rawDx, (v) => Math.round(v).toString());\n const displayY = useTransform(rawDy, (v) => Math.round(v).toString());\n const displayScale = useTransform(scale, (v) => v.toFixed(2));\n\n // For custom formatters, we need to use state to track values\n const [currentX, setCurrentX] = useState(0);\n const [currentY, setCurrentY] = useState(0);\n const [currentScale, setCurrentScale] = useState(1);\n\n useEffect(() => {\n const unsubX = rawDx.on(\"change\", (v) => setCurrentX(Math.round(v)));\n const unsubY = rawDy.on(\"change\", (v) => setCurrentY(Math.round(v)));\n const unsubScale = scale.on(\"change\", (v) => setCurrentScale(v));\n return () => {\n unsubX();\n unsubY();\n unsubScale();\n };\n }, [rawDx, rawDy, scale]);\n\n const opacity = useTransform([rawDx, rawDy, scale], ([dx, dy, ls]) => {\n if (disableAutoHide) return 1;\n return Math.abs(dx as number) < TOOLBAR_OPACITY_POS_EPS &&\n Math.abs(dy as number) < TOOLBAR_OPACITY_POS_EPS &&\n Math.abs((ls as number) - 1) < TOOLBAR_OPACITY_SCALE_EPS\n ? 0\n : 1;\n });\n\n const handlePointerDown = (e: React.PointerEvent) => e.stopPropagation();\n\n const showCoordinates = display === \"coordinates\" || display === \"both\";\n const showScale = display === \"scale\" || display === \"both\";\n const showSeparator = display === \"both\";\n\n // Compute formatted values\n const formattedCoordinates = useMemo(() => {\n if (coordinatesFormat) {\n return coordinatesFormat(currentX, currentY);\n }\n return null; // Will use motion spans for default\n }, [coordinatesFormat, currentX, currentY]);\n\n const formattedScale = useMemo(() => {\n if (scaleFormat) {\n return scaleFormat(currentScale);\n }\n return null; // Will use motion span for default\n }, [scaleFormat, currentScale]);\n\n // Placeholder content for SSR/initial render\n const placeholderContent = useMemo(() => {\n const parts: string[] = [];\n if (showCoordinates) parts.push(\"(0, 0)\");\n if (showSeparator) parts.push(separator);\n if (showScale) parts.push(\"1.00x\");\n return parts.join(\"\");\n }, [showCoordinates, showScale, showSeparator, separator]);\n\n return (\n <motion.div\n className={cn(\n \"absolute z-[1000] cursor-default select-none rounded-[10px] border border-border bg-canvas-offwhite p-2 font-mono text-xs text-canvas-heavy shadow-[0_6px_12px_rgba(0,0,0,0.10)] md:text-sm\",\n positionStyles[position],\n className\n )}\n onPointerDown={handlePointerDown}\n data-toolbar-button\n style={{ opacity, ...style }}\n >\n {hasMounted ? (\n <>\n {showCoordinates && (\n <span className={coordinatesClassName} style={coordinatesStyle}>\n {formattedCoordinates !== null ? (\n formattedCoordinates\n ) : (\n <>\n (<motion.span>{displayX}</motion.span>,{\" \"}\n <motion.span>{displayY}</motion.span>)\n </>\n )}\n </span>\n )}\n {showSeparator && (\n <span\n className={cn(\"text-canvas-light\", separatorClassName)}\n style={separatorStyle}\n >\n {separator}\n </span>\n )}\n {showScale && (\n <span className={scaleClassName} style={scaleStyle}>\n {formattedScale !== null ? (\n formattedScale\n ) : (\n <>\n <motion.span>{displayScale}</motion.span>x\n </>\n )}\n </span>\n )}\n </>\n ) : (\n <span style={{ opacity: 0 }}>{placeholderContent}</span>\n )}\n </motion.div>\n );\n};\n\nexport default Toolbar;\n"],"mappings":";;;;;;;;AAeA,MAAM,iBAAkD;CACtD,YAAY;CACZ,aAAa;CACb,eAAe;CACf,gBAAgB;CACjB;AAED,MAAM,WAAW,EACf,kBAAkB;CAAE,GAAG;CAAG,GAAG;CAAG,EAChC,SAAS,EAAE,OACO;CAClB,MAAM,EAAE,GAAG,GAAG,UAAU,kBAAkB;CAC1C,MAAM,CAAC,YAAY,iBAAiB,SAAS,MAAM;CAEnD,MAAM,EACJ,UAAU,QACV,WAAW,YACX,kBAAkB,OAClB,WACA,sBACA,gBACA,oBACA,OACA,kBACA,YACA,YAAY,KACZ,cACA,mBACA,gBACE;CAEJ,MAAM,iBAAkD,eACpD,EACE,cACE,OAAO,iBAAiB,WAAW,GAAG,aAAa,MAAM,cAC5D,GACD;AAEJ,iBAAgB;AACd,gBAAc,KAAK;IAClB,EAAE,CAAC;CAGN,MAAM,QAAQ,aACZ,CAAC,GAAG,MAAM,GACT,CAAC,IAAI,QAAQ,EAAG,KAAiB,MAAiB,gBAAgB,EACpE;CACD,MAAM,QAAQ,aACZ,CAAC,GAAG,MAAM,GACT,CAAC,IAAI,QAAQ,EAAG,KAAiB,MAAiB,gBAAgB,EACpE;CAGD,MAAM,WAAW,aAAa,QAAQ,MAAM,KAAK,MAAM,EAAE,CAAC,UAAU,CAAC;CACrE,MAAM,WAAW,aAAa,QAAQ,MAAM,KAAK,MAAM,EAAE,CAAC,UAAU,CAAC;CACrE,MAAM,eAAe,aAAa,QAAQ,MAAM,EAAE,QAAQ,EAAE,CAAC;CAG7D,MAAM,CAAC,UAAU,eAAe,SAAS,EAAE;CAC3C,MAAM,CAAC,UAAU,eAAe,SAAS,EAAE;CAC3C,MAAM,CAAC,cAAc,mBAAmB,SAAS,EAAE;AAEnD,iBAAgB;EACd,MAAM,SAAS,MAAM,GAAG,WAAW,MAAM,YAAY,KAAK,MAAM,EAAE,CAAC,CAAC;EACpE,MAAM,SAAS,MAAM,GAAG,WAAW,MAAM,YAAY,KAAK,MAAM,EAAE,CAAC,CAAC;EACpE,MAAM,aAAa,MAAM,GAAG,WAAW,MAAM,gBAAgB,EAAE,CAAC;AAChE,eAAa;AACX,WAAQ;AACR,WAAQ;AACR,eAAY;;IAEb;EAAC;EAAO;EAAO;EAAM,CAAC;CAEzB,MAAM,UAAU,aAAa;EAAC;EAAO;EAAO;EAAM,GAAG,CAAC,IAAI,IAAI,QAAQ;AACpE,MAAI,gBAAiB,QAAO;AAC5B,SAAO,KAAK,IAAI,GAAa,GAAG,2BAC9B,KAAK,IAAI,GAAa,GAAG,2BACzB,KAAK,IAAK,KAAgB,EAAE,GAAG,4BAC7B,IACA;GACJ;CAEF,MAAM,qBAAqB,MAA0B,EAAE,iBAAiB;CAExE,MAAM,kBAAkB,YAAY,iBAAiB,YAAY;CACjE,MAAM,YAAY,YAAY,WAAW,YAAY;CACrD,MAAM,gBAAgB,YAAY;CAGlC,MAAM,uBAAuB,cAAc;AACzC,MAAI,kBACF,QAAO,kBAAkB,UAAU,SAAS;AAE9C,SAAO;IACN;EAAC;EAAmB;EAAU;EAAS,CAAC;CAE3C,MAAM,iBAAiB,cAAc;AACnC,MAAI,YACF,QAAO,YAAY,aAAa;AAElC,SAAO;IACN,CAAC,aAAa,aAAa,CAAC;CAG/B,MAAM,qBAAqB,cAAc;EACvC,MAAM,QAAkB,EAAE;AAC1B,MAAI,gBAAiB,OAAM,KAAK,SAAS;AACzC,MAAI,cAAe,OAAM,KAAK,UAAU;AACxC,MAAI,UAAW,OAAM,KAAK,QAAQ;AAClC,SAAO,MAAM,KAAK,GAAG;IACpB;EAAC;EAAiB;EAAW;EAAe;EAAU,CAAC;AAE1D,QACE,oBAAC,OAAO;EACN,WAAW,GACT,+LACA,eAAe,WACf,UACD;EACD,eAAe;EACf;EACA,OAAO;GAAE;GAAS,GAAG;GAAO;YAE3B,aACC;GACG,mBACC,oBAAC;IAAK,WAAW;IAAsB,OAAO;cAC3C,yBAAyB,OACxB,uBAEA;KAAE;KACC,oBAAC,OAAO,kBAAM,WAAuB;;KAAE;KACxC,oBAAC,OAAO,kBAAM,WAAuB;;QACpC;KAEA;GAER,iBACC,oBAAC;IACC,WAAW,GAAG,qBAAqB,mBAAmB;IACtD,OAAO;cAEN;KACI;GAER,aACC,oBAAC;IAAK,WAAW;IAAgB,OAAO;cACrC,mBAAmB,OAClB,iBAEA,4CACE,oBAAC,OAAO,kBAAM,eAA2B,SACxC;KAEA;MAER,GAEH,oBAAC;GAAK,OAAO,EAAE,SAAS,GAAG;aAAG;IAA0B;GAE/C;;AAIjB,sBAAe"}
@@ -1,102 +1,130 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { BLUR_TRANSITION, GROW_TRANSITION, INTRO_ASPECT_RATIO, MAX_DIM_RATIO } from "../../lib/constants.js";
2
2
  import { motion } from "framer-motion";
3
- import { useState, useEffect, useRef } from "react";
4
- import { MAX_DIM_RATIO, GROW_TRANSITION, BLUR_TRANSITION, INTRO_ASPECT_RATIO, } from "../../lib/constants";
5
- // Re-export for backward compatibility
6
- export { GROW_TRANSITION as growTransition } from "../../lib/constants";
7
- export const CanvasWrapper = ({ children, introProgress, onIntroGrowComplete, skipIntro = false, introContent, loadingText = "LOADING CANVAS", introBackgroundGradient = "linear-gradient(to top, #d4d4d4 0%, #e5e5e5 50%, #f5f5f5 100%)", wrapperBackground, canvasBoxGradient = "radial-gradient(130.38% 95% at 50.03% 97.25%, #d4d4d4 0%, #e5e5e5 48.09%, #f5f5f5 100%)", growTransition = GROW_TRANSITION, blurTransition = BLUR_TRANSITION, }) => {
8
- const [dimensions, setDimensions] = useState(null);
9
- const [dots, setDots] = useState("..");
10
- const [stage1NotFinished, setStage1NotFinished] = useState(true);
11
- const completedRef = useRef(false);
12
- // If skipIntro is true, immediately complete the intro
13
- useEffect(() => {
14
- if (skipIntro && !completedRef.current) {
15
- completedRef.current = true;
16
- introProgress.set(1);
17
- onIntroGrowComplete?.();
18
- }
19
- }, [skipIntro, introProgress, onIntroGrowComplete]);
20
- // add up to 4 dots, then go back down to 2
21
- useEffect(() => {
22
- if (skipIntro)
23
- return; // Don't animate dots if skipping intro
24
- const interval = setInterval(() => {
25
- setDots((prevDots) => {
26
- if (prevDots.length < 3) {
27
- return prevDots + ".";
28
- }
29
- else {
30
- return ".";
31
- }
32
- });
33
- }, 500);
34
- return () => clearInterval(interval);
35
- }, [skipIntro]);
36
- useEffect(() => {
37
- if (skipIntro)
38
- return; // Don't calculate dimensions if skipping intro
39
- // calculate the initial 3:2 box size with margins (client-only)
40
- const calculateInitialSize = () => {
41
- const vw = window.innerWidth;
42
- const vh = window.innerHeight;
43
- const maxWidth = vw * MAX_DIM_RATIO.width;
44
- const maxHeight = vh * MAX_DIM_RATIO.height;
45
- // width or height as limiter
46
- if (maxWidth / INTRO_ASPECT_RATIO <= maxHeight) {
47
- return { width: maxWidth, height: maxWidth / INTRO_ASPECT_RATIO };
48
- }
49
- else {
50
- return { height: maxHeight, width: maxHeight * INTRO_ASPECT_RATIO };
51
- }
52
- };
53
- setDimensions(calculateInitialSize());
54
- }, [skipIntro]);
55
- // If skipIntro, render children directly without animation wrapper
56
- if (skipIntro) {
57
- return (_jsx(motion.div, { className: "fixed inset-0 overflow-hidden", style: {
58
- touchAction: "none",
59
- userSelect: "none",
60
- pointerEvents: "none",
61
- }, onContextMenu: (e) => e.preventDefault(), children: children }));
62
- }
63
- return (_jsxs(motion.div, { className: "fixed inset-0 overflow-hidden", style: {
64
- // Only use gradient style if no custom wrapperBackground is provided
65
- backgroundImage: stage1NotFinished && !wrapperBackground ? introBackgroundGradient : undefined,
66
- touchAction: "none",
67
- userSelect: "none",
68
- pointerEvents: "none",
69
- }, onContextMenu: (e) => e.preventDefault(), children: [stage1NotFinished && wrapperBackground, stage1NotFinished && (_jsx(_Fragment, { children: introContent })), dimensions && (_jsxs(_Fragment, { children: [_jsx(motion.div, { initial: {
70
- width: dimensions.width,
71
- height: dimensions.height,
72
- opacity: 1,
73
- backgroundImage: canvasBoxGradient,
74
- }, animate: {
75
- opacity: 0,
76
- display: "none",
77
- }, transition: blurTransition, className: "absolute left-1/2 top-1/2 z-20 origin-center -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg" }), _jsx(motion.div, { initial: {
78
- width: dimensions.width,
79
- height: dimensions.height,
80
- }, animate: {
81
- width: "100vw",
82
- height: "100vh",
83
- }, transition: growTransition, onUpdate: (latest) => {
84
- if (completedRef.current)
85
- return;
86
- if (typeof latest.width === "number") {
87
- const w0 = dimensions.width;
88
- const w1 = window.innerWidth;
89
- const progress = w1 === w0 ? 1 : (latest.width - w0) / (w1 - w0);
90
- const clamped = Math.min(Math.max(progress, 0), 1);
91
- introProgress.set(clamped);
92
- }
93
- }, onAnimationComplete: () => {
94
- if (!completedRef.current) {
95
- completedRef.current = true;
96
- introProgress.set(1);
97
- setStage1NotFinished(false);
98
- onIntroGrowComplete?.();
99
- }
100
- }, className: "absolute left-1/2 top-1/2 z-10 origin-center -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg shadow-[0_20px_40px_rgba(103,86,86,0.15)]", children: _jsx("div", { className: "h-full w-full", children: children }) })] })), stage1NotFinished && loadingText && (_jsxs("div", { className: "absolute bottom-24 left-1/2 -translate-x-1/2 text-center font-mono font-semibold text-neutral-500", children: [loadingText, dots] }))] }));
3
+ import { useEffect, useRef, useState } from "react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+
6
+ //#region src/components/canvas/wrapper.tsx
7
+ const CanvasWrapper = ({ children, introProgress, onIntroGrowComplete, skipIntro = false, introContent, loadingText = "LOADING CANVAS", introBackgroundGradient = "linear-gradient(to top, #d4d4d4 0%, #e5e5e5 50%, #f5f5f5 100%)", wrapperBackground, canvasBoxGradient = "radial-gradient(130.38% 95% at 50.03% 97.25%, #d4d4d4 0%, #e5e5e5 48.09%, #f5f5f5 100%)", growTransition = GROW_TRANSITION, blurTransition = BLUR_TRANSITION }) => {
8
+ const [dimensions, setDimensions] = useState(null);
9
+ const [dots, setDots] = useState("..");
10
+ const [stage1NotFinished, setStage1NotFinished] = useState(true);
11
+ const completedRef = useRef(false);
12
+ useEffect(() => {
13
+ if (skipIntro && !completedRef.current) {
14
+ completedRef.current = true;
15
+ introProgress.set(1);
16
+ onIntroGrowComplete?.();
17
+ }
18
+ }, [
19
+ skipIntro,
20
+ introProgress,
21
+ onIntroGrowComplete
22
+ ]);
23
+ useEffect(() => {
24
+ if (skipIntro) return;
25
+ const interval = setInterval(() => {
26
+ setDots((prevDots) => {
27
+ if (prevDots.length < 3) return prevDots + ".";
28
+ else return ".";
29
+ });
30
+ }, 500);
31
+ return () => clearInterval(interval);
32
+ }, [skipIntro]);
33
+ useEffect(() => {
34
+ if (skipIntro) return;
35
+ const calculateInitialSize = () => {
36
+ const vw = window.innerWidth;
37
+ const vh = window.innerHeight;
38
+ const maxWidth = vw * MAX_DIM_RATIO.width;
39
+ const maxHeight = vh * MAX_DIM_RATIO.height;
40
+ if (maxWidth / INTRO_ASPECT_RATIO <= maxHeight) return {
41
+ width: maxWidth,
42
+ height: maxWidth / INTRO_ASPECT_RATIO
43
+ };
44
+ else return {
45
+ height: maxHeight,
46
+ width: maxHeight * INTRO_ASPECT_RATIO
47
+ };
48
+ };
49
+ setDimensions(calculateInitialSize());
50
+ }, [skipIntro]);
51
+ if (skipIntro) return /* @__PURE__ */ jsx(motion.div, {
52
+ className: "fixed inset-0 overflow-hidden",
53
+ style: {
54
+ touchAction: "none",
55
+ userSelect: "none",
56
+ pointerEvents: "none"
57
+ },
58
+ onContextMenu: (e) => e.preventDefault(),
59
+ children
60
+ });
61
+ return /* @__PURE__ */ jsxs(motion.div, {
62
+ className: "fixed inset-0 overflow-hidden",
63
+ style: {
64
+ backgroundImage: stage1NotFinished && !wrapperBackground ? introBackgroundGradient : void 0,
65
+ touchAction: "none",
66
+ userSelect: "none",
67
+ pointerEvents: "none"
68
+ },
69
+ onContextMenu: (e) => e.preventDefault(),
70
+ children: [
71
+ stage1NotFinished && wrapperBackground,
72
+ stage1NotFinished && /* @__PURE__ */ jsx(Fragment, { children: introContent }),
73
+ dimensions && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(motion.div, {
74
+ initial: {
75
+ width: dimensions.width,
76
+ height: dimensions.height,
77
+ opacity: 1,
78
+ backgroundImage: canvasBoxGradient
79
+ },
80
+ animate: {
81
+ opacity: 0,
82
+ display: "none"
83
+ },
84
+ transition: blurTransition,
85
+ className: "absolute left-1/2 top-1/2 z-20 origin-center -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg"
86
+ }), /* @__PURE__ */ jsx(motion.div, {
87
+ initial: {
88
+ width: dimensions.width,
89
+ height: dimensions.height
90
+ },
91
+ animate: {
92
+ width: "100vw",
93
+ height: "100vh"
94
+ },
95
+ transition: growTransition,
96
+ onUpdate: (latest) => {
97
+ if (completedRef.current) return;
98
+ if (typeof latest.width === "number") {
99
+ const w0 = dimensions.width;
100
+ const w1 = window.innerWidth;
101
+ const progress = w1 === w0 ? 1 : (latest.width - w0) / (w1 - w0);
102
+ const clamped = Math.min(Math.max(progress, 0), 1);
103
+ introProgress.set(clamped);
104
+ }
105
+ },
106
+ onAnimationComplete: () => {
107
+ if (!completedRef.current) {
108
+ completedRef.current = true;
109
+ introProgress.set(1);
110
+ setStage1NotFinished(false);
111
+ onIntroGrowComplete?.();
112
+ }
113
+ },
114
+ className: "absolute left-1/2 top-1/2 z-10 origin-center -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg shadow-[0_20px_40px_rgba(103,86,86,0.15)]",
115
+ children: /* @__PURE__ */ jsx("div", {
116
+ className: "h-full w-full",
117
+ children
118
+ })
119
+ })] }),
120
+ stage1NotFinished && loadingText && /* @__PURE__ */ jsxs("div", {
121
+ className: "absolute bottom-24 left-1/2 -translate-x-1/2 text-center font-mono font-semibold text-neutral-500",
122
+ children: [loadingText, dots]
123
+ })
124
+ ]
125
+ });
101
126
  };
127
+
128
+ //#endregion
129
+ export { CanvasWrapper };
102
130
  //# sourceMappingURL=wrapper.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../../../src/components/canvas/wrapper.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wrapper.js","names":[],"sources":["../../../src/components/canvas/wrapper.tsx"],"sourcesContent":["import { motion, type MotionValue, type Transition, useMotionValue } from \"framer-motion\";\nimport { useState, useEffect, useRef, type ReactNode } from \"react\";\nimport {\n MAX_DIM_RATIO,\n GROW_TRANSITION,\n BLUR_TRANSITION,\n INTRO_ASPECT_RATIO,\n} from \"../../lib/constants\";\n\n// Re-export for backward compatibility\nexport { GROW_TRANSITION as growTransition } from \"../../lib/constants\";\n\ninterface CanvasWrapperProps {\n children: React.ReactNode;\n /** Shared progress MV (0->1) for the grow animation */\n introProgress: MotionValue<number>;\n /** Callback when the grow (stage1) completes */\n onIntroGrowComplete?: () => void;\n\n // ============== Intro Customization ==============\n /** Disable intro animation entirely (starts at full size) */\n skipIntro?: boolean;\n /** Custom intro content to show during loading */\n introContent?: ReactNode;\n /** Custom loading text (default: \"LOADING CANVAS\") */\n loadingText?: string;\n /** Background gradient for intro screen (CSS gradient string) */\n introBackgroundGradient?: string;\n /** Custom wrapper background component (overrides introBackgroundGradient if provided) */\n wrapperBackground?: ReactNode;\n /** Canvas box gradient for blur mask */\n canvasBoxGradient?: string;\n /** Grow animation transition config */\n growTransition?: Transition;\n /** Blur animation transition config */\n blurTransition?: Transition;\n}\n\nexport const CanvasWrapper = ({\n children,\n introProgress,\n onIntroGrowComplete,\n skipIntro = false,\n introContent,\n loadingText = \"LOADING CANVAS\",\n introBackgroundGradient = \"linear-gradient(to top, #d4d4d4 0%, #e5e5e5 50%, #f5f5f5 100%)\",\n wrapperBackground,\n canvasBoxGradient = \"radial-gradient(130.38% 95% at 50.03% 97.25%, #d4d4d4 0%, #e5e5e5 48.09%, #f5f5f5 100%)\",\n growTransition = GROW_TRANSITION,\n blurTransition = BLUR_TRANSITION,\n}: CanvasWrapperProps) => {\n const [dimensions, setDimensions] = useState<{\n width: number;\n height: number;\n } | null>(null);\n const [dots, setDots] = useState<string>(\"..\");\n const [stage1NotFinished, setStage1NotFinished] = useState(true);\n const completedRef = useRef(false);\n\n // If skipIntro is true, immediately complete the intro\n useEffect(() => {\n if (skipIntro && !completedRef.current) {\n completedRef.current = true;\n introProgress.set(1);\n onIntroGrowComplete?.();\n }\n }, [skipIntro, introProgress, onIntroGrowComplete]);\n\n // add up to 4 dots, then go back down to 2\n useEffect(() => {\n if (skipIntro) return; // Don't animate dots if skipping intro\n\n const interval = setInterval(() => {\n setDots((prevDots) => {\n if (prevDots.length < 3) {\n return prevDots + \".\";\n } else {\n return \".\";\n }\n });\n }, 500);\n return () => clearInterval(interval);\n }, [skipIntro]);\n\n useEffect(() => {\n if (skipIntro) return; // Don't calculate dimensions if skipping intro\n\n // calculate the initial 3:2 box size with margins (client-only)\n const calculateInitialSize = () => {\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n const maxWidth = vw * MAX_DIM_RATIO.width;\n const maxHeight = vh * MAX_DIM_RATIO.height;\n\n // width or height as limiter\n if (maxWidth / INTRO_ASPECT_RATIO <= maxHeight) {\n return { width: maxWidth, height: maxWidth / INTRO_ASPECT_RATIO };\n } else {\n return { height: maxHeight, width: maxHeight * INTRO_ASPECT_RATIO };\n }\n };\n\n setDimensions(calculateInitialSize());\n }, [skipIntro]);\n\n // If skipIntro, render children directly without animation wrapper\n if (skipIntro) {\n return (\n <motion.div\n className=\"fixed inset-0 overflow-hidden\"\n style={{\n touchAction: \"none\",\n userSelect: \"none\",\n pointerEvents: \"none\",\n }}\n onContextMenu={(e) => e.preventDefault()}\n >\n {children}\n </motion.div>\n );\n }\n\n return (\n <motion.div\n className=\"fixed inset-0 overflow-hidden\"\n style={{\n // Only use gradient style if no custom wrapperBackground is provided\n backgroundImage: stage1NotFinished && !wrapperBackground ? introBackgroundGradient : undefined,\n touchAction: \"none\",\n userSelect: \"none\",\n pointerEvents: \"none\",\n }}\n onContextMenu={(e) => e.preventDefault()}\n >\n {/* Custom wrapper background (renders behind everything) */}\n {stage1NotFinished && wrapperBackground}\n\n {stage1NotFinished && (\n <>\n {introContent}\n </>\n )}\n\n {dimensions && (\n <>\n {/* Blurring mask box */}\n <motion.div\n initial={{\n width: dimensions.width,\n height: dimensions.height,\n opacity: 1,\n backgroundImage: canvasBoxGradient,\n }}\n animate={{\n opacity: 0,\n display: \"none\",\n }}\n transition={blurTransition}\n className=\"absolute left-1/2 top-1/2 z-20 origin-center -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg\"\n />\n {/* Growing wrapper drives introProgress */}\n <motion.div\n initial={{\n width: dimensions.width,\n height: dimensions.height,\n }}\n animate={{\n width: \"100vw\",\n height: \"100vh\",\n }}\n transition={growTransition}\n onUpdate={(latest: { width?: number; height?: number }) => {\n if (completedRef.current) return;\n if (typeof latest.width === \"number\") {\n const w0 = dimensions.width;\n const w1 = window.innerWidth;\n const progress =\n w1 === w0 ? 1 : (latest.width - w0) / (w1 - w0);\n const clamped = Math.min(Math.max(progress, 0), 1);\n introProgress.set(clamped);\n }\n }}\n onAnimationComplete={() => {\n if (!completedRef.current) {\n completedRef.current = true;\n introProgress.set(1);\n setStage1NotFinished(false);\n onIntroGrowComplete?.();\n }\n }}\n className=\"absolute left-1/2 top-1/2 z-10 origin-center -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg shadow-[0_20px_40px_rgba(103,86,86,0.15)]\"\n >\n <div className=\"h-full w-full\">{children}</div>\n </motion.div>\n </>\n )}\n {stage1NotFinished && loadingText && (\n <div className=\"absolute bottom-24 left-1/2 -translate-x-1/2 text-center font-mono font-semibold text-neutral-500\">\n {loadingText}{dots}\n </div>\n )}\n </motion.div>\n );\n};\n"],"mappings":";;;;;;AAsCA,MAAa,iBAAiB,EAC5B,UACA,eACA,qBACA,YAAY,OACZ,cACA,cAAc,kBACd,0BAA0B,kEAC1B,mBACA,oBAAoB,2FACpB,iBAAiB,iBACjB,iBAAiB,sBACO;CACxB,MAAM,CAAC,YAAY,iBAAiB,SAG1B,KAAK;CACf,MAAM,CAAC,MAAM,WAAW,SAAiB,KAAK;CAC9C,MAAM,CAAC,mBAAmB,wBAAwB,SAAS,KAAK;CAChE,MAAM,eAAe,OAAO,MAAM;AAGlC,iBAAgB;AACd,MAAI,aAAa,CAAC,aAAa,SAAS;AACtC,gBAAa,UAAU;AACvB,iBAAc,IAAI,EAAE;AACpB,0BAAuB;;IAExB;EAAC;EAAW;EAAe;EAAoB,CAAC;AAGnD,iBAAgB;AACd,MAAI,UAAW;EAEf,MAAM,WAAW,kBAAkB;AACjC,YAAS,aAAa;AACpB,QAAI,SAAS,SAAS,EACpB,QAAO,WAAW;QAElB,QAAO;KAET;KACD,IAAI;AACP,eAAa,cAAc,SAAS;IACnC,CAAC,UAAU,CAAC;AAEf,iBAAgB;AACd,MAAI,UAAW;EAGf,MAAM,6BAA6B;GACjC,MAAM,KAAK,OAAO;GAClB,MAAM,KAAK,OAAO;GAElB,MAAM,WAAW,KAAK,cAAc;GACpC,MAAM,YAAY,KAAK,cAAc;AAGrC,OAAI,WAAW,sBAAsB,UACnC,QAAO;IAAE,OAAO;IAAU,QAAQ,WAAW;IAAoB;OAEjE,QAAO;IAAE,QAAQ;IAAW,OAAO,YAAY;IAAoB;;AAIvE,gBAAc,sBAAsB,CAAC;IACpC,CAAC,UAAU,CAAC;AAGf,KAAI,UACF,QACE,oBAAC,OAAO;EACN,WAAU;EACV,OAAO;GACL,aAAa;GACb,YAAY;GACZ,eAAe;GAChB;EACD,gBAAgB,MAAM,EAAE,gBAAgB;EAEvC;GACU;AAIjB,QACE,qBAAC,OAAO;EACN,WAAU;EACV,OAAO;GAEL,iBAAiB,qBAAqB,CAAC,oBAAoB,0BAA0B;GACrF,aAAa;GACb,YAAY;GACZ,eAAe;GAChB;EACD,gBAAgB,MAAM,EAAE,gBAAgB;;GAGvC,qBAAqB;GAErB,qBACC,0CACG,eACA;GAGJ,cACC,4CAEE,oBAAC,OAAO;IACN,SAAS;KACP,OAAO,WAAW;KAClB,QAAQ,WAAW;KACnB,SAAS;KACT,iBAAiB;KAClB;IACD,SAAS;KACP,SAAS;KACT,SAAS;KACV;IACD,YAAY;IACZ,WAAU;KACV,EAEF,oBAAC,OAAO;IACN,SAAS;KACP,OAAO,WAAW;KAClB,QAAQ,WAAW;KACpB;IACD,SAAS;KACP,OAAO;KACP,QAAQ;KACT;IACD,YAAY;IACZ,WAAW,WAAgD;AACzD,SAAI,aAAa,QAAS;AAC1B,SAAI,OAAO,OAAO,UAAU,UAAU;MACpC,MAAM,KAAK,WAAW;MACtB,MAAM,KAAK,OAAO;MAClB,MAAM,WACJ,OAAO,KAAK,KAAK,OAAO,QAAQ,OAAO,KAAK;MAC9C,MAAM,UAAU,KAAK,IAAI,KAAK,IAAI,UAAU,EAAE,EAAE,EAAE;AAClD,oBAAc,IAAI,QAAQ;;;IAG9B,2BAA2B;AACzB,SAAI,CAAC,aAAa,SAAS;AACzB,mBAAa,UAAU;AACvB,oBAAc,IAAI,EAAE;AACpB,2BAAqB,MAAM;AAC3B,6BAAuB;;;IAG3B,WAAU;cAEV,oBAAC;KAAI,WAAU;KAAiB;MAAe;KACpC,IACZ;GAEJ,qBAAqB,eACpB,qBAAC;IAAI,WAAU;eACZ,aAAa;KACV;;GAEG"}
@@ -1,22 +1,30 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
1
  import React, { createContext, useContext } from "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+
4
+ //#region src/contexts/CanvasContext.tsx
3
5
  const defaultState = {
4
- x: undefined,
5
- y: undefined,
6
- scale: 1,
7
- isResetting: false,
8
- maxZIndex: 1,
9
- setMaxZIndex: () => {
10
- console.log("setMaxZIndex not set");
11
- },
12
- animationStage: 0,
13
- nextTargetSection: null,
14
- setNextTargetSection: () => {
15
- console.log("setNextTargetSection not set");
16
- },
6
+ x: void 0,
7
+ y: void 0,
8
+ scale: 1,
9
+ isResetting: false,
10
+ maxZIndex: 1,
11
+ setMaxZIndex: () => {
12
+ console.log("setMaxZIndex not set");
13
+ },
14
+ animationStage: 0,
15
+ nextTargetSection: null,
16
+ setNextTargetSection: () => {
17
+ console.log("setNextTargetSection not set");
18
+ }
17
19
  };
18
- export const CanvasContext = createContext(defaultState);
19
- export const useCanvasContext = () => useContext(CanvasContext);
20
- export const CanvasProvider = React.memo(({ children, ...value }) => (_jsx(CanvasContext.Provider, { value: value, children: children })));
20
+ const CanvasContext = createContext(defaultState);
21
+ const useCanvasContext = () => useContext(CanvasContext);
22
+ const CanvasProvider = React.memo(({ children, ...value }) => /* @__PURE__ */ jsx(CanvasContext.Provider, {
23
+ value,
24
+ children
25
+ }));
21
26
  CanvasProvider.displayName = "CanvasProvider";
27
+
28
+ //#endregion
29
+ export { CanvasContext, CanvasProvider, useCanvasContext };
22
30
  //# sourceMappingURL=CanvasContext.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CanvasContext.js","sourceRoot":"","sources":["../../src/contexts/CanvasContext.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,UAAU,EAAkB,MAAM,OAAO,CAAC;AAqBzE,MAAM,YAAY,GAAG;IACnB,CAAC,EAAE,SAA2C;IAC9C,CAAC,EAAE,SAA2C;IAC9C,KAAK,EAAE,CAAmC;IAC1C,WAAW,EAAE,KAAK;IAClB,SAAS,EAAE,CAAC;IACZ,YAAY,EAAE,GAAG,EAAE;QACjB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACtC,CAAC;IACD,cAAc,EAAE,CAAC;IACjB,iBAAiB,EAAE,IAAI;IACvB,oBAAoB,EAAE,GAAG,EAAE;QACzB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC9C,CAAC;CACO,CAAC;AAEX,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAqB,YAAY,CAAC,CAAC;AAE7E,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAMhE,MAAM,CAAC,MAAM,cAAc,GAAkC,KAAK,CAAC,IAAI,CACrE,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,CAAC,CAC1B,KAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,KAA2B,YACvD,QAAQ,GACc,CAC1B,CACF,CAAC;AAEF,cAAc,CAAC,WAAW,GAAG,gBAAgB,CAAC"}
1
+ {"version":3,"file":"CanvasContext.js","names":[],"sources":["../../src/contexts/CanvasContext.tsx"],"sourcesContent":["import React, { createContext, useContext, type ReactNode } from \"react\";\nimport { type MotionValue } from \"framer-motion\";\nimport { CanvasSection } from \"../types\";\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface CanvasContextState {\n x: MotionValue<number>;\n y: MotionValue<number>;\n scale: MotionValue<number>;\n isResetting: boolean;\n maxZIndex: number;\n setMaxZIndex: (zIndex: number) => void;\n animationStage: number;\n nextTargetSection: CanvasSection | null; // predictive pre-render target\n setNextTargetSection: (section: CanvasSection | null) => void;\n}\n\nconst defaultState = {\n x: undefined as unknown as MotionValue<number>,\n y: undefined as unknown as MotionValue<number>,\n scale: 1 as unknown as MotionValue<number>,\n isResetting: false,\n maxZIndex: 1,\n setMaxZIndex: () => {\n console.log(\"setMaxZIndex not set\");\n },\n animationStage: 0,\n nextTargetSection: null,\n setNextTargetSection: () => {\n console.log(\"setNextTargetSection not set\");\n },\n} as const;\n\nexport const CanvasContext = createContext<CanvasContextState>(defaultState);\n\nexport const useCanvasContext = () => useContext(CanvasContext);\n\ninterface CanvasProviderProps extends CanvasContextState {\n children: ReactNode;\n}\n\nexport const CanvasProvider: React.FC<CanvasProviderProps> = React.memo(\n ({ children, ...value }) => (\n <CanvasContext.Provider value={value as CanvasContextState}>\n {children}\n </CanvasContext.Provider>\n ),\n);\n\nCanvasProvider.displayName = \"CanvasProvider\";\n"],"mappings":";;;;AAqBA,MAAM,eAAe;CACnB,GAAG;CACH,GAAG;CACH,OAAO;CACP,aAAa;CACb,WAAW;CACX,oBAAoB;AAClB,UAAQ,IAAI,uBAAuB;;CAErC,gBAAgB;CAChB,mBAAmB;CACnB,4BAA4B;AAC1B,UAAQ,IAAI,+BAA+B;;CAE9C;AAED,MAAa,gBAAgB,cAAkC,aAAa;AAE5E,MAAa,yBAAyB,WAAW,cAAc;AAM/D,MAAa,iBAAgD,MAAM,MAChE,EAAE,UAAU,GAAG,YACd,oBAAC,cAAc;CAAgB;CAC5B;EACsB,CAE5B;AAED,eAAe,cAAc"}
@@ -1,56 +1,57 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createContext, useContext, useEffect, useState } from "react";
3
- import useWindowDimensions from "../hooks/useWindowDimensions";
4
- import { isIOS, isMobile, prefersReducedMotion } from "../utils/performance";
1
+ import useWindowDimensions_default from "../hooks/useWindowDimensions.js";
2
+ import { isIOS, isMobile, prefersReducedMotion } from "../utils/performance.js";
3
+ import React, { createContext, useContext, useEffect, useState } from "react";
4
+ import { jsx } from "react/jsx-runtime";
5
+
6
+ //#region src/contexts/PerformanceContext.tsx
5
7
  const defaultConfig = {
6
- mode: "high",
7
- isIOS: false,
8
- isMobile: false,
9
- prefersReducedMotion: false,
10
- enableComplexShadows: true,
8
+ mode: "high",
9
+ isIOS: false,
10
+ isMobile: false,
11
+ prefersReducedMotion: false,
12
+ enableComplexShadows: true
11
13
  };
12
14
  const PerformanceContext = createContext(defaultConfig);
13
- export const usePerformance = () => useContext(PerformanceContext);
14
- // Backward compatibility alias
15
- export const usePerformanceMode = usePerformance;
15
+ const usePerformance = () => useContext(PerformanceContext);
16
+ const usePerformanceMode = usePerformance;
16
17
  /**
17
- * Performance Provider - Centralized performance mode detection
18
- *
19
- * Detects device capabilities and user preferences once at the top level,
20
- * avoiding redundant device detection across multiple components.
21
- *
22
- * Usage:
23
- * <PerformanceProvider>
24
- * <App />
25
- * </PerformanceProvider>
26
- *
27
- * Then in components:
28
- * const { mode, isIOS, enableComplexShadows } = usePerformance();
29
- */
30
- export const PerformanceProvider = ({ children }) => {
31
- const [config, setConfig] = useState(defaultConfig);
32
- const { width } = useWindowDimensions();
33
- useEffect(() => {
34
- const isIOSDevice = isIOS();
35
- const isMobileDevice = isMobile();
36
- const reducedMotion = prefersReducedMotion();
37
- let mode = "high";
38
- // Determine performance mode based on device and screen size
39
- if (isIOSDevice || reducedMotion || width < 768) {
40
- mode = "low";
41
- }
42
- else if (isMobileDevice || width < 1024) {
43
- mode = "medium";
44
- }
45
- setConfig({
46
- mode,
47
- isIOS: isIOSDevice,
48
- isMobile: isMobileDevice,
49
- prefersReducedMotion: reducedMotion,
50
- // Use simpler shadows on iOS and low-end devices for better performance
51
- enableComplexShadows: mode !== "low",
52
- });
53
- }, [width]);
54
- return (_jsx(PerformanceContext.Provider, { value: config, children: children }));
18
+ * Performance Provider - Centralized performance mode detection
19
+ *
20
+ * Detects device capabilities and user preferences once at the top level,
21
+ * avoiding redundant device detection across multiple components.
22
+ *
23
+ * Usage:
24
+ * <PerformanceProvider>
25
+ * <App />
26
+ * </PerformanceProvider>
27
+ *
28
+ * Then in components:
29
+ * const { mode, isIOS, enableComplexShadows } = usePerformance();
30
+ */
31
+ const PerformanceProvider = ({ children }) => {
32
+ const [config, setConfig] = useState(defaultConfig);
33
+ const { width } = useWindowDimensions_default();
34
+ useEffect(() => {
35
+ const isIOSDevice = isIOS();
36
+ const isMobileDevice = isMobile();
37
+ const reducedMotion = prefersReducedMotion();
38
+ let mode = "high";
39
+ if (isIOSDevice || reducedMotion || width < 768) mode = "low";
40
+ else if (isMobileDevice || width < 1024) mode = "medium";
41
+ setConfig({
42
+ mode,
43
+ isIOS: isIOSDevice,
44
+ isMobile: isMobileDevice,
45
+ prefersReducedMotion: reducedMotion,
46
+ enableComplexShadows: mode !== "low"
47
+ });
48
+ }, [width]);
49
+ return /* @__PURE__ */ jsx(PerformanceContext.Provider, {
50
+ value: config,
51
+ children
52
+ });
55
53
  };
54
+
55
+ //#endregion
56
+ export { PerformanceProvider, usePerformance, usePerformanceMode };
56
57
  //# sourceMappingURL=PerformanceContext.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PerformanceContext.js","sourceRoot":"","sources":["../../src/contexts/PerformanceContext.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAC9F,OAAO,mBAAmB,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAY7E,MAAM,aAAa,GAAsB;IACrC,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,KAAK;IACZ,QAAQ,EAAE,KAAK;IACf,oBAAoB,EAAE,KAAK;IAC3B,oBAAoB,EAAE,IAAI;CAC7B,CAAC;AAEF,MAAM,kBAAkB,GAAG,aAAa,CAAoB,aAAa,CAAC,CAAC;AAE3E,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;AAEnE,+BAA+B;AAC/B,MAAM,CAAC,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAMjD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAuC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IACpF,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAoB,aAAa,CAAC,CAAC;IACvE,MAAM,EAAE,KAAK,EAAE,GAAG,mBAAmB,EAAE,CAAC;IAExC,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,WAAW,GAAG,KAAK,EAAE,CAAC;QAC5B,MAAM,cAAc,GAAG,QAAQ,EAAE,CAAC;QAClC,MAAM,aAAa,GAAG,oBAAoB,EAAE,CAAC;QAE7C,IAAI,IAAI,GAAoB,MAAM,CAAC;QAEnC,6DAA6D;QAC7D,IAAI,WAAW,IAAI,aAAa,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;YAC9C,IAAI,GAAG,KAAK,CAAC;QACjB,CAAC;aAAM,IAAI,cAAc,IAAI,KAAK,GAAG,IAAI,EAAE,CAAC;YACxC,IAAI,GAAG,QAAQ,CAAC;QACpB,CAAC;QAED,SAAS,CAAC;YACN,IAAI;YACJ,KAAK,EAAE,WAAW;YAClB,QAAQ,EAAE,cAAc;YACxB,oBAAoB,EAAE,aAAa;YACnC,wEAAwE;YACxE,oBAAoB,EAAE,IAAI,KAAK,KAAK;SACvC,CAAC,CAAC;IACP,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,OAAO,CACH,KAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,YACrC,QAAQ,GACiB,CACjC,CAAC;AACN,CAAC,CAAC"}
1
+ {"version":3,"file":"PerformanceContext.js","names":["useWindowDimensions"],"sources":["../../src/contexts/PerformanceContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useState, type ReactNode } from \"react\";\nimport useWindowDimensions from \"../hooks/useWindowDimensions\";\nimport { isIOS, isMobile, prefersReducedMotion } from \"../utils/performance\";\n\nexport type PerformanceMode = \"high\" | \"medium\" | \"low\";\n\nexport interface PerformanceConfig {\n mode: PerformanceMode;\n isIOS: boolean;\n isMobile: boolean;\n prefersReducedMotion: boolean;\n enableComplexShadows: boolean;\n}\n\nconst defaultConfig: PerformanceConfig = {\n mode: \"high\",\n isIOS: false,\n isMobile: false,\n prefersReducedMotion: false,\n enableComplexShadows: true,\n};\n\nconst PerformanceContext = createContext<PerformanceConfig>(defaultConfig);\n\nexport const usePerformance = () => useContext(PerformanceContext);\n\n// Backward compatibility alias\nexport const usePerformanceMode = usePerformance;\n\ninterface PerformanceProviderProps {\n children: ReactNode;\n}\n\n/**\n * Performance Provider - Centralized performance mode detection\n * \n * Detects device capabilities and user preferences once at the top level,\n * avoiding redundant device detection across multiple components.\n * \n * Usage:\n * <PerformanceProvider>\n * <App />\n * </PerformanceProvider>\n * \n * Then in components:\n * const { mode, isIOS, enableComplexShadows } = usePerformance();\n */\nexport const PerformanceProvider: React.FC<PerformanceProviderProps> = ({ children }) => {\n const [config, setConfig] = useState<PerformanceConfig>(defaultConfig);\n const { width } = useWindowDimensions();\n\n useEffect(() => {\n const isIOSDevice = isIOS();\n const isMobileDevice = isMobile();\n const reducedMotion = prefersReducedMotion();\n\n let mode: PerformanceMode = \"high\";\n\n // Determine performance mode based on device and screen size\n if (isIOSDevice || reducedMotion || width < 768) {\n mode = \"low\";\n } else if (isMobileDevice || width < 1024) {\n mode = \"medium\";\n }\n\n setConfig({\n mode,\n isIOS: isIOSDevice,\n isMobile: isMobileDevice,\n prefersReducedMotion: reducedMotion,\n // Use simpler shadows on iOS and low-end devices for better performance\n enableComplexShadows: mode !== \"low\",\n });\n }, [width]);\n\n return (\n <PerformanceContext.Provider value={config}>\n {children}\n </PerformanceContext.Provider>\n );\n};\n"],"mappings":";;;;;;AAcA,MAAM,gBAAmC;CACrC,MAAM;CACN,OAAO;CACP,UAAU;CACV,sBAAsB;CACtB,sBAAsB;CACzB;AAED,MAAM,qBAAqB,cAAiC,cAAc;AAE1E,MAAa,uBAAuB,WAAW,mBAAmB;AAGlE,MAAa,qBAAqB;;;;;;;;;;;;;;;AAoBlC,MAAa,uBAA2D,EAAE,eAAe;CACrF,MAAM,CAAC,QAAQ,aAAa,SAA4B,cAAc;CACtE,MAAM,EAAE,UAAUA,6BAAqB;AAEvC,iBAAgB;EACZ,MAAM,cAAc,OAAO;EAC3B,MAAM,iBAAiB,UAAU;EACjC,MAAM,gBAAgB,sBAAsB;EAE5C,IAAI,OAAwB;AAG5B,MAAI,eAAe,iBAAiB,QAAQ,IACxC,QAAO;WACA,kBAAkB,QAAQ,KACjC,QAAO;AAGX,YAAU;GACN;GACA,OAAO;GACP,UAAU;GACV,sBAAsB;GAEtB,sBAAsB,SAAS;GAClC,CAAC;IACH,CAAC,MAAM,CAAC;AAEX,QACI,oBAAC,mBAAmB;EAAS,OAAO;EAC/B;GACyB"}
@@ -1,40 +1,39 @@
1
- import { useState, useEffect } from "react";
2
- import { isIOS, isMobile, prefersReducedMotion } from "../utils/performance";
3
- import useWindowDimensions from "./useWindowDimensions";
1
+ import useWindowDimensions_default from "./useWindowDimensions.js";
2
+ import { isIOS, isMobile, prefersReducedMotion } from "../utils/performance.js";
3
+ import { useEffect, useState } from "react";
4
+
5
+ //#region src/hooks/usePerformanceMode.ts
4
6
  /**
5
- * Hook to determine optimal performance settings based on device capabilities
6
- * Does not disable any animations - only provides info for optimization
7
- */
8
- export const usePerformanceMode = () => {
9
- const [config, setConfig] = useState({
10
- mode: "high",
11
- isIOS: false,
12
- isMobile: false,
13
- prefersReducedMotion: false,
14
- enableComplexShadows: true,
15
- });
16
- const { width } = useWindowDimensions();
17
- useEffect(() => {
18
- const isIOSDevice = isIOS();
19
- const isMobileDevice = isMobile();
20
- const reducedMotion = prefersReducedMotion();
21
- let mode = "high";
22
- // Determine performance mode
23
- if (isIOSDevice || reducedMotion || width < 768) {
24
- mode = "low";
25
- }
26
- else if (isMobileDevice || width < 1024) {
27
- mode = "medium";
28
- }
29
- setConfig({
30
- mode,
31
- isIOS: isIOSDevice,
32
- isMobile: isMobileDevice,
33
- prefersReducedMotion: reducedMotion,
34
- // Use simpler shadows on iOS for better performance
35
- enableComplexShadows: mode !== "low",
36
- });
37
- }, []);
38
- return config;
7
+ * Hook to determine optimal performance settings based on device capabilities
8
+ * Does not disable any animations - only provides info for optimization
9
+ */
10
+ const usePerformanceMode = () => {
11
+ const [config, setConfig] = useState({
12
+ mode: "high",
13
+ isIOS: false,
14
+ isMobile: false,
15
+ prefersReducedMotion: false,
16
+ enableComplexShadows: true
17
+ });
18
+ const { width } = useWindowDimensions_default();
19
+ useEffect(() => {
20
+ const isIOSDevice = isIOS();
21
+ const isMobileDevice = isMobile();
22
+ const reducedMotion = prefersReducedMotion();
23
+ let mode = "high";
24
+ if (isIOSDevice || reducedMotion || width < 768) mode = "low";
25
+ else if (isMobileDevice || width < 1024) mode = "medium";
26
+ setConfig({
27
+ mode,
28
+ isIOS: isIOSDevice,
29
+ isMobile: isMobileDevice,
30
+ prefersReducedMotion: reducedMotion,
31
+ enableComplexShadows: mode !== "low"
32
+ });
33
+ }, []);
34
+ return config;
39
35
  };
36
+
37
+ //#endregion
38
+ export { usePerformanceMode };
40
39
  //# sourceMappingURL=usePerformanceMode.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePerformanceMode.js","sourceRoot":"","sources":["../../src/hooks/usePerformanceMode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AAYxD;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAsB,EAAE;IACxD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAoB;QACtD,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,KAAK;QACZ,QAAQ,EAAE,KAAK;QACf,oBAAoB,EAAE,KAAK;QAC3B,oBAAoB,EAAE,IAAI;KAC3B,CAAC,CAAC;IAEH,MAAM,EAAE,KAAK,EAAE,GAAG,mBAAmB,EAAE,CAAC;IAExC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,WAAW,GAAG,KAAK,EAAE,CAAC;QAC5B,MAAM,cAAc,GAAG,QAAQ,EAAE,CAAC;QAClC,MAAM,aAAa,GAAG,oBAAoB,EAAE,CAAC;QAE7C,IAAI,IAAI,GAAoB,MAAM,CAAC;QAEnC,6BAA6B;QAC7B,IAAI,WAAW,IAAI,aAAa,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;YAChD,IAAI,GAAG,KAAK,CAAC;QACf,CAAC;aAAM,IAAI,cAAc,IAAI,KAAK,GAAG,IAAI,EAAE,CAAC;YAC1C,IAAI,GAAG,QAAQ,CAAC;QAClB,CAAC;QAED,SAAS,CAAC;YACR,IAAI;YACJ,KAAK,EAAE,WAAW;YAClB,QAAQ,EAAE,cAAc;YACxB,oBAAoB,EAAE,aAAa;YACnC,oDAAoD;YACpD,oBAAoB,EAAE,IAAI,KAAK,KAAK;SACrC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
1
+ {"version":3,"file":"usePerformanceMode.js","names":["useWindowDimensions"],"sources":["../../src/hooks/usePerformanceMode.ts"],"sourcesContent":["import { useState, useEffect } from \"react\";\nimport { isIOS, isMobile, prefersReducedMotion } from \"../utils/performance\";\nimport useWindowDimensions from \"./useWindowDimensions\";\n\nexport type PerformanceMode = \"high\" | \"medium\" | \"low\";\n\nexport interface PerformanceConfig {\n mode: PerformanceMode;\n isIOS: boolean;\n isMobile: boolean;\n prefersReducedMotion: boolean;\n enableComplexShadows: boolean;\n}\n\n/**\n * Hook to determine optimal performance settings based on device capabilities\n * Does not disable any animations - only provides info for optimization\n */\nexport const usePerformanceMode = (): PerformanceConfig => {\n const [config, setConfig] = useState<PerformanceConfig>({\n mode: \"high\",\n isIOS: false,\n isMobile: false,\n prefersReducedMotion: false,\n enableComplexShadows: true,\n });\n\n const { width } = useWindowDimensions();\n\n useEffect(() => {\n const isIOSDevice = isIOS();\n const isMobileDevice = isMobile();\n const reducedMotion = prefersReducedMotion();\n\n let mode: PerformanceMode = \"high\";\n\n // Determine performance mode\n if (isIOSDevice || reducedMotion || width < 768) {\n mode = \"low\";\n } else if (isMobileDevice || width < 1024) {\n mode = \"medium\";\n }\n\n setConfig({\n mode,\n isIOS: isIOSDevice,\n isMobile: isMobileDevice,\n prefersReducedMotion: reducedMotion,\n // Use simpler shadows on iOS for better performance\n enableComplexShadows: mode !== \"low\",\n });\n }, []);\n\n return config;\n};\n"],"mappings":";;;;;;;;;AAkBA,MAAa,2BAA8C;CACzD,MAAM,CAAC,QAAQ,aAAa,SAA4B;EACtD,MAAM;EACN,OAAO;EACP,UAAU;EACV,sBAAsB;EACtB,sBAAsB;EACvB,CAAC;CAEF,MAAM,EAAE,UAAUA,6BAAqB;AAEvC,iBAAgB;EACd,MAAM,cAAc,OAAO;EAC3B,MAAM,iBAAiB,UAAU;EACjC,MAAM,gBAAgB,sBAAsB;EAE5C,IAAI,OAAwB;AAG5B,MAAI,eAAe,iBAAiB,QAAQ,IAC1C,QAAO;WACE,kBAAkB,QAAQ,KACnC,QAAO;AAGT,YAAU;GACR;GACA,OAAO;GACP,UAAU;GACV,sBAAsB;GAEtB,sBAAsB,SAAS;GAChC,CAAC;IACD,EAAE,CAAC;AAEN,QAAO"}