@hunterchen/canvas 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +196 -8
  2. package/dist/components/canvas/backgrounds.d.ts +4 -4
  3. package/dist/components/canvas/backgrounds.d.ts.map +1 -1
  4. package/dist/components/canvas/backgrounds.js +68 -39
  5. package/dist/components/canvas/backgrounds.js.map +1 -1
  6. package/dist/components/canvas/canvas.d.ts +3 -1
  7. package/dist/components/canvas/canvas.d.ts.map +1 -1
  8. package/dist/components/canvas/canvas.js +451 -387
  9. package/dist/components/canvas/canvas.js.map +1 -1
  10. package/dist/components/canvas/component.js +108 -174
  11. package/dist/components/canvas/component.js.map +1 -1
  12. package/dist/components/canvas/draggable.js +168 -151
  13. package/dist/components/canvas/draggable.js.map +1 -1
  14. package/dist/components/canvas/navbar/index.d.ts +4 -2
  15. package/dist/components/canvas/navbar/index.d.ts.map +1 -1
  16. package/dist/components/canvas/navbar/index.js +168 -101
  17. package/dist/components/canvas/navbar/index.js.map +1 -1
  18. package/dist/components/canvas/navbar/single-button.d.ts +10 -1
  19. package/dist/components/canvas/navbar/single-button.d.ts.map +1 -1
  20. package/dist/components/canvas/navbar/single-button.js +176 -69
  21. package/dist/components/canvas/navbar/single-button.js.map +1 -1
  22. package/dist/components/canvas/toolbar.js +121 -82
  23. package/dist/components/canvas/toolbar.js.map +1 -1
  24. package/dist/components/canvas/wrapper.js +127 -99
  25. package/dist/components/canvas/wrapper.js.map +1 -1
  26. package/dist/contexts/CanvasContext.js +25 -17
  27. package/dist/contexts/CanvasContext.js.map +1 -1
  28. package/dist/contexts/PerformanceContext.js +51 -50
  29. package/dist/contexts/PerformanceContext.js.map +1 -1
  30. package/dist/hooks/usePerformanceMode.js +36 -37
  31. package/dist/hooks/usePerformanceMode.js.map +1 -1
  32. package/dist/hooks/useWindowDimensions.js +22 -18
  33. package/dist/hooks/useWindowDimensions.js.map +1 -1
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +17 -21
  37. package/dist/lib/canvas.js +65 -72
  38. package/dist/lib/canvas.js.map +1 -1
  39. package/dist/lib/constants.js +78 -92
  40. package/dist/lib/constants.js.map +1 -1
  41. package/dist/lib/utils.js +10 -5
  42. package/dist/lib/utils.js.map +1 -1
  43. package/dist/styles.css +1 -1
  44. package/dist/types/index.d.ts +69 -0
  45. package/dist/types/index.d.ts.map +1 -1
  46. package/dist/utils/performance.js +18 -23
  47. package/dist/utils/performance.js.map +1 -1
  48. package/package.json +7 -21
  49. package/src/components/canvas/backgrounds.tsx +7 -7
  50. package/src/components/canvas/canvas.tsx +9 -2
  51. package/src/components/canvas/navbar/index.tsx +91 -15
  52. package/src/components/canvas/navbar/single-button.tsx +210 -56
  53. package/src/index.ts +5 -0
  54. package/src/styles.css +15 -13
  55. package/src/types/index.ts +91 -0
  56. package/dist/components/canvas/offest.js +0 -12
  57. package/dist/components/canvas/offest.js.map +0 -1
  58. package/dist/index.js.map +0 -1
  59. package/dist/types/index.js +0 -6
  60. package/dist/types/index.js.map +0 -1
@@ -1,122 +1,108 @@
1
+ //#region src/lib/constants.ts
1
2
  /**
2
- * Canvas Library Constants
3
- * All configurable constants consolidated in one place
4
- */
5
- // ============================================================================
6
- // SCREEN SIZE BREAKPOINTS
7
- // ============================================================================
8
- export var ScreenSizeEnum;
9
- (function (ScreenSizeEnum) {
10
- ScreenSizeEnum["SMALL_MOBILE"] = "small-mobile";
11
- ScreenSizeEnum["MOBILE"] = "mobile";
12
- ScreenSizeEnum["TABLET"] = "tablet";
13
- ScreenSizeEnum["SMALL_DESKTOP"] = "small-desktop";
14
- ScreenSizeEnum["MEDIUM_DESKTOP"] = "medium-desktop";
15
- ScreenSizeEnum["LARGE_DESKTOP"] = "large-desktop";
16
- ScreenSizeEnum["HUGE_DESKTOP"] = "huge-desktop";
17
- })(ScreenSizeEnum || (ScreenSizeEnum = {}));
18
- // ============================================================================
19
- // CANVAS DIMENSIONS
20
- // ============================================================================
3
+ * Canvas Library Constants
4
+ * All configurable constants consolidated in one place
5
+ */
6
+ let ScreenSizeEnum = /* @__PURE__ */ function(ScreenSizeEnum) {
7
+ ScreenSizeEnum["SMALL_MOBILE"] = "small-mobile";
8
+ ScreenSizeEnum["MOBILE"] = "mobile";
9
+ ScreenSizeEnum["TABLET"] = "tablet";
10
+ ScreenSizeEnum["SMALL_DESKTOP"] = "small-desktop";
11
+ ScreenSizeEnum["MEDIUM_DESKTOP"] = "medium-desktop";
12
+ ScreenSizeEnum["LARGE_DESKTOP"] = "large-desktop";
13
+ ScreenSizeEnum["HUGE_DESKTOP"] = "huge-desktop";
14
+ return ScreenSizeEnum;
15
+ }({});
21
16
  /** Default canvas width in pixels */
