@hunterchen/canvas 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -1
- package/dist/components/canvas/canvas.d.ts +5 -1
- package/dist/components/canvas/canvas.d.ts.map +1 -1
- package/dist/components/canvas/canvas.js +19 -17
- package/dist/components/canvas/canvas.js.map +1 -1
- package/dist/components/canvas/toolbar.d.ts +3 -1
- package/dist/components/canvas/toolbar.d.ts.map +1 -1
- package/dist/components/canvas/toolbar.js +67 -9
- package/dist/components/canvas/toolbar.js.map +1 -1
- package/dist/index.d.ts +19 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -15
- package/dist/index.js.map +1 -1
- package/dist/lib/canvas.d.ts.map +1 -1
- package/dist/lib/canvas.js +3 -3
- package/dist/lib/canvas.js.map +1 -1
- package/dist/lib/constants.d.ts +2 -2
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +2 -2
- package/dist/lib/constants.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/index.d.ts +43 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -1
- package/src/components/canvas/canvas.tsx +59 -36
- package/src/components/canvas/toolbar.tsx +129 -16
- package/src/index.ts +46 -28
- package/src/lib/canvas.ts +4 -4
- package/src/lib/constants.ts +2 -2
- package/src/types/index.ts +59 -0
package/dist/lib/canvas.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { animate } from "framer-motion";
|
|
2
2
|
import { useMemo } from "react";
|
|
3
|
-
import {
|
|
4
|
-
export const canvasWidth =
|
|
5
|
-
export const canvasHeight =
|
|
3
|
+
import { DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT, MAX_DIM_RATIO, INTRO_ASPECT_RATIO, PAN_SPRING, ScreenSizeEnum, } from "./constants";
|
|
4
|
+
export const canvasWidth = DEFAULT_CANVAS_WIDTH;
|
|
5
|
+
export const canvasHeight = DEFAULT_CANVAS_HEIGHT;
|
|
6
6
|
// Re-export ScreenSizeEnum for backward compatibility
|
|
7
7
|
export { ScreenSizeEnum } from "./constants";
|
|
8
8
|
export const useMemoPoint = (x, y) => {
|
package/dist/lib/canvas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas.js","sourceRoot":"","sources":["../../src/lib/canvas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAgC,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"canvas.js","sourceRoot":"","sources":["../../src/lib/canvas.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/constants.d.ts
CHANGED
|
@@ -13,9 +13,9 @@ export declare enum ScreenSizeEnum {
|
|
|
13
13
|
HUGE_DESKTOP = "huge-desktop"
|
|
14
14
|
}
|
|
15
15
|
/** Default canvas width in pixels */
|
|
16
|
-
export declare const
|
|
16
|
+
export declare const DEFAULT_CANVAS_WIDTH = 6000;
|
|
17
17
|
/** Default canvas height in pixels */
|
|
18
|
-
export declare const
|
|
18
|
+
export declare const DEFAULT_CANVAS_HEIGHT = 4000;
|
|
19
19
|
/** Maximum dimensions ratio for the intro box relative to viewport */
|
|
20
20
|
export declare const MAX_DIM_RATIO: {
|
|
21
21
|
readonly width: 0.8;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C;;;GAGG;AAMH,oBAAY,cAAc;IACtB,YAAY,iBAAiB;IAC7B,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;IACjC,aAAa,kBAAkB;IAC/B,YAAY,iBAAiB;CAChC;AAMD,qCAAqC;AACrC,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C;;;GAGG;AAMH,oBAAY,cAAc;IACtB,YAAY,iBAAiB;IAC7B,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;IACjC,aAAa,kBAAkB;IAC/B,YAAY,iBAAiB;CAChC;AAMD,qCAAqC;AACrC,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,sCAAsC;AACtC,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAM1C,sEAAsE;AACtE,eAAO,MAAM,aAAa;;;CAGhB,CAAC;AAEX,4CAA4C;AAC5C,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC,uCAAuC;AACvC,eAAO,MAAM,eAAe;;;mBAGK,MAAM;CAC7B,CAAC;AAEX,4CAA4C;AAC5C,eAAO,MAAM,eAAe;;;mBAGN,MAAM;CAClB,CAAC;AAEX,4CAA4C;AAC5C,eAAO,MAAM,iBAAiB;;;CAGpB,CAAC;AAMX,yBAAyB;AACzB,eAAO,MAAM,QAAQ,IAAI,CAAC;AAE1B,6EAA6E;AAC7E,eAAO,MAAM,UAAU,OAAO,CAAC;AAE/B,0CAA0C;AAC1C,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAQ3C,CAAC;AAEX,kCAAkC;AAClC,eAAO,MAAM,UAAU;;;;;CAKb,CAAC;AAEX,6CAA6C;AAC7C,eAAO,MAAM,4BAA4B,SAAS,CAAC;AAEnD,0CAA0C;AAC1C,eAAO,MAAM,yBAAyB,QAAQ,CAAC;AAM/C,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,QAEe,CAAC;AAMjD,gEAAgE;AAChE,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,8DAA8D;AAC9D,eAAO,MAAM,8BAA8B,OAAO,CAAC;AAMnD,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAQrD,CAAC;AAMX,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB;;;;CAIrB,CAAC;AAMX,mEAAmE;AACnE,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC,8DAA8D;AAC9D,eAAO,MAAM,yBAAyB,OAAO,CAAC"}
|
package/dist/lib/constants.js
CHANGED
|
@@ -19,9 +19,9 @@ export var ScreenSizeEnum;
|
|
|
19
19
|
// CANVAS DIMENSIONS
|
|
20
20
|
// ============================================================================
|
|
21
21
|
/** Default canvas width in pixels */
|
|
22
|
-
export const
|
|
22
|
+
export const DEFAULT_CANVAS_WIDTH = 6000;
|
|
23
23
|
/** Default canvas height in pixels */
|
|
24
|
-
export const
|
|
24
|
+
export const DEFAULT_CANVAS_HEIGHT = 4000;
|
|
25
25
|
// ============================================================================
|
|
26
26
|
// INTRO ANIMATION
|
|
27
27
|
// ============================================================================
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,+EAA+E;AAC/E,0BAA0B;AAC1B,+EAA+E;AAE/E,MAAM,CAAN,IAAY,cAQX;AARD,WAAY,cAAc;IACtB,+CAA6B,CAAA;IAC7B,mCAAiB,CAAA;IACjB,mCAAiB,CAAA;IACjB,iDAA+B,CAAA;IAC/B,mDAAiC,CAAA;IACjC,iDAA+B,CAAA;IAC/B,+CAA6B,CAAA;AACjC,CAAC,EARW,cAAc,KAAd,cAAc,QAQzB;AAED,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,qCAAqC;AACrC,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"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"}
|
package/dist/styles.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--canvas-beige:#f7f1e5;--canvas-coral:#ffb5a7;--canvas-lilac:#d9c8e6;--canvas-salmon:#ffa585;--canvas-heavy:#3c204c;--canvas-emphasis:#513b7a;--canvas-active:#8f57ad;--canvas-tinted:#c9a7db;--canvas-medium:#776780;--canvas-light:#c3b8cb;--canvas-faint-lilac:#f5f2f7;--canvas-offwhite:#fdfcfd;--canvas-highlight:#f5f2f7;--canvas-border-light:0 0% 89%}.container{width:100%;margin-right:auto;margin-left:auto;padding-right:2rem;padding-left:2rem}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1600px){.container{max-width:1600px}}@media (min-width:2000px){.container{max-width:2000px}}@media (min-width:3000px){.container{max-width:3000px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.-top-10{top:-2.5rem}.bottom-12{bottom:3rem}.bottom-24{bottom:6rem}.left-1\/2{left:50%}.left-4{left:1rem}.top-1\/2{top:50%}.top-24{top:6rem}.top-6{top:1.5rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-50{z-index:50}.z-\[1000\]{z-index:1000}.m-auto{margin:auto}.mb-4{margin-bottom:1rem}.block{display:block}.inline{display:inline}.flex{display:flex}.hidden{display:none}.h-5{height:1.25rem}.h-auto{height:auto}.h-full{height:100%}.w-5{width:1.25rem}.w-full{width:100%}.flex-shrink-0{flex-shrink:0}.grow{flex-grow:1}.origin-center{transform-origin:center}.origin-top-left{transform-origin:top left}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-default{cursor:default}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.overflow-hidden{overflow:hidden}.whitespace-nowrap{white-space:nowrap}.rounded-\[10px\]{border-radius:10px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.border,.border-\[1px\]{border-width:1px}.border-border{border-color:hsl(var(--border))}.bg-\[\#EEE2FB\]{--tw-bg-opacity:1;background-color:rgb(238 226 251/var(--tw-bg-opacity,1))}.bg-canvas-highlight{background-color:var(--canvas-highlight)}.bg-canvas-offwhite{background-color:var(--canvas-offwhite)}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.bg-none{background-image:none}.from-black\/10{--tw-gradient-from:rgba(0,0,0,.1) var(--tw-gradient-from-position);--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.object-contain{-o-object-fit:contain;object-fit:contain}.p-1{padding:.25rem}.p-2{padding:.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-\[1px\]{padding-left:1px;padding-right:1px}.py-1{padding-top:.25rem;padding-bottom:.25rem}.pb-\[2\.5px\]{padding-bottom:2.5px}.pt-\[1px\]{padding-top:1px}.text-center{text-align:center}.font-canvas-figtree{font-family:var(--font-figtree)}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.text-canvas-emphasis{color:var(--canvas-emphasis)}.text-canvas-heavy{color:var(--canvas-heavy)}.text-canvas-light{color:var(--canvas-light)}.text-canvas-medium{color:var(--canvas-medium)}.text-neutral-500{--tw-text-opacity:1;color:rgb(115 115 115/var(--tw-text-opacity,1))}.text-neutral-600{--tw-text-opacity:1;color:rgb(82 82 82/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.shadow-\[0_20px_40px_rgba\(103\2c 86\2c 86\2c 0\.15\)\]{--tw-shadow:0 20px 40px hsla(0,9%,37%,.15);--tw-shadow-colored:0 20px 40px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_6px_12px_rgba\(0\2c 0\2c 0\2c 0\.10\)\]{--tw-shadow:0 6px 12px rgba(0,0,0,.1);--tw-shadow-colored:0 6px 12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.blur{--tw-blur:blur(8px)}.blur,.drop-shadow{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow{--tw-drop-shadow:drop-shadow(0 1px 2px rgba(0,0,0,.1)) drop-shadow(0 1px 1px rgba(0,0,0,.06))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0) scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1)) rotate(var(--tw-enter-rotate,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0) scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1)) rotate(var(--tw-exit-rotate,0))}}.duration-200{animation-duration:.2s}.running{animation-play-state:running}@media (min-width:640px){.sm\:top-4{top:1rem}}@media (min-width:768px){.md\:bottom-4{bottom:1rem}.md\:inline{display:inline}.md\:px-8{padding-left:2rem;padding-right:2rem}.md\:text-sm{font-size:.875rem;line-height:1.25rem}}
|
|
1
|
+
*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--canvas-beige:#f7f1e5;--canvas-coral:#ffb5a7;--canvas-lilac:#d9c8e6;--canvas-salmon:#ffa585;--canvas-heavy:#3c204c;--canvas-emphasis:#513b7a;--canvas-active:#8f57ad;--canvas-tinted:#c9a7db;--canvas-medium:#776780;--canvas-light:#c3b8cb;--canvas-faint-lilac:#f5f2f7;--canvas-offwhite:#fdfcfd;--canvas-highlight:#f5f2f7;--canvas-border-light:0 0% 89%}.container{width:100%;margin-right:auto;margin-left:auto;padding-right:2rem;padding-left:2rem}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1600px){.container{max-width:1600px}}@media (min-width:2000px){.container{max-width:2000px}}@media (min-width:3000px){.container{max-width:3000px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.-top-10{top:-2.5rem}.bottom-12{bottom:3rem}.bottom-24{bottom:6rem}.bottom-6{bottom:1.5rem}.left-1\/2{left:50%}.left-4{left:1rem}.right-4{right:1rem}.top-1\/2{top:50%}.top-24{top:6rem}.top-6{top:1.5rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-50{z-index:50}.z-\[1000\]{z-index:1000}.m-auto{margin:auto}.mb-4{margin-bottom:1rem}.block{display:block}.inline{display:inline}.flex{display:flex}.hidden{display:none}.h-5{height:1.25rem}.h-auto{height:auto}.h-full{height:100%}.w-5{width:1.25rem}.w-full{width:100%}.flex-shrink-0{flex-shrink:0}.grow{flex-grow:1}.origin-center{transform-origin:center}.origin-top-left{transform-origin:top left}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-default{cursor:default}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.overflow-hidden{overflow:hidden}.whitespace-nowrap{white-space:nowrap}.rounded-\[10px\]{border-radius:10px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.border,.border-\[1px\]{border-width:1px}.border-border{border-color:hsl(var(--border))}.bg-\[\#EEE2FB\]{--tw-bg-opacity:1;background-color:rgb(238 226 251/var(--tw-bg-opacity,1))}.bg-canvas-highlight{background-color:var(--canvas-highlight)}.bg-canvas-offwhite{background-color:var(--canvas-offwhite)}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.bg-none{background-image:none}.from-black\/10{--tw-gradient-from:rgba(0,0,0,.1) var(--tw-gradient-from-position);--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.object-contain{-o-object-fit:contain;object-fit:contain}.p-1{padding:.25rem}.p-2{padding:.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-\[1px\]{padding-left:1px;padding-right:1px}.py-1{padding-top:.25rem;padding-bottom:.25rem}.pb-\[2\.5px\]{padding-bottom:2.5px}.pt-\[1px\]{padding-top:1px}.text-center{text-align:center}.font-canvas-figtree{font-family:var(--font-figtree)}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.text-canvas-emphasis{color:var(--canvas-emphasis)}.text-canvas-heavy{color:var(--canvas-heavy)}.text-canvas-light{color:var(--canvas-light)}.text-canvas-medium{color:var(--canvas-medium)}.text-neutral-500{--tw-text-opacity:1;color:rgb(115 115 115/var(--tw-text-opacity,1))}.text-neutral-600{--tw-text-opacity:1;color:rgb(82 82 82/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.shadow-\[0_20px_40px_rgba\(103\2c 86\2c 86\2c 0\.15\)\]{--tw-shadow:0 20px 40px hsla(0,9%,37%,.15);--tw-shadow-colored:0 20px 40px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_6px_12px_rgba\(0\2c 0\2c 0\2c 0\.10\)\]{--tw-shadow:0 6px 12px rgba(0,0,0,.1);--tw-shadow-colored:0 6px 12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.blur{--tw-blur:blur(8px)}.blur,.drop-shadow{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow{--tw-drop-shadow:drop-shadow(0 1px 2px rgba(0,0,0,.1)) drop-shadow(0 1px 1px rgba(0,0,0,.06))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0) scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1)) rotate(var(--tw-enter-rotate,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0) scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1)) rotate(var(--tw-exit-rotate,0))}}.duration-200{animation-duration:.2s}.running{animation-play-state:running}@media (min-width:640px){.sm\:bottom-4{bottom:1rem}.sm\:top-4{top:1rem}}@media (min-width:768px){.md\:bottom-4{bottom:1rem}.md\:inline{display:inline}.md\:px-8{padding-left:2rem;padding-right:2rem}.md\:text-sm{font-size:.875rem;line-height:1.25rem}}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -37,4 +37,47 @@ export interface NavItem {
|
|
|
37
37
|
/** If true, clicking this section triggers the reset/home behavior */
|
|
38
38
|
isHome?: boolean;
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Preset positions for the toolbar
|
|
42
|
+
*/
|
|
43
|
+
export type ToolbarPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
44
|
+
/**
|
|
45
|
+
* What to display in the toolbar
|
|
46
|
+
*/
|
|
47
|
+
export type ToolbarDisplayMode = 'coordinates' | 'scale' | 'both';
|
|
48
|
+
/**
|
|
49
|
+
* Configuration options for the canvas toolbar
|
|
50
|
+
*/
|
|
51
|
+
export interface ToolbarConfig {
|
|
52
|
+
/** Hide the toolbar entirely. Default: false */
|
|
53
|
+
hidden?: boolean;
|
|
54
|
+
/** What to show: 'coordinates', 'scale', or 'both'. Default: 'both' */
|
|
55
|
+
display?: ToolbarDisplayMode;
|
|
56
|
+
/** Preset position. Default: 'top-left' */
|
|
57
|
+
position?: ToolbarPosition;
|
|
58
|
+
/** Disable auto-hide when at home position. Default: false */
|
|
59
|
+
disableAutoHide?: boolean;
|
|
60
|
+
/** Additional className for the container */
|
|
61
|
+
className?: string;
|
|
62
|
+
/** Additional className for the coordinates text */
|
|
63
|
+
coordinatesClassName?: string;
|
|
64
|
+
/** Additional className for the scale text */
|
|
65
|
+
scaleClassName?: string;
|
|
66
|
+
/** Additional className for the separator */
|
|
67
|
+
separatorClassName?: string;
|
|
68
|
+
/** Inline styles for the container */
|
|
69
|
+
style?: React.CSSProperties;
|
|
70
|
+
/** Inline styles for the coordinates */
|
|
71
|
+
coordinatesStyle?: React.CSSProperties;
|
|
72
|
+
/** Inline styles for the scale */
|
|
73
|
+
scaleStyle?: React.CSSProperties;
|
|
74
|
+
/** Custom separator between coordinates and scale. Default: ' | ' */
|
|
75
|
+
separator?: string;
|
|
76
|
+
/** Gap around the separator in pixels or CSS value. Default: undefined (uses inline spacing) */
|
|
77
|
+
separatorGap?: number | string;
|
|
78
|
+
/** Format for coordinates. Default: '(x, y)' */
|
|
79
|
+
coordinatesFormat?: (x: number, y: number) => string;
|
|
80
|
+
/** Format for scale. Default: '1.00x' */
|
|
81
|
+
scaleFormat?: (scale: number) => string;
|
|
82
|
+
}
|
|
40
83
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,kBAAkB;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,iCAAiC;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,iCAAiC;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,kBAAkB;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,iCAAiC;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,iCAAiC;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,WAAW,GAAG,aAAa,GAAG,cAAc,CAAC;AAExF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,aAAa;IAE5B,gDAAgD;IAChD,MAAM,CAAC,EAAE,OAAO,CAAC;IAGjB,uEAAuE;IACvE,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAG7B,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,eAAe,CAAC;IAG3B,8DAA8D;IAC9D,eAAe,CAAC,EAAE,OAAO,CAAC;IAG1B,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAG5B,sCAAsC;IACtC,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IACvC,kCAAkC;IAClC,UAAU,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAGjC,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gGAAgG;IAChG,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACrD,yCAAyC;IACzC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACzC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hunterchen/canvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "A React-based canvas library for creating pannable, zoomable, and interactive canvas experiences.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -58,6 +58,9 @@
|
|
|
58
58
|
"@types/node": "^25.0.6",
|
|
59
59
|
"@types/react": "19.0.12",
|
|
60
60
|
"@types/react-dom": "19.0.4",
|
|
61
|
+
"framer-motion": "^12.26.2",
|
|
62
|
+
"react": "^19.2.3",
|
|
63
|
+
"react-dom": "^19.2.3",
|
|
61
64
|
"tailwindcss": "^3.4.19",
|
|
62
65
|
"tailwindcss-animate": "^1.0.7",
|
|
63
66
|
"typescript": "^5.8.2"
|
|
@@ -35,11 +35,18 @@ import {
|
|
|
35
35
|
STAGE2_TRANSITION,
|
|
36
36
|
MOUSE_WHEEL_ZOOM_SENSITIVITY,
|
|
37
37
|
TRACKPAD_ZOOM_SENSITIVITY,
|
|
38
|
+
DEFAULT_CANVAS_WIDTH,
|
|
39
|
+
DEFAULT_CANVAS_HEIGHT,
|
|
38
40
|
} from "../../lib/constants";
|
|
39
41
|
import useWindowDimensions from "../../hooks/useWindowDimensions";
|
|
40
42
|
import Navbar from "./navbar";
|
|
41
43
|
import Toolbar from "./toolbar";
|
|
42
|
-
import type {
|
|
44
|
+
import type {
|
|
45
|
+
CanvasSection,
|
|
46
|
+
NavItem,
|
|
47
|
+
SectionCoordinates,
|
|
48
|
+
ToolbarConfig,
|
|
49
|
+
} from "../../types";
|
|
43
50
|
import { CanvasWrapper } from "./wrapper";
|
|
44
51
|
import { usePerformanceMode } from "../../hooks/usePerformanceMode";
|
|
45
52
|
import type { ReactNode } from "react";
|
|
@@ -49,6 +56,10 @@ interface Props {
|
|
|
49
56
|
homeCoordinates: SectionCoordinates;
|
|
50
57
|
children: React.ReactNode;
|
|
51
58
|
|
|
59
|
+
// Optional height and with params, if omitted sizing will be 6000x4000
|
|
60
|
+
canvasWidth?:number;
|
|
61
|
+
canvasHeight?:number;
|
|
62
|
+
|
|
52
63
|
// Navbar data (optional). If omitted, navbar is hidden.
|
|
53
64
|
/** Array of navigation items for the navbar. If omitted, navbar is hidden. */
|
|
54
65
|
navItems?: NavItem[];
|
|
@@ -74,12 +85,16 @@ interface Props {
|
|
|
74
85
|
canvasBackground?: ReactNode;
|
|
75
86
|
/** Custom wrapper/intro background. If not provided, uses introBackgroundGradient. */
|
|
76
87
|
wrapperBackground?: ReactNode;
|
|
88
|
+
|
|
89
|
+
// ============== Toolbar Customization ==============
|
|
90
|
+
/** Toolbar customization options */
|
|
91
|
+
toolbarConfig?: ToolbarConfig;
|
|
77
92
|
}
|
|
78
93
|
|
|
79
94
|
const stopAllMotion = (
|
|
80
95
|
x: MotionValue<number>,
|
|
81
96
|
y: MotionValue<number>,
|
|
82
|
-
scale: MotionValue<number
|
|
97
|
+
scale: MotionValue<number>
|
|
83
98
|
) => {
|
|
84
99
|
x.stop();
|
|
85
100
|
y.stop();
|
|
@@ -99,6 +114,9 @@ const Canvas: FC<Props> = ({
|
|
|
99
114
|
blurTransition,
|
|
100
115
|
canvasBackground,
|
|
101
116
|
wrapperBackground,
|
|
117
|
+
toolbarConfig,
|
|
118
|
+
canvasHeight,
|
|
119
|
+
canvasWidth,
|
|
102
120
|
}) => {
|
|
103
121
|
const { height: windowHeight, width: windowWidth } = useWindowDimensions();
|
|
104
122
|
|
|
@@ -106,8 +124,8 @@ const Canvas: FC<Props> = ({
|
|
|
106
124
|
|
|
107
125
|
const hasNavbar = Boolean(navItems && navItems.length > 0);
|
|
108
126
|
|
|
109
|
-
const sceneWidth = canvasWidth;
|
|
110
|
-
const sceneHeight = canvasHeight;
|
|
127
|
+
const sceneWidth = canvasWidth ?? DEFAULT_CANVAS_WIDTH;
|
|
128
|
+
const sceneHeight = canvasHeight ?? DEFAULT_CANVAS_HEIGHT;
|
|
111
129
|
|
|
112
130
|
const MIN_ZOOM = MIN_ZOOMS[getScreenSizeEnum(windowWidth)];
|
|
113
131
|
|
|
@@ -130,7 +148,7 @@ const Canvas: FC<Props> = ({
|
|
|
130
148
|
|
|
131
149
|
const initialBoxWidth = useMemo(
|
|
132
150
|
() => calcInitialBoxWidth(windowWidth, windowHeight),
|
|
133
|
-
[windowWidth, windowHeight]
|
|
151
|
+
[windowWidth, windowHeight]
|
|
134
152
|
);
|
|
135
153
|
|
|
136
154
|
// somewhere near the middle-ish
|
|
@@ -145,7 +163,7 @@ const Canvas: FC<Props> = ({
|
|
|
145
163
|
coords: homeCoordinates,
|
|
146
164
|
targetZoom: 1,
|
|
147
165
|
}),
|
|
148
|
-
[homeCoordinates, windowWidth, windowHeight]
|
|
166
|
+
[homeCoordinates, windowWidth, windowHeight]
|
|
149
167
|
);
|
|
150
168
|
|
|
151
169
|
const onResetViewAndItems = useCallback(
|
|
@@ -157,7 +175,7 @@ const Canvas: FC<Props> = ({
|
|
|
157
175
|
if (onComplete) onComplete();
|
|
158
176
|
});
|
|
159
177
|
},
|
|
160
|
-
[offsetHomeCoordinates, x, y, scale]
|
|
178
|
+
[offsetHomeCoordinates, x, y, scale]
|
|
161
179
|
);
|
|
162
180
|
|
|
163
181
|
// Shared intro progress (0->1) driven by CanvasWrapper
|
|
@@ -166,19 +184,19 @@ const Canvas: FC<Props> = ({
|
|
|
166
184
|
// Precompute final stage1 scale and offsets (snapshot dimensions once on mount)
|
|
167
185
|
const stage1Targets = useMemo(() => {
|
|
168
186
|
const finalScale = Math.max(
|
|
169
|
-
(windowWidth || 0) /
|
|
170
|
-
(windowHeight || 0) /
|
|
187
|
+
(windowWidth || 0) / sceneWidth,
|
|
188
|
+
(windowHeight || 0) / sceneHeight
|
|
171
189
|
);
|
|
172
|
-
const endX = (windowWidth -
|
|
173
|
-
const endY = (windowHeight -
|
|
190
|
+
const endX = (windowWidth - sceneWidth * finalScale) / 2;
|
|
191
|
+
const endY = (windowHeight - sceneHeight * finalScale) / 2;
|
|
174
192
|
return { finalScale, endX, endY };
|
|
175
|
-
}, [windowWidth, windowHeight]);
|
|
193
|
+
}, [windowWidth, windowHeight, sceneWidth, sceneHeight]);
|
|
176
194
|
|
|
177
195
|
// Replace direct motion values with derived transforms during stage1
|
|
178
196
|
const derivedScale = useTransform(
|
|
179
197
|
introProgress,
|
|
180
198
|
[0, 1],
|
|
181
|
-
[initialBoxWidth, stage1Targets.finalScale]
|
|
199
|
+
[initialBoxWidth, stage1Targets.finalScale]
|
|
182
200
|
);
|
|
183
201
|
const derivedX = useTransform(introProgress, [0, 1], [0, stage1Targets.endX]);
|
|
184
202
|
const derivedY = useTransform(introProgress, [0, 1], [0, stage1Targets.endY]);
|
|
@@ -240,11 +258,11 @@ const Canvas: FC<Props> = ({
|
|
|
240
258
|
node.addEventListener("wheel", wheelWrapper, { passive: false });
|
|
241
259
|
}
|
|
242
260
|
},
|
|
243
|
-
[wheelWrapper]
|
|
261
|
+
[wheelWrapper]
|
|
244
262
|
);
|
|
245
263
|
|
|
246
264
|
const activePointersRef = useRef<Map<number, PointerEvent<HTMLDivElement>>>(
|
|
247
|
-
new Map()
|
|
265
|
+
new Map()
|
|
248
266
|
);
|
|
249
267
|
const initialPinchStateRef = useRef<{
|
|
250
268
|
distance: number;
|
|
@@ -258,7 +276,7 @@ const Canvas: FC<Props> = ({
|
|
|
258
276
|
offset: Point,
|
|
259
277
|
viewportRef: React.RefObject<HTMLDivElement | null>,
|
|
260
278
|
onComplete?: () => void,
|
|
261
|
-
zoom?: number
|
|
279
|
+
zoom?: number
|
|
262
280
|
): void => {
|
|
263
281
|
if (!viewportRef.current) return;
|
|
264
282
|
setIsSceneMoving(true);
|
|
@@ -281,13 +299,13 @@ const Canvas: FC<Props> = ({
|
|
|
281
299
|
x,
|
|
282
300
|
y,
|
|
283
301
|
scale,
|
|
284
|
-
zoom
|
|
302
|
+
zoom
|
|
285
303
|
).then(() => {
|
|
286
304
|
setIsSceneMoving(false);
|
|
287
305
|
if (onComplete) onComplete();
|
|
288
306
|
});
|
|
289
307
|
},
|
|
290
|
-
[sceneWidth, sceneHeight, x, y, scale]
|
|
308
|
+
[sceneWidth, sceneHeight, x, y, scale]
|
|
291
309
|
);
|
|
292
310
|
|
|
293
311
|
// Guarded stop that ignores attempts during intro animations
|
|
@@ -340,7 +358,7 @@ const Canvas: FC<Props> = ({
|
|
|
340
358
|
viewportRef,
|
|
341
359
|
animationStage,
|
|
342
360
|
stopAllSceneMotion,
|
|
343
|
-
]
|
|
361
|
+
]
|
|
344
362
|
);
|
|
345
363
|
|
|
346
364
|
const handlePointerMove = useCallback(
|
|
@@ -366,11 +384,11 @@ const Canvas: FC<Props> = ({
|
|
|
366
384
|
|
|
367
385
|
const newX = Math.min(
|
|
368
386
|
Math.max(initialPanOffsetOnDrag.x + deltaX, minPanX),
|
|
369
|
-
maxPanX
|
|
387
|
+
maxPanX
|
|
370
388
|
);
|
|
371
389
|
const newY = Math.min(
|
|
372
390
|
Math.max(initialPanOffsetOnDrag.y + deltaY, minPanY),
|
|
373
|
-
maxPanY
|
|
391
|
+
maxPanY
|
|
374
392
|
);
|
|
375
393
|
x.set(newX);
|
|
376
394
|
y.set(newY);
|
|
@@ -396,10 +414,10 @@ const Canvas: FC<Props> = ({
|
|
|
396
414
|
|
|
397
415
|
let newZoom = initialZoom * (currentDistance / initialDistance);
|
|
398
416
|
newZoom = Math.max(
|
|
399
|
-
(window.innerWidth /
|
|
400
|
-
(window.innerHeight /
|
|
417
|
+
(window.innerWidth / sceneWidth) * ZOOM_BOUND, // Ensure zoom is at least the width of the canvas
|
|
418
|
+
(window.innerHeight / sceneHeight) * ZOOM_BOUND, // Ensure zoom is at least the height of the canvas
|
|
401
419
|
Math.min(newZoom, 10),
|
|
402
|
-
MIN_ZOOM
|
|
420
|
+
MIN_ZOOM // Ensure zoom is not less than MIN_ZOOM
|
|
403
421
|
);
|
|
404
422
|
|
|
405
423
|
const mx = currentMidpoint.x;
|
|
@@ -441,7 +459,7 @@ const Canvas: FC<Props> = ({
|
|
|
441
459
|
MIN_ZOOM,
|
|
442
460
|
animationStage,
|
|
443
461
|
stopAllSceneMotion,
|
|
444
|
-
]
|
|
462
|
+
]
|
|
445
463
|
);
|
|
446
464
|
|
|
447
465
|
const handlePointerUpOrCancel = useCallback(
|
|
@@ -478,7 +496,7 @@ const Canvas: FC<Props> = ({
|
|
|
478
496
|
setInitialPanOffsetOnDrag({ x: x.get(), y: y.get() });
|
|
479
497
|
}
|
|
480
498
|
},
|
|
481
|
-
[x, y, isPanning, animationStage, stopAllSceneMotion]
|
|
499
|
+
[x, y, isPanning, animationStage, stopAllSceneMotion]
|
|
482
500
|
);
|
|
483
501
|
|
|
484
502
|
const handleWheelZoom = useCallback(
|
|
@@ -504,11 +522,11 @@ const Canvas: FC<Props> = ({
|
|
|
504
522
|
const nextZoom = Math.max(
|
|
505
523
|
Math.min(
|
|
506
524
|
currentZoom * (1 - event.deltaY * ZOOM_SENSITIVITY),
|
|
507
|
-
MAX_ZOOM
|
|
525
|
+
MAX_ZOOM
|
|
508
526
|
),
|
|
509
527
|
MIN_ZOOM,
|
|
510
|
-
(window.innerWidth /
|
|
511
|
-
(window.innerHeight /
|
|
528
|
+
(window.innerWidth / sceneWidth) * ZOOM_BOUND, // Ensure zoom is at least the width of the canvas
|
|
529
|
+
(window.innerHeight / sceneHeight) * ZOOM_BOUND // Ensure zoom is at least the height of the canvas
|
|
512
530
|
);
|
|
513
531
|
|
|
514
532
|
const rect = viewportRef.current?.getBoundingClientRect();
|
|
@@ -567,7 +585,7 @@ const Canvas: FC<Props> = ({
|
|
|
567
585
|
windowHeight,
|
|
568
586
|
animationStage,
|
|
569
587
|
stopAllSceneMotion,
|
|
570
|
-
]
|
|
588
|
+
]
|
|
571
589
|
);
|
|
572
590
|
|
|
573
591
|
// Keep the wheel handler ref pointing to the latest implementation
|
|
@@ -579,7 +597,7 @@ const Canvas: FC<Props> = ({
|
|
|
579
597
|
(
|
|
580
598
|
offset: { x: number; y: number },
|
|
581
599
|
onComplete?: () => void,
|
|
582
|
-
zoom?: number
|
|
600
|
+
zoom?: number
|
|
583
601
|
) => {
|
|
584
602
|
panToOffset(
|
|
585
603
|
{
|
|
@@ -588,10 +606,10 @@ const Canvas: FC<Props> = ({
|
|
|
588
606
|
},
|
|
589
607
|
viewportRef,
|
|
590
608
|
onComplete,
|
|
591
|
-
zoom
|
|
609
|
+
zoom
|
|
592
610
|
);
|
|
593
611
|
},
|
|
594
|
-
[panToOffset, viewportRef]
|
|
612
|
+
[panToOffset, viewportRef]
|
|
595
613
|
);
|
|
596
614
|
|
|
597
615
|
return (
|
|
@@ -620,7 +638,12 @@ const Canvas: FC<Props> = ({
|
|
|
620
638
|
>
|
|
621
639
|
{animationStage >= 2 && (
|
|
622
640
|
<>
|
|
623
|
-
|
|
641
|
+
{!toolbarConfig?.hidden && (
|
|
642
|
+
<Toolbar
|
|
643
|
+
homeCoordinates={offsetHomeCoordinates}
|
|
644
|
+
config={toolbarConfig}
|
|
645
|
+
/>
|
|
646
|
+
)}
|
|
624
647
|
{hasNavbar && navItems ? (
|
|
625
648
|
<Navbar
|
|
626
649
|
panToOffset={handlePanToOffset}
|
|
@@ -651,8 +674,8 @@ const Canvas: FC<Props> = ({
|
|
|
651
674
|
animate={{ opacity: 1 }}
|
|
652
675
|
transition={{ duration: 0.3, ease: "easeIn" }}
|
|
653
676
|
style={{
|
|
654
|
-
width: `${
|
|
655
|
-
height: `${
|
|
677
|
+
width: `${sceneWidth}px`,
|
|
678
|
+
height: `${sceneHeight}px`,
|
|
656
679
|
x,
|
|
657
680
|
y,
|
|
658
681
|
scale,
|