@autumnsgrove/groveengine 0.7.0 → 0.8.5
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/components/OnboardingChecklist.svelte +2 -2
- package/dist/components/WispButton.svelte +83 -0
- package/dist/components/WispButton.svelte.d.ts +49 -0
- package/dist/components/WispPanel.svelte +1093 -0
- package/dist/components/WispPanel.svelte.d.ts +49 -0
- package/dist/components/custom/TableOfContents.svelte +12 -1
- package/dist/components/quota/UpgradePrompt.svelte +1 -0
- package/dist/config/wisp.d.ts +145 -0
- package/dist/config/wisp.js +175 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/server/inference-client.d.ts +139 -0
- package/dist/server/inference-client.js +294 -0
- 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 +260 -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 +602 -0
- package/dist/ui/components/nature/palette.js +472 -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/primitives/textarea/textarea.svelte +1 -1
- package/dist/ui/components/typography/Alagard.svelte +17 -0
- package/dist/ui/components/typography/Alagard.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Atkinson.svelte +17 -0
- package/dist/ui/components/typography/Atkinson.svelte.d.ts +10 -0
- package/dist/ui/components/typography/BodoniModa.svelte +17 -0
- package/dist/ui/components/typography/BodoniModa.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Calistoga.svelte +17 -0
- package/dist/ui/components/typography/Calistoga.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Caveat.svelte +17 -0
- package/dist/ui/components/typography/Caveat.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Cormorant.svelte +17 -0
- package/dist/ui/components/typography/Cormorant.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Cozette.svelte +17 -0
- package/dist/ui/components/typography/Cozette.svelte.d.ts +10 -0
- package/dist/ui/components/typography/EBGaramond.svelte +17 -0
- package/dist/ui/components/typography/EBGaramond.svelte.d.ts +10 -0
- package/dist/ui/components/typography/FontProvider.svelte +98 -0
- package/dist/ui/components/typography/FontProvider.svelte.d.ts +17 -0
- package/dist/ui/components/typography/Fraunces.svelte +17 -0
- package/dist/ui/components/typography/Fraunces.svelte.d.ts +10 -0
- package/dist/ui/components/typography/IBMPlexMono.svelte +17 -0
- package/dist/ui/components/typography/IBMPlexMono.svelte.d.ts +10 -0
- package/dist/ui/components/typography/InstrumentSans.svelte +17 -0
- package/dist/ui/components/typography/InstrumentSans.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Lexend.svelte +17 -0
- package/dist/ui/components/typography/Lexend.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Lora.svelte +17 -0
- package/dist/ui/components/typography/Lora.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Luciole.svelte +17 -0
- package/dist/ui/components/typography/Luciole.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Manrope.svelte +17 -0
- package/dist/ui/components/typography/Manrope.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Merriweather.svelte +17 -0
- package/dist/ui/components/typography/Merriweather.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Nunito.svelte +17 -0
- package/dist/ui/components/typography/Nunito.svelte.d.ts +10 -0
- package/dist/ui/components/typography/OpenDyslexic.svelte +17 -0
- package/dist/ui/components/typography/OpenDyslexic.svelte.d.ts +10 -0
- package/dist/ui/components/typography/PlusJakartaSans.svelte +17 -0
- package/dist/ui/components/typography/PlusJakartaSans.svelte.d.ts +10 -0
- package/dist/ui/components/typography/Quicksand.svelte +17 -0
- package/dist/ui/components/typography/Quicksand.svelte.d.ts +10 -0
- package/dist/ui/components/typography/README.md +153 -0
- package/dist/ui/components/typography/index.d.ts +23 -0
- package/dist/ui/components/typography/index.js +42 -0
- package/dist/ui/components/ui/GlassCarousel.svelte +446 -0
- package/dist/ui/components/ui/GlassCarousel.svelte.d.ts +57 -0
- package/dist/ui/components/ui/GlassConfirmDialog.svelte +2 -1
- package/dist/ui/components/ui/GlassLogo.svelte +423 -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/GlassOverlay.svelte +1 -1
- 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 +3 -0
- package/dist/ui/components/ui/index.js +3 -0
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.js +2 -0
- package/dist/ui/styles/grove.css +15 -1
- package/dist/ui/vineyard/index.d.ts +9 -0
- package/dist/ui/vineyard/index.js +8 -0
- package/dist/utils/csrf.js +5 -2
- package/dist/utils/readability.d.ts +89 -0
- package/dist/utils/readability.js +204 -0
- package/package.json +27 -1
|
@@ -2,12 +2,19 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Grove Logo Component
|
|
4
4
|
*
|
|
5
|
-
* A logo
|
|
6
|
-
*
|
|
7
|
-
* when placed in an accent-colored context, or can be overridden.
|
|
5
|
+
* A seasonal logo with beautiful nature-inspired colors.
|
|
6
|
+
* Defaults to summer (emerald green) but supports all seasons.
|
|
8
7
|
*
|
|
9
8
|
* The trunk defaults to Grove's classic bark brown (#5d4037).
|
|
10
9
|
*
|
|
10
|
+
* @example Basic usage
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <Logo /> <!-- Summer green by default -->
|
|
13
|
+
* <Logo season="spring" /> <!-- Cherry blossom pink -->
|
|
14
|
+
* <Logo season="autumn" /> <!-- Warm orange -->
|
|
15
|
+
* <Logo season="winter" /> <!-- Frosted green -->
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
11
18
|
* @example Loading state (breathing animation)
|
|
12
19
|
* ```svelte
|
|
13
20
|
* <Logo breathing />
|
|
@@ -20,18 +27,27 @@
|
|
|
20
27
|
import { cubicInOut } from 'svelte/easing';
|
|
21
28
|
import { browser } from '$app/environment';
|
|
22
29
|
|
|
30
|
+
type Season = 'spring' | 'summer' | 'autumn' | 'winter';
|
|
23
31
|
type BreathingSpeed = 'slow' | 'normal' | 'fast';
|
|
24
32
|
|
|
33
|
+
// Seasonal color palette - matches GlassLogo for consistency
|
|
34
|
+
const seasonalColors = {
|
|
35
|
+
spring: '#f472b6', // pink-400 - cherry blossom
|
|
36
|
+
summer: '#10b981', // emerald-500 - lush growth
|
|
37
|
+
autumn: '#fb923c', // orange-400 - warm harvest
|
|
38
|
+
winter: '#86efac' // green-300 - frosted evergreen
|
|
39
|
+
} as const;
|
|
40
|
+
|
|
25
41
|
interface Props {
|
|
26
42
|
class?: string;
|
|
27
|
-
/**
|
|
43
|
+
/** Seasonal color theme - defaults to summer */
|
|
44
|
+
season?: Season;
|
|
45
|
+
/** Custom foliage color - overrides season if provided */
|
|
28
46
|
color?: string;
|
|
29
47
|
/** Trunk color - defaults to classic bark brown */
|
|
30
48
|
trunkColor?: string;
|
|
31
49
|
/** Whether foliage and trunk should be the same color */
|
|
32
50
|
monochrome?: boolean;
|
|
33
|
-
/** Add subtle sway animation */
|
|
34
|
-
animate?: boolean;
|
|
35
51
|
/** Add breathing animation (for loading states, not lists) */
|
|
36
52
|
breathing?: boolean;
|
|
37
53
|
/** Breathing animation speed - 'slow' (1500ms), 'normal' (800ms), 'fast' (400ms) */
|
|
@@ -40,10 +56,10 @@
|
|
|
40
56
|
|
|
41
57
|
let {
|
|
42
58
|
class: className = 'w-6 h-6',
|
|
59
|
+
season = 'summer',
|
|
43
60
|
color,
|
|
44
61
|
trunkColor,
|
|
45
62
|
monochrome = false,
|
|
46
|
-
animate = false,
|
|
47
63
|
breathing = false,
|
|
48
64
|
breathingSpeed = 'normal'
|
|
49
65
|
}: Props = $props();
|
|
@@ -69,11 +85,11 @@
|
|
|
69
85
|
// Classic bark brown from the nature palette
|
|
70
86
|
const BARK_BROWN = '#5d4037';
|
|
71
87
|
|
|
72
|
-
// Compute actual colors
|
|
73
|
-
const foliageColor = color ??
|
|
74
|
-
const actualTrunkColor = monochrome
|
|
88
|
+
// Compute actual colors - use custom color if provided, otherwise use seasonal color
|
|
89
|
+
const foliageColor = $derived(color ?? seasonalColors[season]);
|
|
90
|
+
const actualTrunkColor = $derived(monochrome
|
|
75
91
|
? foliageColor
|
|
76
|
-
: (trunkColor ?? BARK_BROWN);
|
|
92
|
+
: (trunkColor ?? BARK_BROWN));
|
|
77
93
|
|
|
78
94
|
// Breathing animation using tweened store (duration set dynamically in $effect)
|
|
79
95
|
const breathValue = tweened(0, { easing: cubicInOut });
|
|
@@ -123,53 +139,43 @@
|
|
|
123
139
|
const bottomLeftTransform = $derived(`translate(${-diagExpansion}, ${diagExpansion})`);
|
|
124
140
|
const bottomRightTransform = $derived(`translate(${diagExpansion}, ${diagExpansion})`);
|
|
125
141
|
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// Decomposed foliage paths (8 pieces) for breathing animation
|
|
130
|
-
// Original path: "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"
|
|
131
|
-
// Decomposed by tracing path commands and isolating geometric boundaries where arms meet center.
|
|
132
|
-
// If modifying, ensure pieces align at rest (breathValue=0) to match the original silhouette.
|
|
142
|
+
// Decomposed foliage paths for breathing animation
|
|
143
|
+
// Each bar extends toward the center so they overlap at rest, forming the complete logo
|
|
144
|
+
// When expanded, the overlapping regions separate creating the burst effect
|
|
133
145
|
|
|
134
|
-
//
|
|
135
|
-
const
|
|
146
|
+
// Left horizontal bar - extends right to center
|
|
147
|
+
const leftBarPath = "M0 173.468 L171.476 173.468 L171.476 243.97 L0 243.97 Z";
|
|
136
148
|
|
|
137
|
-
//
|
|
138
|
-
const
|
|
149
|
+
// Right horizontal bar - extends left to center
|
|
150
|
+
const rightBarPath = "M245.562 173.268 L417 173.268 L417 243.77 L245.562 243.77 Z";
|
|
139
151
|
|
|
140
|
-
//
|
|
141
|
-
const
|
|
152
|
+
// Top vertical bar - extends down to center
|
|
153
|
+
const topBarPath = "M171.476 0 L245.562 0 L245.562 173.468 L171.476 173.468 Z";
|
|
142
154
|
|
|
143
|
-
// Top
|
|
144
|
-
const
|
|
155
|
+
// Top-left diagonal - arrow with extended inner edge
|
|
156
|
+
const topLeftDiagPath = "M171.476 173.468 L171.476 124.872 L86.037 37.043 L36.446 88.028 L126 173.468 Z";
|
|
145
157
|
|
|
146
|
-
// Top-
|
|
147
|
-
const
|
|
158
|
+
// Top-right diagonal - arrow with extended inner edge
|
|
159
|
+
const topRightDiagPath = "M245.562 173.268 L245.562 124.872 L331 37.243 L380.552 88.028 L290.972 173.268 Z";
|
|
148
160
|
|
|
149
|
-
//
|
|
150
|
-
const
|
|
161
|
+
// Bottom-left diagonal - arrow with extended inner edge to center point
|
|
162
|
+
const bottomLeftDiagPath = "M171.476 243.97 L208.519 258.11 L86.037 381.192 L36.446 331.601 L126.664 243.97 Z";
|
|
151
163
|
|
|
152
|
-
// Bottom-
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
// Bottom-right diagonal branch (arrow shape)
|
|
156
|
-
const bottomRightDiagPath = "M290.252 243.77 L380.435 331.399 L331 381.192 L208.519 258.11 L245.562 243.77 Z";
|
|
164
|
+
// Bottom-right diagonal - arrow with extended inner edge to center point
|
|
165
|
+
const bottomRightDiagPath = "M245.562 243.77 L208.519 258.11 L331 381.192 L380.435 331.399 L290.252 243.77 Z";
|
|
157
166
|
</script>
|
|
158
167
|
|
|
159
168
|
<svg
|
|
160
|
-
class=
|
|
169
|
+
class={className}
|
|
161
170
|
xmlns="http://www.w3.org/2000/svg"
|
|
162
|
-
viewBox="0
|
|
171
|
+
viewBox="0 -30 417 542.238"
|
|
163
172
|
aria-label="Grove logo"
|
|
164
173
|
>
|
|
165
174
|
<!-- Trunk (always static) -->
|
|
166
175
|
<path fill={actualTrunkColor} d="M171.274 344.942h74.09v167.296h-74.09V344.942z"/>
|
|
167
176
|
|
|
168
177
|
{#if breathing}
|
|
169
|
-
<!-- Decomposed foliage with breathing animation -->
|
|
170
|
-
|
|
171
|
-
<!-- Center anchor (stationary) -->
|
|
172
|
-
<path fill={foliageColor} d={centerPath}/>
|
|
178
|
+
<!-- Decomposed foliage with breathing animation - bars expand outward from center -->
|
|
173
179
|
|
|
174
180
|
<!-- Left horizontal bar -->
|
|
175
181
|
<g transform={leftTransform}>
|
|
@@ -211,14 +217,3 @@
|
|
|
211
217
|
{/if}
|
|
212
218
|
</svg>
|
|
213
219
|
|
|
214
|
-
<style>
|
|
215
|
-
@keyframes grove-logo-sway {
|
|
216
|
-
0%, 100% { transform: rotate(0deg); }
|
|
217
|
-
50% { transform: rotate(1deg); }
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
.grove-logo-sway {
|
|
221
|
-
transform-origin: center bottom;
|
|
222
|
-
animation: grove-logo-sway 4s ease-in-out infinite;
|
|
223
|
-
}
|
|
224
|
-
</style>
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
type Season = 'spring' | 'summer' | 'autumn' | 'winter';
|
|
1
2
|
type BreathingSpeed = 'slow' | 'normal' | 'fast';
|
|
2
3
|
interface Props {
|
|
3
4
|
class?: string;
|
|
4
|
-
/**
|
|
5
|
+
/** Seasonal color theme - defaults to summer */
|
|
6
|
+
season?: Season;
|
|
7
|
+
/** Custom foliage color - overrides season if provided */
|
|
5
8
|
color?: string;
|
|
6
9
|
/** Trunk color - defaults to classic bark brown */
|
|
7
10
|
trunkColor?: string;
|
|
8
11
|
/** Whether foliage and trunk should be the same color */
|
|
9
12
|
monochrome?: boolean;
|
|
10
|
-
/** Add subtle sway animation */
|
|
11
|
-
animate?: boolean;
|
|
12
13
|
/** Add breathing animation (for loading states, not lists) */
|
|
13
14
|
breathing?: boolean;
|
|
14
15
|
/** Breathing animation speed - 'slow' (1500ms), 'normal' (800ms), 'fast' (400ms) */
|
|
@@ -19,7 +19,10 @@ export { default as Glass } from './Glass.svelte';
|
|
|
19
19
|
export { default as GlassButton } from './GlassButton.svelte';
|
|
20
20
|
export { default as GlassCard } from './GlassCard.svelte';
|
|
21
21
|
export { default as GlassConfirmDialog } from './GlassConfirmDialog.svelte';
|
|
22
|
+
export { default as GlassNavbar } from './GlassNavbar.svelte';
|
|
22
23
|
export { default as GlassOverlay } from './GlassOverlay.svelte';
|
|
24
|
+
export { default as GlassLogo } from './GlassLogo.svelte';
|
|
25
|
+
export { default as GlassCarousel } from './GlassCarousel.svelte';
|
|
23
26
|
export { TableHeader, TableBody, TableRow, TableCell, TableHead, TableFooter, TableCaption, } from '../primitives/table';
|
|
24
27
|
export * from './toast.js';
|
|
25
28
|
export declare const UI_VERSION = "0.2.0";
|
|
@@ -28,7 +28,10 @@ export { default as Glass } from './Glass.svelte';
|
|
|
28
28
|
export { default as GlassButton } from './GlassButton.svelte';
|
|
29
29
|
export { default as GlassCard } from './GlassCard.svelte';
|
|
30
30
|
export { default as GlassConfirmDialog } from './GlassConfirmDialog.svelte';
|
|
31
|
+
export { default as GlassNavbar } from './GlassNavbar.svelte';
|
|
31
32
|
export { default as GlassOverlay } from './GlassOverlay.svelte';
|
|
33
|
+
export { default as GlassLogo } from './GlassLogo.svelte';
|
|
34
|
+
export { default as GlassCarousel } from './GlassCarousel.svelte';
|
|
32
35
|
// Table sub-components (from primitives)
|
|
33
36
|
export { TableHeader, TableBody, TableRow, TableCell, TableHead, TableFooter, TableCaption, } from '../primitives/table';
|
|
34
37
|
// Toast utility
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -6,5 +6,6 @@ export * from './components/forms/index.js';
|
|
|
6
6
|
export * from './components/icons/index.js';
|
|
7
7
|
export * from './components/states/index.js';
|
|
8
8
|
export * from './components/charts/index.js';
|
|
9
|
+
export * from './components/typography/index.js';
|
|
9
10
|
export * from './tokens/index.js';
|
|
10
11
|
export { cn } from './utils/cn.js';
|
package/dist/ui/index.js
CHANGED
|
@@ -16,6 +16,8 @@ export * from './components/icons/index.js';
|
|
|
16
16
|
export * from './components/states/index.js';
|
|
17
17
|
// Charts (from AutumnsGrove)
|
|
18
18
|
export * from './components/charts/index.js';
|
|
19
|
+
// Typography (font wrapper components)
|
|
20
|
+
export * from './components/typography/index.js';
|
|
19
21
|
// Export design tokens
|
|
20
22
|
export * from './tokens/index.js';
|
|
21
23
|
// Export utilities
|
package/dist/ui/styles/grove.css
CHANGED
|
@@ -681,12 +681,26 @@
|
|
|
681
681
|
═══════════════════════════════════════════════════════════════ */
|
|
682
682
|
|
|
683
683
|
@layer utilities {
|
|
684
|
-
/*
|
|
684
|
+
/* ─────────────────────────────────────────────────────────────
|
|
685
|
+
ORGANIC BACKGROUNDS
|
|
686
|
+
Subtle vine/leaf patterns that create the Grove atmosphere
|
|
687
|
+
───────────────────────────────────────────────────────────── */
|
|
688
|
+
|
|
689
|
+
/* Simple leaf pattern - basic organic texture */
|
|
685
690
|
.bg-leaf-pattern {
|
|
686
691
|
background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M30 5c-5 8-15 12-15 20s10 15 15 25c5-10 15-17 15-25S35 13 30 5z' fill='%2316a34a' fill-opacity='0.03'/%3E%3C/svg%3E");
|
|
687
692
|
background-repeat: repeat;
|
|
688
693
|
}
|
|
689
694
|
|
|
695
|
+
/* Elaborate vine pattern - flowing vines with leaves and ferns */
|
|
696
|
+
.leaf-pattern {
|
|
697
|
+
background-image: url("data:image/svg+xml,%3Csvg width='450' height='450' viewBox='0 0 450 450' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' stroke='%2322c55e' stroke-linecap='round'%3E%3C!-- Long flowing vine 1 - dramatic S-curve --%3E%3Cpath d='M-30 420 C50 380 30 320 80 260 S150 180 120 120 S180 40 140 -30' stroke-width='1.5' opacity='0.12'/%3E%3C!-- Long flowing vine 2 - opposite sweep --%3E%3Cpath d='M480 380 C400 350 420 280 360 230 S280 160 310 100 S250 30 290 -20' stroke-width='1.4' opacity='0.10'/%3E%3C!-- Diagonal vine crossing --%3E%3Cpath d='M-20 280 C60 250 100 220 160 200 S250 160 320 170 S400 130 470 100' stroke-width='1.2' opacity='0.09'/%3E%3C!-- Vertical accent vine --%3E%3Cpath d='M200 480 C180 420 210 360 190 300 S220 220 200 160 S230 80 210 20' stroke-width='1.1' opacity='0.08'/%3E%3C!-- Wandering vine --%3E%3Cpath d='M350 480 C330 430 360 380 340 320 S380 260 350 200' stroke-width='1' opacity='0.08'/%3E%3C!-- Spiral tendrils scattered --%3E%3Cpath d='M80 260 Q100 250 108 238 Q115 225 105 215 Q95 208 85 215' stroke-width='0.8' opacity='0.10'/%3E%3Cpath d='M120 120 Q140 130 150 120 Q158 108 145 98 Q132 92 125 102' stroke-width='0.7' opacity='0.09'/%3E%3Cpath d='M360 230 Q340 222 330 232 Q322 245 335 255 Q348 262 358 250' stroke-width='0.7' opacity='0.09'/%3E%3Cpath d='M310 100 Q290 92 280 102 Q272 115 288 125' stroke-width='0.6' opacity='0.08'/%3E%3Cpath d='M160 200 Q180 192 188 202 Q195 215 182 225' stroke-width='0.6' opacity='0.08'/%3E%3Cpath d='M190 300 Q210 292 218 305 Q224 320 210 328' stroke-width='0.6' opacity='0.07'/%3E%3Cpath d='M340 320 Q360 328 365 342 Q368 358 352 362' stroke-width='0.6' opacity='0.07'/%3E%3Cpath d='M55 380 Q75 372 82 385 Q88 400 72 408' stroke-width='0.5' opacity='0.06'/%3E%3C/g%3E%3Cg fill='%2322c55e'%3E%3C!-- Pointed ivy leaves --%3E%3Cpath d='M70 300 Q85 280 78 265 Q70 280 55 288 Q70 295 70 300Z' opacity='0.11'/%3E%3Cpath d='M135 145 Q150 128 143 115 Q135 128 120 135 Q135 142 135 145Z' opacity='0.10'/%3E%3Cpath d='M375 255 Q360 240 365 225 Q375 240 390 245 Q375 252 375 255Z' opacity='0.09'/%3E%3Cpath d='M220 180 Q235 165 228 152 Q220 165 205 172 Q220 178 220 180Z' opacity='0.08'/%3E%3C!-- Round soft leaves --%3E%3Cellipse cx='95' cy='210' rx='9' ry='14' transform='rotate(-35 95 210)' opacity='0.10'/%3E%3Cellipse cx='335' cy='145' rx='8' ry='12' transform='rotate(28 335 145)' opacity='0.09'/%3E%3Cellipse cx='175' cy='255' rx='7' ry='11' transform='rotate(-18 175 255)' opacity='0.08'/%3E%3Cellipse cx='280' cy='195' rx='6' ry='10' transform='rotate(40 280 195)' opacity='0.08'/%3E%3Cellipse cx='405' cy='120' rx='7' ry='10' transform='rotate(-25 405 120)' opacity='0.07'/%3E%3C!-- Long slender leaves --%3E%3Cpath d='M145 175 Q152 155 145 135 Q138 155 145 175Z' opacity='0.09'/%3E%3Cpath d='M295 130 Q305 115 298 98 Q288 115 295 130Z' opacity='0.08'/%3E%3Cpath d='M210 275 Q200 258 205 240 Q218 258 210 275Z' opacity='0.08'/%3E%3Cpath d='M365 195 Q375 180 368 162 Q358 180 365 195Z' opacity='0.07'/%3E%3Cpath d='M115 365 Q125 348 118 330 Q108 348 115 365Z' opacity='0.07'/%3E%3C!-- Fern fronds scattered asymmetrically --%3E%3Cg transform='translate(45 365) rotate(-45)' opacity='0.10'%3E%3Cpath d='M0,0 L0,-30' stroke='%2322c55e' stroke-width='0.6' fill='none'/%3E%3Cellipse cx='-5' cy='-7' rx='3.5' ry='6' transform='rotate(-30 -5 -7)'/%3E%3Cellipse cx='5' cy='-12' rx='3.5' ry='6' transform='rotate(30 5 -12)'/%3E%3Cellipse cx='-4' cy='-17' rx='3' ry='5' transform='rotate(-30 -4 -17)'/%3E%3Cellipse cx='4' cy='-22' rx='3' ry='5' transform='rotate(30 4 -22)'/%3E%3Cellipse cx='0' cy='-28' rx='2.5' ry='4'/%3E%3C/g%3E%3Cg transform='translate(390 185) rotate(40)' opacity='0.09'%3E%3Cpath d='M0,0 L0,-28' stroke='%2322c55e' stroke-width='0.6' fill='none'/%3E%3Cellipse cx='-4' cy='-6' rx='3' ry='5' transform='rotate(-25 -4 -6)'/%3E%3Cellipse cx='4' cy='-11' rx='3' ry='5' transform='rotate(25 4 -11)'/%3E%3Cellipse cx='-3' cy='-16' rx='2.5' ry='4' transform='rotate(-25 -3 -16)'/%3E%3Cellipse cx='3' cy='-21' rx='2.5' ry='4' transform='rotate(25 3 -21)'/%3E%3Cellipse cx='0' cy='-26' rx='2' ry='3'/%3E%3C/g%3E%3Cg transform='translate(255 65) rotate(-25)' opacity='0.08'%3E%3Cpath d='M0,0 L0,-25' stroke='%2322c55e' stroke-width='0.5' fill='none'/%3E%3Cellipse cx='-4' cy='-6' rx='2.5' ry='4' transform='rotate(-30 -4 -6)'/%3E%3Cellipse cx='4' cy='-10' rx='2.5' ry='4' transform='rotate(30 4 -10)'/%3E%3Cellipse cx='-3' cy='-15' rx='2' ry='3.5' transform='rotate(-30 -3 -15)'/%3E%3Cellipse cx='3' cy='-20' rx='2' ry='3' transform='rotate(30 3 -20)'/%3E%3C/g%3E%3Cg transform='translate(140 420) rotate(55)' opacity='0.08'%3E%3Cpath d='M0,0 L0,-22' stroke='%2322c55e' stroke-width='0.5' fill='none'/%3E%3Cellipse cx='-3' cy='-5' rx='2' ry='3.5' transform='rotate(-25 -3 -5)'/%3E%3Cellipse cx='3' cy='-9' rx='2' ry='3.5' transform='rotate(25 3 -9)'/%3E%3Cellipse cx='-2' cy='-14' rx='1.5' ry='3' transform='rotate(-25 -2 -14)'/%3E%3Cellipse cx='2' cy='-18' rx='1.5' ry='2.5' transform='rotate(25 2 -18)'/%3E%3C/g%3E%3C!-- Tiny floating seeds/spores --%3E%3Ccircle cx='180' cy='90' r='2' opacity='0.06'/%3E%3Ccircle cx='85' cy='175' r='1.5' opacity='0.05'/%3E%3Ccircle cx='345' cy='290' r='2' opacity='0.06'/%3E%3Ccircle cx='420' cy='200' r='1.5' opacity='0.05'/%3E%3Ccircle cx='260' cy='350' r='2' opacity='0.05'/%3E%3Ccircle cx='40' cy='120' r='1.5' opacity='0.04'/%3E%3Ccircle cx='310' cy='400' r='1.5' opacity='0.04'/%3E%3C/g%3E%3C/svg%3E");
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
:is(.dark .leaf-pattern) {
|
|
701
|
+
background-image: url("data:image/svg+xml,%3Csvg width='450' height='450' viewBox='0 0 450 450' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' stroke='%2322c55e' stroke-linecap='round'%3E%3C!-- Long flowing vine 1 - dramatic S-curve --%3E%3Cpath d='M-30 420 C50 380 30 320 80 260 S150 180 120 120 S180 40 140 -30' stroke-width='1.5' opacity='0.14'/%3E%3C!-- Long flowing vine 2 - opposite sweep --%3E%3Cpath d='M480 380 C400 350 420 280 360 230 S280 160 310 100 S250 30 290 -20' stroke-width='1.4' opacity='0.12'/%3E%3C!-- Diagonal vine crossing --%3E%3Cpath d='M-20 280 C60 250 100 220 160 200 S250 160 320 170 S400 130 470 100' stroke-width='1.2' opacity='0.11'/%3E%3C!-- Vertical accent vine --%3E%3Cpath d='M200 480 C180 420 210 360 190 300 S220 220 200 160 S230 80 210 20' stroke-width='1.1' opacity='0.10'/%3E%3C!-- Wandering vine --%3E%3Cpath d='M350 480 C330 430 360 380 340 320 S380 260 350 200' stroke-width='1' opacity='0.10'/%3E%3C!-- Spiral tendrils scattered --%3E%3Cpath d='M80 260 Q100 250 108 238 Q115 225 105 215 Q95 208 85 215' stroke-width='0.8' opacity='0.12'/%3E%3Cpath d='M120 120 Q140 130 150 120 Q158 108 145 98 Q132 92 125 102' stroke-width='0.7' opacity='0.11'/%3E%3Cpath d='M360 230 Q340 222 330 232 Q322 245 335 255 Q348 262 358 250' stroke-width='0.7' opacity='0.11'/%3E%3Cpath d='M310 100 Q290 92 280 102 Q272 115 288 125' stroke-width='0.6' opacity='0.10'/%3E%3Cpath d='M160 200 Q180 192 188 202 Q195 215 182 225' stroke-width='0.6' opacity='0.10'/%3E%3Cpath d='M190 300 Q210 292 218 305 Q224 320 210 328' stroke-width='0.6' opacity='0.09'/%3E%3Cpath d='M340 320 Q360 328 365 342 Q368 358 352 362' stroke-width='0.6' opacity='0.09'/%3E%3Cpath d='M55 380 Q75 372 82 385 Q88 400 72 408' stroke-width='0.5' opacity='0.08'/%3E%3C/g%3E%3Cg fill='%2322c55e'%3E%3C!-- Pointed ivy leaves --%3E%3Cpath d='M70 300 Q85 280 78 265 Q70 280 55 288 Q70 295 70 300Z' opacity='0.13'/%3E%3Cpath d='M135 145 Q150 128 143 115 Q135 128 120 135 Q135 142 135 145Z' opacity='0.12'/%3E%3Cpath d='M375 255 Q360 240 365 225 Q375 240 390 245 Q375 252 375 255Z' opacity='0.11'/%3E%3Cpath d='M220 180 Q235 165 228 152 Q220 165 205 172 Q220 178 220 180Z' opacity='0.10'/%3E%3C!-- Round soft leaves --%3E%3Cellipse cx='95' cy='210' rx='9' ry='14' transform='rotate(-35 95 210)' opacity='0.12'/%3E%3Cellipse cx='335' cy='145' rx='8' ry='12' transform='rotate(28 335 145)' opacity='0.11'/%3E%3Cellipse cx='175' cy='255' rx='7' ry='11' transform='rotate(-18 175 255)' opacity='0.10'/%3E%3Cellipse cx='280' cy='195' rx='6' ry='10' transform='rotate(40 280 195)' opacity='0.10'/%3E%3Cellipse cx='405' cy='120' rx='7' ry='10' transform='rotate(-25 405 120)' opacity='0.09'/%3E%3C!-- Long slender leaves --%3E%3Cpath d='M145 175 Q152 155 145 135 Q138 155 145 175Z' opacity='0.11'/%3E%3Cpath d='M295 130 Q305 115 298 98 Q288 115 295 130Z' opacity='0.10'/%3E%3Cpath d='M210 275 Q200 258 205 240 Q218 258 210 275Z' opacity='0.10'/%3E%3Cpath d='M365 195 Q375 180 368 162 Q358 180 365 195Z' opacity='0.09'/%3E%3Cpath d='M115 365 Q125 348 118 330 Q108 348 115 365Z' opacity='0.09'/%3E%3C!-- Fern fronds scattered asymmetrically --%3E%3Cg transform='translate(45 365) rotate(-45)' opacity='0.12'%3E%3Cpath d='M0,0 L0,-30' stroke='%2322c55e' stroke-width='0.6' fill='none'/%3E%3Cellipse cx='-5' cy='-7' rx='3.5' ry='6' transform='rotate(-30 -5 -7)'/%3E%3Cellipse cx='5' cy='-12' rx='3.5' ry='6' transform='rotate(30 5 -12)'/%3E%3Cellipse cx='-4' cy='-17' rx='3' ry='5' transform='rotate(-30 -4 -17)'/%3E%3Cellipse cx='4' cy='-22' rx='3' ry='5' transform='rotate(30 4 -22)'/%3E%3Cellipse cx='0' cy='-28' rx='2.5' ry='4'/%3E%3C/g%3E%3Cg transform='translate(390 185) rotate(40)' opacity='0.11'%3E%3Cpath d='M0,0 L0,-28' stroke='%2322c55e' stroke-width='0.6' fill='none'/%3E%3Cellipse cx='-4' cy='-6' rx='3' ry='5' transform='rotate(-25 -4 -6)'/%3E%3Cellipse cx='4' cy='-11' rx='3' ry='5' transform='rotate(25 4 -11)'/%3E%3Cellipse cx='-3' cy='-16' rx='2.5' ry='4' transform='rotate(-25 -3 -16)'/%3E%3Cellipse cx='3' cy='-21' rx='2.5' ry='4' transform='rotate(25 3 -21)'/%3E%3Cellipse cx='0' cy='-26' rx='2' ry='3'/%3E%3C/g%3E%3Cg transform='translate(255 65) rotate(-25)' opacity='0.10'%3E%3Cpath d='M0,0 L0,-25' stroke='%2322c55e' stroke-width='0.5' fill='none'/%3E%3Cellipse cx='-4' cy='-6' rx='2.5' ry='4' transform='rotate(-30 -4 -6)'/%3E%3Cellipse cx='4' cy='-10' rx='2.5' ry='4' transform='rotate(30 4 -10)'/%3E%3Cellipse cx='-3' cy='-15' rx='2' ry='3.5' transform='rotate(-30 -3 -15)'/%3E%3Cellipse cx='3' cy='-20' rx='2' ry='3' transform='rotate(30 3 -20)'/%3E%3C/g%3E%3Cg transform='translate(140 420) rotate(55)' opacity='0.10'%3E%3Cpath d='M0,0 L0,-22' stroke='%2322c55e' stroke-width='0.5' fill='none'/%3E%3Cellipse cx='-3' cy='-5' rx='2' ry='3.5' transform='rotate(-25 -3 -5)'/%3E%3Cellipse cx='3' cy='-9' rx='2' ry='3.5' transform='rotate(25 3 -9)'/%3E%3Cellipse cx='-2' cy='-14' rx='1.5' ry='3' transform='rotate(-25 -2 -14)'/%3E%3Cellipse cx='2' cy='-18' rx='1.5' ry='2.5' transform='rotate(25 2 -18)'/%3E%3C/g%3E%3C!-- Tiny floating seeds/spores --%3E%3Ccircle cx='180' cy='90' r='2' opacity='0.08'/%3E%3Ccircle cx='85' cy='175' r='1.5' opacity='0.07'/%3E%3Ccircle cx='345' cy='290' r='2' opacity='0.08'/%3E%3Ccircle cx='420' cy='200' r='1.5' opacity='0.07'/%3E%3Ccircle cx='260' cy='350' r='2' opacity='0.07'/%3E%3Ccircle cx='40' cy='120' r='1.5' opacity='0.06'/%3E%3Ccircle cx='310' cy='400' r='1.5' opacity='0.06'/%3E%3C/g%3E%3C/svg%3E");
|
|
702
|
+
}
|
|
703
|
+
|
|
690
704
|
/* Text wrapping */
|
|
691
705
|
.text-balance {
|
|
692
706
|
text-wrap: balance;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vineyard Components
|
|
3
|
+
* Re-exports from @autumnsgrove/vineyard package
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* import { VineyardLayout, FeatureCard, StatusBadge } from '@autumnsgrove/groveengine/vineyard';
|
|
7
|
+
*/
|
|
8
|
+
export { VineyardLayout, FeatureCard, StatusBadge, DemoContainer, CodeExample, TierGate, RoadmapSection, } from "@autumnsgrove/vineyard/vineyard";
|
|
9
|
+
export type { VineyardStatus, GroveTool, GroveTier, VineyardLayoutProps, FeatureCardProps, StatusBadgeProps, DemoContainerProps, CodeExampleProps, TierGateProps, RoadmapSectionProps, } from "@autumnsgrove/vineyard/vineyard";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vineyard Components
|
|
3
|
+
* Re-exports from @autumnsgrove/vineyard package
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* import { VineyardLayout, FeatureCard, StatusBadge } from '@autumnsgrove/groveengine/vineyard';
|
|
7
|
+
*/
|
|
8
|
+
export { VineyardLayout, FeatureCard, StatusBadge, DemoContainer, CodeExample, TierGate, RoadmapSection, } from "@autumnsgrove/vineyard/vineyard";
|
package/dist/utils/csrf.js
CHANGED
|
@@ -44,7 +44,8 @@ export function validateCSRF(request) {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
const origin = request.headers.get("origin");
|
|
47
|
-
|
|
47
|
+
// Check X-Forwarded-Host first (set by grove-router proxy), then fall back to host
|
|
48
|
+
const host = request.headers.get("x-forwarded-host") || request.headers.get("host");
|
|
48
49
|
|
|
49
50
|
// Allow same-origin requests
|
|
50
51
|
if (origin) {
|
|
@@ -65,9 +66,11 @@ export function validateCSRF(request) {
|
|
|
65
66
|
return false;
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
// Check if origin matches host OR is a *.grove.place subdomain
|
|
68
70
|
const hostMatches = host && originUrl.host === host;
|
|
71
|
+
const isGroveDomain = originUrl.hostname.endsWith(".grove.place") || originUrl.hostname === "grove.place";
|
|
69
72
|
|
|
70
|
-
if (!isLocalhost && !hostMatches) {
|
|
73
|
+
if (!isLocalhost && !hostMatches && !isGroveDomain) {
|
|
71
74
|
return false;
|
|
72
75
|
}
|
|
73
76
|
} catch {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Readability Analysis - Local Calculations
|
|
3
|
+
*
|
|
4
|
+
* Readability scoring using Flesch-Kincaid and other metrics.
|
|
5
|
+
* No AI needed - purely algorithmic analysis.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/specs/writing-assistant-unified-spec.md
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {Object} ReadabilityResult
|
|
11
|
+
* @property {number} fleschKincaid - Grade level (e.g., 8.5)
|
|
12
|
+
* @property {string} readingTime - Human-readable time (e.g., "5 min read")
|
|
13
|
+
* @property {number} wordCount - Total words
|
|
14
|
+
* @property {number} sentenceCount - Total sentences
|
|
15
|
+
* @property {Object} sentenceStats - Sentence statistics
|
|
16
|
+
* @property {number} sentenceStats.average - Average words per sentence
|
|
17
|
+
* @property {number} sentenceStats.longest - Longest sentence word count
|
|
18
|
+
* @property {number} sentenceStats.shortest - Shortest sentence word count
|
|
19
|
+
* @property {string[]} suggestions - Improvement suggestions
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Calculate readability metrics for content
|
|
23
|
+
*
|
|
24
|
+
* @param {string} content - The text to analyze (can include markdown)
|
|
25
|
+
* @returns {ReadabilityResult}
|
|
26
|
+
*/
|
|
27
|
+
export function calculateReadability(content: string): ReadabilityResult;
|
|
28
|
+
/**
|
|
29
|
+
* Strip markdown syntax for cleaner readability analysis
|
|
30
|
+
*
|
|
31
|
+
* @param {string} content - Markdown content
|
|
32
|
+
* @returns {string} Plain text
|
|
33
|
+
*/
|
|
34
|
+
export function stripMarkdownForAnalysis(content: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Count syllables in a word (approximate)
|
|
37
|
+
*
|
|
38
|
+
* NOTE: This is a regex-based approximation that works reasonably well for
|
|
39
|
+
* common English words but will be inaccurate for:
|
|
40
|
+
* - Words with silent vowels (e.g., "subtle", "queue")
|
|
41
|
+
* - Compound words and contractions
|
|
42
|
+
* - Words borrowed from other languages
|
|
43
|
+
* - Proper nouns and technical terms
|
|
44
|
+
*
|
|
45
|
+
* For readability scoring purposes, this approximation is sufficient since
|
|
46
|
+
* Flesch-Kincaid is already an estimate and small syllable miscounts don't
|
|
47
|
+
* significantly impact the final grade level calculation.
|
|
48
|
+
*
|
|
49
|
+
* @param {string} word - The word to count syllables for
|
|
50
|
+
* @returns {number} Estimated syllable count
|
|
51
|
+
*/
|
|
52
|
+
export function countSyllables(word: string): number;
|
|
53
|
+
/**
|
|
54
|
+
* Get a human-readable description of the grade level
|
|
55
|
+
*
|
|
56
|
+
* @param {number} grade - Flesch-Kincaid grade level
|
|
57
|
+
* @returns {string} Description
|
|
58
|
+
*/
|
|
59
|
+
export function getGradeDescription(grade: number): string;
|
|
60
|
+
export type ReadabilityResult = {
|
|
61
|
+
/**
|
|
62
|
+
* - Grade level (e.g., 8.5)
|
|
63
|
+
*/
|
|
64
|
+
fleschKincaid: number;
|
|
65
|
+
/**
|
|
66
|
+
* - Human-readable time (e.g., "5 min read")
|
|
67
|
+
*/
|
|
68
|
+
readingTime: string;
|
|
69
|
+
/**
|
|
70
|
+
* - Total words
|
|
71
|
+
*/
|
|
72
|
+
wordCount: number;
|
|
73
|
+
/**
|
|
74
|
+
* - Total sentences
|
|
75
|
+
*/
|
|
76
|
+
sentenceCount: number;
|
|
77
|
+
/**
|
|
78
|
+
* - Sentence statistics
|
|
79
|
+
*/
|
|
80
|
+
sentenceStats: {
|
|
81
|
+
average: number;
|
|
82
|
+
longest: number;
|
|
83
|
+
shortest: number;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* - Improvement suggestions
|
|
87
|
+
*/
|
|
88
|
+
suggestions: string[];
|
|
89
|
+
};
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Readability Analysis - Local Calculations
|
|
3
|
+
*
|
|
4
|
+
* Readability scoring using Flesch-Kincaid and other metrics.
|
|
5
|
+
* No AI needed - purely algorithmic analysis.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/specs/writing-assistant-unified-spec.md
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {Object} ReadabilityResult
|
|
12
|
+
* @property {number} fleschKincaid - Grade level (e.g., 8.5)
|
|
13
|
+
* @property {string} readingTime - Human-readable time (e.g., "5 min read")
|
|
14
|
+
* @property {number} wordCount - Total words
|
|
15
|
+
* @property {number} sentenceCount - Total sentences
|
|
16
|
+
* @property {Object} sentenceStats - Sentence statistics
|
|
17
|
+
* @property {number} sentenceStats.average - Average words per sentence
|
|
18
|
+
* @property {number} sentenceStats.longest - Longest sentence word count
|
|
19
|
+
* @property {number} sentenceStats.shortest - Shortest sentence word count
|
|
20
|
+
* @property {string[]} suggestions - Improvement suggestions
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Calculate readability metrics for content
|
|
25
|
+
*
|
|
26
|
+
* @param {string} content - The text to analyze (can include markdown)
|
|
27
|
+
* @returns {ReadabilityResult}
|
|
28
|
+
*/
|
|
29
|
+
export function calculateReadability(content) {
|
|
30
|
+
// Strip markdown syntax for clean text analysis
|
|
31
|
+
const text = stripMarkdownForAnalysis(content);
|
|
32
|
+
|
|
33
|
+
const sentences = text.split(/[.!?]+/).filter((s) => s.trim().length > 0);
|
|
34
|
+
const words = text.split(/\s+/).filter((w) => w.length > 0);
|
|
35
|
+
const syllables = words.reduce((sum, word) => sum + countSyllables(word), 0);
|
|
36
|
+
|
|
37
|
+
const sentenceCount = Math.max(sentences.length, 1);
|
|
38
|
+
const wordCount = Math.max(words.length, 1);
|
|
39
|
+
|
|
40
|
+
const wordsPerSentence = wordCount / sentenceCount;
|
|
41
|
+
const syllablesPerWord = syllables / wordCount;
|
|
42
|
+
|
|
43
|
+
// Flesch-Kincaid Grade Level
|
|
44
|
+
const fleschKincaid = Math.max(
|
|
45
|
+
0,
|
|
46
|
+
0.39 * wordsPerSentence + 11.8 * syllablesPerWord - 15.59
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// Reading time (~200 words per minute for focused reading)
|
|
50
|
+
const minutes = Math.ceil(wordCount / 200);
|
|
51
|
+
|
|
52
|
+
// Sentence length stats
|
|
53
|
+
const sentenceLengths = sentences.map(
|
|
54
|
+
(s) => s.split(/\s+/).filter((w) => w.length > 0).length
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
fleschKincaid: Math.round(fleschKincaid * 10) / 10,
|
|
59
|
+
readingTime: `${minutes} min read`,
|
|
60
|
+
wordCount,
|
|
61
|
+
sentenceCount,
|
|
62
|
+
sentenceStats: {
|
|
63
|
+
average: Math.round(wordsPerSentence),
|
|
64
|
+
longest: sentenceLengths.length > 0 ? Math.max(...sentenceLengths) : 0,
|
|
65
|
+
shortest: sentenceLengths.length > 0 ? Math.min(...sentenceLengths) : 0
|
|
66
|
+
},
|
|
67
|
+
suggestions: generateSuggestions(fleschKincaid, wordsPerSentence, sentenceLengths)
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Strip markdown syntax for cleaner readability analysis
|
|
73
|
+
*
|
|
74
|
+
* @param {string} content - Markdown content
|
|
75
|
+
* @returns {string} Plain text
|
|
76
|
+
*/
|
|
77
|
+
export function stripMarkdownForAnalysis(content) {
|
|
78
|
+
return content
|
|
79
|
+
.replace(/```[\s\S]*?```/g, '') // Remove code blocks
|
|
80
|
+
.replace(/`[^`]+`/g, '') // Remove inline code
|
|
81
|
+
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') // Replace links with text
|
|
82
|
+
.replace(/[#*_~>]/g, '') // Remove markdown chars
|
|
83
|
+
.replace(/^\s*[-+*]\s+/gm, '') // Remove list markers
|
|
84
|
+
.replace(/^\s*\d+\.\s+/gm, '') // Remove numbered list markers
|
|
85
|
+
.trim();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Count syllables in a word (approximate)
|
|
90
|
+
*
|
|
91
|
+
* NOTE: This is a regex-based approximation that works reasonably well for
|
|
92
|
+
* common English words but will be inaccurate for:
|
|
93
|
+
* - Words with silent vowels (e.g., "subtle", "queue")
|
|
94
|
+
* - Compound words and contractions
|
|
95
|
+
* - Words borrowed from other languages
|
|
96
|
+
* - Proper nouns and technical terms
|
|
97
|
+
*
|
|
98
|
+
* For readability scoring purposes, this approximation is sufficient since
|
|
99
|
+
* Flesch-Kincaid is already an estimate and small syllable miscounts don't
|
|
100
|
+
* significantly impact the final grade level calculation.
|
|
101
|
+
*
|
|
102
|
+
* @param {string} word - The word to count syllables for
|
|
103
|
+
* @returns {number} Estimated syllable count
|
|
104
|
+
*/
|
|
105
|
+
export function countSyllables(word) {
|
|
106
|
+
word = word.toLowerCase().replace(/[^a-z]/g, '');
|
|
107
|
+
if (word.length <= 3) return 1;
|
|
108
|
+
|
|
109
|
+
word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '');
|
|
110
|
+
word = word.replace(/^y/, '');
|
|
111
|
+
|
|
112
|
+
const matches = word.match(/[aeiouy]{1,2}/g);
|
|
113
|
+
return matches ? Math.max(matches.length, 1) : 1;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Generate readability improvement suggestions
|
|
118
|
+
*
|
|
119
|
+
* @param {number} grade - Flesch-Kincaid grade level
|
|
120
|
+
* @param {number} avgSentence - Average words per sentence
|
|
121
|
+
* @param {number[]} sentenceLengths - Array of sentence lengths
|
|
122
|
+
* @returns {string[]} Suggestions (max 4)
|
|
123
|
+
*/
|
|
124
|
+
function generateSuggestions(grade, avgSentence, sentenceLengths) {
|
|
125
|
+
const suggestions = [];
|
|
126
|
+
|
|
127
|
+
// Grade level suggestions
|
|
128
|
+
if (grade > 14) {
|
|
129
|
+
suggestions.push(
|
|
130
|
+
'Your writing is quite complex. Consider simplifying for broader accessibility.'
|
|
131
|
+
);
|
|
132
|
+
} else if (grade > 12) {
|
|
133
|
+
suggestions.push(
|
|
134
|
+
'College-level reading. Consider if this matches your audience.'
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Sentence length suggestions
|
|
139
|
+
if (avgSentence > 30) {
|
|
140
|
+
suggestions.push(
|
|
141
|
+
'Many sentences are quite long. Breaking them up could improve clarity.'
|
|
142
|
+
);
|
|
143
|
+
} else if (avgSentence > 25) {
|
|
144
|
+
suggestions.push(
|
|
145
|
+
'Some sentences are on the longer side. Variety in length can improve flow.'
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Very long sentences
|
|
150
|
+
const veryLong = sentenceLengths.filter((l) => l > 40);
|
|
151
|
+
if (veryLong.length > 0) {
|
|
152
|
+
suggestions.push(
|
|
153
|
+
`Found ${veryLong.length} sentence${veryLong.length > 1 ? 's' : ''} over 40 words.`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Very simple
|
|
158
|
+
if (grade < 6 && avgSentence < 10) {
|
|
159
|
+
suggestions.push(
|
|
160
|
+
'Very simple sentences. This works well for accessibility or quick reads.'
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Sentence variety
|
|
165
|
+
if (sentenceLengths.length > 5) {
|
|
166
|
+
const variance = calculateVariance(sentenceLengths);
|
|
167
|
+
if (variance < 10) {
|
|
168
|
+
suggestions.push(
|
|
169
|
+
'Sentence lengths are very uniform. Varying rhythm can make writing more engaging.'
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return suggestions.slice(0, 4); // Max 4 suggestions
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Calculate variance for sentence length variety
|
|
179
|
+
*
|
|
180
|
+
* @param {number[]} numbers - Array of numbers
|
|
181
|
+
* @returns {number} Variance
|
|
182
|
+
*/
|
|
183
|
+
function calculateVariance(numbers) {
|
|
184
|
+
if (numbers.length === 0) return 0;
|
|
185
|
+
const mean = numbers.reduce((a, b) => a + b, 0) / numbers.length;
|
|
186
|
+
return (
|
|
187
|
+
numbers.reduce((sum, n) => sum + Math.pow(n - mean, 2), 0) / numbers.length
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Get a human-readable description of the grade level
|
|
193
|
+
*
|
|
194
|
+
* @param {number} grade - Flesch-Kincaid grade level
|
|
195
|
+
* @returns {string} Description
|
|
196
|
+
*/
|
|
197
|
+
export function getGradeDescription(grade) {
|
|
198
|
+
if (grade <= 5) return 'Elementary school level - very easy to read';
|
|
199
|
+
if (grade <= 8) return 'Middle school level - easy to read';
|
|
200
|
+
if (grade <= 10) return 'High school level - fairly easy to read';
|
|
201
|
+
if (grade <= 12) return 'High school senior level - moderately difficult';
|
|
202
|
+
if (grade <= 14) return 'College level - difficult';
|
|
203
|
+
return 'Graduate level - very difficult';
|
|
204
|
+
}
|