22
- export const DEFAULT_CANVAS_WIDTH = 6000;
17
+ const DEFAULT_CANVAS_WIDTH = 6e3;
23
18
  /** Default canvas height in pixels */
24
- export const DEFAULT_CANVAS_HEIGHT = 4000;
25
- // ============================================================================
26
- // INTRO ANIMATION
27
- // ============================================================================
19
+ const DEFAULT_CANVAS_HEIGHT = 4e3;
28
20
  /** Maximum dimensions ratio for the intro box relative to viewport */
29
- export const MAX_DIM_RATIO = {
30
- width: 0.8,
31
- height: 0.5,
21
+ const MAX_DIM_RATIO = {
22
+ width: .8,
23
+ height: .5
32
24
  };
33
25
  /** Intro box aspect ratio (width:height) */
34
- export const INTRO_ASPECT_RATIO = 3 / 2;
26
+ const INTRO_ASPECT_RATIO = 3 / 2;
35
27
  /** Grow animation transition config */
36
- export const GROW_TRANSITION = {
37
- duration: 0.96,
38
- delay: 3.14,
39
- ease: [0.35, 0.1, 0.8, 1],
28
+ const GROW_TRANSITION = {
29
+ duration: .96,
30
+ delay: 3.14,
31
+ ease: [
32
+ .35,
33
+ .1,
34
+ .8,
35
+ 1
36
+ ]
40
37
  };
41
38
  /** Blur mask animation transition config */
42
- export const BLUR_TRANSITION = {
43
- duration: 0.85,
44
- delay: 1.25,
45
- ease: "easeIn",
39
+ const BLUR_TRANSITION = {
40
+ duration: .85,
41
+ delay: 1.25,
42
+ ease: "easeIn"
46
43
  };
47
44
  /** Stage 2 pan-to-home transition config */
48
- export const STAGE2_TRANSITION = {
49
- duration: 0.96,
50
- ease: [0.37, 0.1, 0.6, 1],
45
+ const STAGE2_TRANSITION = {
46
+ duration: .96,
47
+ ease: [
48
+ .37,
49
+ .1,
50
+ .6,
51
+ 1
52
+ ]
51
53
  };
52
- // ============================================================================
53
- // ZOOM & PAN
54
- // ============================================================================
55
54
  /** Maximum zoom level */
56
- export const MAX_ZOOM = 3;
55
+ const MAX_ZOOM = 3;
57
56
  /** Minimum zoom bound multiplier to prevent zooming out past canvas edges */
58
- export const ZOOM_BOUND = 1.05;
57
+ const ZOOM_BOUND = 1.05;
59
58
  /** Minimum zoom levels per screen size */
60
- export const MIN_ZOOMS = {
61
- [ScreenSizeEnum.SMALL_MOBILE]: 0.3,
62
- [ScreenSizeEnum.MOBILE]: 0.35,
63
- [ScreenSizeEnum.TABLET]: 0.25,
64
- [ScreenSizeEnum.SMALL_DESKTOP]: 0.15,
65
- [ScreenSizeEnum.MEDIUM_DESKTOP]: 0.1,
66
- [ScreenSizeEnum.LARGE_DESKTOP]: 0.1,
67
- [ScreenSizeEnum.HUGE_DESKTOP]: 0.1,
59
+ const MIN_ZOOMS = {
60
+ [ScreenSizeEnum.SMALL_MOBILE]: .3,
61
+ [ScreenSizeEnum.MOBILE]: .35,
62
+ [ScreenSizeEnum.TABLET]: .25,
63
+ [ScreenSizeEnum.SMALL_DESKTOP]: .15,
64
+ [ScreenSizeEnum.MEDIUM_DESKTOP]: .1,
65
+ [ScreenSizeEnum.LARGE_DESKTOP]: .1,
66
+ [ScreenSizeEnum.HUGE_DESKTOP]: .1
68
67
  };
69
68
  /** Pan animation spring config */
70
- export const PAN_SPRING = {
71
- visualDuration: 0.34,
72
- type: "spring",
73
- stiffness: 200,
74
- damping: 25,
69
+ const PAN_SPRING = {
70
+ visualDuration: .34,
71
+ type: "spring",
72
+ stiffness: 200,
73
+ damping: 25
75
74
  };
76
75
  /** Wheel zoom sensitivity for mouse wheel */
77
- export const MOUSE_WHEEL_ZOOM_SENSITIVITY = 0.0015;
76
+ const MOUSE_WHEEL_ZOOM_SENSITIVITY = .0015;
78
77
  /** Wheel zoom sensitivity for trackpad */
79
- export const TRACKPAD_ZOOM_SENSITIVITY = 0.015;
80
- // ============================================================================
81
- // INTERACTIONS
82
- // ============================================================================
78
+ const TRACKPAD_ZOOM_SENSITIVITY = .015;
83
79
  /** CSS selector for interactive elements that should not trigger pan */
84
- export const INTERACTIVE_SELECTOR = "button,[role='button'],input,textarea,[contenteditable='true']," +
85
- "[data-toolbar-button],[data-navbar-button]";
86
- // ============================================================================
87
- // VIEWPORT CULLING
88
- // ============================================================================
80
+ const INTERACTIVE_SELECTOR = "button,[role='button'],input,textarea,[contenteditable='true'],[data-toolbar-button],[data-navbar-button]";
89
81
  /** Buffer zone in pixels for hysteresis visibility detection */
90
- export const VIEWPORT_HYSTERESIS_BUFFER = 120;
82
+ const VIEWPORT_HYSTERESIS_BUFFER = 120;
91
83
  /** Threshold for showing image fallback on smaller screens */
92
- export const IMAGE_FALLBACK_WIDTH_THRESHOLD = 2000;
93
- // ============================================================================
94
- // NAVBAR
95
- // ============================================================================
84
+ const IMAGE_FALLBACK_WIDTH_THRESHOLD = 2e3;
96
85
  /** Responsive zoom levels for navbar navigation per screen size */
97
- export const RESPONSIVE_ZOOM_MAP = {
98
- [ScreenSizeEnum.SMALL_MOBILE]: 0.5,
99
- [ScreenSizeEnum.MOBILE]: 0.6,
100
- [ScreenSizeEnum.TABLET]: 0.8,
101
- [ScreenSizeEnum.SMALL_DESKTOP]: 0.9,
102
- [ScreenSizeEnum.MEDIUM_DESKTOP]: 1,
103
- [ScreenSizeEnum.LARGE_DESKTOP]: 1.25,
104
- [ScreenSizeEnum.HUGE_DESKTOP]: 1.5,
86
+ const RESPONSIVE_ZOOM_MAP = {
87
+ [ScreenSizeEnum.SMALL_MOBILE]: .5,
88
+ [ScreenSizeEnum.MOBILE]: .6,
89
+ [ScreenSizeEnum.TABLET]: .8,
90
+ [ScreenSizeEnum.SMALL_DESKTOP]: .9,
91
+ [ScreenSizeEnum.MEDIUM_DESKTOP]: 1,
92
+ [ScreenSizeEnum.LARGE_DESKTOP]: 1.25,
93
+ [ScreenSizeEnum.HUGE_DESKTOP]: 1.5
105
94
  };
106
- // ============================================================================
107
- // PERFORMANCE
108
- // ============================================================================
109
95
  /** Debounce duration in ms for navbar clicks based on performance mode */
110
- export const NAVBAR_DEBOUNCE_MS = {
111
- high: 0,
112
- medium: 100,
113
- low: 400,
96
+ const NAVBAR_DEBOUNCE_MS = {
97
+ high: 0,
98
+ medium: 100,
99
+ low: 400
114
100
  };
115
- // ============================================================================
116
- // TOOLBAR
117
- // ============================================================================
118
101
  /** Epsilon for position comparison to hide toolbar when at home */
119
- export const TOOLBAR_OPACITY_POS_EPS = 1; // px
102
+ const TOOLBAR_OPACITY_POS_EPS = 1;
120
103
  /** Epsilon for scale comparison to hide toolbar when at 1x */
121
- export const TOOLBAR_OPACITY_SCALE_EPS = 0.01; // scale delta
104
+ const TOOLBAR_OPACITY_SCALE_EPS = .01;
105
+
106
+ //#endregion
107
+ export { BLUR_TRANSITION, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, GROW_TRANSITION, IMAGE_FALLBACK_WIDTH_THRESHOLD, INTERACTIVE_SELECTOR, INTRO_ASPECT_RATIO, MAX_DIM_RATIO, MAX_ZOOM, MIN_ZOOMS, MOUSE_WHEEL_ZOOM_SENSITIVITY, NAVBAR_DEBOUNCE_MS, PAN_SPRING, RESPONSIVE_ZOOM_MAP, STAGE2_TRANSITION, ScreenSizeEnum, TOOLBAR_OPACITY_POS_EPS, TOOLBAR_OPACITY_SCALE_EPS, TRACKPAD_ZOOM_SENSITIVITY, VIEWPORT_HYSTERESIS_BUFFER, ZOOM_BOUND };
122
108
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../../src/lib/constants.ts"],"sourcesContent":["import { type Easing } from \"framer-motion\";\n\n/**\n * Canvas Library Constants\n * All configurable constants consolidated in one place\n */\n\n// ============================================================================\n// SCREEN SIZE BREAKPOINTS\n// ============================================================================\n\nexport enum ScreenSizeEnum {\n SMALL_MOBILE = \"small-mobile\",\n MOBILE = \"mobile\",\n TABLET = \"tablet\",\n SMALL_DESKTOP = \"small-desktop\",\n MEDIUM_DESKTOP = \"medium-desktop\",\n LARGE_DESKTOP = \"large-desktop\",\n HUGE_DESKTOP = \"huge-desktop\",\n}\n\n// ============================================================================\n// CANVAS DIMENSIONS\n// ============================================================================\n\n/** Default canvas width in pixels */\nexport const DEFAULT_CANVAS_WIDTH = 6000;\n\n/** Default canvas height in pixels */\nexport const DEFAULT_CANVAS_HEIGHT = 4000;\n\n// ============================================================================\n// INTRO ANIMATION\n// ============================================================================\n\n/** Maximum dimensions ratio for the intro box relative to viewport */\nexport const MAX_DIM_RATIO = {\n width: 0.8,\n height: 0.5,\n} as const;\n\n/** Intro box aspect ratio (width:height) */\nexport const INTRO_ASPECT_RATIO = 3 / 2;\n\n/** Grow animation transition config */\nexport const GROW_TRANSITION = {\n duration: 0.96,\n delay: 3.14,\n ease: [0.35, 0.1, 0.8, 1] as Easing,\n} as const;\n\n/** Blur mask animation transition config */\nexport const BLUR_TRANSITION = {\n duration: 0.85,\n delay: 1.25,\n ease: \"easeIn\" as Easing,\n} as const;\n\n/** Stage 2 pan-to-home transition config */\nexport const STAGE2_TRANSITION = {\n duration: 0.96,\n ease: [0.37, 0.1, 0.6, 1],\n} as const;\n\n// ============================================================================\n// ZOOM & PAN\n// ============================================================================\n\n/** Maximum zoom level */\nexport const MAX_ZOOM = 3;\n\n/** Minimum zoom bound multiplier to prevent zooming out past canvas edges */\nexport const ZOOM_BOUND = 1.05;\n\n/** Minimum zoom levels per screen size */\nexport const MIN_ZOOMS: Record<ScreenSizeEnum, number> = {\n [ScreenSizeEnum.SMALL_MOBILE]: 0.3,\n [ScreenSizeEnum.MOBILE]: 0.35,\n [ScreenSizeEnum.TABLET]: 0.25,\n [ScreenSizeEnum.SMALL_DESKTOP]: 0.15,\n [ScreenSizeEnum.MEDIUM_DESKTOP]: 0.1,\n [ScreenSizeEnum.LARGE_DESKTOP]: 0.1,\n [ScreenSizeEnum.HUGE_DESKTOP]: 0.1,\n} as const;\n\n/** Pan animation spring config */\nexport const PAN_SPRING = {\n visualDuration: 0.34,\n type: \"spring\",\n stiffness: 200,\n damping: 25,\n} as const;\n\n/** Wheel zoom sensitivity for mouse wheel */\nexport const MOUSE_WHEEL_ZOOM_SENSITIVITY = 0.0015;\n\n/** Wheel zoom sensitivity for trackpad */\nexport const TRACKPAD_ZOOM_SENSITIVITY = 0.015;\n\n// ============================================================================\n// INTERACTIONS\n// ============================================================================\n\n/** CSS selector for interactive elements that should not trigger pan */\nexport const INTERACTIVE_SELECTOR =\n \"button,[role='button'],input,textarea,[contenteditable='true'],\" +\n \"[data-toolbar-button],[data-navbar-button]\";\n\n// ============================================================================\n// VIEWPORT CULLING\n// ============================================================================\n\n/** Buffer zone in pixels for hysteresis visibility detection */\nexport const VIEWPORT_HYSTERESIS_BUFFER = 120;\n\n/** Threshold for showing image fallback on smaller screens */\nexport const IMAGE_FALLBACK_WIDTH_THRESHOLD = 2000;\n\n// ============================================================================\n// NAVBAR\n// ============================================================================\n\n/** Responsive zoom levels for navbar navigation per screen size */\nexport const RESPONSIVE_ZOOM_MAP: Record<ScreenSizeEnum, number> = {\n [ScreenSizeEnum.SMALL_MOBILE]: 0.5,\n [ScreenSizeEnum.MOBILE]: 0.6,\n [ScreenSizeEnum.TABLET]: 0.8,\n [ScreenSizeEnum.SMALL_DESKTOP]: 0.9,\n [ScreenSizeEnum.MEDIUM_DESKTOP]: 1,\n [ScreenSizeEnum.LARGE_DESKTOP]: 1.25,\n [ScreenSizeEnum.HUGE_DESKTOP]: 1.5,\n} as const;\n\n// ============================================================================\n// PERFORMANCE\n// ============================================================================\n\n/** Debounce duration in ms for navbar clicks based on performance mode */\nexport const NAVBAR_DEBOUNCE_MS = {\n high: 0,\n medium: 100,\n low: 400,\n} as const;\n\n// ============================================================================\n// TOOLBAR\n// ============================================================================\n\n/** Epsilon for position comparison to hide toolbar when at home */\nexport const TOOLBAR_OPACITY_POS_EPS = 1; // px\n\n/** Epsilon for scale comparison to hide toolbar when at 1x */\nexport const TOOLBAR_OPACITY_SCALE_EPS = 0.01; // scale delta\n"],"mappings":";;;;;AAWA,IAAY,0DAAL;AACH;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAQJ,MAAa,uBAAuB;;AAGpC,MAAa,wBAAwB;;AAOrC,MAAa,gBAAgB;CACzB,OAAO;CACP,QAAQ;CACX;;AAGD,MAAa,qBAAqB,IAAI;;AAGtC,MAAa,kBAAkB;CAC3B,UAAU;CACV,OAAO;CACP,MAAM;EAAC;EAAM;EAAK;EAAK;EAAE;CAC5B;;AAGD,MAAa,kBAAkB;CAC3B,UAAU;CACV,OAAO;CACP,MAAM;CACT;;AAGD,MAAa,oBAAoB;CAC7B,UAAU;CACV,MAAM;EAAC;EAAM;EAAK;EAAK;EAAE;CAC5B;;AAOD,MAAa,WAAW;;AAGxB,MAAa,aAAa;;AAG1B,MAAa,YAA4C;EACpD,eAAe,eAAe;EAC9B,eAAe,SAAS;EACxB,eAAe,SAAS;EACxB,eAAe,gBAAgB;EAC/B,eAAe,iBAAiB;EAChC,eAAe,gBAAgB;EAC/B,eAAe,eAAe;CAClC;;AAGD,MAAa,aAAa;CACtB,gBAAgB;CAChB,MAAM;CACN,WAAW;CACX,SAAS;CACZ;;AAGD,MAAa,+BAA+B;;AAG5C,MAAa,4BAA4B;;AAOzC,MAAa,uBACT;;AAQJ,MAAa,6BAA6B;;AAG1C,MAAa,iCAAiC;;AAO9C,MAAa,sBAAsD;EAC9D,eAAe,eAAe;EAC9B,eAAe,SAAS;EACxB,eAAe,SAAS;EACxB,eAAe,gBAAgB;EAC/B,eAAe,iBAAiB;EAChC,eAAe,gBAAgB;EAC/B,eAAe,eAAe;CAClC;;AAOD,MAAa,qBAAqB;CAC9B,MAAM;CACN,QAAQ;CACR,KAAK;CACR;;AAOD,MAAa,0BAA0B;;AAGvC,MAAa,4BAA4B"}
package/dist/lib/utils.js CHANGED
@@ -1,10 +1,15 @@
1
1
  import { clsx } from "clsx";
2
2
  import { twMerge } from "tailwind-merge";
3
+
4
+ //#region src/lib/utils.ts
3
5
  /**
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));
6
+ * Utility function to merge Tailwind CSS classes.
7
+ * Combines clsx for conditional classes with tailwind-merge for deduplication.
8
+ */
9
+ function cn(...inputs) {
10
+ return twMerge(clsx(inputs));
9
11
  }
12
+
13
+ //#endregion
14
+ export { cn };
10
15
  //# sourceMappingURL=utils.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../../src/lib/utils.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Utility function to merge Tailwind CSS classes.\n * Combines clsx for conditional classes with tailwind-merge for deduplication.\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,GAAG,GAAG,QAAsB;AAC1C,QAAO,QAAQ,KAAK,OAAO,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%}.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}}
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:#f5f5f5;--canvas-coral:#d4d4d4;--canvas-lilac:#e5e5e5;--canvas-salmon:#a3a3a3;--canvas-heavy:#171717;--canvas-emphasis:#262626;--canvas-active:#525252;--canvas-tinted:#a3a3a3;--canvas-medium:#737373;--canvas-light:#a3a3a3;--canvas-faint-lilac:#fafafa;--canvas-offwhite:#fff;--canvas-highlight:#f5f5f5;--canvas-pushed:#e5e5e5;--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}.left-full{left:100%}.right-4{right:1rem}.top-1\/2{top:50%}.top-12{top:3rem}.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}.ml-2{margin-left:.5rem}.block{display:block}.inline{display:inline}.flex{display:flex}.hidden{display:none}.h-auto{height:auto}.h-full{height:100%}.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-width:1px}.border-border{border-color:hsl(var(--border))}.border-neutral-200{--tw-border-opacity:1;border-color:rgb(229 229 229/var(--tw-border-opacity,1))}.bg-canvas-offwhite{background-color:var(--canvas-offwhite)}.bg-neutral-100{--tw-bg-opacity:1;background-color:rgb(245 245 245/var(--tw-bg-opacity,1))}.bg-neutral-200{--tw-bg-opacity:1;background-color:rgb(229 229 229/var(--tw-bg-opacity,1))}.bg-neutral-50{--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity,1))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.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}.py-4{padding-top:1rem;padding-bottom:1rem}.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-heavy{color:var(--canvas-heavy)}.text-canvas-light{color:var(--canvas-light)}.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-neutral-700{--tw-text-opacity:1;color:rgb(64 64 64/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\.08\)\]{--tw-shadow:0 6px 12px rgba(0,0,0,.08);--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)}.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}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}@media (min-width:640px){.sm\:bottom-4{bottom:1rem}.sm\:top-4{top:1rem}}@media (min-width:768px){.md\:bottom-4{bottom:1rem}.md\:top-4{top:1rem}.md\:inline{display:inline}.md\:px-8{padding-left:2rem;padding-right:2rem}.md\:py-8{padding-top:2rem;padding-bottom:2rem}.md\:text-sm{font-size:.875rem;line-height:1.25rem}}
@@ -80,4 +80,73 @@ export interface ToolbarConfig {
80
80
  /** Format for scale. Default: '1.00x' */
81
81
  scaleFormat?: (scale: number) => string;
82
82
  }
83
+ /**
84
+ * Preset positions for the navbar
85
+ */
86
+ export type NavbarPosition = 'top' | 'bottom' | 'left' | 'right';
87
+ /**
88
+ * Display modes for navbar items
89
+ */
90
+ export type NavbarDisplayMode = 'icons' | 'labels' | 'icons-labels' | 'compact';
91
+ /**
92
+ * Tooltip configuration for navbar buttons
93
+ */
94
+ export interface NavbarTooltipConfig {
95
+ /** Disable tooltips entirely. Default: false */
96
+ disabled?: boolean;
97
+ /** Additional className for tooltip */
98
+ className?: string;
99
+ /** Inline styles for tooltip */
100
+ style?: React.CSSProperties;
101
+ /** Delay before showing tooltip in ms. Default: 100 */
102
+ delay?: number;
103
+ }
104
+ /**
105
+ * Button styling configuration for navbar
106
+ */
107
+ export interface NavbarButtonConfig {
108
+ /** Additional className for all buttons */
109
+ className?: string;
110
+ /** Inline styles for all buttons */
111
+ style?: React.CSSProperties;
112
+ /** Active/pushed state className */
113
+ activeClassName?: string;
114
+ /** Active state inline styles */
115
+ activeStyle?: React.CSSProperties;
116
+ /** Hover state className */
117
+ hoverClassName?: string;
118
+ /** Hover state inline styles */
119
+ hoverStyle?: React.CSSProperties;
120
+ /** Icon className */
121
+ iconClassName?: string;
122
+ /** Icon size in pixels. Default: 20 */
123
+ iconSize?: number;
124
+ /** Label className */
125
+ labelClassName?: string;
126
+ /** Label inline styles */
127
+ labelStyle?: React.CSSProperties;
128
+ }
129
+ /**
130
+ * Configuration options for the canvas navbar
131
+ */
132
+ export interface NavbarConfig {
133
+ /** Hide the navbar entirely. Default: false */
134
+ hidden?: boolean;
135
+ /** How to display items. Default: 'icons' */
136
+ display?: NavbarDisplayMode;
137
+ /** Preset position. Default: 'bottom' */
138
+ position?: NavbarPosition;
139
+ /** Additional className for the navbar container */
140
+ className?: string;
141
+ /** Inline styles for the navbar container */
142
+ style?: React.CSSProperties;
143
+ /** Button styling options */
144
+ buttonConfig?: NavbarButtonConfig;
145
+ /** Tooltip options */
146
+ tooltipConfig?: NavbarTooltipConfig;
147
+ /** Gap between buttons in pixels. Default: 4 */
148
+ gap?: number;
149
+ /** Padding inside the navbar in pixels. Default: 4 */
150
+ padding?: number;
151
+ }
83
152
  //# 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;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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -1,29 +1,24 @@
1
+ //#region src/utils/performance.ts
1
2
  /**
2
- * Performance optimization utilities for cross-platform compatibility
3
- * Particularly focused on iOS Safari performance issues
4
- */
5
- // Detect if the device is iOS
6
- export const isIOS = () => {
7
- if (typeof window === "undefined")
8
- return false;
9
- return /iPad|iPhone|iPod/.test(navigator.userAgent);
3
+ * Performance optimization utilities for cross-platform compatibility
4
+ * Particularly focused on iOS Safari performance issues
5
+ */
6
+ const isIOS = () => {
7
+ if (typeof window === "undefined") return false;
8
+ return /iPad|iPhone|iPod/.test(navigator.userAgent);
10
9
  };
11
- // Detect if the device is a mobile device
12
- export const isMobile = () => {
13
- if (typeof window === "undefined")
14
- return false;
15
- return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
10
+ const isMobile = () => {
11
+ if (typeof window === "undefined") return false;
12
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
16
13
  };
17
- // Check if user prefers reduced motion
18
- export const prefersReducedMotion = () => {
19
- if (typeof window === "undefined")
20
- return false;
21
- return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
14
+ const prefersReducedMotion = () => {
15
+ if (typeof window === "undefined") return false;
16
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
22
17
  };
23
- // Get optimized will-change value based on state
24
- export const getWillChange = (isAnimating, properties = ["transform"]) => {
25
- // Only apply will-change when actually animating
26
- // Leaving it on causes memory issues on iOS
27
- return isAnimating ? properties.join(", ") : "auto";
18
+ const getWillChange = (isAnimating, properties = ["transform"]) => {
19
+ return isAnimating ? properties.join(", ") : "auto";
28
20
  };
21
+
22
+ //#endregion
23
+ export { getWillChange, isIOS, isMobile, prefersReducedMotion };
29
24
  //# sourceMappingURL=performance.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"performance.js","sourceRoot":"","sources":["../../src/utils/performance.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8BAA8B;AAC9B,MAAM,CAAC,MAAM,KAAK,GAAG,GAAY,EAAE;IACjC,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAEhD,OAAO,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAY,EAAE;IACpC,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAEhD,OAAO,gEAAgE,CAAC,IAAI,CAC1E,SAAS,CAAC,SAAS,CACpB,CAAC;AACJ,CAAC,CAAC;AAEF,uCAAuC;AACvC,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAY,EAAE;IAChD,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAEhD,OAAO,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC,OAAO,CAAC;AACvE,CAAC,CAAC;AAEF,iDAAiD;AACjD,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,WAAoB,EACpB,aAAuB,CAAC,WAAW,CAAC,EAC5B,EAAE;IACV,iDAAiD;IACjD,4CAA4C;IAC5C,OAAO,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AACtD,CAAC,CAAC"}
1
+ {"version":3,"file":"performance.js","names":[],"sources":["../../src/utils/performance.ts"],"sourcesContent":["/**\n * Performance optimization utilities for cross-platform compatibility\n * Particularly focused on iOS Safari performance issues\n */\n\n// Detect if the device is iOS\nexport const isIOS = (): boolean => {\n if (typeof window === \"undefined\") return false;\n\n return /iPad|iPhone|iPod/.test(navigator.userAgent);\n};\n\n// Detect if the device is a mobile device\nexport const isMobile = (): boolean => {\n if (typeof window === \"undefined\") return false;\n\n return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n navigator.userAgent,\n );\n};\n\n// Check if user prefers reduced motion\nexport const prefersReducedMotion = (): boolean => {\n if (typeof window === \"undefined\") return false;\n\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n};\n\n// Get optimized will-change value based on state\nexport const getWillChange = (\n isAnimating: boolean,\n properties: string[] = [\"transform\"],\n): string => {\n // Only apply will-change when actually animating\n // Leaving it on causes memory issues on iOS\n return isAnimating ? properties.join(\", \") : \"auto\";\n};\n"],"mappings":";;;;;AAMA,MAAa,cAAuB;AAClC,KAAI,OAAO,WAAW,YAAa,QAAO;AAE1C,QAAO,mBAAmB,KAAK,UAAU,UAAU;;AAIrD,MAAa,iBAA0B;AACrC,KAAI,OAAO,WAAW,YAAa,QAAO;AAE1C,QAAO,iEAAiE,KACtE,UAAU,UACX;;AAIH,MAAa,6BAAsC;AACjD,KAAI,OAAO,WAAW,YAAa,QAAO;AAE1C,QAAO,OAAO,WAAW,mCAAmC,CAAC;;AAI/D,MAAa,iBACX,aACA,aAAuB,CAAC,YAAY,KACzB;AAGX,QAAO,cAAc,WAAW,KAAK,KAAK,GAAG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hunterchen/canvas",
3
- "version": "0.7.0",
3
+ "version": "0.9.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",
@@ -17,30 +17,15 @@
17
17
  "exports": {
18
18
  ".": {
19
19
  "types": "./dist/index.d.ts",
20
- "default": "./dist/index.js"
20
+ "import": "./dist/index.js"
21
21
  },
22
- "./styles.css": "./dist/styles.css",
23
- "./components": {
24
- "types": "./dist/components/index.d.ts",
25
- "default": "./dist/components/index.js"
26
- },
27
- "./contexts": {
28
- "types": "./dist/contexts/index.d.ts",
29
- "default": "./dist/contexts/index.js"
30
- },
31
- "./hooks": {
32
- "types": "./dist/hooks/index.d.ts",
33
- "default": "./dist/hooks/index.js"
34
- },
35
- "./lib": {
36
- "types": "./dist/lib/index.d.ts",
37
- "default": "./dist/lib/index.js"
38
- }
22
+ "./styles.css": "./dist/styles.css"
39
23
  },
40
24
  "scripts": {
41
- "build": "npm run clean && npm run build:css && npm run build:ts",
25
+ "build": "npm run clean && npm run build:css && npm run build:js && npm run build:types",
42
26
  "build:css": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify",
43
- "build:ts": "tsc",
27
+ "build:js": "rolldown -c",
28
+ "build:types": "tsc --emitDeclarationOnly",
44
29
  "type-check": "tsc --noEmit",
45
30
  "clean": "rm -rf dist"
46
31
  },
@@ -61,6 +46,7 @@
61
46
  "framer-motion": "^12.26.2",
62
47
  "react": "^19.2.3",
63
48
  "react-dom": "^19.2.3",
49
+ "rolldown": "^1.0.0-rc.2",
64
50
  "tailwindcss": "^3.4.19",
65
51
  "tailwindcss-animate": "^1.0.7",
66
52
  "typescript": "^5.8.2"
@@ -32,8 +32,8 @@ export interface DefaultCanvasBackgroundProps {
32
32
  children?: ReactNode;
33
33
  }
34
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%)`;
35
+ /** The default canvas gradient (neutral light gray) */
36
+ export const DEFAULT_CANVAS_GRADIENT = `radial-gradient(ellipse ${canvasWidth}px ${canvasHeight}px at ${canvasWidth / 2}px ${canvasHeight}px, #fafafa 0%, #f5f5f5 41%, #e5e5e5 59%, #fafafa 90%)`;
37
37
 
38
38
  /**
39
39
  * Default canvas background with gradient, dots, and noise filter.
@@ -42,7 +42,7 @@ export const DEFAULT_CANVAS_GRADIENT = `radial-gradient(ellipse ${canvasWidth}px
42
42
  export const DefaultCanvasBackground: React.FC<DefaultCanvasBackgroundProps> = ({
43
43
  gradientStyle,
44
44
  showDots = true,
45
- dotColor = "#888888",
45
+ dotColor = "#a3a3a3",
46
46
  dotSize = 1.5,
47
47
  dotSpacing = 22,
48
48
  dotOpacity = 0.35,
@@ -117,7 +117,7 @@ export interface DefaultWrapperBackgroundProps {
117
117
  * Default wrapper/intro background gradient.
118
118
  */
119
119
  export const DefaultWrapperBackground: React.FC<DefaultWrapperBackgroundProps> = ({
120
- gradient = "linear-gradient(to top, #d4d4d4 0%, #e5e5e5 50%, #f5f5f5 100%)",
120
+ gradient = "linear-gradient(to top, #f5f5f5 0%, #fafafa 50%, #ffffff 100%)",
121
121
  className,
122
122
  style,
123
123
  }) => {
@@ -197,9 +197,9 @@ export const DefaultIntroContent: React.FC<DefaultIntroContentProps> = ({
197
197
  );
198
198
  };
199
199
 
200
- // Default gradient values for export (neutral grays)
200
+ // Default gradient values for export (neutral light grays)
201
201
  export const DEFAULT_INTRO_GRADIENT =
202
- "linear-gradient(to top, #d4d4d4 0%, #e5e5e5 50%, #f5f5f5 100%)";
202
+ "linear-gradient(to top, #f5f5f5 0%, #fafafa 50%, #ffffff 100%)";
203
203
 
204
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%)";
205
+ "radial-gradient(130.38% 95% at 50.03% 97.25%, #f5f5f5 0%, #fafafa 48.09%, #ffffff 100%)";
@@ -44,6 +44,7 @@ import Toolbar from "./toolbar";
44
44
  import type {
45
45
  CanvasSection,
46
46
  NavItem,
47
+ NavbarConfig,
47
48
  SectionCoordinates,
48
49
  ToolbarConfig,
49
50
  } from "../../types";
@@ -89,6 +90,10 @@ interface Props {
89
90
  // ============== Toolbar Customization ==============
90
91
  /** Toolbar customization options */
91
92
  toolbarConfig?: ToolbarConfig;
93
+
94
+ // ============== Navbar Customization ==============
95
+ /** Navbar customization options */
96
+ navbarConfig?: NavbarConfig;
92
97
  }
93
98
 
94
99
  const stopAllMotion = (
@@ -115,6 +120,7 @@ const Canvas: FC<Props> = ({
115
120
  canvasBackground,
116
121
  wrapperBackground,
117
122
  toolbarConfig,
123
+ navbarConfig,
118
124
  canvasHeight,
119
125
  canvasWidth,
120
126
  }) => {
@@ -644,13 +650,14 @@ const Canvas: FC<Props> = ({
644
650
  config={toolbarConfig}
645
651
  />
646
652
  )}
647
- {hasNavbar && navItems ? (
653
+ {hasNavbar && navItems && !navbarConfig?.hidden && (
648
654
  <Navbar
649
655
  panToOffset={handlePanToOffset}
650
656
  onReset={onResetViewAndItems}
651
657
  items={navItems}
658
+ config={navbarConfig}
652
659
  />
653
- ) : null}
660
+ )}
654
661
  </>
655
662
  )}
656
663
  <div