@autumnsgrove/groveengine 0.8.5 → 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 (109) hide show
  1. package/dist/components/WispPanel.svelte +0 -1
  2. package/dist/components/admin/GutterManager.svelte +213 -101
  3. package/dist/components/admin/MarkdownEditor.svelte +6 -3
  4. package/dist/components/custom/ContentWithGutter.svelte +7 -13
  5. package/dist/components/custom/GutterItem.svelte +8 -2
  6. package/dist/components/quota/UpgradePrompt.svelte +1 -0
  7. package/dist/config/domain-blocklist.d.ts +59 -0
  8. package/dist/config/domain-blocklist.js +731 -0
  9. package/dist/config/index.d.ts +3 -1
  10. package/dist/config/index.js +2 -1
  11. package/dist/config/offensive-blocklist.d.ts +44 -0
  12. package/dist/config/offensive-blocklist.js +751 -0
  13. package/dist/config/terrarium.d.ts +109 -0
  14. package/dist/config/terrarium.js +125 -0
  15. package/dist/styles/tokens.css +90 -0
  16. package/dist/types/dom-to-image-more.d.ts +39 -0
  17. package/dist/ui/components/chrome/Footer.svelte +137 -0
  18. package/dist/ui/components/chrome/Footer.svelte.d.ts +11 -0
  19. package/dist/ui/components/chrome/FooterMinimal.svelte +75 -0
  20. package/dist/ui/components/chrome/FooterMinimal.svelte.d.ts +10 -0
  21. package/dist/ui/components/chrome/Header.svelte +113 -0
  22. package/dist/ui/components/chrome/Header.svelte.d.ts +11 -0
  23. package/dist/ui/components/chrome/HeaderMinimal.svelte +68 -0
  24. package/dist/ui/components/chrome/HeaderMinimal.svelte.d.ts +9 -0
  25. package/dist/ui/components/chrome/MobileMenu.svelte +145 -0
  26. package/dist/ui/components/chrome/MobileMenu.svelte.d.ts +9 -0
  27. package/dist/ui/components/chrome/ThemeToggle.svelte +34 -0
  28. package/dist/ui/components/chrome/ThemeToggle.svelte.d.ts +3 -0
  29. package/dist/ui/components/chrome/defaults.d.ts +6 -0
  30. package/dist/ui/components/chrome/defaults.js +65 -0
  31. package/dist/ui/components/chrome/index.d.ts +13 -0
  32. package/dist/ui/components/chrome/index.js +14 -0
  33. package/dist/ui/components/chrome/types.d.ts +19 -0
  34. package/dist/ui/components/chrome/types.js +8 -0
  35. package/dist/ui/components/content/RoadmapPreview.svelte +2 -1
  36. package/dist/ui/components/forms/ContentSearch.svelte +406 -0
  37. package/dist/ui/components/forms/ContentSearch.svelte.d.ts +71 -0
  38. package/dist/ui/components/forms/SearchInput.svelte +0 -1
  39. package/dist/ui/components/forms/filterUtils.d.ts +138 -0
  40. package/dist/ui/components/forms/filterUtils.js +240 -0
  41. package/dist/ui/components/forms/index.d.ts +2 -0
  42. package/dist/ui/components/forms/index.js +5 -1
  43. package/dist/ui/components/gallery/ImageGallery.svelte +17 -3
  44. package/dist/ui/components/gallery/Lightbox.svelte +11 -3
  45. package/dist/ui/components/gallery/ZoomableImage.svelte +13 -2
  46. package/dist/ui/components/icons/index.d.ts +2 -1
  47. package/dist/ui/components/icons/index.js +14 -3
  48. package/dist/ui/components/icons/lucide.d.ts +213 -0
  49. package/dist/ui/components/icons/lucide.js +224 -0
  50. package/dist/ui/components/terrarium/AssetPalette.svelte +207 -0
  51. package/dist/ui/components/terrarium/AssetPalette.svelte.d.ts +7 -0
  52. package/dist/ui/components/terrarium/Canvas.svelte +231 -0
  53. package/dist/ui/components/terrarium/Canvas.svelte.d.ts +14 -0
  54. package/dist/ui/components/terrarium/ExportDialog.svelte +307 -0
  55. package/dist/ui/components/terrarium/ExportDialog.svelte.d.ts +18 -0
  56. package/dist/ui/components/terrarium/PaletteItem.svelte +169 -0
  57. package/dist/ui/components/terrarium/PaletteItem.svelte.d.ts +9 -0
  58. package/dist/ui/components/terrarium/PlacedAsset.svelte +222 -0
  59. package/dist/ui/components/terrarium/PlacedAsset.svelte.d.ts +11 -0
  60. package/dist/ui/components/terrarium/Terrarium.svelte +266 -0
  61. package/dist/ui/components/terrarium/Terrarium.svelte.d.ts +3 -0
  62. package/dist/ui/components/terrarium/Toolbar.svelte +299 -0
  63. package/dist/ui/components/terrarium/Toolbar.svelte.d.ts +24 -0
  64. package/dist/ui/components/terrarium/index.d.ts +31 -0
  65. package/dist/ui/components/terrarium/index.js +33 -0
  66. package/dist/ui/components/terrarium/terrariumState.svelte.d.ts +45 -0
  67. package/dist/ui/components/terrarium/terrariumState.svelte.js +291 -0
  68. package/dist/ui/components/terrarium/types.d.ts +139 -0
  69. package/dist/ui/components/terrarium/types.js +43 -0
  70. package/dist/ui/components/terrarium/utils/export.d.ts +48 -0
  71. package/dist/ui/components/terrarium/utils/export.js +148 -0
  72. package/dist/ui/components/typography/index.d.ts +0 -10
  73. package/dist/ui/components/typography/index.js +1 -12
  74. package/dist/ui/components/ui/CollapsibleSection.svelte +12 -0
  75. package/dist/ui/components/ui/GlassConfirmDialog.svelte +9 -0
  76. package/dist/ui/components/ui/GlassOverlay.svelte +2 -1
  77. package/dist/ui/components/ui/Input.svelte +9 -1
  78. package/dist/ui/components/ui/Input.svelte.d.ts +2 -0
  79. package/dist/ui/components/ui/Textarea.svelte +9 -1
  80. package/dist/ui/components/ui/Textarea.svelte.d.ts +2 -0
  81. package/dist/ui/stores/index.d.ts +6 -0
  82. package/dist/ui/stores/index.js +6 -0
  83. package/dist/ui/stores/season.d.ts +14 -0
  84. package/dist/ui/stores/season.js +65 -0
  85. package/dist/ui/tokens/fonts.d.ts +1 -1
  86. package/dist/ui/tokens/fonts.js +0 -126
  87. package/package.json +46 -22
  88. package/static/fonts/alagard.ttf +0 -0
  89. package/LICENSE +0 -378
  90. package/dist/ui/components/typography/BodoniModa.svelte +0 -17
  91. package/dist/ui/components/typography/BodoniModa.svelte.d.ts +0 -10
  92. package/dist/ui/components/typography/Cormorant.svelte +0 -17
  93. package/dist/ui/components/typography/Cormorant.svelte.d.ts +0 -10
  94. package/dist/ui/components/typography/EBGaramond.svelte +0 -17
  95. package/dist/ui/components/typography/EBGaramond.svelte.d.ts +0 -10
  96. package/dist/ui/components/typography/Fraunces.svelte +0 -17
  97. package/dist/ui/components/typography/Fraunces.svelte.d.ts +0 -10
  98. package/dist/ui/components/typography/InstrumentSans.svelte +0 -17
  99. package/dist/ui/components/typography/InstrumentSans.svelte.d.ts +0 -10
  100. package/dist/ui/components/typography/Lora.svelte +0 -17
  101. package/dist/ui/components/typography/Lora.svelte.d.ts +0 -10
  102. package/dist/ui/components/typography/Luciole.svelte +0 -17
  103. package/dist/ui/components/typography/Luciole.svelte.d.ts +0 -10
  104. package/dist/ui/components/typography/Manrope.svelte +0 -17
  105. package/dist/ui/components/typography/Manrope.svelte.d.ts +0 -10
  106. package/dist/ui/components/typography/Merriweather.svelte +0 -17
  107. package/dist/ui/components/typography/Merriweather.svelte.d.ts +0 -10
  108. package/dist/ui/components/typography/Nunito.svelte +0 -17
  109. package/dist/ui/components/typography/Nunito.svelte.d.ts +0 -10
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Common filter utilities for use with ContentSearch component
3
+ * Part of the Grove UI design system
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * import { createTextFilter, createMultiFieldFilter } from '@autumnsgrove/groveengine';
8
+ *
9
+ * const filterPost = createTextFilter(['title', 'description']);
10
+ * <ContentSearch items={posts} filterFn={filterPost} />
11
+ * ```
12
+ */
13
+ /**
14
+ * Normalize text for searching (lowercase, trim)
15
+ */
16
+ export function normalizeSearchText(text) {
17
+ return text.toLowerCase().trim();
18
+ }
19
+ /**
20
+ * Check if normalized text includes a normalized query
21
+ * Note: Both inputs should already be normalized via normalizeSearchText()
22
+ *
23
+ * @param normalizedText - Already normalized text to search in
24
+ * @param normalizedQuery - Already normalized query to search for
25
+ */
26
+ export function includesNormalized(normalizedText, normalizedQuery) {
27
+ return normalizedText.includes(normalizedQuery);
28
+ }
29
+ /**
30
+ * Check if text includes a search query (case-insensitive)
31
+ * This is a convenience function that normalizes both inputs
32
+ *
33
+ * @param text - Text to search in (will be normalized)
34
+ * @param query - Query to search for (will be normalized)
35
+ */
36
+ export function textIncludes(text, query) {
37
+ return normalizeSearchText(text).includes(normalizeSearchText(query));
38
+ }
39
+ /**
40
+ * Create a filter function that searches multiple text fields
41
+ *
42
+ * @param fields - Array of field names to search
43
+ * @returns Filter function for use with ContentSearch
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const filterPost = createTextFilter(['title', 'description', 'author']);
48
+ * <ContentSearch items={posts} filterFn={filterPost} />
49
+ * ```
50
+ */
51
+ export function createTextFilter(fields) {
52
+ return (item, query) => {
53
+ const normalizedQuery = normalizeSearchText(query);
54
+ return fields.some(field => {
55
+ const value = item[field];
56
+ if (typeof value === 'string') {
57
+ // Use includesNormalized to avoid double normalization
58
+ return includesNormalized(normalizeSearchText(value), normalizedQuery);
59
+ }
60
+ return false;
61
+ });
62
+ };
63
+ }
64
+ /**
65
+ * Create a filter function that searches text fields and array fields (like tags)
66
+ *
67
+ * @param textFields - Array of text field names to search
68
+ * @param arrayFields - Array of array field names to search (e.g., tags)
69
+ * @returns Filter function for use with ContentSearch
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const filterPost = createMultiFieldFilter(['title', 'description'], ['tags', 'categories']);
74
+ * <ContentSearch items={posts} filterFn={filterPost} />
75
+ * ```
76
+ */
77
+ export function createMultiFieldFilter(textFields, arrayFields = []) {
78
+ return (item, query) => {
79
+ const normalizedQuery = normalizeSearchText(query);
80
+ // Check text fields
81
+ const matchesText = textFields.some(field => {
82
+ const value = item[field];
83
+ if (typeof value === 'string') {
84
+ // Use includesNormalized to avoid double normalization
85
+ return includesNormalized(normalizeSearchText(value), normalizedQuery);
86
+ }
87
+ return false;
88
+ });
89
+ if (matchesText)
90
+ return true;
91
+ // Check array fields
92
+ const matchesArray = arrayFields.some(field => {
93
+ const value = item[field];
94
+ if (Array.isArray(value)) {
95
+ return value.some(element => {
96
+ if (typeof element === 'string') {
97
+ // Use includesNormalized to avoid double normalization
98
+ return includesNormalized(normalizeSearchText(element), normalizedQuery);
99
+ }
100
+ return false;
101
+ });
102
+ }
103
+ return false;
104
+ });
105
+ return matchesArray;
106
+ };
107
+ }
108
+ /**
109
+ * Pre-compute lowercase versions of searchable fields for performance
110
+ *
111
+ * **When to use this optimization:**
112
+ * - **Large datasets (100+ items)**: Repeated toLowerCase() calls during filtering become expensive
113
+ * - **Frequent searches**: Users actively searching/filtering the same dataset multiple times
114
+ * - **Multiple searchable fields**: More fields = more normalization = more performance gain
115
+ * - **Real-time filtering**: When debouncing isn't enough and you need instant results
116
+ *
117
+ * **When NOT to use:**
118
+ * - Small datasets (<50 items): Minimal performance benefit, adds memory overhead
119
+ * - Static lists that don't change: Consider precomputing at build time instead
120
+ * - Infrequent searches: The setup cost may outweigh the benefit
121
+ *
122
+ * @param items - Array of items to optimize
123
+ * @param fields - Fields to pre-compute lowercase versions of
124
+ * @returns Array of items with lowercase fields added (suffixed with 'Lower')
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * // In your Svelte component with large dataset (100+ posts)
129
+ * let postsWithLowercase = $derived.by(() => {
130
+ * return precomputeLowercaseFields(posts, ['title', 'description', 'tags']);
131
+ * });
132
+ * // Creates: { ...post, titleLower: '...', descriptionLower: '...', tagsLower: [...] }
133
+ *
134
+ * function filterPost(post, query) {
135
+ * const q = query.toLowerCase();
136
+ * return post.titleLower.includes(q) ||
137
+ * post.descriptionLower.includes(q) ||
138
+ * post.tagsLower.some(tag => tag.includes(q));
139
+ * }
140
+ *
141
+ * <ContentSearch items={postsWithLowercase} filterFn={filterPost} />
142
+ * ```
143
+ */
144
+ export function precomputeLowercaseFields(items, fields) {
145
+ return items.map(item => {
146
+ const computed = { ...item };
147
+ fields.forEach(field => {
148
+ const value = item[field];
149
+ if (typeof value === 'string') {
150
+ computed[`${String(field)}Lower`] = value.toLowerCase();
151
+ }
152
+ else if (Array.isArray(value)) {
153
+ computed[`${String(field)}Lower`] = value.map(v => typeof v === 'string' ? v.toLowerCase() : v);
154
+ }
155
+ });
156
+ return computed;
157
+ });
158
+ }
159
+ /**
160
+ * Create a fuzzy filter that matches partial words
161
+ *
162
+ * @param fields - Array of field names to search
163
+ * @param minMatchLength - Minimum length of query before fuzzy matching (default: 2)
164
+ * @returns Filter function for use with ContentSearch
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * const filterPost = createFuzzyFilter(['title', 'description']);
169
+ * // Matches: "jav" in "JavaScript", "scr" in "TypeScript"
170
+ * ```
171
+ */
172
+ export function createFuzzyFilter(fields, minMatchLength = 2) {
173
+ return (item, query) => {
174
+ if (query.length < minMatchLength)
175
+ return true;
176
+ const normalizedQuery = normalizeSearchText(query);
177
+ return fields.some(field => {
178
+ const value = item[field];
179
+ if (typeof value === 'string') {
180
+ const normalizedValue = normalizeSearchText(value);
181
+ // Split into words and check if any word starts with the query
182
+ const words = normalizedValue.split(/\s+/);
183
+ return words.some(word => word.startsWith(normalizedQuery));
184
+ }
185
+ return false;
186
+ });
187
+ };
188
+ }
189
+ /**
190
+ * Combine multiple filter functions with AND logic
191
+ *
192
+ * @param filters - Array of filter functions to combine
193
+ * @returns Combined filter function
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * const hasTag = (item, tag) => item.tags.includes(tag);
198
+ * const matchesText = createTextFilter(['title']);
199
+ * const combinedFilter = combineFilters([matchesText, (item) => hasTag(item, 'featured')]);
200
+ * ```
201
+ */
202
+ export function combineFilters(filters) {
203
+ return (item, query) => {
204
+ return filters.every(filter => filter(item, query));
205
+ };
206
+ }
207
+ /**
208
+ * Create a date range filter
209
+ *
210
+ * @param dateField - Field name containing the date
211
+ * @param startDate - Start of date range (optional)
212
+ * @param endDate - End of date range (optional)
213
+ * @returns Filter function for use with ContentSearch
214
+ *
215
+ * @example
216
+ * ```typescript
217
+ * const recentPostsFilter = createDateFilter('publishedAt', new Date('2024-01-01'));
218
+ * ```
219
+ */
220
+ export function createDateFilter(dateField, startDate, endDate) {
221
+ // Date filters don't use the query string, but must match the filterFn signature
222
+ return (item, _query) => {
223
+ const dateValue = item[dateField];
224
+ if (!dateValue)
225
+ return false;
226
+ // Validate dateValue is a valid date type before constructing Date
227
+ if (typeof dateValue !== 'string' && typeof dateValue !== 'number' && !(dateValue instanceof Date)) {
228
+ return false;
229
+ }
230
+ const itemDate = new Date(dateValue);
231
+ // Check if the date is valid (invalid dates return NaN for getTime())
232
+ if (isNaN(itemDate.getTime()))
233
+ return false;
234
+ if (startDate && itemDate < startDate)
235
+ return false;
236
+ if (endDate && itemDate > endDate)
237
+ return false;
238
+ return true;
239
+ };
240
+ }
@@ -1,2 +1,4 @@
1
1
  export { default as SearchInput } from './SearchInput.svelte';
