@autumnsgrove/groveengine 0.8.6 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/components/admin/GutterManager.svelte +213 -101
  2. package/dist/components/admin/MarkdownEditor.svelte +6 -3
  3. package/dist/components/custom/GutterItem.svelte +8 -2
  4. package/dist/components/quota/UpgradePrompt.svelte +1 -0
  5. package/dist/config/domain-blocklist.d.ts +59 -0
  6. package/dist/config/domain-blocklist.js +731 -0
  7. package/dist/config/index.d.ts +3 -1
  8. package/dist/config/index.js +2 -1
  9. package/dist/config/offensive-blocklist.d.ts +44 -0
  10. package/dist/config/offensive-blocklist.js +751 -0
  11. package/dist/config/terrarium.d.ts +109 -0
  12. package/dist/config/terrarium.js +125 -0
  13. package/dist/styles/tokens.css +90 -0
  14. package/dist/types/dom-to-image-more.d.ts +39 -0
  15. package/dist/ui/components/chrome/Footer.svelte +137 -0
  16. package/dist/ui/components/chrome/Footer.svelte.d.ts +11 -0
  17. package/dist/ui/components/chrome/FooterMinimal.svelte +75 -0
  18. package/dist/ui/components/chrome/FooterMinimal.svelte.d.ts +10 -0
  19. package/dist/ui/components/chrome/Header.svelte +113 -0
  20. package/dist/ui/components/chrome/Header.svelte.d.ts +11 -0
  21. package/dist/ui/components/chrome/HeaderMinimal.svelte +68 -0
  22. package/dist/ui/components/chrome/HeaderMinimal.svelte.d.ts +9 -0
  23. package/dist/ui/components/chrome/MobileMenu.svelte +145 -0
  24. package/dist/ui/components/chrome/MobileMenu.svelte.d.ts +9 -0
  25. package/dist/ui/components/chrome/ThemeToggle.svelte +34 -0
  26. package/dist/ui/components/chrome/ThemeToggle.svelte.d.ts +3 -0
  27. package/dist/ui/components/chrome/defaults.d.ts +6 -0
  28. package/dist/ui/components/chrome/defaults.js +65 -0
  29. package/dist/ui/components/chrome/index.d.ts +13 -0
  30. package/dist/ui/components/chrome/index.js +14 -0
  31. package/dist/ui/components/chrome/types.d.ts +19 -0
  32. package/dist/ui/components/chrome/types.js +8 -0
  33. package/dist/ui/components/content/RoadmapPreview.svelte +2 -1
  34. package/dist/ui/components/forms/ContentSearch.svelte +406 -0
  35. package/dist/ui/components/forms/ContentSearch.svelte.d.ts +71 -0
  36. package/dist/ui/components/forms/filterUtils.d.ts +138 -0
  37. package/dist/ui/components/forms/filterUtils.js +240 -0
  38. package/dist/ui/components/forms/index.d.ts +2 -0
  39. package/dist/ui/components/forms/index.js +5 -1
  40. package/dist/ui/components/gallery/ImageGallery.svelte +3 -0
  41. package/dist/ui/components/gallery/Lightbox.svelte +3 -0
  42. package/dist/ui/components/gallery/ZoomableImage.svelte +1 -0
  43. package/dist/ui/components/icons/index.d.ts +2 -1
  44. package/dist/ui/components/icons/index.js +14 -3
  45. package/dist/ui/components/icons/lucide.d.ts +213 -0
  46. package/dist/ui/components/icons/lucide.js +224 -0
  47. package/dist/ui/components/terrarium/AssetPalette.svelte +207 -0
  48. package/dist/ui/components/terrarium/AssetPalette.svelte.d.ts +7 -0
  49. package/dist/ui/components/terrarium/Canvas.svelte +231 -0
  50. package/dist/ui/components/terrarium/Canvas.svelte.d.ts +14 -0
  51. package/dist/ui/components/terrarium/ExportDialog.svelte +307 -0
  52. package/dist/ui/components/terrarium/ExportDialog.svelte.d.ts +18 -0
  53. package/dist/ui/components/terrarium/PaletteItem.svelte +169 -0
  54. package/dist/ui/components/terrarium/PaletteItem.svelte.d.ts +9 -0
  55. package/dist/ui/components/terrarium/PlacedAsset.svelte +222 -0
  56. package/dist/ui/components/terrarium/PlacedAsset.svelte.d.ts +11 -0
  57. package/dist/ui/components/terrarium/Terrarium.svelte +266 -0
  58. package/dist/ui/components/terrarium/Terrarium.svelte.d.ts +3 -0
  59. package/dist/ui/components/terrarium/Toolbar.svelte +299 -0
  60. package/dist/ui/components/terrarium/Toolbar.svelte.d.ts +24 -0
  61. package/dist/ui/components/terrarium/index.d.ts +31 -0
  62. package/dist/ui/components/terrarium/index.js +33 -0
  63. package/dist/ui/components/terrarium/terrariumState.svelte.d.ts +45 -0
  64. package/dist/ui/components/terrarium/terrariumState.svelte.js +291 -0
  65. package/dist/ui/components/terrarium/types.d.ts +139 -0
  66. package/dist/ui/components/terrarium/types.js +43 -0
  67. package/dist/ui/components/terrarium/utils/export.d.ts +48 -0
  68. package/dist/ui/components/terrarium/utils/export.js +148 -0
  69. package/dist/ui/components/ui/CollapsibleSection.svelte +2 -0
  70. package/dist/ui/components/ui/GlassConfirmDialog.svelte +9 -0
  71. package/dist/ui/components/ui/GlassOverlay.svelte +2 -1
  72. package/dist/ui/components/ui/Input.svelte +9 -1
  73. package/dist/ui/components/ui/Input.svelte.d.ts +2 -0
  74. package/dist/ui/components/ui/Textarea.svelte +9 -1
  75. package/dist/ui/components/ui/Textarea.svelte.d.ts +2 -0
  76. package/dist/ui/stores/index.d.ts +6 -0
  77. package/dist/ui/stores/index.js +6 -0
  78. package/dist/ui/stores/season.d.ts +14 -0
  79. package/dist/ui/stores/season.js +65 -0
  80. package/package.json +27 -4
