@hunterchen/canvas 0.3.0 → 0.4.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 +173 -0
- package/dist/components/canvas/backgrounds.d.ts +70 -0
- package/dist/components/canvas/backgrounds.d.ts.map +1 -0
- package/dist/components/canvas/backgrounds.js +47 -0
- package/dist/components/canvas/backgrounds.js.map +1 -0
- package/dist/components/canvas/canvas.d.ts +4 -1
- package/dist/components/canvas/canvas.d.ts.map +1 -1
- package/dist/components/canvas/canvas.js +5 -17
- package/dist/components/canvas/canvas.js.map +1 -1
- package/dist/components/canvas/component.js +2 -2
- package/dist/components/canvas/component.js.map +1 -1
- package/dist/components/canvas/wrapper.d.ts +4 -2
- package/dist/components/canvas/wrapper.d.ts.map +1 -1
- package/dist/components/canvas/wrapper.js +6 -11
- package/dist/components/canvas/wrapper.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/utils.d.ts +7 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +10 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/styles.css +1 -1
- package/package.json +5 -4
- package/src/components/canvas/backgrounds.tsx +205 -0
- package/src/components/canvas/canvas.tsx +28 -42
- package/src/components/canvas/component.tsx +2 -2
- package/src/components/canvas/wrapper.tsx +13 -27
- package/src/index.ts +17 -1
- package/src/lib/utils.ts +10 -0
- package/dist/components/canvas/reset.d.ts +0 -5
- package/dist/components/canvas/reset.d.ts.map +0 -1
- package/dist/components/canvas/reset.js +0 -7
- package/dist/components/canvas/reset.js.map +0 -1
- package/src/components/canvas/reset.tsx +0 -21
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../../../src/components/canvas/wrapper.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAqD,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAC;AACpE,OAAO,
|
|
1
|
+
{"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../../../src/components/canvas/wrapper.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
export { default as Canvas
|
|
1
|
+
export { default as Canvas } from './components/canvas/canvas';
|
|
2
2
|
export { CanvasComponent } from './components/canvas/component';
|
|
3
3
|
export { Draggable, DraggableImage } from './components/canvas/draggable';
|
|
4
4
|
export { CanvasWrapper, growTransition } from './components/canvas/wrapper';
|
|
5
5
|
export { default as CanvasToolbar } from './components/canvas/toolbar';
|
|
6
6
|
export { default as CanvasNavbar } from './components/canvas/navbar';
|
|
7
|
+
export { DefaultCanvasBackground, DefaultWrapperBackground, DefaultIntroContent, DEFAULT_CANVAS_GRADIENT, DEFAULT_INTRO_GRADIENT, DEFAULT_CANVAS_BOX_GRADIENT, } from './components/canvas/backgrounds';
|
|
8
|
+
export type { DefaultCanvasBackgroundProps, DefaultWrapperBackgroundProps, DefaultIntroContentProps, } from './components/canvas/backgrounds';
|
|
7
9
|
export { CanvasContext, CanvasProvider, useCanvasContext } from './contexts/CanvasContext';
|
|
8
10
|
export type { CanvasContextState } from './contexts/CanvasContext';
|
|
9
11
|
export { PerformanceProvider, usePerformanceMode, usePerformance } from './contexts/PerformanceContext';
|
|
@@ -12,6 +14,7 @@ export { default as useWindowDimensions } from './hooks/useWindowDimensions';
|
|
|
12
14
|
export { usePerformanceMode as usePerformanceModeLegacy } from './hooks/usePerformanceMode';
|
|
13
15
|
export * from './lib/canvas';
|
|
14
16
|
export * from './lib/constants';
|
|
17
|
+
export * from './lib/utils';
|
|
15
18
|
export * from './utils/performance';
|
|
16
19
|
export type { SectionCoordinates, NavItem, CanvasSection } from './types';
|
|
17
20
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAGrE,OAAO,EACH,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,EACtB,2BAA2B,GAC9B,MAAM,iCAAiC,CAAC;AACzC,YAAY,EACR,4BAA4B,EAC5B,6BAA6B,EAC7B,wBAAwB,GAC3B,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC3F,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACxG,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAGxF,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,kBAAkB,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAG5F,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AAGpC,YAAY,EAAE,kBAAkB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// Components
|
|
2
|
-
export { default as Canvas
|
|
2
|
+
export { default as Canvas } from './components/canvas/canvas';
|
|
3
3
|
export { CanvasComponent } from './components/canvas/component';
|
|
4
4
|
export { Draggable, DraggableImage } from './components/canvas/draggable';
|
|
5
5
|
export { CanvasWrapper, growTransition } from './components/canvas/wrapper';
|
|
6
6
|
export { default as CanvasToolbar } from './components/canvas/toolbar';
|
|
7
7
|
export { default as CanvasNavbar } from './components/canvas/navbar';
|
|
8
|
+
// Background Components
|
|
9
|
+
export { DefaultCanvasBackground, DefaultWrapperBackground, DefaultIntroContent, DEFAULT_CANVAS_GRADIENT, DEFAULT_INTRO_GRADIENT, DEFAULT_CANVAS_BOX_GRADIENT, } from './components/canvas/backgrounds';
|
|
8
10
|
// Contexts
|
|
9
11
|
export { CanvasContext, CanvasProvider, useCanvasContext } from './contexts/CanvasContext';
|
|
10
12
|
export { PerformanceProvider, usePerformanceMode, usePerformance } from './contexts/PerformanceContext';
|
|
@@ -14,5 +16,6 @@ export { usePerformanceMode as usePerformanceModeLegacy } from './hooks/usePerfo
|
|
|
14
16
|
// Utilities
|
|
15
17
|
export * from './lib/canvas';
|
|
16
18
|
export * from './lib/constants';
|
|
19
|
+
export * from './lib/utils';
|
|
17
20
|
export * from './utils/performance';
|
|
18
21
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAErE,wBAAwB;AACxB,OAAO,EACH,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,EACtB,2BAA2B,GAC9B,MAAM,iCAAiC,CAAC;AAOzC,WAAW;AACX,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE3F,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAGxG,QAAQ;AACR,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,kBAAkB,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAE5F,YAAY;AACZ,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ClassValue } from "clsx";
|
|
2
|
+
/**
|
|
3
|
+
* Utility function to merge Tailwind CSS classes.
|
|
4
|
+
* Combines clsx for conditional classes with tailwind-merge for deduplication.
|
|
5
|
+
*/
|
|
6
|
+
export declare function cn(...inputs: ClassValue[]): string;
|
|
7
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAG7C;;;GAGG;AACH,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { clsx } from "clsx";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
3
|
+
/**
|
|
4
|
+
* Utility function to merge Tailwind CSS classes.
|
|
5
|
+
* Combines clsx for conditional classes with tailwind-merge for deduplication.
|
|
6
|
+
*/
|
|
7
|
+
export function cn(...inputs) {
|
|
8
|
+
return twMerge(clsx(inputs));
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,IAAI,EAAE,MAAM,MAAM,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/B,CAAC"}
|
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%}.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-4{bottom:1rem}.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}.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-\[url\(\'\/customcursor\.svg\'\)\2c auto\]{cursor:url(/customcursor.svg),auto}.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{border-radius:.25rem}.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-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.bg-\[radial-gradient\(\#776780_1\.5px\2c transparent_1px\)\]{background-image:radial-gradient(#776780 1.5px,transparent 0)}.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-1\.5{padding:.375rem}.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-canvas-jetbrains-mono{font-family:var(--font-jetbrainsmono)}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.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-\[\#543C5AB2\]{color:#543c5ab2}.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-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.opacity-100{opacity:1}.opacity-35{opacity:.35}.opacity-60{opacity:.6}.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)}.shadow-\[0_6px_12px_rgba\(0\2c 0\2c 0\2c 0\.10\)\],.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.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}.\[background-size\:22px_22px\]{background-size:22px 22px}.hover\:bg-gray-600:hover{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}@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}.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}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hunterchen/canvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.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",
|
|
@@ -50,15 +50,16 @@
|
|
|
50
50
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"
|
|
53
|
+
"clsx": "^2.1.1",
|
|
54
|
+
"lucide-react": "^0.483.0",
|
|
55
|
+
"tailwind-merge": "^3.4.0"
|
|
54
56
|
},
|
|
55
57
|
"devDependencies": {
|
|
56
58
|
"@types/node": "^25.0.6",
|
|
57
59
|
"@types/react": "19.0.12",
|
|
58
60
|
"@types/react-dom": "19.0.4",
|
|
59
|
-
"next": "^16.1.1",
|
|
60
61
|
"tailwindcss": "^3.4.19",
|
|
61
62
|
"tailwindcss-animate": "^1.0.7",
|
|
62
63
|
"typescript": "^5.8.2"
|
|
63
64
|
}
|
|
64
|
-
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import React, { type ReactNode } from "react";
|
|
2
|
+
import { motion } from "framer-motion";
|
|
3
|
+
import { canvasWidth, canvasHeight } from "../../lib/canvas";
|
|
4
|
+
import { cn } from "../../lib/utils";
|
|
5
|
+
|
|
6
|
+
// ============== Canvas Background ==============
|
|
7
|
+
|
|
8
|
+
export interface DefaultCanvasBackgroundProps {
|
|
9
|
+
/** Custom gradient CSS string. If not provided, uses the default radial gradient. */
|
|
10
|
+
gradientStyle?: string;
|
|
11
|
+
/** Whether to show the dot pattern. Default: true */
|
|
12
|
+
showDots?: boolean;
|
|
13
|
+
/** Dot pattern color. Default: #888888 */
|
|
14
|
+
dotColor?: string;
|
|
15
|
+
/** Dot pattern size in pixels. Default: 1.5 */
|
|
16
|
+
dotSize?: number;
|
|
17
|
+
/** Dot pattern spacing in pixels. Default: 22 */
|
|
18
|
+
dotSpacing?: number;
|
|
19
|
+
/** Dot pattern opacity (0-1). Default: 0.35 */
|
|
20
|
+
dotOpacity?: number;
|
|
21
|
+
/** Whether to show the noise filter. Default: true */
|
|
22
|
+
showFilter?: boolean;
|
|
23
|
+
/** Filter opacity (0-1). Default: 0.6 */
|
|
24
|
+
filterOpacity?: number;
|
|
25
|
+
/** Additional className for the gradient layer */
|
|
26
|
+
gradientClassName?: string;
|
|
27
|
+
/** Additional className for the dots layer */
|
|
28
|
+
dotsClassName?: string;
|
|
29
|
+
/** Additional className for the filter layer */
|
|
30
|
+
filterClassName?: string;
|
|
31
|
+
/** Additional children to render in the background */
|
|
32
|
+
children?: ReactNode;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The default canvas gradient (neutral gray) */
|
|
36
|
+
export const DEFAULT_CANVAS_GRADIENT = `radial-gradient(ellipse ${canvasWidth}px ${canvasHeight}px at ${canvasWidth / 2}px ${canvasHeight}px, #e5e5e5 0%, #d4d4d4 41%, #a3a3a3 59%, #f5f5f5 90%)`;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Default canvas background with gradient, dots, and noise filter.
|
|
40
|
+
* All aspects are customizable via props.
|
|
41
|
+
*/
|
|
42
|
+
export const DefaultCanvasBackground: React.FC<DefaultCanvasBackgroundProps> = ({
|
|
43
|
+
gradientStyle,
|
|
44
|
+
showDots = true,
|
|
45
|
+
dotColor = "#888888",
|
|
46
|
+
dotSize = 1.5,
|
|
47
|
+
dotSpacing = 22,
|
|
48
|
+
dotOpacity = 0.35,
|
|
49
|
+
showFilter = true,
|
|
50
|
+
filterOpacity = 0.6,
|
|
51
|
+
gradientClassName,
|
|
52
|
+
dotsClassName,
|
|
53
|
+
filterClassName,
|
|
54
|
+
children,
|
|
55
|
+
}) => {
|
|
56
|
+
const gradientImage = gradientStyle ?? DEFAULT_CANVAS_GRADIENT;
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<>
|
|
60
|
+
{/* Gradient layer */}
|
|
61
|
+
<div
|
|
62
|
+
className={cn(
|
|
63
|
+
"pointer-events-none absolute inset-0 h-full w-full",
|
|
64
|
+
gradientClassName
|
|
65
|
+
)}
|
|
66
|
+
style={{
|
|
67
|
+
backgroundImage: gradientImage,
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
70
|
+
|
|
71
|
+
{/* Dots layer */}
|
|
72
|
+
{showDots && (
|
|
73
|
+
<div
|
|
74
|
+
className={cn(
|
|
75
|
+
"pointer-events-none absolute inset-0 h-full w-full",
|
|
76
|
+
dotsClassName
|
|
77
|
+
)}
|
|
78
|
+
style={{
|
|
79
|
+
backgroundImage: `radial-gradient(${dotColor} ${dotSize}px, transparent ${dotSize}px)`,
|
|
80
|
+
backgroundSize: `${dotSpacing}px ${dotSpacing}px`,
|
|
81
|
+
opacity: dotOpacity,
|
|
82
|
+
}}
|
|
83
|
+
/>
|
|
84
|
+
)}
|
|
85
|
+
|
|
86
|
+
{/* Filter/noise layer */}
|
|
87
|
+
{showFilter && (
|
|
88
|
+
<div
|
|
89
|
+
className={cn(
|
|
90
|
+
"pointer-events-none absolute inset-0 hidden h-full w-full bg-none filter md:inline md:bg-noise",
|
|
91
|
+
filterClassName
|
|
92
|
+
)}
|
|
93
|
+
style={{
|
|
94
|
+
opacity: filterOpacity,
|
|
95
|
+
filter: "contrast(0.6)",
|
|
96
|
+
}}
|
|
97
|
+
/>
|
|
98
|
+
)}
|
|
99
|
+
|
|
100
|
+
{children}
|
|
101
|
+
</>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// ============== Wrapper/Intro Background ==============
|
|
106
|
+
|
|
107
|
+
export interface DefaultWrapperBackgroundProps {
|
|
108
|
+
/** Background gradient for the intro screen */
|
|
109
|
+
gradient?: string;
|
|
110
|
+
/** Additional className */
|
|
111
|
+
className?: string;
|
|
112
|
+
/** Additional inline styles */
|
|
113
|
+
style?: React.CSSProperties;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Default wrapper/intro background gradient.
|
|
118
|
+
*/
|
|
119
|
+
export const DefaultWrapperBackground: React.FC<DefaultWrapperBackgroundProps> = ({
|
|
120
|
+
gradient = "linear-gradient(to top, #d4d4d4 0%, #e5e5e5 50%, #f5f5f5 100%)",
|
|
121
|
+
className,
|
|
122
|
+
style,
|
|
123
|
+
}) => {
|
|
124
|
+
return (
|
|
125
|
+
<div
|
|
126
|
+
className={cn("absolute inset-0 h-full w-full", className)}
|
|
127
|
+
style={{
|
|
128
|
+
backgroundImage: gradient,
|
|
129
|
+
...style,
|
|
130
|
+
}}
|
|
131
|
+
/>
|
|
132
|
+
);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export interface DefaultIntroContentProps {
|
|
136
|
+
/** Logo image source */
|
|
137
|
+
logoSrc?: string;
|
|
138
|
+
/** Logo alt text */
|
|
139
|
+
logoAlt?: string;
|
|
140
|
+
/** Logo width */
|
|
141
|
+
logoWidth?: number;
|
|
142
|
+
/** Logo height */
|
|
143
|
+
logoHeight?: number;
|
|
144
|
+
/** Title text */
|
|
145
|
+
title?: string;
|
|
146
|
+
/** Additional className for the container */
|
|
147
|
+
className?: string;
|
|
148
|
+
/** Additional className for the title */
|
|
149
|
+
titleClassName?: string;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Default intro content shown during loading.
|
|
154
|
+
* Can be customized or replaced entirely.
|
|
155
|
+
*/
|
|
156
|
+
export const DefaultIntroContent: React.FC<DefaultIntroContentProps> = ({
|
|
157
|
+
logoSrc,
|
|
158
|
+
logoAlt = "Logo",
|
|
159
|
+
logoWidth = 64,
|
|
160
|
+
logoHeight = 64,
|
|
161
|
+
title,
|
|
162
|
+
className,
|
|
163
|
+
titleClassName,
|
|
164
|
+
}) => {
|
|
165
|
+
// If no logo or title provided, render nothing
|
|
166
|
+
if (!logoSrc && !title) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<div
|
|
172
|
+
className={cn(
|
|
173
|
+
"absolute left-1/2 top-24 flex -translate-x-1/2 flex-col items-center text-center",
|
|
174
|
+
className
|
|
175
|
+
)}
|
|
176
|
+
>
|
|
177
|
+
{logoSrc && (
|
|
178
|
+
<motion.img
|
|
179
|
+
src={logoSrc}
|
|
180
|
+
alt={logoAlt}
|
|
181
|
+
width={logoWidth}
|
|
182
|
+
height={logoHeight}
|
|
183
|
+
className="mb-4"
|
|
184
|
+
/>
|
|
185
|
+
)}
|
|
186
|
+
{title && (
|
|
187
|
+
<div
|
|
188
|
+
className={cn(
|
|
189
|
+
"font-sans font-semibold text-neutral-600",
|
|
190
|
+
titleClassName
|
|
191
|
+
)}
|
|
192
|
+
>
|
|
193
|
+
{title}
|
|
194
|
+
</div>
|
|
195
|
+
)}
|
|
196
|
+
</div>
|
|
197
|
+
);
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// Default gradient values for export (neutral grays)
|
|
201
|
+
export const DEFAULT_INTRO_GRADIENT =
|
|
202
|
+
"linear-gradient(to top, #d4d4d4 0%, #e5e5e5 50%, #f5f5f5 100%)";
|
|
203
|
+
|
|
204
|
+
export const DEFAULT_CANVAS_BOX_GRADIENT =
|
|
205
|
+
"radial-gradient(130.38% 95% at 50.03% 97.25%, #d4d4d4 0%, #e5e5e5 48.09%, #f5f5f5 100%)";
|
|
@@ -43,6 +43,7 @@ import type { CanvasSection, NavItem, SectionCoordinates } from "../../types";
|
|
|
43
43
|
import { CanvasWrapper } from "./wrapper";
|
|
44
44
|
import { usePerformanceMode } from "../../hooks/usePerformanceMode";
|
|
45
45
|
import type { ReactNode } from "react";
|
|
46
|
+
import { DefaultCanvasBackground } from "./backgrounds";
|
|
46
47
|
|
|
47
48
|
interface Props {
|
|
48
49
|
homeCoordinates: SectionCoordinates;
|
|
@@ -67,6 +68,12 @@ interface Props {
|
|
|
67
68
|
growTransition?: Transition;
|
|
68
69
|
/** Custom blur transition */
|
|
69
70
|
blurTransition?: Transition;
|
|
71
|
+
|
|
72
|
+
// ============== Background Customization ==============
|
|
73
|
+
/** Custom canvas background. If not provided, uses DefaultCanvasBackground. */
|
|
74
|
+
canvasBackground?: ReactNode;
|
|
75
|
+
/** Custom wrapper/intro background. If not provided, uses introBackgroundGradient. */
|
|
76
|
+
wrapperBackground?: ReactNode;
|
|
70
77
|
}
|
|
71
78
|
|
|
72
79
|
const stopAllMotion = (
|
|
@@ -90,6 +97,8 @@ const Canvas: FC<Props> = ({
|
|
|
90
97
|
canvasBoxGradient,
|
|
91
98
|
growTransition,
|
|
92
99
|
blurTransition,
|
|
100
|
+
canvasBackground,
|
|
101
|
+
wrapperBackground,
|
|
93
102
|
}) => {
|
|
94
103
|
const { height: windowHeight, width: windowWidth } = useWindowDimensions();
|
|
95
104
|
|
|
@@ -593,6 +602,7 @@ const Canvas: FC<Props> = ({
|
|
|
593
602
|
introContent={introContent}
|
|
594
603
|
loadingText={loadingText}
|
|
595
604
|
introBackgroundGradient={introBackgroundGradient}
|
|
605
|
+
wrapperBackground={wrapperBackground}
|
|
596
606
|
canvasBoxGradient={canvasBoxGradient}
|
|
597
607
|
growTransition={growTransition}
|
|
598
608
|
blurTransition={blurTransition}
|
|
@@ -652,23 +662,24 @@ const Canvas: FC<Props> = ({
|
|
|
652
662
|
: "auto",
|
|
653
663
|
}}
|
|
654
664
|
>
|
|
655
|
-
|
|
656
|
-
{
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
<
|
|
670
|
-
|
|
671
|
-
|
|
665
|
+
{/* Canvas Background - customizable or default */}
|
|
666
|
+
{canvasBackground !== undefined ? (
|
|
667
|
+
canvasBackground
|
|
668
|
+
) : (
|
|
669
|
+
<>
|
|
670
|
+
{animationStage >= 1 && mode === "high" ? (
|
|
671
|
+
<motion.div
|
|
672
|
+
initial={{ opacity: 0 }}
|
|
673
|
+
animate={{ opacity: 1 }}
|
|
674
|
+
transition={{ duration: 0.5, ease: "easeIn" }}
|
|
675
|
+
>
|
|
676
|
+
<DefaultCanvasBackground />
|
|
677
|
+
</motion.div>
|
|
678
|
+
) : (
|
|
679
|
+
<DefaultCanvasBackground />
|
|
680
|
+
)}
|
|
681
|
+
</>
|
|
682
|
+
)}
|
|
672
683
|
{children}
|
|
673
684
|
</motion.div>
|
|
674
685
|
</div>
|
|
@@ -677,29 +688,4 @@ const Canvas: FC<Props> = ({
|
|
|
677
688
|
);
|
|
678
689
|
};
|
|
679
690
|
|
|
680
|
-
export const gradientBgImage = `radial-gradient(ellipse ${canvasWidth}px ${canvasHeight}px at ${canvasWidth / 2}px ${canvasHeight}px, var(--coral) 0%, var(--salmon) 41%, var(--lilac) 59%, var(--beige) 90%)`;
|
|
681
|
-
|
|
682
|
-
const Gradient = React.memo(function Gradient() {
|
|
683
|
-
return (
|
|
684
|
-
<div
|
|
685
|
-
className="pointer-events-none absolute inset-0 h-full w-full opacity-100"
|
|
686
|
-
style={{
|
|
687
|
-
backgroundImage: gradientBgImage,
|
|
688
|
-
}}
|
|
689
|
-
/>
|
|
690
|
-
);
|
|
691
|
-
});
|
|
692
|
-
|
|
693
|
-
const Dots = React.memo(function Dots() {
|
|
694
|
-
return (
|
|
695
|
-
<div className="pointer-events-none absolute inset-0 h-full w-full bg-[radial-gradient(#776780_1.5px,transparent_1px)] opacity-35 [background-size:22px_22px] " />
|
|
696
|
-
);
|
|
697
|
-
});
|
|
698
|
-
|
|
699
|
-
const Filter = React.memo(function Filter() {
|
|
700
|
-
return (
|
|
701
|
-
<div className="contrast-60 md:bg-noise pointer-events-none absolute inset-0 hidden h-full w-full bg-none opacity-60 filter md:inline" />
|
|
702
|
-
);
|
|
703
|
-
});
|
|
704
|
-
|
|
705
691
|
export default Canvas;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type FC, useEffect, useState } from "react";
|
|
2
2
|
import type { SectionCoordinates } from "../../types";
|
|
3
3
|
import { useCanvasContext } from "../../contexts/CanvasContext";
|
|
4
|
-
import
|
|
4
|
+
import { motion } from "framer-motion";
|
|
5
5
|
import useWindowDimensions from "../../hooks/useWindowDimensions";
|
|
6
6
|
import { usePerformanceMode } from "../../hooks/usePerformanceMode";
|
|
7
7
|
import {
|
|
@@ -210,7 +210,7 @@ export const CanvasComponent: FC<CanvasProps> = ({
|
|
|
210
210
|
}}
|
|
211
211
|
>
|
|
212
212
|
{shouldShowFallback ? (
|
|
213
|
-
<
|
|
213
|
+
<motion.img
|
|
214
214
|
src={imageFallback}
|
|
215
215
|
alt="Canvas Fallback"
|
|
216
216
|
width={offset?.width ?? 1920}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { motion, type MotionValue, type Transition, useMotionValue } from "framer-motion";
|
|
2
2
|
import { useState, useEffect, useRef, type ReactNode } from "react";
|
|
3
|
-
import Image from "next/image";
|
|
4
3
|
import {
|
|
5
4
|
MAX_DIM_RATIO,
|
|
6
5
|
GROW_TRANSITION,
|
|
@@ -25,8 +24,10 @@ interface CanvasWrapperProps {
|
|
|
25
24
|
introContent?: ReactNode;
|
|
26
25
|
/** Custom loading text (default: "LOADING CANVAS") */
|
|
27
26
|
loadingText?: string;
|
|
28
|
-
/** Background gradient for intro screen */
|
|
27
|
+
/** Background gradient for intro screen (CSS gradient string) */
|
|
29
28
|
introBackgroundGradient?: string;
|
|
29
|
+
/** Custom wrapper background component (overrides introBackgroundGradient if provided) */
|
|
30
|
+
wrapperBackground?: ReactNode;
|
|
30
31
|
/** Canvas box gradient for blur mask */
|
|
31
32
|
canvasBoxGradient?: string;
|
|
32
33
|
/** Grow animation transition config */
|
|
@@ -35,25 +36,6 @@ interface CanvasWrapperProps {
|
|
|
35
36
|
blurTransition?: Transition;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
/**
|
|
39
|
-
* Default intro content (Hack Western branding)
|
|
40
|
-
* Positioned in the upper third of the screen
|
|
41
|
-
*/
|
|
42
|
-
const DefaultIntroContent = () => (
|
|
43
|
-
<div className="absolute left-1/2 top-24 flex -translate-x-1/2 flex-col items-center text-center">
|
|
44
|
-
<Image
|
|
45
|
-
src="/horse.svg"
|
|
46
|
-
alt="Hack Western Logo"
|
|
47
|
-
width={64}
|
|
48
|
-
height={64}
|
|
49
|
-
className="mb-4"
|
|
50
|
-
/>
|
|
51
|
-
<div className="font-canvas-jetbrains-mono font-semibold text-[#543C5AB2]">
|
|
52
|
-
HACK WESTERN 12
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
55
|
-
);
|
|
56
|
-
|
|
57
39
|
export const CanvasWrapper = ({
|
|
58
40
|
children,
|
|
59
41
|
introProgress,
|
|
@@ -61,8 +43,9 @@ export const CanvasWrapper = ({
|
|
|
61
43
|
skipIntro = false,
|
|
62
44
|
introContent,
|
|
63
45
|
loadingText = "LOADING CANVAS",
|
|
64
|
-
introBackgroundGradient = "linear-gradient(to top, #
|
|
65
|
-
|
|
46
|
+
introBackgroundGradient = "linear-gradient(to top, #d4d4d4 0%, #e5e5e5 50%, #f5f5f5 100%)",
|
|
47
|
+
wrapperBackground,
|
|
48
|
+
canvasBoxGradient = "radial-gradient(130.38% 95% at 50.03% 97.25%, #d4d4d4 0%, #e5e5e5 48.09%, #f5f5f5 100%)",
|
|
66
49
|
growTransition = GROW_TRANSITION,
|
|
67
50
|
blurTransition = BLUR_TRANSITION,
|
|
68
51
|
}: CanvasWrapperProps) => {
|
|
@@ -142,17 +125,20 @@ export const CanvasWrapper = ({
|
|
|
142
125
|
<motion.div
|
|
143
126
|
className="fixed inset-0 overflow-hidden"
|
|
144
127
|
style={{
|
|
145
|
-
|
|
128
|
+
// Only use gradient style if no custom wrapperBackground is provided
|
|
129
|
+
backgroundImage: stage1NotFinished && !wrapperBackground ? introBackgroundGradient : undefined,
|
|
146
130
|
touchAction: "none",
|
|
147
131
|
userSelect: "none",
|
|
148
132
|
pointerEvents: "none",
|
|
149
133
|
}}
|
|
150
134
|
onContextMenu={(e) => e.preventDefault()}
|
|
151
135
|
>
|
|
136
|
+
{/* Custom wrapper background (renders behind everything) */}
|
|
137
|
+
{stage1NotFinished && wrapperBackground}
|
|
138
|
+
|
|
152
139
|
{stage1NotFinished && (
|
|
153
140
|
<>
|
|
154
|
-
{
|
|
155
|
-
{introContent !== undefined ? introContent : <DefaultIntroContent />}
|
|
141
|
+
{introContent}
|
|
156
142
|
</>
|
|
157
143
|
)}
|
|
158
144
|
|
|
@@ -210,7 +196,7 @@ export const CanvasWrapper = ({
|
|
|
210
196
|
</>
|
|
211
197
|
)}
|
|
212
198
|
{stage1NotFinished && loadingText && (
|
|
213
|
-
<div className="absolute bottom-24 left-1/2 -translate-x-1/2 text-center font-
|
|
199
|
+
<div className="absolute bottom-24 left-1/2 -translate-x-1/2 text-center font-mono font-semibold text-neutral-500">
|
|
214
200
|
{loadingText}{dots}
|
|
215
201
|
</div>
|
|
216
202
|
)}
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
// Components
|
|
2
|
-
export { default as Canvas
|
|
2
|
+
export { default as Canvas } from './components/canvas/canvas';
|
|
3
3
|
export { CanvasComponent } from './components/canvas/component';
|
|
4
4
|
export { Draggable, DraggableImage } from './components/canvas/draggable';
|
|
5
5
|
export { CanvasWrapper, growTransition } from './components/canvas/wrapper';
|
|
6
6
|
export { default as CanvasToolbar } from './components/canvas/toolbar';
|
|
7
7
|
export { default as CanvasNavbar } from './components/canvas/navbar';
|
|
8
8
|
|
|
9
|
+
// Background Components
|
|
10
|
+
export {
|
|
11
|
+
DefaultCanvasBackground,
|
|
12
|
+
DefaultWrapperBackground,
|
|
13
|
+
DefaultIntroContent,
|
|
14
|
+
DEFAULT_CANVAS_GRADIENT,
|
|
15
|
+
DEFAULT_INTRO_GRADIENT,
|
|
16
|
+
DEFAULT_CANVAS_BOX_GRADIENT,
|
|
17
|
+
} from './components/canvas/backgrounds';
|
|
18
|
+
export type {
|
|
19
|
+
DefaultCanvasBackgroundProps,
|
|
20
|
+
DefaultWrapperBackgroundProps,
|
|
21
|
+
DefaultIntroContentProps,
|
|
22
|
+
} from './components/canvas/backgrounds';
|
|
23
|
+
|
|
9
24
|
// Contexts
|
|
10
25
|
export { CanvasContext, CanvasProvider, useCanvasContext } from './contexts/CanvasContext';
|
|
11
26
|
export type { CanvasContextState } from './contexts/CanvasContext';
|
|
@@ -19,6 +34,7 @@ export { usePerformanceMode as usePerformanceModeLegacy } from './hooks/usePerfo
|
|
|
19
34
|
// Utilities
|
|
20
35
|
export * from './lib/canvas';
|
|
21
36
|
export * from './lib/constants';
|
|
37
|
+
export * from './lib/utils';
|
|
22
38
|
export * from './utils/performance';
|
|
23
39
|
|
|
24
40
|
// Types
|