2
+ export { default as ContentSearch } from './ContentSearch.svelte';
3
+ export { normalizeSearchText, includesNormalized, textIncludes, createTextFilter, createMultiFieldFilter, precomputeLowercaseFields, createFuzzyFilter, combineFilters, createDateFilter } from './filterUtils.js';
2
4
  export declare const FORMS_VERSION = "0.2.0";
@@ -3,6 +3,10 @@
3
3
  // This module exports specialized form input components
4
4
  //
5
5
  // Usage:
6
- // import { SearchInput } from '@groveengine/ui/forms';
6
+ // import { SearchInput, ContentSearch } from '@groveengine/ui/forms';
7
+ // import { createTextFilter, createMultiFieldFilter } from '@groveengine/ui/forms';
7
8
  export { default as SearchInput } from './SearchInput.svelte';
9
+ export { default as ContentSearch } from './ContentSearch.svelte';
10
+ // Filter utilities for ContentSearch
11
+ export { normalizeSearchText, includesNormalized, textIncludes, createTextFilter, createMultiFieldFilter, precomputeLowercaseFields, createFuzzyFilter, combineFilters, createDateFilter } from './filterUtils.js';
8
12
  export const FORMS_VERSION = '0.2.0';
@@ -263,10 +263,15 @@
263
263
 
