@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.
- package/dist/ui/components/content/RoadmapPreview.svelte +91 -0
- package/dist/ui/components/content/RoadmapPreview.svelte.d.ts +36 -0
- package/dist/ui/components/content/index.d.ts +1 -0
- package/dist/ui/components/content/index.js +1 -0
- package/dist/ui/components/nature/Logo.svelte +224 -0
- package/dist/ui/components/nature/Logo.svelte.d.ts +14 -0
- package/dist/ui/components/nature/botanical/Acorn.svelte +48 -0
- package/dist/ui/components/nature/botanical/Acorn.svelte.d.ts +8 -0
- package/dist/ui/components/nature/botanical/Berry.svelte +67 -0
- package/dist/ui/components/nature/botanical/Berry.svelte.d.ts +8 -0
- package/dist/ui/components/nature/botanical/DandelionPuff.svelte +98 -0
- package/dist/ui/components/nature/botanical/DandelionPuff.svelte.d.ts +8 -0
- package/dist/ui/components/nature/botanical/FallingLeavesLayer.svelte +170 -0
- package/dist/ui/components/nature/botanical/FallingLeavesLayer.svelte.d.ts +35 -0
- package/dist/ui/components/nature/botanical/FallingPetalsLayer.svelte +174 -0
- package/dist/ui/components/nature/botanical/FallingPetalsLayer.svelte.d.ts +25 -0
- package/dist/ui/components/nature/botanical/Leaf.svelte +77 -0
- package/dist/ui/components/nature/botanical/Leaf.svelte.d.ts +10 -0
- package/dist/ui/components/nature/botanical/LeafFalling.svelte +186 -0
- package/dist/ui/components/nature/botanical/LeafFalling.svelte.d.ts +22 -0
- package/dist/ui/components/nature/botanical/PetalFalling.svelte +266 -0
- package/dist/ui/components/nature/botanical/PetalFalling.svelte.d.ts +25 -0
- package/dist/ui/components/nature/botanical/PineCone.svelte +61 -0
- package/dist/ui/components/nature/botanical/PineCone.svelte.d.ts +7 -0
- package/dist/ui/components/nature/botanical/Vine.svelte +102 -0
- package/dist/ui/components/nature/botanical/Vine.svelte.d.ts +11 -0
- package/dist/ui/components/nature/botanical/index.d.ts +10 -0
- package/dist/ui/components/nature/botanical/index.js +11 -0
- package/dist/ui/components/nature/creatures/Bee.svelte +78 -0
- package/dist/ui/components/nature/creatures/Bee.svelte.d.ts +9 -0
- package/dist/ui/components/nature/creatures/Bird.svelte +94 -0
- package/dist/ui/components/nature/creatures/Bird.svelte.d.ts +11 -0
- package/dist/ui/components/nature/creatures/BirdFlying.svelte +83 -0
- package/dist/ui/components/nature/creatures/BirdFlying.svelte.d.ts +9 -0
- package/dist/ui/components/nature/creatures/Bluebird.svelte +95 -0
- package/dist/ui/components/nature/creatures/Bluebird.svelte.d.ts +12 -0
- package/dist/ui/components/nature/creatures/Butterfly.svelte +87 -0
- package/dist/ui/components/nature/creatures/Butterfly.svelte.d.ts +9 -0
- package/dist/ui/components/nature/creatures/Cardinal.svelte +95 -0
- package/dist/ui/components/nature/creatures/Cardinal.svelte.d.ts +12 -0
- package/dist/ui/components/nature/creatures/Chickadee.svelte +97 -0
- package/dist/ui/components/nature/creatures/Chickadee.svelte.d.ts +12 -0
- package/dist/ui/components/nature/creatures/Deer.svelte +95 -0
- package/dist/ui/components/nature/creatures/Deer.svelte.d.ts +9 -0
- package/dist/ui/components/nature/creatures/Firefly.svelte +111 -0
- package/dist/ui/components/nature/creatures/Firefly.svelte.d.ts +10 -0
- package/dist/ui/components/nature/creatures/Owl.svelte +91 -0
- package/dist/ui/components/nature/creatures/Owl.svelte.d.ts +9 -0
- package/dist/ui/components/nature/creatures/Rabbit.svelte +90 -0
- package/dist/ui/components/nature/creatures/Rabbit.svelte.d.ts +9 -0
- package/dist/ui/components/nature/creatures/Robin.svelte +98 -0
- package/dist/ui/components/nature/creatures/Robin.svelte.d.ts +12 -0
- package/dist/ui/components/nature/creatures/Squirrel.svelte +97 -0
- package/dist/ui/components/nature/creatures/Squirrel.svelte.d.ts +9 -0
- package/dist/ui/components/nature/creatures/index.d.ts +13 -0
- package/dist/ui/components/nature/creatures/index.js +14 -0
- package/dist/ui/components/nature/ground/Bush.svelte +57 -0
- package/dist/ui/components/nature/ground/Bush.svelte.d.ts +10 -0
- package/dist/ui/components/nature/ground/Crocus.svelte +83 -0
- package/dist/ui/components/nature/ground/Crocus.svelte.d.ts +12 -0
- package/dist/ui/components/nature/ground/Daffodil.svelte +75 -0
- package/dist/ui/components/nature/ground/Daffodil.svelte.d.ts +11 -0
- package/dist/ui/components/nature/ground/Fern.svelte +72 -0
- package/dist/ui/components/nature/ground/Fern.svelte.d.ts +10 -0
- package/dist/ui/components/nature/ground/FlowerWild.svelte +60 -0
- package/dist/ui/components/nature/ground/FlowerWild.svelte.d.ts +10 -0
- package/dist/ui/components/nature/ground/GrassTuft.svelte +49 -0
- package/dist/ui/components/nature/ground/GrassTuft.svelte.d.ts +10 -0
- package/dist/ui/components/nature/ground/Log.svelte +42 -0
- package/dist/ui/components/nature/ground/Log.svelte.d.ts +7 -0
- package/dist/ui/components/nature/ground/Mushroom.svelte +48 -0
- package/dist/ui/components/nature/ground/Mushroom.svelte.d.ts +9 -0
- package/dist/ui/components/nature/ground/MushroomCluster.svelte +41 -0
- package/dist/ui/components/nature/ground/MushroomCluster.svelte.d.ts +8 -0
- package/dist/ui/components/nature/ground/Rock.svelte +59 -0
- package/dist/ui/components/nature/ground/Rock.svelte.d.ts +8 -0
- package/dist/ui/components/nature/ground/Stump.svelte +44 -0
- package/dist/ui/components/nature/ground/Stump.svelte.d.ts +8 -0
- package/dist/ui/components/nature/ground/Tulip.svelte +79 -0
- package/dist/ui/components/nature/ground/Tulip.svelte.d.ts +11 -0
- package/dist/ui/components/nature/ground/index.d.ts +12 -0
- package/dist/ui/components/nature/ground/index.js +13 -0
- package/dist/ui/components/nature/index.d.ts +28 -0
- package/dist/ui/components/nature/index.js +38 -0
- package/dist/ui/components/nature/palette.d.ts +491 -0
- package/dist/ui/components/nature/palette.js +384 -0
- package/dist/ui/components/nature/sky/Cloud.svelte +122 -0
- package/dist/ui/components/nature/sky/Cloud.svelte.d.ts +11 -0
- package/dist/ui/components/nature/sky/CloudWispy.svelte +79 -0
- package/dist/ui/components/nature/sky/CloudWispy.svelte.d.ts +9 -0
- package/dist/ui/components/nature/sky/Moon.svelte +60 -0
- package/dist/ui/components/nature/sky/Moon.svelte.d.ts +9 -0
- package/dist/ui/components/nature/sky/Rainbow.svelte +101 -0
- package/dist/ui/components/nature/sky/Rainbow.svelte.d.ts +8 -0
- package/dist/ui/components/nature/sky/Star.svelte +84 -0
- package/dist/ui/components/nature/sky/Star.svelte.d.ts +10 -0
- package/dist/ui/components/nature/sky/StarCluster.svelte +85 -0
- package/dist/ui/components/nature/sky/StarCluster.svelte.d.ts +9 -0
- package/dist/ui/components/nature/sky/StarShooting.svelte +90 -0
- package/dist/ui/components/nature/sky/StarShooting.svelte.d.ts +9 -0
- package/dist/ui/components/nature/sky/Sun.svelte +70 -0
- package/dist/ui/components/nature/sky/Sun.svelte.d.ts +9 -0
- package/dist/ui/components/nature/sky/index.d.ts +8 -0
- package/dist/ui/components/nature/sky/index.js +9 -0
- package/dist/ui/components/nature/structural/Birdhouse.svelte +53 -0
- package/dist/ui/components/nature/structural/Birdhouse.svelte.d.ts +8 -0
- package/dist/ui/components/nature/structural/Bridge.svelte +65 -0
- package/dist/ui/components/nature/structural/Bridge.svelte.d.ts +7 -0
- package/dist/ui/components/nature/structural/FencePost.svelte +54 -0
- package/dist/ui/components/nature/structural/FencePost.svelte.d.ts +8 -0
- package/dist/ui/components/nature/structural/GardenGate.svelte +70 -0
- package/dist/ui/components/nature/structural/GardenGate.svelte.d.ts +8 -0
- package/dist/ui/components/nature/structural/Lantern.svelte +113 -0
- package/dist/ui/components/nature/structural/Lantern.svelte.d.ts +10 -0
- package/dist/ui/components/nature/structural/Lattice.svelte +89 -0
- package/dist/ui/components/nature/structural/Lattice.svelte.d.ts +8 -0
- package/dist/ui/components/nature/structural/LatticeWithVine.svelte +89 -0
- package/dist/ui/components/nature/structural/LatticeWithVine.svelte.d.ts +11 -0
- package/dist/ui/components/nature/structural/StonePath.svelte +48 -0
- package/dist/ui/components/nature/structural/StonePath.svelte.d.ts +7 -0
- package/dist/ui/components/nature/structural/index.d.ts +8 -0
- package/dist/ui/components/nature/structural/index.js +9 -0
- package/dist/ui/components/nature/trees/TreeAspen.svelte +163 -0
- package/dist/ui/components/nature/trees/TreeAspen.svelte.d.ts +11 -0
- package/dist/ui/components/nature/trees/TreeBirch.svelte +186 -0
- package/dist/ui/components/nature/trees/TreeBirch.svelte.d.ts +11 -0
- package/dist/ui/components/nature/trees/TreeCherry.svelte +108 -0
- package/dist/ui/components/nature/trees/TreeCherry.svelte.d.ts +11 -0
- package/dist/ui/components/nature/trees/TreePine.svelte +79 -0
- package/dist/ui/components/nature/trees/TreePine.svelte.d.ts +11 -0
- package/dist/ui/components/nature/trees/index.d.ts +4 -0
- package/dist/ui/components/nature/trees/index.js +5 -0
- package/dist/ui/components/nature/water/LilyPad.svelte +99 -0
- package/dist/ui/components/nature/water/LilyPad.svelte.d.ts +10 -0
- package/dist/ui/components/nature/water/Pond.svelte +104 -0
- package/dist/ui/components/nature/water/Pond.svelte.d.ts +8 -0
- package/dist/ui/components/nature/water/Reeds.svelte +85 -0
- package/dist/ui/components/nature/water/Reeds.svelte.d.ts +11 -0
- package/dist/ui/components/nature/water/Stream.svelte +98 -0
- package/dist/ui/components/nature/water/Stream.svelte.d.ts +8 -0
- package/dist/ui/components/nature/water/index.d.ts +4 -0
- package/dist/ui/components/nature/water/index.js +5 -0
- package/dist/ui/components/nature/weather/SnowfallLayer.svelte +175 -0
- package/dist/ui/components/nature/weather/SnowfallLayer.svelte.d.ts +25 -0
- package/dist/ui/components/nature/weather/Snowflake.svelte +99 -0
- package/dist/ui/components/nature/weather/Snowflake.svelte.d.ts +11 -0
- package/dist/ui/components/nature/weather/SnowflakeFalling.svelte +162 -0
- package/dist/ui/components/nature/weather/SnowflakeFalling.svelte.d.ts +23 -0
- package/dist/ui/components/nature/weather/index.d.ts +3 -0
- package/dist/ui/components/nature/weather/index.js +4 -0
- package/dist/ui/components/ui/GlassLogo.svelte +422 -0
- package/dist/ui/components/ui/GlassLogo.svelte.d.ts +23 -0
- package/dist/ui/components/ui/GlassNavbar.svelte +120 -0
- package/dist/ui/components/ui/GlassNavbar.svelte.d.ts +42 -0
- package/dist/ui/components/ui/Logo.svelte +47 -52
- package/dist/ui/components/ui/Logo.svelte.d.ts +4 -3
- package/dist/ui/components/ui/index.d.ts +2 -0
- package/dist/ui/components/ui/index.js +2 -0
- package/dist/ui/styles/grove.css +15 -1
- package/package.json +11 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Season } from '../palette';
|
|
2
|
+
type LeafVariant = 'simple' | 'maple' | 'cherry' | 'aspen' | 'pine';
|
|
3
|
+
interface Props {
|
|
4
|
+
class?: string;
|
|
5
|
+
color?: string;
|
|
6
|
+
season?: Season;
|
|
7
|
+
animate?: boolean;
|
|
8
|
+
variant?: LeafVariant;
|
|
9
|
+
/** Animation duration in seconds */
|
|
10
|
+
duration?: number;
|
|
11
|
+
/** Animation delay in seconds */
|
|
12
|
+
delay?: number;
|
|
13
|
+
/** Horizontal drift amount (positive = right, negative = left) */
|
|
14
|
+
drift?: number;
|
|
15
|
+
/** Fall distance in vh units (how far the leaf travels) */
|
|
16
|
+
fallDistance?: number;
|
|
17
|
+
/** Seed for deterministic color selection */
|
|
18
|
+
seed?: number;
|
|
19
|
+
}
|
|
20
|
+
declare const LeafFalling: import("svelte").Component<Props, {}, "">;
|
|
21
|
+
type LeafFalling = ReturnType<typeof LeafFalling>;
|
|
22
|
+
export default LeafFalling;
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Grove — A place to Be
|
|
3
|
+
Copyright (c) 2025 Autumn Brown
|
|
4
|
+
Licensed under AGPL-3.0
|
|
5
|
+
-->
|
|
6
|
+
<script lang="ts">
|
|
7
|
+
import { springBlossoms } from '../palette';
|
|
8
|
+
import { browser } from '$app/environment';
|
|
9
|
+
|
|
10
|
+
type PetalVariant = 'round' | 'pointed' | 'heart' | 'curled' | 'tiny';
|
|
11
|
+
|
|
12
|
+
interface Props {
|
|
13
|
+
class?: string;
|
|
14
|
+
/** Petal shape variant */
|
|
15
|
+
variant?: PetalVariant;
|
|
16
|
+
/** Override petal color (defaults to spring blossom pink) */
|
|
17
|
+
color?: string;
|
|
18
|
+
/** Fall animation duration in seconds */
|
|
19
|
+
duration?: number;
|
|
20
|
+
/** Animation delay in seconds */
|
|
21
|
+
delay?: number;
|
|
22
|
+
/** Horizontal drift amount in pixels (can be negative) */
|
|
23
|
+
drift?: number;
|
|
24
|
+
/** Fall distance in vh units */
|
|
25
|
+
fallDistance?: number;
|
|
26
|
+
/** Enable falling animation */
|
|
27
|
+
animate?: boolean;
|
|
28
|
+
/** Opacity for depth effect */
|
|
29
|
+
opacity?: number;
|
|
30
|
+
/** Seed for deterministic rotation patterns */
|
|
31
|
+
seed?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let {
|
|
35
|
+
class: className = 'w-3 h-3',
|
|
36
|
+
variant = 'round',
|
|
37
|
+
color,
|
|
38
|
+
duration = 12,
|
|
39
|
+
delay = 0,
|
|
40
|
+
drift = 0,
|
|
41
|
+
fallDistance = 100,
|
|
42
|
+
animate = true,
|
|
43
|
+
opacity = 0.85,
|
|
44
|
+
seed = 0
|
|
45
|
+
}: Props = $props();
|
|
46
|
+
|
|
47
|
+
// Use spring blossom colors with slight variation based on variant
|
|
48
|
+
const petalColor = $derived(color ?? (
|
|
49
|
+
variant === 'tiny' ? springBlossoms.palePink :
|
|
50
|
+
variant === 'curled' ? springBlossoms.rose :
|
|
51
|
+
springBlossoms.blush
|
|
52
|
+
));
|
|
53
|
+
|
|
54
|
+
// Secondary color for gradient effect
|
|
55
|
+
const highlightColor = $derived(springBlossoms.palePink);
|
|
56
|
+
|
|
57
|
+
// Deterministic rotation based on seed - more dramatic for dancing effect
|
|
58
|
+
const initialRotation = $derived((seed * 37) % 360);
|
|
59
|
+
const rotationDirection = $derived(seed % 2 === 0 ? 1 : -1);
|
|
60
|
+
const rotationAmount = $derived(360 + (seed % 360)); // 360-720 degrees total rotation - more twirling!
|
|
61
|
+
|
|
62
|
+
// Dancing sway parameters - create organic horizontal movement
|
|
63
|
+
// Dramatically increased for true gliding, dancing motion!
|
|
64
|
+
const swayAmplitude = $derived(80 + (seed % 100)); // 80-180px horizontal sway - GLIDE!
|
|
65
|
+
const swayFrequency = $derived(2 + (seed % 4)); // 2-5 complete waves during fall
|
|
66
|
+
|
|
67
|
+
// Unique animation name to prevent conflicts
|
|
68
|
+
const animId = $derived(`petal-${seed}`);
|
|
69
|
+
|
|
70
|
+
// Inject dynamic keyframes at runtime to avoid PostCSS parsing issues
|
|
71
|
+
$effect(() => {
|
|
72
|
+
if (!browser || !animate) return;
|
|
73
|
+
|
|
74
|
+
const styleId = `petal-style-${seed}`;
|
|
75
|
+
// Check if already injected
|
|
76
|
+
if (document.getElementById(styleId)) return;
|
|
77
|
+
|
|
78
|
+
const style = document.createElement('style');
|
|
79
|
+
style.id = styleId;
|
|
80
|
+
// Create dancing, swaying motion with sine wave horizontal movement
|
|
81
|
+
// Opacity fade-in for gentle appearance (0 → target opacity)
|
|
82
|
+
style.textContent = `
|
|
83
|
+
@keyframes ${animId}-fall {
|
|
84
|
+
0% {
|
|
85
|
+
transform: translateY(0) translateX(0) rotate(${initialRotation}deg);
|
|
86
|
+
opacity: 0;
|
|
87
|
+
}
|
|
88
|
+
8% {
|
|
89
|
+
opacity: ${opacity};
|
|
90
|
+
}
|
|
91
|
+
12.5% {
|
|
92
|
+
transform: translateY(${fallDistance * 0.125}vh) translateX(${Math.sin(Math.PI * 0.25 * swayFrequency) * swayAmplitude + drift * 0.125}px) rotate(${initialRotation + rotationAmount * rotationDirection * 0.125}deg);
|
|
93
|
+
}
|
|
94
|
+
25% {
|
|
95
|
+
transform: translateY(${fallDistance * 0.25}vh) translateX(${Math.sin(Math.PI * 0.5 * swayFrequency) * swayAmplitude + drift * 0.25}px) rotate(${initialRotation + rotationAmount * rotationDirection * 0.25}deg);
|
|
96
|
+
}
|
|
97
|
+
37.5% {
|
|
98
|
+
transform: translateY(${fallDistance * 0.375}vh) translateX(${Math.sin(Math.PI * 0.75 * swayFrequency) * swayAmplitude + drift * 0.375}px) rotate(${initialRotation + rotationAmount * rotationDirection * 0.375}deg);
|
|
99
|
+
}
|
|
100
|
+
50% {
|
|
101
|
+
transform: translateY(${fallDistance * 0.5}vh) translateX(${Math.sin(Math.PI * swayFrequency) * swayAmplitude + drift * 0.5}px) rotate(${initialRotation + rotationAmount * rotationDirection * 0.5}deg);
|
|
102
|
+
}
|
|
103
|
+
62.5% {
|
|
104
|
+
transform: translateY(${fallDistance * 0.625}vh) translateX(${Math.sin(Math.PI * 1.25 * swayFrequency) * swayAmplitude + drift * 0.625}px) rotate(${initialRotation + rotationAmount * rotationDirection * 0.625}deg);
|
|
105
|
+
}
|
|
106
|
+
75% {
|
|
107
|
+
transform: translateY(${fallDistance * 0.75}vh) translateX(${Math.sin(Math.PI * 1.5 * swayFrequency) * swayAmplitude + drift * 0.75}px) rotate(${initialRotation + rotationAmount * rotationDirection * 0.75}deg);
|
|
108
|
+
}
|
|
109
|
+
87.5% {
|
|
110
|
+
transform: translateY(${fallDistance * 0.875}vh) translateX(${Math.sin(Math.PI * 1.75 * swayFrequency) * swayAmplitude + drift * 0.875}px) rotate(${initialRotation + rotationAmount * rotationDirection * 0.875}deg);
|
|
111
|
+
}
|
|
112
|
+
100% {
|
|
113
|
+
transform: translateY(${fallDistance}vh) translateX(${Math.sin(Math.PI * 2 * swayFrequency) * swayAmplitude + drift}px) rotate(${initialRotation + rotationAmount * rotationDirection}deg);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
@keyframes ${animId}-flutter {
|
|
117
|
+
0%, 100% {
|
|
118
|
+
transform: rotateX(0deg) rotateY(0deg) scale(1);
|
|
119
|
+
}
|
|
120
|
+
16% {
|
|
121
|
+
transform: rotateX(30deg) rotateY(40deg) scale(0.9);
|
|
122
|
+
}
|
|
123
|
+
33% {
|
|
124
|
+
transform: rotateX(-25deg) rotateY(-35deg) scale(1.08);
|
|
125
|
+
}
|
|
126
|
+
50% {
|
|
127
|
+
transform: rotateX(35deg) rotateY(30deg) scale(0.95);
|
|
128
|
+
}
|
|
129
|
+
66% {
|
|
130
|
+
transform: rotateX(-30deg) rotateY(-40deg) scale(1.05);
|
|
131
|
+
}
|
|
132
|
+
83% {
|
|
133
|
+
transform: rotateX(25deg) rotateY(35deg) scale(0.92);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
`;
|
|
137
|
+
document.head.appendChild(style);
|
|
138
|
+
|
|
139
|
+
return () => {
|
|
140
|
+
// Cleanup on component destroy
|
|
141
|
+
const el = document.getElementById(styleId);
|
|
142
|
+
if (el) el.remove();
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
</script>
|
|
146
|
+
|
|
147
|
+
<!-- Cherry blossom petal - delicate and flutter-y -->
|
|
148
|
+
<!-- Wrapper div for fall animation (translateY/X), SVG for flutter (3D rotations) -->
|
|
149
|
+
<div
|
|
150
|
+
class="petal-wrapper"
|
|
151
|
+
style="{animate ? `animation: ${animId}-fall ${duration}s linear ${delay}s infinite;` : `opacity: ${opacity};`}"
|
|
152
|
+
>
|
|
153
|
+
<svg
|
|
154
|
+
class="{className}"
|
|
155
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
156
|
+
viewBox="0 0 20 20"
|
|
157
|
+
style="{animate ? `animation: ${animId}-flutter ${duration / 4}s ease-in-out ${delay}s infinite;` : ''}"
|
|
158
|
+
>
|
|
159
|
+
<defs>
|
|
160
|
+
<!-- Gradient for depth -->
|
|
161
|
+
<radialGradient id="petal-grad-{seed}" cx="30%" cy="30%" r="70%">
|
|
162
|
+
<stop offset="0%" stop-color={highlightColor} />
|
|
163
|
+
<stop offset="100%" stop-color={petalColor} />
|
|
164
|
+
</radialGradient>
|
|
165
|
+
</defs>
|
|
166
|
+
|
|
167
|
+
{#if variant === 'round'}
|
|
168
|
+
<!-- Classic round cherry blossom petal -->
|
|
169
|
+
<ellipse
|
|
170
|
+
cx="10"
|
|
171
|
+
cy="10"
|
|
172
|
+
rx="8"
|
|
173
|
+
ry="9"
|
|
174
|
+
fill="url(#petal-grad-{seed})"
|
|
175
|
+
transform="rotate({initialRotation} 10 10)"
|
|
176
|
+
/>
|
|
177
|
+
<!-- Subtle vein -->
|
|
178
|
+
<path
|
|
179
|
+
d="M10 3 Q10 10 10 18"
|
|
180
|
+
fill="none"
|
|
181
|
+
stroke={springBlossoms.rose}
|
|
182
|
+
stroke-width="0.5"
|
|
183
|
+
opacity="0.3"
|
|
184
|
+
transform="rotate({initialRotation} 10 10)"
|
|
185
|
+
/>
|
|
186
|
+
{:else if variant === 'pointed'}
|
|
187
|
+
<!-- Pointed petal - slightly more dramatic -->
|
|
188
|
+
<path
|
|
189
|
+
d="M10 2 Q18 8 16 14 Q12 20 10 18 Q8 20 4 14 Q2 8 10 2"
|
|
190
|
+
fill="url(#petal-grad-{seed})"
|
|
191
|
+
transform="rotate({initialRotation} 10 10)"
|
|
192
|
+
/>
|
|
193
|
+
{:else if variant === 'heart'}
|
|
194
|
+
<!-- Heart-shaped petal with notch at top -->
|
|
195
|
+
<path
|
|
196
|
+
d="M10 18 Q4 12 4 8 Q4 4 8 4 Q10 4 10 6 Q10 4 12 4 Q16 4 16 8 Q16 12 10 18"
|
|
197
|
+
fill="url(#petal-grad-{seed})"
|
|
198
|
+
transform="rotate({initialRotation} 10 10)"
|
|
199
|
+
/>
|
|
200
|
+
{:else if variant === 'curled'}
|
|
201
|
+
<!-- Curled petal - caught by the wind -->
|
|
202
|
+
<path
|
|
203
|
+
d="M6 4 Q14 2 16 8 Q18 14 14 18 Q8 18 6 14 Q4 10 6 4"
|
|
204
|
+
fill="url(#petal-grad-{seed})"
|
|
205
|
+
transform="rotate({initialRotation} 10 10)"
|
|
206
|
+
/>
|
|
207
|
+
<!-- Curl shadow -->
|
|
208
|
+
<path
|
|
209
|
+
d="M8 6 Q12 5 14 8"
|
|
210
|
+
fill="none"
|
|
211
|
+
stroke={springBlossoms.rose}
|
|
212
|
+
stroke-width="0.5"
|
|
213
|
+
opacity="0.4"
|
|
214
|
+
transform="rotate({initialRotation} 10 10)"
|
|
215
|
+
/>
|
|
216
|
+
{:else}
|
|
217
|
+
<!-- Tiny - simple dot for distant petals -->
|
|
218
|
+
<circle
|
|
219
|
+
cx="10"
|
|
220
|
+
cy="10"
|
|
221
|
+
r="6"
|
|
222
|
+
fill={petalColor}
|
|
223
|
+
transform="rotate({initialRotation} 10 10)"
|
|
224
|
+
/>
|
|
225
|
+
{/if}
|
|
226
|
+
</svg>
|
|
227
|
+
</div>
|
|
228
|
+
|
|
229
|
+
<style>
|
|
230
|
+
/* Dynamic keyframes are injected via style attribute */
|
|
231
|
+
/* These are fallback static versions */
|
|
232
|
+
@keyframes petal-fall-base {
|
|
233
|
+
0% {
|
|
234
|
+
transform: translateY(0) translateX(0);
|
|
235
|
+
}
|
|
236
|
+
100% {
|
|
237
|
+
transform: translateY(100vh) translateX(var(--drift, 30px));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
@keyframes petal-flutter-base {
|
|
242
|
+
0%, 100% {
|
|
243
|
+
transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
|
|
244
|
+
}
|
|
245
|
+
25% {
|
|
246
|
+
transform: rotateX(15deg) rotateY(30deg) rotateZ(10deg);
|
|
247
|
+
}
|
|
248
|
+
50% {
|
|
249
|
+
transform: rotateX(-10deg) rotateY(-20deg) rotateZ(-5deg);
|
|
250
|
+
}
|
|
251
|
+
75% {
|
|
252
|
+
transform: rotateX(20deg) rotateY(10deg) rotateZ(15deg);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.petal-wrapper {
|
|
257
|
+
display: inline-block;
|
|
258
|
+
will-change: transform, opacity;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
svg {
|
|
262
|
+
display: block;
|
|
263
|
+
transform-style: preserve-3d;
|
|
264
|
+
will-change: transform;
|
|
265
|
+
}
|
|
266
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type PetalVariant = 'round' | 'pointed' | 'heart' | 'curled' | 'tiny';
|
|
2
|
+
interface Props {
|
|
3
|
+
class?: string;
|
|
4
|
+
/** Petal shape variant */
|
|
5
|
+
variant?: PetalVariant;
|
|
6
|
+
/** Override petal color (defaults to spring blossom pink) */
|
|
7
|
+
color?: string;
|
|
8
|
+
/** Fall animation duration in seconds */
|
|
9
|
+
duration?: number;
|
|
10
|
+
/** Animation delay in seconds */
|
|
11
|
+
delay?: number;
|
|
12
|
+
/** Horizontal drift amount in pixels (can be negative) */
|
|
13
|
+
drift?: number;
|
|
14
|
+
/** Fall distance in vh units */
|
|
15
|
+
fallDistance?: number;
|
|
16
|
+
/** Enable falling animation */
|
|
17
|
+
animate?: boolean;
|
|
18
|
+
/** Opacity for depth effect */
|
|
19
|
+
opacity?: number;
|
|
20
|
+
/** Seed for deterministic rotation patterns */
|
|
21
|
+
seed?: number;
|
|
22
|
+
}
|
|
23
|
+
declare const PetalFalling: import("svelte").Component<Props, {}, "">;
|
|
24
|
+
type PetalFalling = ReturnType<typeof PetalFalling>;
|
|
25
|
+
export default PetalFalling;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Grove — A place to Be
|
|
3
|
+
Copyright (c) 2025 Autumn Brown
|
|
4
|
+
Licensed under AGPL-3.0
|
|
5
|
+
-->
|
|
6
|
+
<script lang="ts">
|
|
7
|
+
import { bark } from '../palette';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
class?: string;
|
|
11
|
+
color?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
class: className = 'w-5 h-8',
|
|
16
|
+
color
|
|
17
|
+
}: Props = $props();
|
|
18
|
+
|
|
19
|
+
const coneColor = $derived(color ?? bark.warmBark);
|
|
20
|
+
const scaleLight = bark.lightBark;
|
|
21
|
+
const scaleDark = bark.darkBark;
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<!-- Pine cone -->
|
|
25
|
+
<svg class={className} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 55">
|
|
26
|
+
<!-- Stem -->
|
|
27
|
+
<rect fill={scaleDark} x="15" y="0" width="5" height="6" rx="1" />
|
|
28
|
+
|
|
29
|
+
<!-- Pine cone body (overlapping scales) -->
|
|
30
|
+
<!-- Top scales -->
|
|
31
|
+
<ellipse fill={coneColor} cx="17.5" cy="12" rx="6" ry="4" />
|
|
32
|
+
<path fill={scaleDark} d="M12 12 Q17.5 10 23 12" stroke-width="0" opacity="0.3" />
|
|
33
|
+
|
|
34
|
+
<!-- Upper-mid scales -->
|
|
35
|
+
<ellipse fill={coneColor} cx="12" cy="18" rx="7" ry="5" />
|
|
36
|
+
<ellipse fill={coneColor} cx="23" cy="18" rx="7" ry="5" />
|
|
37
|
+
<path fill={scaleLight} d="M6 18 Q12 15 18 18" opacity="0.2" />
|
|
38
|
+
<path fill={scaleLight} d="M17 18 Q23 15 29 18" opacity="0.2" />
|
|
39
|
+
|
|
40
|
+
<!-- Middle scales -->
|
|
41
|
+
<ellipse fill={coneColor} cx="17.5" cy="24" rx="8" ry="5" />
|
|
42
|
+
<ellipse fill={coneColor} cx="8" cy="26" rx="7" ry="5" />
|
|
43
|
+
<ellipse fill={coneColor} cx="27" cy="26" rx="7" ry="5" />
|
|
44
|
+
<path fill={scaleDark} d="M10 24 Q17.5 21 25 24" opacity="0.3" />
|
|
45
|
+
|
|
46
|
+
<!-- Lower-mid scales -->
|
|
47
|
+
<ellipse fill={coneColor} cx="12" cy="33" rx="8" ry="5" />
|
|
48
|
+
<ellipse fill={coneColor} cx="23" cy="33" rx="8" ry="5" />
|
|
49
|
+
<path fill={scaleLight} d="M5 33 Q12 30 19 33" opacity="0.2" />
|
|
50
|
+
<path fill={scaleLight} d="M16 33 Q23 30 30 33" opacity="0.2" />
|
|
51
|
+
|
|
52
|
+
<!-- Bottom scales -->
|
|
53
|
+
<ellipse fill={coneColor} cx="17.5" cy="40" rx="9" ry="5" />
|
|
54
|
+
<ellipse fill={coneColor} cx="10" cy="42" rx="6" ry="4" />
|
|
55
|
+
<ellipse fill={coneColor} cx="25" cy="42" rx="6" ry="4" />
|
|
56
|
+
<path fill={scaleDark} d="M9 40 Q17.5 37 26 40" opacity="0.3" />
|
|
57
|
+
|
|
58
|
+
<!-- Tip scales -->
|
|
59
|
+
<ellipse fill={coneColor} cx="17.5" cy="48" rx="7" ry="4" />
|
|
60
|
+
<ellipse fill={coneColor} cx="17.5" cy="52" rx="4" ry="3" />
|
|
61
|
+
</svg>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Grove — A place to Be
|
|
3
|
+
Copyright (c) 2025 Autumn Brown
|
|
4
|
+
Licensed under AGPL-3.0
|
|
5
|
+
-->
|
|
6
|
+
<script lang="ts">
|
|
7
|
+
import type { Season } from '../palette';
|
|
8
|
+
import { greens, autumn } from '../palette';
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
class?: string;
|
|
12
|
+
color?: string;
|
|
13
|
+
season?: Season;
|
|
14
|
+
animate?: boolean;
|
|
15
|
+
variant?: 'tendril' | 'ivy' | 'flowering';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
class: className = 'w-8 h-12',
|
|
20
|
+
color,
|
|
21
|
+
season = 'summer',
|
|
22
|
+
animate = false,
|
|
23
|
+
variant = 'tendril'
|
|
24
|
+
}: Props = $props();
|
|
25
|
+
|
|
26
|
+
const defaultColor = $derived(season === 'autumn' ? autumn.rust : greens.grove);
|
|
27
|
+
const vineColor = $derived(color ?? defaultColor);
|
|
28
|
+
const leafColor = $derived(season === 'autumn' ? autumn.amber : greens.meadow);
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<!-- Vine/tendril -->
|
|
32
|
+
<svg class="{className} {animate ? 'grow' : ''}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 80">
|
|
33
|
+
{#if variant === 'tendril'}
|
|
34
|
+
<!-- Simple curling tendril -->
|
|
35
|
+
<path
|
|
36
|
+
fill="none"
|
|
37
|
+
stroke={vineColor}
|
|
38
|
+
stroke-width="2"
|
|
39
|
+
d="M25 80 Q20 60 25 50 Q30 40 25 30 Q20 20 30 15 Q40 10 45 5"
|
|
40
|
+
stroke-linecap="round"
|
|
41
|
+
/>
|
|
42
|
+
<!-- Curl at end -->
|
|
43
|
+
<path
|
|
44
|
+
fill="none"
|
|
45
|
+
stroke={vineColor}
|
|
46
|
+
stroke-width="1.5"
|
|
47
|
+
d="M45 5 Q50 8 48 12 Q45 15 42 12 Q40 8 45 5"
|
|
48
|
+
stroke-linecap="round"
|
|
49
|
+
/>
|
|
50
|
+
<!-- Small leaves -->
|
|
51
|
+
<ellipse fill={leafColor} cx="22" cy="55" rx="5" ry="3" transform="rotate(-30 22 55)" />
|
|
52
|
+
<ellipse fill={leafColor} cx="28" cy="35" rx="5" ry="3" transform="rotate(20 28 35)" />
|
|
53
|
+
{:else if variant === 'ivy'}
|
|
54
|
+
<!-- Ivy vine with leaves -->
|
|
55
|
+
<path
|
|
56
|
+
fill="none"
|
|
57
|
+
stroke={vineColor}
|
|
58
|
+
stroke-width="2"
|
|
59
|
+
d="M25 80 Q22 65 28 55 Q34 45 26 35 Q18 25 25 15 Q32 5 30 0"
|
|
60
|
+
stroke-linecap="round"
|
|
61
|
+
/>
|
|
62
|
+
<!-- Ivy leaves (3-lobed) -->
|
|
63
|
+
<path fill={leafColor} d="M18 60 Q12 55 10 60 Q8 65 12 68 Q16 70 18 65 Q20 62 18 60" />
|
|
64
|
+
<path fill={leafColor} d="M32 45 Q38 40 40 45 Q42 50 38 53 Q34 55 32 50 Q30 47 32 45" />
|
|
65
|
+
<path fill={leafColor} d="M20 30 Q14 25 12 30 Q10 35 14 38 Q18 40 20 35 Q22 32 20 30" />
|
|
66
|
+
<path fill={leafColor} d="M30 15 Q36 10 38 15 Q40 20 36 23 Q32 25 30 20 Q28 17 30 15" />
|
|
67
|
+
{:else}
|
|
68
|
+
<!-- Flowering vine -->
|
|
69
|
+
<path
|
|
70
|
+
fill="none"
|
|
71
|
+
stroke={vineColor}
|
|
72
|
+
stroke-width="2"
|
|
73
|
+
d="M25 80 Q20 60 30 45 Q40 30 30 15 Q20 0 25 -5"
|
|
74
|
+
stroke-linecap="round"
|
|
75
|
+
/>
|
|
76
|
+
<!-- Leaves -->
|
|
77
|
+
<ellipse fill={leafColor} cx="22" cy="58" rx="6" ry="4" transform="rotate(-20 22 58)" />
|
|
78
|
+
<ellipse fill={leafColor} cx="35" cy="38" rx="6" ry="4" transform="rotate(25 35 38)" />
|
|
79
|
+
<ellipse fill={leafColor} cx="25" cy="20" rx="5" ry="3" transform="rotate(-15 25 20)" />
|
|
80
|
+
<!-- Small flowers -->
|
|
81
|
+
<circle fill="#f9a8d4" cx="28" cy="50" r="4" />
|
|
82
|
+
<circle fill="#fbbf24" cx="28" cy="50" r="1.5" />
|
|
83
|
+
<circle fill="#f9a8d4" cx="32" cy="28" r="3" />
|
|
84
|
+
<circle fill="#fbbf24" cx="32" cy="28" r="1" />
|
|
85
|
+
{/if}
|
|
86
|
+
</svg>
|
|
87
|
+
|
|
88
|
+
<style>
|
|
89
|
+
@keyframes grow {
|
|
90
|
+
0% {
|
|
91
|
+
stroke-dasharray: 200;
|
|
92
|
+
stroke-dashoffset: 200;
|
|
93
|
+
}
|
|
94
|
+
100% {
|
|
95
|
+
stroke-dashoffset: 0;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.grow path {
|
|
100
|
+
animation: grow 3s ease-out forwards;
|
|
101
|
+
}
|
|
102
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Season } from '../palette';
|
|
2
|
+
interface Props {
|
|
3
|
+
class?: string;
|
|
4
|
+
color?: string;
|
|
5
|
+
season?: Season;
|
|
6
|
+
animate?: boolean;
|
|
7
|
+
variant?: 'tendril' | 'ivy' | 'flowering';
|
|
8
|
+
}
|
|
9
|
+
declare const Vine: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type Vine = ReturnType<typeof Vine>;
|
|
11
|
+
export default Vine;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { default as Acorn } from './Acorn.svelte';
|
|
2
|
+
export { default as Berry } from './Berry.svelte';
|
|
3
|
+
export { default as DandelionPuff } from './DandelionPuff.svelte';
|
|
4
|
+
export { default as FallingLeavesLayer } from './FallingLeavesLayer.svelte';
|
|
5
|
+
export { default as FallingPetalsLayer } from './FallingPetalsLayer.svelte';
|
|
6
|
+
export { default as Leaf } from './Leaf.svelte';
|
|
7
|
+
export { default as LeafFalling } from './LeafFalling.svelte';
|
|
8
|
+
export { default as PetalFalling } from './PetalFalling.svelte';
|
|
9
|
+
export { default as PineCone } from './PineCone.svelte';
|
|
10
|
+
export { default as Vine } from './Vine.svelte';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Botanical components - leaves, petals, and plant elements
|
|
2
|
+
export { default as Acorn } from './Acorn.svelte';
|
|
3
|
+
export { default as Berry } from './Berry.svelte';
|
|
4
|
+
export { default as DandelionPuff } from './DandelionPuff.svelte';
|
|
5
|
+
export { default as FallingLeavesLayer } from './FallingLeavesLayer.svelte';
|
|
6
|
+
export { default as FallingPetalsLayer } from './FallingPetalsLayer.svelte';
|
|
7
|
+
export { default as Leaf } from './Leaf.svelte';
|
|
8
|
+
export { default as LeafFalling } from './LeafFalling.svelte';
|
|
9
|
+
export { default as PetalFalling } from './PetalFalling.svelte';
|
|
10
|
+
export { default as PineCone } from './PineCone.svelte';
|
|
11
|
+
export { default as Vine } from './Vine.svelte';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Grove — A place to Be
|
|
3
|
+
Copyright (c) 2025 Autumn Brown
|
|
4
|
+
Licensed under AGPL-3.0
|
|
5
|
+
-->
|
|
6
|
+
<script lang="ts">
|
|
7
|
+
import { accents, bark } from '../palette';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
class?: string;
|
|
11
|
+
bodyColor?: string;
|
|
12
|
+
stripeColor?: string;
|
|
13
|
+
animate?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
class: className = 'w-5 h-5',
|
|
18
|
+
bodyColor,
|
|
19
|
+
stripeColor,
|
|
20
|
+
animate = true
|
|
21
|
+
}: Props = $props();
|
|
22
|
+
|
|
23
|
+
const body = $derived(bodyColor ?? accents.flower.yellow);
|
|
24
|
+
const stripes = $derived(stripeColor ?? bark.darkBark);
|
|
25
|
+
const wingColor = $derived('#e0f2fe'); // Light blue-ish transparent
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<!-- Bumble bee -->
|
|
29
|
+
<svg class="{className} {animate ? 'hover' : ''}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 40">
|
|
30
|
+
<!-- Wings -->
|
|
31
|
+
<g class={animate ? 'buzz' : ''}>
|
|
32
|
+
<ellipse fill={wingColor} cx="20" cy="12" rx="10" ry="6" opacity="0.6" />
|
|
33
|
+
<ellipse fill={wingColor} cx="30" cy="12" rx="10" ry="6" opacity="0.6" />
|
|
34
|
+
</g>
|
|
35
|
+
|
|
36
|
+
<!-- Body -->
|
|
37
|
+
<ellipse fill={body} cx="25" cy="24" rx="18" ry="12" />
|
|
38
|
+
|
|
39
|
+
<!-- Stripes -->
|
|
40
|
+
<path fill={stripes} d="M15 18 Q25 14 35 18 L35 22 Q25 18 15 22 Z" />
|
|
41
|
+
<path fill={stripes} d="M12 26 Q25 22 38 26 L38 30 Q25 26 12 30 Z" />
|
|
42
|
+
|
|
43
|
+
<!-- Head -->
|
|
44
|
+
<circle fill={stripes} cx="8" cy="24" r="6" />
|
|
45
|
+
|
|
46
|
+
<!-- Eyes -->
|
|
47
|
+
<circle fill="white" cx="5" cy="22" r="2" />
|
|
48
|
+
<circle fill={stripes} cx="5" cy="22" r="1" />
|
|
49
|
+
|
|
50
|
+
<!-- Antennae -->
|
|
51
|
+
<path fill="none" stroke={stripes} stroke-width="1" d="M6 18 Q4 14 2 12" />
|
|
52
|
+
<path fill="none" stroke={stripes} stroke-width="1" d="M10 18 Q8 14 6 12" />
|
|
53
|
+
|
|
54
|
+
<!-- Stinger -->
|
|
55
|
+
<path fill={stripes} d="M43 24 L48 24 L43 26 Z" />
|
|
56
|
+
</svg>
|
|
57
|
+
|
|
58
|
+
<style>
|
|
59
|
+
@keyframes hover {
|
|
60
|
+
0%, 100% { transform: translateY(0) translateX(0); }
|
|
61
|
+
25% { transform: translateY(-2px) translateX(1px); }
|
|
62
|
+
75% { transform: translateY(-1px) translateX(-1px); }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@keyframes buzz {
|
|
66
|
+
0%, 100% { transform: scaleY(1); }
|
|
67
|
+
50% { transform: scaleY(0.85); }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.hover {
|
|
71
|
+
animation: hover 1s ease-in-out infinite;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.buzz {
|
|
75
|
+
transform-origin: center bottom;
|
|
76
|
+
animation: buzz 0.05s linear infinite;
|
|
77
|
+
}
|
|
78
|
+
</style>
|