@autumnsgrove/groveengine 0.7.0 → 0.8.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 (160) hide show
  1. package/dist/ui/components/content/RoadmapPreview.svelte +91 -0
  2. package/dist/ui/components/content/RoadmapPreview.svelte.d.ts +36 -0
  3. package/dist/ui/components/content/index.d.ts +1 -0
  4. package/dist/ui/components/content/index.js +1 -0
  5. package/dist/ui/components/nature/Logo.svelte +224 -0
  6. package/dist/ui/components/nature/Logo.svelte.d.ts +14 -0
  7. package/dist/ui/components/nature/botanical/Acorn.svelte +48 -0
  8. package/dist/ui/components/nature/botanical/Acorn.svelte.d.ts +8 -0
  9. package/dist/ui/components/nature/botanical/Berry.svelte +67 -0
  10. package/dist/ui/components/nature/botanical/Berry.svelte.d.ts +8 -0
  11. package/dist/ui/components/nature/botanical/DandelionPuff.svelte +98 -0
  12. package/dist/ui/components/nature/botanical/DandelionPuff.svelte.d.ts +8 -0
  13. package/dist/ui/components/nature/botanical/FallingLeavesLayer.svelte +170 -0
  14. package/dist/ui/components/nature/botanical/FallingLeavesLayer.svelte.d.ts +35 -0
  15. package/dist/ui/components/nature/botanical/FallingPetalsLayer.svelte +174 -0
  16. package/dist/ui/components/nature/botanical/FallingPetalsLayer.svelte.d.ts +25 -0
  17. package/dist/ui/components/nature/botanical/Leaf.svelte +77 -0
  18. package/dist/ui/components/nature/botanical/Leaf.svelte.d.ts +10 -0
  19. package/dist/ui/components/nature/botanical/LeafFalling.svelte +186 -0
  20. package/dist/ui/components/nature/botanical/LeafFalling.svelte.d.ts +22 -0
  21. package/dist/ui/components/nature/botanical/PetalFalling.svelte +266 -0
  22. package/dist/ui/components/nature/botanical/PetalFalling.svelte.d.ts +25 -0
  23. package/dist/ui/components/nature/botanical/PineCone.svelte +61 -0
  24. package/dist/ui/components/nature/botanical/PineCone.svelte.d.ts +7 -0
  25. package/dist/ui/components/nature/botanical/Vine.svelte +102 -0
  26. package/dist/ui/components/nature/botanical/Vine.svelte.d.ts +11 -0
  27. package/dist/ui/components/nature/botanical/index.d.ts +10 -0
  28. package/dist/ui/components/nature/botanical/index.js +11 -0
  29. package/dist/ui/components/nature/creatures/Bee.svelte +78 -0
  30. package/dist/ui/components/nature/creatures/Bee.svelte.d.ts +9 -0
  31. package/dist/ui/components/nature/creatures/Bird.svelte +94 -0
  32. package/dist/ui/components/nature/creatures/Bird.svelte.d.ts +11 -0
  33. package/dist/ui/components/nature/creatures/BirdFlying.svelte +83 -0
  34. package/dist/ui/components/nature/creatures/BirdFlying.svelte.d.ts +9 -0
  35. package/dist/ui/components/nature/creatures/Bluebird.svelte +95 -0
  36. package/dist/ui/components/nature/creatures/Bluebird.svelte.d.ts +12 -0
  37. package/dist/ui/components/nature/creatures/Butterfly.svelte +87 -0
  38. package/dist/ui/components/nature/creatures/Butterfly.svelte.d.ts +9 -0
  39. package/dist/ui/components/nature/creatures/Cardinal.svelte +95 -0
  40. package/dist/ui/components/nature/creatures/Cardinal.svelte.d.ts +12 -0
  41. package/dist/ui/components/nature/creatures/Chickadee.svelte +97 -0
  42. package/dist/ui/components/nature/creatures/Chickadee.svelte.d.ts +12 -0
  43. package/dist/ui/components/nature/creatures/Deer.svelte +95 -0
  44. package/dist/ui/components/nature/creatures/Deer.svelte.d.ts +9 -0
  45. package/dist/ui/components/nature/creatures/Firefly.svelte +111 -0
  46. package/dist/ui/components/nature/creatures/Firefly.svelte.d.ts +10 -0
  47. package/dist/ui/components/nature/creatures/Owl.svelte +91 -0
  48. package/dist/ui/components/nature/creatures/Owl.svelte.d.ts +9 -0
  49. package/dist/ui/components/nature/creatures/Rabbit.svelte +90 -0
  50. package/dist/ui/components/nature/creatures/Rabbit.svelte.d.ts +9 -0
  51. package/dist/ui/components/nature/creatures/Robin.svelte +98 -0
  52. package/dist/ui/components/nature/creatures/Robin.svelte.d.ts +12 -0
  53. package/dist/ui/components/nature/creatures/Squirrel.svelte +97 -0
  54. package/dist/ui/components/nature/creatures/Squirrel.svelte.d.ts +9 -0
  55. package/dist/ui/components/nature/creatures/index.d.ts +13 -0
  56. package/dist/ui/components/nature/creatures/index.js +14 -0
  57. package/dist/ui/components/nature/ground/Bush.svelte +57 -0
  58. package/dist/ui/components/nature/ground/Bush.svelte.d.ts +10 -0
  59. package/dist/ui/components/nature/ground/Crocus.svelte +83 -0
  60. package/dist/ui/components/nature/ground/Crocus.svelte.d.ts +12 -0
  61. package/dist/ui/components/nature/ground/Daffodil.svelte +75 -0
  62. package/dist/ui/components/nature/ground/Daffodil.svelte.d.ts +11 -0
  63. package/dist/ui/components/nature/ground/Fern.svelte +72 -0
  64. package/dist/ui/components/nature/ground/Fern.svelte.d.ts +10 -0
  65. package/dist/ui/components/nature/ground/FlowerWild.svelte +60 -0
  66. package/dist/ui/components/nature/ground/FlowerWild.svelte.d.ts +10 -0
  67. package/dist/ui/components/nature/ground/GrassTuft.svelte +49 -0
  68. package/dist/ui/components/nature/ground/GrassTuft.svelte.d.ts +10 -0
  69. package/dist/ui/components/nature/ground/Log.svelte +42 -0
  70. package/dist/ui/components/nature/ground/Log.svelte.d.ts +7 -0
  71. package/dist/ui/components/nature/ground/Mushroom.svelte +48 -0
  72. package/dist/ui/components/nature/ground/Mushroom.svelte.d.ts +9 -0
  73. package/dist/ui/components/nature/ground/MushroomCluster.svelte +41 -0
  74. package/dist/ui/components/nature/ground/MushroomCluster.svelte.d.ts +8 -0
  75. package/dist/ui/components/nature/ground/Rock.svelte +59 -0
  76. package/dist/ui/components/nature/ground/Rock.svelte.d.ts +8 -0
  77. package/dist/ui/components/nature/ground/Stump.svelte +44 -0
  78. package/dist/ui/components/nature/ground/Stump.svelte.d.ts +8 -0
  79. package/dist/ui/components/nature/ground/Tulip.svelte +79 -0
  80. package/dist/ui/components/nature/ground/Tulip.svelte.d.ts +11 -0
  81. package/dist/ui/components/nature/ground/index.d.ts +12 -0
  82. package/dist/ui/components/nature/ground/index.js +13 -0
  83. package/dist/ui/components/nature/index.d.ts +28 -0
  84. package/dist/ui/components/nature/index.js +38 -0
  85. package/dist/ui/components/nature/palette.d.ts +491 -0
  86. package/dist/ui/components/nature/palette.js +384 -0
  87. package/dist/ui/components/nature/sky/Cloud.svelte +122 -0
  88. package/dist/ui/components/nature/sky/Cloud.svelte.d.ts +11 -0
  89. package/dist/ui/components/nature/sky/CloudWispy.svelte +79 -0
  90. package/dist/ui/components/nature/sky/CloudWispy.svelte.d.ts +9 -0
  91. package/dist/ui/components/nature/sky/Moon.svelte +60 -0
  92. package/dist/ui/components/nature/sky/Moon.svelte.d.ts +9 -0
  93. package/dist/ui/components/nature/sky/Rainbow.svelte +101 -0
  94. package/dist/ui/components/nature/sky/Rainbow.svelte.d.ts +8 -0
  95. package/dist/ui/components/nature/sky/Star.svelte +84 -0
  96. package/dist/ui/components/nature/sky/Star.svelte.d.ts +10 -0
  97. package/dist/ui/components/nature/sky/StarCluster.svelte +85 -0
  98. package/dist/ui/components/nature/sky/StarCluster.svelte.d.ts +9 -0
  99. package/dist/ui/components/nature/sky/StarShooting.svelte +90 -0
  100. package/dist/ui/components/nature/sky/StarShooting.svelte.d.ts +9 -0
  101. package/dist/ui/components/nature/sky/Sun.svelte +70 -0
  102. package/dist/ui/components/nature/sky/Sun.svelte.d.ts +9 -0
  103. package/dist/ui/components/nature/sky/index.d.ts +8 -0
  104. package/dist/ui/components/nature/sky/index.js +9 -0
  105. package/dist/ui/components/nature/structural/Birdhouse.svelte +53 -0
  106. package/dist/ui/components/nature/structural/Birdhouse.svelte.d.ts +8 -0
  107. package/dist/ui/components/nature/structural/Bridge.svelte +65 -0
  108. package/dist/ui/components/nature/structural/Bridge.svelte.d.ts +7 -0
  109. package/dist/ui/components/nature/structural/FencePost.svelte +54 -0
  110. package/dist/ui/components/nature/structural/FencePost.svelte.d.ts +8 -0
  111. package/dist/ui/components/nature/structural/GardenGate.svelte +70 -0
  112. package/dist/ui/components/nature/structural/GardenGate.svelte.d.ts +8 -0
  113. package/dist/ui/components/nature/structural/Lantern.svelte +113 -0
  114. package/dist/ui/components/nature/structural/Lantern.svelte.d.ts +10 -0
  115. package/dist/ui/components/nature/structural/Lattice.svelte +89 -0
  116. package/dist/ui/components/nature/structural/Lattice.svelte.d.ts +8 -0
  117. package/dist/ui/components/nature/structural/LatticeWithVine.svelte +89 -0
  118. package/dist/ui/components/nature/structural/LatticeWithVine.svelte.d.ts +11 -0
  119. package/dist/ui/components/nature/structural/StonePath.svelte +48 -0
  120. package/dist/ui/components/nature/structural/StonePath.svelte.d.ts +7 -0
  121. package/dist/ui/components/nature/structural/index.d.ts +8 -0
  122. package/dist/ui/components/nature/structural/index.js +9 -0
  123. package/dist/ui/components/nature/trees/TreeAspen.svelte +163 -0
  124. package/dist/ui/components/nature/trees/TreeAspen.svelte.d.ts +11 -0
  125. package/dist/ui/components/nature/trees/TreeBirch.svelte +186 -0
  126. package/dist/ui/components/nature/trees/TreeBirch.svelte.d.ts +11 -0
  127. package/dist/ui/components/nature/trees/TreeCherry.svelte +108 -0
  128. package/dist/ui/components/nature/trees/TreeCherry.svelte.d.ts +11 -0
  129. package/dist/ui/components/nature/trees/TreePine.svelte +79 -0
  130. package/dist/ui/components/nature/trees/TreePine.svelte.d.ts +11 -0
  131. package/dist/ui/components/nature/trees/index.d.ts +4 -0
  132. package/dist/ui/components/nature/trees/index.js +5 -0
  133. package/dist/ui/components/nature/water/LilyPad.svelte +99 -0
  134. package/dist/ui/components/nature/water/LilyPad.svelte.d.ts +10 -0
  135. package/dist/ui/components/nature/water/Pond.svelte +104 -0
  136. package/dist/ui/components/nature/water/Pond.svelte.d.ts +8 -0
  137. package/dist/ui/components/nature/water/Reeds.svelte +85 -0
  138. package/dist/ui/components/nature/water/Reeds.svelte.d.ts +11 -0
  139. package/dist/ui/components/nature/water/Stream.svelte +98 -0
  140. package/dist/ui/components/nature/water/Stream.svelte.d.ts +8 -0
  141. package/dist/ui/components/nature/water/index.d.ts +4 -0
  142. package/dist/ui/components/nature/water/index.js +5 -0
  143. package/dist/ui/components/nature/weather/SnowfallLayer.svelte +175 -0
  144. package/dist/ui/components/nature/weather/SnowfallLayer.svelte.d.ts +25 -0
  145. package/dist/ui/components/nature/weather/Snowflake.svelte +99 -0
  146. package/dist/ui/components/nature/weather/Snowflake.svelte.d.ts +11 -0
  147. package/dist/ui/components/nature/weather/SnowflakeFalling.svelte +162 -0
  148. package/dist/ui/components/nature/weather/SnowflakeFalling.svelte.d.ts +23 -0
  149. package/dist/ui/components/nature/weather/index.d.ts +3 -0
  150. package/dist/ui/components/nature/weather/index.js +4 -0
  151. package/dist/ui/components/ui/GlassLogo.svelte +422 -0
  152. package/dist/ui/components/ui/GlassLogo.svelte.d.ts +23 -0
  153. package/dist/ui/components/ui/GlassNavbar.svelte +120 -0
  154. package/dist/ui/components/ui/GlassNavbar.svelte.d.ts +42 -0
  155. package/dist/ui/components/ui/Logo.svelte +47 -52
  156. package/dist/ui/components/ui/Logo.svelte.d.ts +4 -3
  157. package/dist/ui/components/ui/index.d.ts +2 -0
  158. package/dist/ui/components/ui/index.js +2 -0
  159. package/dist/ui/styles/grove.css +15 -1
  160. package/package.json +11 -1