264
264
  <!-- Lightbox modal -->
265
265
  {#if lightboxOpen}
266
- <!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events a11y_interactive_supports_focus -->
266
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
267
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
267
268
  <div
268
269
  class="lightbox-backdrop"
269
270
  onclick={(/** @type {MouseEvent} */ e) => e.target === e.currentTarget && closeLightbox()}
271
+ onkeydown={(/** @type {KeyboardEvent} */ e) => {
272
+ if (e.key === 'Escape') closeLightbox();
273
+ if (e.key === 'Enter' || e.key === ' ') closeLightbox();
274
+ }}
270
275
  role="dialog"
271
276
  aria-modal="true"
272
277
  aria-label="Image viewer"
@@ -279,8 +284,17 @@
279
284
  </svg>
280
285
  </button>
281
286
 
282
- <!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events -->
283
- <div class="lightbox-content" onclick={(/** @type {MouseEvent} */ e) => e.target === e.currentTarget && closeLightbox()}>
287
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
288
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
289
+ <div
290
+ class="lightbox-content"
291
+ onclick={(/** @type {MouseEvent} */ e) => e.target === e.currentTarget && closeLightbox()}
292
+ onkeydown={(/** @type {KeyboardEvent} */ e) => {
293
+ if (e.key === 'Escape') closeLightbox();
294
+ if (e.key === 'Enter' || e.key === ' ') closeLightbox();
295
+ }}
296
+ role="presentation"
297
+ >
284
298
  <ZoomableImage
285
299
  src={currentImage.url}
286
300
  alt={currentImage.alt || `Image ${currentIndex + 1}`}
@@ -24,10 +24,12 @@
24
24
  <svelte:window onkeydown={handleKeydown} />
25
25
 
26
26
  {#if isOpen}
27
- <!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events a11y_interactive_supports_focus -->
27
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
28
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
28
29
  <div
29
30
  class="lightbox-backdrop"
30
31
  onclick={handleBackdropClick}
32
+ onkeydown={handleKeydown}
31
33
  role="dialog"
32
34
  aria-modal="true"
33
35
  aria-label="Image viewer"
@@ -39,8 +41,14 @@
39
41
  <line x1="6" y1="6" x2="18" y2="18"></line>
40
42
  </svg>
41
43
  </button>
42
- <!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events -->
43
- <div class="lightbox-content" onclick={handleBackdropClick}>
44
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
45
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
46
+ <div
47
+ class="lightbox-content"
48
+ onclick={handleBackdropClick}
49
+ onkeydown={handleKeydown}
50
+ role="presentation"
51
+ >
44
52
  <ZoomableImage {src} {alt} isActive={isOpen} class="lightbox-image" />
45
53
  </div>
46
54
  <LightboxCaption {caption} />
@@ -124,11 +124,20 @@
124
124
  }
125
125
  cycleZoom();
126
126
  }