@@ -80,10 +80,11 @@
80
80
  );
81
81
  </script>
82
82
 
83
+ <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
83
84
  <div
84
85
  class={computedClass}
85
86
  role={interactive ? "button" : "presentation"}
86
- tabindex={interactive ? 0 : undefined}
87
+ tabindex={interactive ? 0 : -1}
87
88
  aria-label={interactive ? "Close overlay" : undefined}
88
89
  {...restProps}
89
90
  >
@@ -14,6 +14,7 @@
14
14
  * @prop {boolean} [required=false] - Whether input is required (shows asterisk)
15
15
  * @prop {boolean} [disabled=false] - Whether input is disabled
16
16
  * @prop {string} [class] - Additional CSS classes to apply
17
+ * @prop {string} [id] - Input ID for label association (auto-generated if not provided)
17
18
  * @prop {HTMLInputElement} [ref] - Reference to the underlying input element (bindable)
18
19
  *
19
20
  * @example
@@ -34,6 +35,7 @@
34
35
  required?: boolean;
35
36
  disabled?: boolean;
36
37
  class?: string;
38
+ id?: string;
37
39
  ref?: HTMLInputElement | null;
38
40
  }
39
41
 
@@ -46,10 +48,15 @@
46
48
  required = false,
47
49
  disabled = false,
48
50
  class: className,
51
+ id,
49
52
  ref = $bindable(null),
50
53
  ...restProps
51
54
  }: Props = $props();
52
55
 