@@ -0,0 +1,422 @@
1
+ <script lang="ts">
2
+ /**
3
+ * GlassLogo - Grove Logo with glassmorphism styling
4
+ *
5
+ * A beautiful translucent logo with frosted glass effects,
6
+ * subtle highlights, and soft glows. Perfect for hero sections,
7
+ * glass cards, and modern UI designs.
8
+ *
9
+ * @example Basic glass logo
10
+ * ```svelte
11
+ * <GlassLogo class="w-16 h-20" />
12
+ * ```
13
+ *
14
+ * @example Seasonal glass logo
15
+ * ```svelte
16
+ * <GlassLogo season="winter" class="w-16 h-20" />
17
+ * <GlassLogo season="spring" breathing />
18
+ * <GlassLogo season="autumn" variant="frosted" />
19
+ * ```
20
+ *
21
+ * @example Accent variant with breathing
22
+ * ```svelte
23
+ * <GlassLogo variant="accent" breathing />
24
+ * ```
25
+ */
26
+
27
+ import { tweened } from 'svelte/motion';
28
+ import { cubicInOut } from 'svelte/easing';
29
+ import { browser } from '$app/environment';
30
+
31
+ type GlassVariant =
32
+ | "default" // Light translucent - uses seasonal color or white/emerald
33
+ | "accent" // Accent-colored glass
34
+ | "frosted" // Strong frosted effect, more opaque
35
+ | "dark" // Dark translucent for light backgrounds
36
+ | "ethereal"; // Dreamy, highly transparent with glow
37
+
38
+ type Season = 'spring' | 'summer' | 'autumn' | 'winter';
39
+
40
+ type BreathingSpeed = 'slow' | 'normal' | 'fast';
41
+
42
+ interface Props {
43
+ class?: string;
44
+ /** Glass style variant */
45
+ variant?: GlassVariant;
46
+ /** Seasonal color theme - defaults to summer */
47
+ season?: Season;
48
+ /** Add breathing animation (for loading states) */
49
+ breathing?: boolean;
50
+ /** Breathing animation speed */
51
+ breathingSpeed?: BreathingSpeed;
52
+ /** Whether trunk should match foliage color */
53
+ monochrome?: boolean;
54
+ /** Custom accent color (CSS color value) - only applies when season is not set */
55
+ accentColor?: string;
56
+ /** Unique ID for SVG filters (auto-generated if not provided) */
57
+ filterId?: string;
58
+ }
59
+
60
+ let {
61
+ class: className = 'w-6 h-6',
62
+ variant = "default",
63
+ season = 'summer',
64
+ breathing = false,
65
+ breathingSpeed = 'normal',
66
+ monochrome = false,
67
+ accentColor,
68
+ filterId
69
+ }: Props = $props();
70
+
71
+ // Check if winter for snow accents
72
+ const isWinter = $derived(season === 'winter');
73
+
74
+ // Generate unique ID for SVG filters to avoid conflicts when multiple logos exist
75
+ const uniqueId = filterId ?? `glass-logo-${Math.random().toString(36).slice(2, 9)}`;
76
+
77
+ // Breathing speed presets
78
+ const BREATHING_SPEEDS = {
79
+ slow: 1500,
80
+ normal: 800,
81
+ fast: 400
82
+ } as const;
83
+
84
+ // Reduced motion preference
85
+ const reducedMotionQuery = browser ? window.matchMedia('(prefers-reduced-motion: reduce)') : null;
86
+ let prefersReducedMotion = $state(reducedMotionQuery?.matches ?? false);
87
+
88
+ $effect(() => {
89
+ if (!reducedMotionQuery) return;
90
+ const handler = (e: MediaQueryListEvent) => { prefersReducedMotion = e.matches; };
91
+ reducedMotionQuery.addEventListener('change', handler);
92
+ return () => reducedMotionQuery.removeEventListener('change', handler);
93
+ });
94
+
95
+ // Seasonal color palettes (glass-tinted versions)
96
+ // These define the base hues for each season
97
+ const seasonalPalettes = {
98
+ spring: {
99
+ // Cherry blossom pink - soft, hopeful
100
+ primary: 'rgba(244, 114, 182, 0.75)', // pink-400
101
+ secondary: 'rgba(251, 207, 232, 0.5)', // pink-200
102
+ glow: 'rgba(236, 72, 153, 0.35)', // pink-500
103
+ shadow: 'rgba(219, 39, 119, 0.2)' // pink-600
104
+ },
105
+ summer: {
106
+ // Grove brand green - growth, warmth
107
+ primary: 'rgba(16, 185, 129, 0.75)', // emerald-500
108
+ secondary: 'rgba(167, 243, 208, 0.5)', // emerald-200
109
+ glow: 'rgba(5, 150, 105, 0.35)', // emerald-600
110
+ shadow: 'rgba(4, 120, 87, 0.2)' // emerald-700
111
+ },
112
+ autumn: {
113
+ // Warm amber/orange - harvest, reflection
114
+ primary: 'rgba(251, 146, 60, 0.75)', // orange-400
115
+ secondary: 'rgba(254, 215, 170, 0.5)', // orange-200
116
+ glow: 'rgba(234, 88, 12, 0.35)', // orange-600
117
+ shadow: 'rgba(194, 65, 12, 0.2)' // orange-700
118
+ },
119
+ winter: {
120
+ // Frosted evergreen - stillness, rest
121
+ primary: 'rgba(134, 239, 172, 0.6)', // green-300 (muted)
122
+ secondary: 'rgba(220, 252, 231, 0.4)', // green-100
123
+ glow: 'rgba(74, 222, 128, 0.3)', // green-400
124
+ shadow: 'rgba(34, 197, 94, 0.15)' // green-500
125
+ }
126
+ } as const;
127
+
128
+ // Snow color for winter accents
129
+ const snowColor = 'rgba(248, 250, 252, 0.9)'; // slate-50
130
+
131
+ // Get seasonal colors or null if no season specified
132
+ const seasonColors = $derived(season ? seasonalPalettes[season] : null);
133
+
134
+ // Glass color schemes per variant, using seasonal colors
135
+ const variantColors = $derived.by(() => {
136
+ // Base colors from variant (all variants use seasonal colors now)
137
+ const baseColors = {
138
+ default: {
139
+ gradientStart: seasonColors?.primary ?? 'rgba(255, 255, 255, 0.7)',
140
+ gradientEnd: seasonColors?.secondary ?? 'rgba(236, 253, 245, 0.5)',
141
+ highlight: 'rgba(255, 255, 255, 0.9)',
142
+ shadow: seasonColors?.shadow ?? 'rgba(16, 185, 129, 0.2)',
143
+ trunk: monochrome
144
+ ? (seasonColors?.primary ?? 'rgba(255, 255, 255, 0.5)')
145
+ : 'rgba(93, 64, 55, 0.7)',
146
+ glowColor: seasonColors?.glow ?? 'rgba(16, 185, 129, 0.3)'
147
+ },
148
+ accent: {
149
+ // Accent uses custom accentColor if provided, otherwise seasonal colors
150
+ gradientStart: accentColor ? `${accentColor}cc` : (seasonColors?.primary ?? 'rgba(var(--accent-rgb, 16, 185, 129), 0.8)'),
151
+ gradientEnd: accentColor ? `${accentColor}99` : (seasonColors?.secondary ?? 'rgba(var(--accent-rgb, 16, 185, 129), 0.6)'),
152
+ highlight: 'rgba(255, 255, 255, 0.6)',
153
+ shadow: accentColor ? `${accentColor}40` : (seasonColors?.shadow ?? 'rgba(var(--accent-rgb, 16, 185, 129), 0.25)'),
154
+ trunk: monochrome
155
+ ? (accentColor ? `${accentColor}99` : (seasonColors?.primary ?? 'rgba(var(--accent-rgb, 16, 185, 129), 0.6)'))
156
+ : 'rgba(93, 64, 55, 0.8)',
157
+ glowColor: accentColor ? `${accentColor}50` : (seasonColors?.glow ?? 'rgba(var(--accent-rgb, 16, 185, 129), 0.3)')
158
+ },
159
+ frosted: {
160
+ // Frosted: more opaque, tinted with season
161
+ gradientStart: seasonColors
162
+ ? seasonColors.primary.replace('0.75)', '0.85)').replace('0.6)', '0.8)')
163
+ : 'rgba(255, 255, 255, 0.85)',
164
+ gradientEnd: seasonColors
165
+ ? seasonColors.secondary.replace('0.5)', '0.7)').replace('0.4)', '0.6)')
166
+ : 'rgba(248, 250, 252, 0.75)',
167
+ highlight: 'rgba(255, 255, 255, 0.95)',
168
+ shadow: seasonColors?.shadow ?? 'rgba(100, 116, 139, 0.15)',
169
+ trunk: monochrome
170
+ ? (seasonColors?.primary ?? 'rgba(255, 255, 255, 0.7)')
171
+ : 'rgba(93, 64, 55, 0.85)',
172
+ glowColor: seasonColors?.glow ?? 'rgba(148, 163, 184, 0.2)'
173
+ },
174
+ dark: {
175
+ // Dark: subtle seasonal tint in shadow/glow only
176
+ gradientStart: 'rgba(30, 41, 59, 0.7)',
177
+ gradientEnd: 'rgba(15, 23, 42, 0.6)',
178
+ highlight: 'rgba(148, 163, 184, 0.4)',
179
+ shadow: 'rgba(0, 0, 0, 0.3)',
180
+ trunk: monochrome ? 'rgba(30, 41, 59, 0.6)' : 'rgba(60, 45, 38, 0.8)',
181
+ glowColor: seasonColors?.glow ?? 'rgba(100, 116, 139, 0.2)'
182
+ },
183
+ ethereal: {
184
+ // Ethereal: dreamy seasonal colors with strong glow
185
+ gradientStart: seasonColors
186
+ ? seasonColors.primary.replace(/0\.\d+\)$/, '0.4)')
187
+ : 'rgba(255, 255, 255, 0.4)',
188
+ gradientEnd: seasonColors
189
+ ? seasonColors.secondary.replace(/0\.\d+\)$/, '0.25)')
190
+ : 'rgba(236, 254, 255, 0.25)',
191
+ highlight: 'rgba(255, 255, 255, 0.7)',
192
+ shadow: seasonColors?.shadow ?? 'rgba(34, 211, 238, 0.2)',
193
+ trunk: monochrome
194
+ ? (seasonColors?.primary?.replace(/0\.\d+\)$/, '0.3)') ?? 'rgba(255, 255, 255, 0.3)')
195
+ : 'rgba(93, 64, 55, 0.5)',
196
+ glowColor: seasonColors
197
+ ? seasonColors.glow.replace(/0\.\d+\)$/, '0.4)')
198
+ : 'rgba(34, 211, 238, 0.4)'
199
+ }
200
+ };
201
+
202
+ return baseColors[variant];
203
+ });
204
+
205
+ // Breathing animation
206
+ const breathValue = tweened(0, { easing: cubicInOut });
207
+
208
+ $effect(() => {
209
+ const duration = BREATHING_SPEEDS[breathingSpeed];
210
+
211
+ if (!breathing || prefersReducedMotion) {
212
+ breathValue.set(0, { duration: Math.min(duration / 2, 300) });
213
+ return;
214
+ }
215
+
216
+ let cancelled = false;
217
+
218
+ async function pulse() {
219
+ while (!cancelled) {
220
+ await breathValue.set(1, { duration });
221
+ if (cancelled) break;
222
+ await breathValue.set(0, { duration });
223
+ if (cancelled) break;
224
+ }
225
+ }
226
+
227
+ pulse();
228
+
229
+ return () => { cancelled = true; };
230
+ });
231
+
232
+ // Breathing expansion values
233
+ const expansion = $derived($breathValue * 22);
234
+ const diagExpansion = $derived($breathValue * 16);
235
+
236
+ // Individual branch transforms for breathing
237
+ const leftTransform = $derived(`translate(${-expansion}, 0)`);
238
+ const rightTransform = $derived(`translate(${expansion}, 0)`);
239
+ const topTransform = $derived(`translate(0, ${-expansion})`);
240
+ const topLeftTransform = $derived(`translate(${-diagExpansion}, ${-diagExpansion})`);
241
+ const topRightTransform = $derived(`translate(${diagExpansion}, ${-diagExpansion})`);
242
+ const bottomLeftTransform = $derived(`translate(${-diagExpansion}, ${diagExpansion})`);
243
+ const bottomRightTransform = $derived(`translate(${diagExpansion}, ${diagExpansion})`);
244
+
245
+ // Glow intensity for breathing (pulses with breath)
246
+ const glowIntensity = $derived(4 + $breathValue * 4);
247
+
248
+
249
+ // Decomposed foliage paths for breathing animation
250
+ // Each bar extends toward the center so they overlap at rest, forming the complete logo
251
+ // When expanded, the overlapping regions separate creating the burst effect
252
+
253
+ // Left horizontal bar - extends right to center, includes connection wedge
254
+ const leftBarPath = "M0 173.468 L171.476 173.468 L171.476 243.97 L0 243.97 Z";
255
+
256
+ // Right horizontal bar - extends left to center, includes connection wedge
257
+ const rightBarPath = "M245.562 173.268 L417 173.268 L417 243.77 L245.562 243.77 Z";
258
+
259
+ // Top vertical bar - extends down to center, includes connection wedge
260
+ const topBarPath = "M171.476 0 L245.562 0 L245.562 173.468 L171.476 173.468 Z";
261
+
262
+ // Top-left diagonal - arrow with extended inner edge
263
+ const topLeftDiagPath = "M171.476 173.468 L171.476 124.872 L86.037 37.043 L36.446 88.028 L126 173.468 Z";
264
+
265
+ // Top-right diagonal - arrow with extended inner edge
266
+ const topRightDiagPath = "M245.562 173.268 L245.562 124.872 L331 37.243 L380.552 88.028 L290.972 173.268 Z";
267
+
268
+ // Bottom-left diagonal - arrow with extended inner edge to center point
269
+ const bottomLeftDiagPath = "M171.476 243.97 L208.519 258.11 L86.037 381.192 L36.446 331.601 L126.664 243.97 Z";
270
+
271
+ // Bottom-right diagonal - arrow with extended inner edge to center point
272
+ const bottomRightDiagPath = "M245.562 243.77 L208.519 258.11 L331 381.192 L380.435 331.399 L290.252 243.77 Z";
273
+
274
+ // Full foliage path for non-breathing state
275
+ const fullFoliagePath = "M0 173.468h126.068l-89.622-85.44 49.591-50.985 85.439 87.829V0h74.086v124.872L331 37.243l49.552 50.785-89.58 85.24H417v70.502H290.252l90.183 87.629L331 381.192 208.519 258.11 86.037 381.192l-49.591-49.591 90.218-87.631H0v-70.502z";
276
+ </script>
277
+
278
+ <svg
279
+ class={className}
280
+ xmlns="http://www.w3.org/2000/svg"
281
+ viewBox="0 -30 417 542.238"
282
+ aria-label="Grove logo"
283
+ >
284
+ <defs>
285
+ <!-- Main glass gradient for foliage -->
286
+ <linearGradient id="{uniqueId}-foliage-grad" x1="0%" y1="0%" x2="100%" y2="100%">
287
+ <stop offset="0%" stop-color={variantColors.gradientStart} />
288
+ <stop offset="50%" stop-color={variantColors.gradientEnd} />
289
+ <stop offset="100%" stop-color={variantColors.gradientStart} />
290
+ </linearGradient>
291
+
292
+ <!-- Highlight gradient (top-left shine) -->
293
+ <linearGradient id="{uniqueId}-highlight" x1="0%" y1="0%" x2="50%" y2="50%">
294
+ <stop offset="0%" stop-color={variantColors.highlight} />
295
+ <stop offset="100%" stop-color="transparent" />
296
+ </linearGradient>
297
+
298
+ <!-- Trunk gradient -->
299
+ <linearGradient id="{uniqueId}-trunk-grad" x1="0%" y1="0%" x2="100%" y2="100%">
300
+ <stop offset="0%" stop-color={variantColors.trunk} />
301
+ <stop offset="100%" stop-color={variantColors.trunk} stop-opacity="0.8" />
302
+ </linearGradient>
303
+
304
+ <!-- Soft glow filter -->
305
+ <filter id="{uniqueId}-glow" x="-30%" y="-30%" width="160%" height="160%">
306
+ <feGaussianBlur in="SourceGraphic" stdDeviation={glowIntensity} result="blur" />
307
+ <feFlood flood-color={variantColors.glowColor} />
308
+ <feComposite in2="blur" operator="in" />
309
+ <feMerge>
310
+ <feMergeNode />
311
+ <feMergeNode in="SourceGraphic" />
312
+ </feMerge>
313
+ </filter>
314
+
315
+ <!-- Inner shadow/depth filter -->
316
+ <filter id="{uniqueId}-inner-shadow" x="-10%" y="-10%" width="120%" height="120%">
317
+ <feOffset dx="2" dy="2" />
318
+ <feGaussianBlur stdDeviation="3" result="shadow" />
319
+ <feFlood flood-color={variantColors.shadow} />
320
+ <feComposite in2="shadow" operator="in" />
321
+ <feComposite in2="SourceGraphic" operator="over" />
322
+ </filter>
323
+
324
+ <!-- Glass edge highlight mask -->
325
+ <mask id="{uniqueId}-edge-mask">
326
+ <path d={fullFoliagePath} fill="white" />
327
+ </mask>
328
+ </defs>
329
+
330
+ <!-- Trunk with glass effect -->
331
+ <path
332
+ fill="url(#{uniqueId}-trunk-grad)"
333
+ d="M171.274 344.942h74.09v167.296h-74.09V344.942z"
334
+ filter="url(#{uniqueId}-inner-shadow)"
335
+ />
336
+
337
+ {#if breathing}
338
+ <!-- Decomposed foliage with breathing animation - bars expand outward from center -->
339
+ <g filter="url(#{uniqueId}-glow)">
340
+ <!-- Left horizontal bar -->
341
+ <g transform={leftTransform}>
342
+ <path fill="url(#{uniqueId}-foliage-grad)" d={leftBarPath} />
343
+ </g>
344
+
345
+ <!-- Right horizontal bar -->
346
+ <g transform={rightTransform}>
347
+ <path fill="url(#{uniqueId}-foliage-grad)" d={rightBarPath} />
348
+ </g>
349
+
350
+ <!-- Top vertical bar -->
351
+ <g transform={topTransform}>
352
+ <path fill="url(#{uniqueId}-foliage-grad)" d={topBarPath} />
353
+ </g>
354
+
355
+ <!-- Top-left diagonal -->
356
+ <g transform={topLeftTransform}>
357
+ <path fill="url(#{uniqueId}-foliage-grad)" d={topLeftDiagPath} />
358
+ </g>
359
+
360
+ <!-- Top-right diagonal -->
361
+ <g transform={topRightTransform}>
362
+ <path fill="url(#{uniqueId}-foliage-grad)" d={topRightDiagPath} />
363
+ </g>
364
+
365
+ <!-- Bottom-left diagonal -->
366
+ <g transform={bottomLeftTransform}>
367
+ <path fill="url(#{uniqueId}-foliage-grad)" d={bottomLeftDiagPath} />
368
+ </g>
369
+
370
+ <!-- Bottom-right diagonal -->
371
+ <g transform={bottomRightTransform}>
372
+ <path fill="url(#{uniqueId}-foliage-grad)" d={bottomRightDiagPath} />
373
+ </g>
374
+ </g>
375
+ {:else}
376
+ <!-- Static foliage with glass effect -->
377
+ <g filter="url(#{uniqueId}-glow)">
378
+ <path
379
+ fill="url(#{uniqueId}-foliage-grad)"
380
+ d={fullFoliagePath}
381
+ />
382
+ </g>
383
+
384
+ <!-- Top-left highlight/shine overlay -->
385
+ <path
386
+ d={fullFoliagePath}
387
+ fill="url(#{uniqueId}-highlight)"
388
+ opacity="0.5"
389
+ />
390
+
391
+ <!-- Subtle edge highlight (inner stroke effect) -->
392
+ <path
393
+ d={fullFoliagePath}
394
+ fill="none"
395
+ stroke={variantColors.highlight}
396
+ stroke-width="2"
397
+ stroke-opacity="0.3"
398
+ />
399
+ {/if}
400
+
401
+ <!-- Winter snow accents -->
402
+ {#if isWinter}
403
+ <!-- Top point snow cap -->
404
+ <ellipse fill={snowColor} cx="208" cy="8" rx="32" ry="10" opacity="0.85" />
405
+
406
+ <!-- Upper diagonal arm tips (the angled parts pointing up-left and up-right) -->
407
+ <ellipse fill={snowColor} cx="52" cy="60" rx="18" ry="6" opacity="0.7" transform="rotate(-25 52 60)" />
408
+ <ellipse fill={snowColor} cx="365" cy="60" rx="18" ry="6" opacity="0.7" transform="rotate(25 365 60)" />
409
+
410
+ <!-- Horizontal arm snow (left and right extending arms) -->
411
+ <ellipse fill={snowColor} cx="45" cy="175" rx="28" ry="7" opacity="0.75" />
412
+ <ellipse fill={snowColor} cx="372" cy="175" rx="28" ry="7" opacity="0.75" />
413
+
414
+ <!-- Center intersection snow pile -->
415
+ <ellipse fill={snowColor} cx="208" cy="175" rx="25" ry="8" opacity="0.6" />
416
+
417
+ <!-- Lower diagonal arm tips -->
418
+ <ellipse fill={snowColor} cx="95" cy="320" rx="16" ry="5" opacity="0.55" transform="rotate(25 95 320)" />
419
+ <ellipse fill={snowColor} cx="322" cy="320" rx="16" ry="5" opacity="0.55" transform="rotate(-25 322 320)" />
420
+ {/if}
421
+ </svg>
422
+
@@ -0,0 +1,23 @@
1
+ type GlassVariant = "default" | "accent" | "frosted" | "dark" | "ethereal";
2
+ type Season = 'spring' | 'summer' | 'autumn' | 'winter';
3
+ type BreathingSpeed = 'slow' | 'normal' | 'fast';
4
+ interface Props {
5
+ class?: string;
6
+ /** Glass style variant */
7
+ variant?: GlassVariant;
8
+ /** Seasonal color theme - defaults to summer */
9
+ season?: Season;
10
+ /** Add breathing animation (for loading states) */
11
+ breathing?: boolean;
12
+ /** Breathing animation speed */
13
+ breathingSpeed?: BreathingSpeed;
14
+ /** Whether trunk should match foliage color */
15
+ monochrome?: boolean;
16
+ /** Custom accent color (CSS color value) - only applies when season is not set */
17
+ accentColor?: string;
18
+ /** Unique ID for SVG filters (auto-generated if not provided) */
19
+ filterId?: string;
20
+ }
21
+ declare const GlassLogo: import("svelte").Component<Props, {}, "">;
22
+ type GlassLogo = ReturnType<typeof GlassLogo>;
23
+ export default GlassLogo;
@@ -0,0 +1,120 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { cn } from "../../utils";
4
+ import Logo from "./Logo.svelte";
5
+
6
+ /**
7
+ * GlassNavbar - A sticky glassmorphism navigation bar
8
+ *
9
+ * A reusable navigation component with glass styling that can be used
10
+ * across Grove properties (landing, plant, etc.)
11
+ *
12
+ * @example Basic usage
13
+ * ```svelte
14
+ * <GlassNavbar logoHref="https://grove.place" title="Grove" />
15
+ * ```
16
+ *
17
+ * @example With custom content
18
+ * ```svelte
19
+ * <GlassNavbar logoHref="/" title="Grove">
20
+ * {#snippet actions()}
21
+ * <ThemeToggle />
22
+ * {/snippet}
23
+ * </GlassNavbar>
24
+ * ```
25
+ */
26
+
27
+ interface Props {
28
+ /** URL the logo links to */
29
+ logoHref?: string;
30
+ /** Title text next to logo */
31
+ title?: string;
32
+ /** Whether to show the title text */
33
+ showTitle?: boolean;
34
+ /** Max width constraint */
35
+ maxWidth?: 'narrow' | 'default' | 'wide';
36
+ /** Additional CSS classes */
37
+ class?: string;
38
+ /** Slot for navigation items */
39
+ navigation?: Snippet;
40
+ /** Slot for action items (right side) */
41
+ actions?: Snippet;
42
+ /** Callback when logo is clicked */
43
+ onLogoClick?: () => void;
44
+ }
45
+
46
+ let {
47
+ logoHref = "/",
48
+ title = "Grove",
49
+ showTitle = true,
50
+ maxWidth = 'default',
51
+ class: className,
52
+ navigation,
53
+ actions,
54
+ onLogoClick
55
+ }: Props = $props();
56
+
57
+ const maxWidthClass = {
58
+ narrow: 'max-w-2xl',
59
+ default: 'max-w-4xl',
60
+ wide: 'max-w-5xl'
61
+ };
62
+
63
+ function handleLogoClick(e: MouseEvent) {
64
+ if (onLogoClick) {
65
+ e.preventDefault();
66
+ onLogoClick();
67
+ }
68
+ }
69
+ </script>
70
+
71
+ <header
72
+ class={cn(
73
+ "sticky top-0 z-40 py-4 px-6",
74
+ "bg-white/60 dark:bg-emerald-950/25 backdrop-blur-md",
75
+ "border-b border-white/40 dark:border-emerald-800/25",
76
+ className
77
+ )}
78
+ >
79
+ <div class="{maxWidthClass[maxWidth]} mx-auto flex items-center justify-between">
80
+ <!-- Logo area -->
81
+ <div class="flex items-center gap-2">
82
+ {#if onLogoClick}
83
+ <button
84
+ onclick={handleLogoClick}
85
+ class="flex-shrink-0 transition-transform hover:scale-110 active:scale-95"
86
+ aria-label="Go to homepage"
87
+ >
88
+ <Logo class="w-7 h-7" />
89
+ </button>
90
+ {:else}
91
+ <a href={logoHref} class="flex-shrink-0 transition-transform hover:scale-105">
92
+ <Logo class="w-7 h-7" />
93
+ </a>
94
+ {/if}
95
+
96
+ {#if showTitle}
97
+ <a
98
+ href={logoHref}
99
+ class="text-lg font-medium text-foreground hover:text-primary transition-colors"
100
+ >
101
+ {title}
102
+ </a>
103
+ {/if}
104
+ </div>
105
+
106
+ <!-- Navigation (center or left of actions) -->
107
+ {#if navigation}
108
+ <nav class="hidden md:flex items-center gap-4 lg:gap-6 text-sm">
109
+ {@render navigation()}
110
+ </nav>
111
+ {/if}
112
+
113
+ <!-- Actions (right side) -->
114
+ {#if actions}
115
+ <div class="flex items-center gap-2">
116
+ {@render actions()}
117
+ </div>
118
+ {/if}
119
+ </div>
120
+ </header>
@@ -0,0 +1,42 @@
1
+ import type { Snippet } from "svelte";
2
+ /**
3
+ * GlassNavbar - A sticky glassmorphism navigation bar
4
+ *
5
+ * A reusable navigation component with glass styling that can be used
6
+ * across Grove properties (landing, plant, etc.)
7
+ *
8
+ * @example Basic usage
9
+ * ```svelte
10
+ * <GlassNavbar logoHref="https://grove.place" title="Grove" />
11
+ * ```
12
+ *
13
+ * @example With custom content
14
+ * ```svelte
15
+ * <GlassNavbar logoHref="/" title="Grove">
16
+ * {#snippet actions()}
17
+ * <ThemeToggle />
18
+ * {/snippet}
19
+ * </GlassNavbar>
20
+ * ```
21
+ */
22
+ interface Props {
23
+ /** URL the logo links to */
24
+ logoHref?: string;
25
+ /** Title text next to logo */
26
+ title?: string;
27
+ /** Whether to show the title text */
28
+ showTitle?: boolean;
29
+ /** Max width constraint */
30
+ maxWidth?: 'narrow' | 'default' | 'wide';
31
+ /** Additional CSS classes */
32
+ class?: string;
33
+ /** Slot for navigation items */
34
+ navigation?: Snippet;
35
+ /** Slot for action items (right side) */
36
+ actions?: Snippet;
37
+ /** Callback when logo is clicked */
38
+ onLogoClick?: () => void;
39
+ }
40
+ declare const GlassNavbar: import("svelte").Component<Props, {}, "">;
41
+ type GlassNavbar = ReturnType<typeof GlassNavbar>;
42
+ export default GlassNavbar;