127
+
128
+ // Keyboard handler for accessibility
129
+ function handleKeydown(/** @type {KeyboardEvent} */ event) {
130
+ if (event.key === 'Enter' || event.key === ' ') {
131
+ event.preventDefault();
132
+ cycleZoom();
133
+ }
134
+ }
127
135
  </script>
128
136
 
129
137
  <svelte:window onmousemove={handleMouseMove} onmouseup={handleMouseUp} />
130
138
 
131
- <!-- svelte-ignore a11y_no_noninteractive_element_interactions a11y_click_events_have_key_events a11y_no_noninteractive_element_to_interactive_role -->
139
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
140
+ <!-- svelte-ignore a11y_no_noninteractive_element_to_interactive_role -->
132
141
  <img
133
142
  {src}
134
143
  {alt}
@@ -141,8 +150,10 @@
141
150
  ontouchmove={handleTouchMove}
142
151
  ontouchend={handleTouchEnd}
143
152
  onclick={handleClick}
144
- role="button"
153
+ onkeydown={handleKeydown}
145
154
  tabindex="0"
155
+ role="button"
156
+ aria-label="Click to zoom image"
146
157
  />
147
158
 
148
159
  <style>
@@ -1,3 +1,4 @@
1
1
  export { default as Icons } from './Icons.svelte';