56
+ // Generate unique ID for label association if not provided
57
+ // svelte-ignore state_referenced_locally - id is intentionally captured at initialization for stable IDs
58
+ const inputId = id ?? `input-${crypto.randomUUID()}`;
59
+
53
60
  const inputClass = $derived(
54
61
  cn(
55
62
  error && "border-destructive focus-visible:ring-destructive/20",
@@ -60,7 +67,7 @@
60
67
 
61
68
  <div class="flex flex-col gap-1.5">
62
69
  {#if label}
63
- <label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
70
+ <label for={inputId} class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
64
71
  {label}
65
72
  {#if required}
66
73
  <span class="text-destructive">*</span>
@@ -69,6 +76,7 @@
69
76
  {/if}
70
77
 
71
78
  <ShadcnInput
79
+ id={inputId}
72
80
  bind:ref={ref}
73
81
  bind:value
74
82
  {type}
@@ -10,6 +10,7 @@ import type { HTMLInputAttributes } from "svelte/elements";
10
10
  * @prop {boolean} [required=false] - Whether input is required (shows asterisk)
11
11
  * @prop {boolean} [disabled=false] - Whether input is disabled
12
12
  * @prop {string} [class] - Additional CSS classes to apply
13
+ * @prop {string} [id] - Input ID for label association (auto-generated if not provided)
13
14
  * @prop {HTMLInputElement} [ref] - Reference to the underlying input element (bindable)
14
15
  *
15
16
  * @example
@@ -30,6 +31,7 @@ interface Props extends Omit<HTMLInputAttributes, "class"> {
30
31
  required?: boolean;
31
32
  disabled?: boolean;
32
33
  class?: string;
34
+ id?: string;
33
35
  ref?: HTMLInputElement | null;
34
36
  }
35
37
  declare const Input: import("svelte").Component<Props, {}, "ref" | "value">;
@@ -14,6 +14,7 @@
14
14
  * @prop {boolean} [required=false] - Whether textarea is required (shows asterisk)
15
15
  * @prop {boolean} [disabled=false] - Whether textarea is disabled
16
16
  * @prop {string} [class] - Additional CSS classes to apply
17
+ * @prop {string} [id] - Textarea ID for label association (auto-generated if not provided)
17
18
  *
18
19
  * @example
19
20
  * <Textarea label="Description" bind:value={description} required />
@@ -33,6 +34,7 @@
33
34
  required?: boolean;
34
35
  disabled?: boolean;
35
36
  class?: string;
37
+ id?: string;
36
38
  }
37
39
 
38
40
  let {
@@ -44,9 +46,14 @@
44
46
  required = false,
45
47
  disabled = false,
46
48
  class: className,
49
+ id,
47
50
  ...restProps
48
51
  }: Props = $props();
49
52
 
53
+ // Generate unique ID for label association if not provided
54
+ // svelte-ignore state_referenced_locally - id is intentionally captured at initialization for stable IDs
55
+ const textareaId = id ?? `textarea-${crypto.randomUUID()}`;
56
+
50
57
  const textareaClass = $derived(
51
58
  cn(
52
59
  error && "border-destructive focus-visible:ring-destructive/20",
@@ -57,7 +64,7 @@
57
64
 
58
65
  <div class="flex flex-col gap-1.5">
59
66
  {#if label}
60
- <label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
67
+ <label for={textareaId} class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
61
68
  {label}
62
69
  {#if required}
63
70
  <span class="text-destructive">*</span>
@@ -66,6 +73,7 @@
66
73
  {/if}
67
74
 
68
75
  <ShadcnTextarea
76
+ id={textareaId}
69
77
  bind:value
70
78
  {placeholder}
71
79
  {rows}
@@ -10,6 +10,7 @@ import type { HTMLTextareaAttributes } from "svelte/elements";
10
10
  * @prop {boolean} [required=false] - Whether textarea is required (shows asterisk)
11
11
  * @prop {boolean} [disabled=false] - Whether textarea is disabled
12
12
  * @prop {string} [class] - Additional CSS classes to apply
13
+ * @prop {string} [id] - Textarea ID for label association (auto-generated if not provided)
13
14
  *
14
15
  * @example
15
16
  * <Textarea label="Description" bind:value={description} required />
@@ -29,6 +30,7 @@ interface Props extends Omit<HTMLTextareaAttributes, "class"> {
29
30
  required?: boolean;
30
31
  disabled?: boolean;
31
32
  class?: string;
33
+ id?: string;
32
34
  }
33
35
  declare const Textarea: import("svelte").Component<Props, {}, "value">;
34
36
  type Textarea = ReturnType<typeof Textarea>;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * UI Stores Index
3
+ * Re-exports all shared UI stores from the engine package
4
+ */
5
+ export { seasonStore } from "./season";
6
+ export { themeStore } from "./theme";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * UI Stores Index
3
+ * Re-exports all shared UI stores from the engine package
4
+ */
5
+ export { seasonStore } from "./season";
6
+ export { themeStore } from "./theme";
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Season Store for Grove Engine
3
+ * Manages seasonal theme preferences (spring, summer, autumn, winter)
4
+ * Defaults to autumn on first visit, remembers user choice thereafter
5
+ *
6
+ * The logo and other nature components react to season changes.
7
+ */
8
+ import type { Season } from "../components/nature/palette";
9
+ export declare const seasonStore: {
10
+ subscribe: (this: void, run: import("svelte/store").Subscriber<Season>, invalidate?: () => void) => import("svelte/store").Unsubscriber;
11
+ cycle: () => void;
12
+ setSeason: (newSeason: Season) => void;
13
+ getCurrent: () => Season;
14
+ };
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Season Store for Grove Engine
3
+ * Manages seasonal theme preferences (spring, summer, autumn, winter)
4
+ * Defaults to autumn on first visit, remembers user choice thereafter
5
+ *
6
+ * The logo and other nature components react to season changes.
7
+ */
8
+ import { writable, get } from "svelte/store";
9
+ import { browser } from "$app/environment";
10
+ const STORAGE_KEY = "grove-season";
11
+ // Season cycle order
12
+ const SEASONS = ["spring", "summer", "autumn", "winter"];
13
+ function getInitialSeason() {
14
+ if (!browser)
15
+ return "autumn";
16
+ // Check if user has a stored preference
17
+ const stored = localStorage.getItem(STORAGE_KEY);
18
+ if (stored && SEASONS.includes(stored)) {
19
+ return stored;
20
+ }
21
+ // Clean up invalid stored value if present
22
+ if (stored) {
23
+ localStorage.removeItem(STORAGE_KEY);
24
+ }
25
+ // First visit (or invalid value): default to autumn (Grove's signature season)
26
+ return "autumn";
27
+ }
28
+ function createSeasonStore() {
29
+ const season = writable(getInitialSeason());
30
+ // Persist to localStorage on change
31
+ if (browser) {
32
+ season.subscribe((s) => {
33
+ localStorage.setItem(STORAGE_KEY, s);
34
+ });
35
+ }
36
+ /**
37
+ * Cycle to the next season: spring → summer → autumn → winter → spring
38
+ */
39
+ function cycle() {
40
+ season.update((current) => {
41
+ const currentIndex = SEASONS.indexOf(current);
42
+ const nextIndex = (currentIndex + 1) % SEASONS.length;
43
+ return SEASONS[nextIndex];
44
+ });
45
+ }
46
+ /**
47
+ * Set a specific season
48
+ */
49
+ function setSeason(newSeason) {
50
+ season.set(newSeason);
51
+ }
52
+ /**
53
+ * Get current season value (for non-reactive contexts)
54
+ */
55
+ function getCurrent() {
56
+ return get(season);
57
+ }
58
+ return {
59
+ subscribe: season.subscribe,
60
+ cycle,
61
+ setSeason,
62
+ getCurrent,
63
+ };
64
+ }
65
+ export const seasonStore = createSeasonStore();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autumnsgrove/groveengine",
3
- "version": "0.8.6",
3
+ "version": "0.9.0",
4
4
  "description": "Multi-tenant blog engine for Grove Platform. Features gutter annotations, markdown editing, magic code auth, and Cloudflare Workers deployment.",
5
5
  "author": "AutumnsGrove",
6
6
  "license": "AGPL-3.0-only",
@@ -9,6 +9,10 @@
9
9
  "url": "https://github.com/AutumnsGrove/GroveEngine.git",
10
10
  "directory": "packages/engine"
11
11
  },
12
+ "publishConfig": {
13
+ "registry": "https://registry.npmjs.org",
14
+ "access": "public"
15
+ },
12
16
  "keywords": [
13
17
  "blog",
14
18
  "cms",
@@ -38,6 +42,16 @@
38
42
  "svelte": "./dist/ui/index.js",
39
43
  "default": "./dist/ui/index.js"
40
44
  },
45
+ "./ui/chrome": {
46
+ "types": "./dist/ui/components/chrome/index.d.ts",
47
+ "svelte": "./dist/ui/components/chrome/index.js",
48
+ "default": "./dist/ui/components/chrome/index.js"
49
+ },
50
+ "./ui/stores": {
51
+ "types": "./dist/ui/stores/index.d.ts",
52
+ "svelte": "./dist/ui/stores/index.js",
53
+ "default": "./dist/ui/stores/index.js"
54
+ },
41
55
  "./ui/gallery": {
42
56
  "types": "./dist/ui/components/gallery/index.d.ts",
43
57
  "svelte": "./dist/ui/components/gallery/index.js",
@@ -151,6 +165,15 @@
151
165
  "types": "./dist/ui/vineyard/index.d.ts",
152
166
  "svelte": "./dist/ui/vineyard/index.js",
153
167
  "default": "./dist/ui/vineyard/index.js"
168
+ },
169
+ "./ui/terrarium": {
170
+ "types": "./dist/ui/components/terrarium/index.d.ts",
171
+ "svelte": "./dist/ui/components/terrarium/index.js",
172
+ "default": "./dist/ui/components/terrarium/index.js"
173
+ },
174
+ "./config/terrarium": {
175
+ "types": "./dist/config/terrarium.d.ts",
176
+ "default": "./dist/config/terrarium.js"
154
177
  }
155
178
  },
156
179
  "files": [
@@ -214,7 +237,6 @@
214
237
  "vitest": "^4.0.14"
215
238
  },
216
239
  "dependencies": {
217
- "@autumnsgrove/vineyard": "link:../../../Vineyard",
218
240
  "chart.js": "^4.5.1",
219
241
  "clsx": "^2.1.1",
220
242
  "dompurify": "^3.3.0",
@@ -223,6 +245,7 @@
223
245
  "lucide-svelte": "^0.554.0",
224
246
  "marked": "^17.0.1",
225
247
  "svelte-sonner": "^1.0.7",
226
- "tailwind-merge": "^3.4.0"
248
+ "tailwind-merge": "^3.4.0",
249
+ "dom-to-image-more": "^3.5.0"
227
250
  }
228
- }
251
+ }