2
2
  export { default as IconLegend } from './IconLegend.svelte';
3
- export declare const ICONS_VERSION = "0.2.0";
3
+ export { navIcons, stateIcons, pricingIcons, featureIcons, growthIcons, phaseIcons, actionIcons, metricsIcons, allIcons, type IconKey, getIcon, getIconFromAll, Check, CheckCircle, X, ArrowRight, ArrowLeft, MapPin, Sprout, Trees, TreeDeciduous, Crown, Flower2, Leaf, Heart, Home, Menu, Settings, ExternalLink, ChevronDown, LogIn, Github, Mail, HardDrive, Palette, Shield, Download, Rss, Eye, MessageCircle, Loader2, AlertTriangle, HelpCircle, Lock, Sparkles, Clock, TrendingUp, Users, Activity, } from './lucide';
4
+ export declare const ICONS_VERSION = "0.3.0";
@@ -1,9 +1,20 @@
1
1
  // GroveUI - Icon Components
2
2
  //
3
- // This module exports SVG icon components used across the Grove platform
3
+ // This module exports SVG icon components and Lucide icon registries
4
+ // used across the Grove platform.
4
5
  //
5
6
  // Usage:
6
- // import { Icons, IconLegend } from '@groveengine/ui/icons';
7
+ // import { Icons, IconLegend } from '@autumnsgrove/groveengine/ui/icons';
8
+ // import { stateIcons, pricingIcons, Check } from '@autumnsgrove/groveengine/ui/icons';
9
+ // Custom SVG components
7
10
  export { default as Icons } from './Icons.svelte';
8
11
  export { default as IconLegend } from './IconLegend.svelte';
9
- export const ICONS_VERSION = '0.2.0';
12
+ // Lucide icon registries and utilities
13
+ export {
14
+ // Icon maps (semantic groupings)
15
+ navIcons, stateIcons, pricingIcons, featureIcons, growthIcons, phaseIcons, actionIcons, metricsIcons, allIcons,
16
+ // Utilities
17
+ getIcon, getIconFromAll,
18
+ // Direct icon exports (commonly used)
19
+ Check, CheckCircle, X, ArrowRight, ArrowLeft, MapPin, Sprout, Trees, TreeDeciduous, Crown, Flower2, Leaf, Heart, Home, Menu, Settings, ExternalLink, ChevronDown, LogIn, Github, Mail, HardDrive, Palette, Shield, Download, Rss, Eye, MessageCircle, Loader2, AlertTriangle, HelpCircle, Lock, Sparkles, Clock, TrendingUp, Users, Activity, } from './lucide';
20
+ export const ICONS_VERSION = '0.3.0';
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Shared Lucide icon registry for Grove Platform.
3
+ * Single source of truth for commonly used icons across all Grove apps.
4
+ *
5
+ * DO: Import icons from '@autumnsgrove/groveengine/ui/icons'
6
+ * DON'T: Import directly from 'lucide-svelte' in app components
7
+ *
8
+ * @example
9
+ * ```svelte
10
+ * import { stateIcons, navIcons } from '@autumnsgrove/groveengine/ui/icons';
11
+ *
12
+ * <svelte:component this={stateIcons.check} class="w-5 h-5" />
13
+ * ```
14
+ */
15
+ import { Home, Info, Telescope, MapPin, CircleDollarSign, BookOpen, Trees, PenLine, ArrowRight, ArrowLeft, ChevronRight, ChevronLeft, ChevronDown, ExternalLink, LogIn, Mail, HardDrive, Palette, ShieldCheck, Shield, Cloud, SearchCode, Archive, Upload, MessagesSquare, MessageCircle, FileText, Tag, Rss, Eye, Github, Layers, Sprout, Heart, Leaf, Flower2, TreeDeciduous, Crown, Check, CheckCircle, X, Loader2, AlertTriangle, HelpCircle, Circle, Lock, Gem, Sparkles, Star, Moon, Sun, Compass, Megaphone, Lightbulb, Download, Settings, Menu, Clock, TrendingUp, TrendingDown, Activity, Users, ShieldUser, BarChart3, Globe, CalendarDays, LifeBuoy } from 'lucide-svelte';
16
+ /** Icons for main navigation items */
17
+ export declare const navIcons: {
18
+ readonly home: typeof Home;
19
+ readonly about: typeof Info;
20
+ readonly vision: typeof Telescope;
21
+ readonly roadmap: typeof MapPin;
22
+ readonly pricing: typeof CircleDollarSign;
23
+ readonly knowledge: typeof BookOpen;
24
+ readonly forest: typeof Trees;
25
+ readonly blog: typeof PenLine;
26
+ readonly arrow: typeof ArrowRight;
27
+ readonly arrowLeft: typeof ArrowLeft;
28
+ readonly chevron: typeof ChevronRight;
29
+ readonly chevronLeft: typeof ChevronLeft;
30
+ readonly chevronDown: typeof ChevronDown;
31
+ readonly external: typeof ExternalLink;
32
+ readonly login: typeof LogIn;
33
+ readonly github: typeof Github;
34
+ };
35
+ /** Icons for states: success, error, loading, etc. */
36
+ export declare const stateIcons: {
37
+ readonly check: typeof Check;
38
+ readonly checkcircle: typeof CheckCircle;
39
+ readonly x: typeof X;
40
+ readonly loader: typeof Loader2;
41
+ readonly warning: typeof AlertTriangle;
42
+ readonly help: typeof HelpCircle;
43
+ readonly info: typeof Info;
44
+ readonly circle: typeof Circle;
45
+ readonly lock: typeof Lock;
46
+ };
47
+ /** Icons for pricing tiers and feature comparison */
48
+ export declare const pricingIcons: {
49
+ readonly sprout: typeof Sprout;
50
+ readonly treedeciduous: typeof TreeDeciduous;
51
+ readonly trees: typeof Trees;
52
+ readonly crown: typeof Crown;
53
+ readonly penline: typeof PenLine;
54
+ readonly filetext: typeof FileText;
55
+ readonly harddrive: typeof HardDrive;
56
+ readonly palette: typeof Palette;
57
+ readonly flower2: typeof Flower2;
58
+ readonly messagecircle: typeof MessageCircle;
59
+ readonly globe: typeof Globe;
60
+ readonly searchcode: typeof SearchCode;
61
+ readonly mail: typeof Mail;
62
+ readonly lifebuoy: typeof LifeBuoy;
63
+ readonly calendardays: typeof CalendarDays;
64
+ readonly clock: typeof Clock;
65
+ readonly check: typeof Check;
66
+ };
67
+ /** Icons for features, tools, and content types */
68
+ export declare const featureIcons: {
69
+ readonly mail: typeof Mail;
70
+ readonly harddrive: typeof HardDrive;
71
+ readonly palette: typeof Palette;
72
+ readonly shieldcheck: typeof ShieldCheck;
73
+ readonly shield: typeof Shield;
74
+ readonly cloud: typeof Cloud;
75
+ readonly searchcode: typeof SearchCode;
76
+ readonly archive: typeof Archive;
77
+ readonly upload: typeof Upload;
78
+ readonly messagessquare: typeof MessagesSquare;
79
+ readonly externallink: typeof ExternalLink;
80
+ readonly filetext: typeof FileText;
81
+ readonly tag: typeof Tag;
82
+ readonly rss: typeof Rss;
83
+ readonly eye: typeof Eye;
84
+ readonly download: typeof Download;
85
+ readonly layers: typeof Layers;
86
+ };
87
+ /** Icons representing growth and nature (Grove themed) */
88
+ export declare const growthIcons: {
89
+ readonly sprout: typeof Sprout;
90
+ readonly heart: typeof Heart;
91
+ readonly leaf: typeof Leaf;
92
+ readonly flower2: typeof Flower2;
93
+ readonly trees: typeof Trees;
94
+ readonly treedeciduous: typeof TreeDeciduous;
95
+ };
96
+ /** Icons for phases, refinement, and mystical/future content */
97
+ export declare const phaseIcons: {
98
+ readonly gem: typeof Gem;
99
+ readonly sparkles: typeof Sparkles;
100
+ readonly star: typeof Star;
101
+ readonly moon: typeof Moon;
102
+ readonly sun: typeof Sun;
103
+ readonly sprout: typeof Sprout;
104
+ };
105
+ /** Icons for user actions and processes */
106
+ export declare const actionIcons: {
107
+ readonly compass: typeof Compass;
108
+ readonly megaphone: typeof Megaphone;
109
+ readonly lightbulb: typeof Lightbulb;
110
+ readonly download: typeof Download;
111
+ readonly settings: typeof Settings;
112
+ readonly menu: typeof Menu;
113
+ readonly trend: typeof TrendingUp;
114
+ readonly trenddown: typeof TrendingDown;
115
+ readonly arrow: typeof ArrowRight;
116
+ };
117
+ /** Icons for analytics and metrics display */
118
+ export declare const metricsIcons: {
119
+ readonly clock: typeof Clock;
120
+ readonly trending: typeof TrendingUp;
121
+ readonly trenddown: typeof TrendingDown;
122
+ readonly activity: typeof Activity;
123
+ readonly users: typeof Users;
124
+ readonly shield: typeof ShieldUser;
125
+ readonly barchart: typeof BarChart3;
126
+ };
127
+ /** All icons in one map (use specific maps above when possible) */
128
+ export declare const allIcons: {
129
+ readonly clock: typeof Clock;
130
+ readonly trending: typeof TrendingUp;
131
+ readonly trenddown: typeof TrendingDown;
132
+ readonly activity: typeof Activity;
133
+ readonly users: typeof Users;
134
+ readonly shield: typeof ShieldUser;
135
+ readonly barchart: typeof BarChart3;
136
+ readonly compass: typeof Compass;
137
+ readonly megaphone: typeof Megaphone;
138
+ readonly lightbulb: typeof Lightbulb;
139
+ readonly download: typeof Download;
140
+ readonly settings: typeof Settings;
141
+ readonly menu: typeof Menu;
142
+ readonly trend: typeof TrendingUp;
143
+ readonly arrow: typeof ArrowRight;
144
+ readonly gem: typeof Gem;
145
+ readonly sparkles: typeof Sparkles;
146
+ readonly star: typeof Star;
147
+ readonly moon: typeof Moon;
148
+ readonly sun: typeof Sun;
149
+ readonly sprout: typeof Sprout;
150
+ readonly heart: typeof Heart;
151
+ readonly leaf: typeof Leaf;
152
+ readonly flower2: typeof Flower2;
153
+ readonly trees: typeof Trees;
154
+ readonly treedeciduous: typeof TreeDeciduous;
155
+ readonly mail: typeof Mail;
156
+ readonly harddrive: typeof HardDrive;
157
+ readonly palette: typeof Palette;
158
+ readonly shieldcheck: typeof ShieldCheck;
159
+ readonly cloud: typeof Cloud;
160
+ readonly searchcode: typeof SearchCode;
161
+ readonly archive: typeof Archive;
162
+ readonly upload: typeof Upload;
163
+ readonly messagessquare: typeof MessagesSquare;
164
+ readonly externallink: typeof ExternalLink;
165
+ readonly filetext: typeof FileText;
166
+ readonly tag: typeof Tag;
167
+ readonly rss: typeof Rss;
168
+ readonly eye: typeof Eye;
169
+ readonly layers: typeof Layers;
170
+ readonly check: typeof Check;
171
+ readonly checkcircle: typeof CheckCircle;
172
+ readonly x: typeof X;
173
+ readonly loader: typeof Loader2;
174
+ readonly warning: typeof AlertTriangle;
175
+ readonly help: typeof HelpCircle;
176
+ readonly info: typeof Info;
177
+ readonly circle: typeof Circle;
178
+ readonly lock: typeof Lock;
179
+ readonly home: typeof Home;
180
+ readonly about: typeof Info;
181
+ readonly vision: typeof Telescope;
182
+ readonly roadmap: typeof MapPin;
183
+ readonly pricing: typeof CircleDollarSign;
184
+ readonly knowledge: typeof BookOpen;
185
+ readonly forest: typeof Trees;
186
+ readonly blog: typeof PenLine;
187
+ readonly arrowLeft: typeof ArrowLeft;
188
+ readonly chevron: typeof ChevronRight;
189
+ readonly chevronLeft: typeof ChevronLeft;
190
+ readonly chevronDown: typeof ChevronDown;
191
+ readonly external: typeof ExternalLink;
192
+ readonly login: typeof LogIn;
193
+ readonly github: typeof Github;
194
+ };
195
+ /** Type for any icon key in the registry */
196
+ export type IconKey = keyof typeof allIcons;
197
+ /**
198
+ * Get an icon from a specific map by key
199
+ * @example
200
+ * ```ts
201
+ * const icon = getIcon(stateIcons, 'check');
202
+ * ```
203
+ */
204
+ export declare function getIcon<T extends Record<string, any>>(map: T, key: keyof T | string): any;
205
+ /**
206
+ * Get an icon from the unified map
207
+ * @example
208
+ * ```ts
209
+ * const icon = getIconFromAll('check');
210
+ * ```
211
+ */
212
+ export declare function getIconFromAll(key: string): any;
213
+ export { Check, CheckCircle, X, ArrowRight, ArrowLeft, MapPin, Sprout, Trees, TreeDeciduous, Crown, Flower2, Leaf, Heart, Home, Menu, Settings, ExternalLink, ChevronDown, LogIn, Github, Mail, HardDrive, Palette, Shield, Download, Rss, Eye, MessageCircle, Layers, Loader2, AlertTriangle, HelpCircle, Lock, Sparkles, Clock, TrendingUp, Users, Activity, };