astro-tractstack 2.0.0-rc.8 → 2.0.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 (141) hide show
  1. package/LICENSE +8 -97
  2. package/README.md +7 -5
  3. package/bin/create-tractstack.js +35 -11
  4. package/dist/index.js +106 -29
  5. package/package.json +10 -5
  6. package/templates/css/frontend.css +1 -1
  7. package/templates/custom/minimal/CodeHook.astro +13 -12
  8. package/templates/custom/minimal/CustomRoutes.astro +25 -31
  9. package/templates/custom/with-examples/CodeHook.astro +22 -11
  10. package/templates/custom/with-examples/CustomRoutes.astro +4 -8
  11. package/templates/custom/with-examples/ProductCard.astro +29 -0
  12. package/templates/custom/with-examples/ProductCardWrapper.astro +43 -0
  13. package/templates/custom/with-examples/ProductGrid.astro +64 -0
  14. package/templates/custom/with-examples/pages/Collections.astro +58 -98
  15. package/templates/gitignore +42 -0
  16. package/templates/prettierignore +5 -0
  17. package/templates/prettierrc +19 -0
  18. package/templates/src/client/app.js +127 -0
  19. package/templates/src/client/htmx.min.js +3519 -0
  20. package/templates/src/client/view.js +429 -0
  21. package/templates/src/components/Footer.astro +4 -9
  22. package/templates/src/components/Header.astro +67 -60
  23. package/templates/src/components/Menu.tsx +188 -52
  24. package/templates/src/components/codehooks/BunnyVideoSetup.tsx +2 -2
  25. package/templates/src/components/codehooks/EpinetDurationSelector.tsx +9 -13
  26. package/templates/src/components/codehooks/EpinetTableView.tsx +11 -7
  27. package/templates/src/components/codehooks/EpinetWrapper.tsx +1 -0
  28. package/templates/src/components/codehooks/FeaturedArticle.astro +105 -0
  29. package/templates/src/components/codehooks/FeaturedArticleSetup.tsx +318 -0
  30. package/templates/src/components/codehooks/ListContent.astro +32 -162
  31. package/templates/src/components/codehooks/ListContentSetup.tsx +43 -138
  32. package/templates/src/components/codehooks/ProductCardSetup.tsx +152 -0
  33. package/templates/src/components/codehooks/ProductGridSetup.tsx +274 -0
  34. package/templates/src/components/codehooks/SearchWidget.tsx +453 -0
  35. package/templates/src/components/compositor/Node.tsx +3 -6
  36. package/templates/src/components/compositor/PanelVisibilityWrapper.tsx +21 -11
  37. package/templates/src/components/compositor/elements/BunnyVideo.tsx +21 -20
  38. package/templates/src/components/compositor/nodes/Pane.tsx +51 -21
  39. package/templates/src/components/compositor/nodes/RenderChildren.tsx +6 -1
  40. package/templates/src/components/compositor/nodes/Widget.tsx +16 -2
  41. package/templates/src/components/compositor/preview/FeaturedArticlePreview.tsx +155 -0
  42. package/templates/src/components/compositor/preview/PaneSnapshotGenerator.tsx +20 -1
  43. package/templates/src/components/edit/Header.tsx +10 -4
  44. package/templates/src/components/edit/PanelSwitch.tsx +11 -7
  45. package/templates/src/components/edit/SettingsPanel.tsx +29 -18
  46. package/templates/src/components/edit/ToolBar.tsx +1 -28
  47. package/templates/src/components/edit/ToolMode.tsx +45 -32
  48. package/templates/src/components/edit/pane/AddPanePanel_break.tsx +12 -2
  49. package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +8 -2
  50. package/templates/src/components/edit/pane/AddPanePanel_newAICopy_modal.tsx +1 -1
  51. package/templates/src/components/edit/pane/ConfigPanePanel.tsx +17 -27
  52. package/templates/src/components/edit/pane/PageGenSelector.tsx +16 -16
  53. package/templates/src/components/edit/pane/PageGenSpecial.tsx +26 -49
  54. package/templates/src/components/edit/pane/PageGen_preview.tsx +17 -2
  55. package/templates/src/components/edit/pane/PanePanel_path.tsx +2 -4
  56. package/templates/src/components/edit/pane/PanePanel_title.tsx +243 -76
  57. package/templates/src/components/edit/panels/StyleBreakPanel.tsx +17 -19
  58. package/templates/src/components/edit/panels/StyleCodeHookPanel.tsx +48 -37
  59. package/templates/src/components/edit/panels/StyleElementPanel_add.tsx +60 -55
  60. package/templates/src/components/edit/panels/StyleImagePanel_add.tsx +56 -50
  61. package/templates/src/components/edit/panels/StyleLiElementPanel_add.tsx +54 -47
  62. package/templates/src/components/edit/panels/StyleLinkPanel_add.tsx +54 -44
  63. package/templates/src/components/edit/panels/StyleLinkPanel_config.tsx +113 -138
  64. package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +54 -40
  65. package/templates/src/components/edit/panels/StyleWidgetPanel.tsx +3 -3
  66. package/templates/src/components/edit/panels/StyleWidgetPanel_add.tsx +56 -49
  67. package/templates/src/components/edit/panels/StyleWidgetPanel_config.tsx +14 -5
  68. package/templates/src/components/edit/state/SaveModal.tsx +316 -169
  69. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_og.tsx +1 -1
  70. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_slug.tsx +56 -55
  71. package/templates/src/components/edit/widgets/BunnyWidget.tsx +538 -59
  72. package/templates/src/components/edit/widgets/InteractiveDisclosureWidget.tsx +656 -0
  73. package/templates/src/components/edit/widgets/ToggleWidget.tsx +9 -16
  74. package/templates/src/components/fields/ArtpackImage.tsx +4 -1
  75. package/templates/src/components/fields/BackgroundImage.tsx +1 -1
  76. package/templates/src/components/fields/BackgroundImageWrapper.tsx +127 -35
  77. package/templates/src/components/fields/ColorPickerCombo.tsx +66 -62
  78. package/templates/src/components/fields/ImageUpload.tsx +1 -1
  79. package/templates/src/components/fields/ViewportComboBox.tsx +59 -42
  80. package/templates/src/components/form/ActionBuilderBeliefSelector.tsx +117 -0
  81. package/templates/src/components/form/ActionBuilderField.tsx +306 -87
  82. package/templates/src/components/search/SearchModal.tsx +420 -0
  83. package/templates/src/components/search/SearchResults.tsx +367 -0
  84. package/templates/src/components/search/SearchWrapper.tsx +46 -0
  85. package/templates/src/components/storykeep/Dashboard_Advanced.tsx +1 -1
  86. package/templates/src/components/storykeep/Dashboard_Analytics.tsx +34 -8
  87. package/templates/src/components/storykeep/Dashboard_Content.tsx +6 -0
  88. package/templates/src/components/storykeep/StoryKeepBackdrop.astro +87 -0
  89. package/templates/src/components/storykeep/controls/content/BeliefForm.tsx +37 -33
  90. package/templates/src/components/storykeep/controls/content/MenuForm.tsx +55 -7
  91. package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +17 -2
  92. package/templates/src/components/storykeep/controls/content/StoryFragmentTable.tsx +5 -8
  93. package/templates/src/components/storykeep/state/FetchAnalytics.tsx +274 -228
  94. package/templates/src/components/storykeep/widgets/Wizard.tsx +14 -7
  95. package/templates/src/components/tenant/RegistrationForm.tsx +1 -1
  96. package/templates/src/components/widgets/ImpressionWrapper.tsx +0 -1
  97. package/templates/src/constants/shapes.ts +9 -0
  98. package/templates/src/constants.ts +2121 -16
  99. package/templates/src/hooks/useSearch.ts +228 -0
  100. package/templates/src/layouts/Layout.astro +213 -104
  101. package/templates/src/lib/storyData.ts +4 -1
  102. package/templates/src/pages/[...slug]/edit.astro +14 -14
  103. package/templates/src/pages/[...slug].astro +82 -21
  104. package/templates/src/pages/api/orphan-analysis.ts +0 -1
  105. package/templates/src/pages/api/tailwind.ts +23 -21
  106. package/templates/src/pages/context/[...contextSlug]/edit.astro +14 -14
  107. package/templates/src/pages/context/[...contextSlug].astro +7 -2
  108. package/templates/src/pages/storykeep/advanced.astro +5 -4
  109. package/templates/src/pages/storykeep/branding.astro +5 -4
  110. package/templates/src/pages/storykeep/content.astro +5 -4
  111. package/templates/src/pages/storykeep/init.astro +40 -1
  112. package/templates/src/pages/storykeep/login.astro +1 -1
  113. package/templates/src/pages/storykeep.astro +5 -4
  114. package/templates/src/stores/nodes.ts +59 -88
  115. package/templates/src/stores/orphanAnalysis.ts +19 -21
  116. package/templates/src/stores/storykeep.ts +7 -0
  117. package/templates/src/types/compositorTypes.ts +6 -0
  118. package/templates/src/types/tractstack.ts +17 -0
  119. package/templates/src/utils/actions/lispLexer.ts +2 -2
  120. package/templates/src/utils/actions/preParse_Action.ts +3 -0
  121. package/templates/src/utils/api/beliefHelpers.ts +12 -36
  122. package/templates/src/utils/api/menuHelpers.ts +2 -2
  123. package/templates/src/utils/api.ts +26 -0
  124. package/templates/src/utils/compositor/TemplateNodes.ts +7 -0
  125. package/templates/src/utils/compositor/allowInsert.ts +5 -3
  126. package/templates/src/utils/compositor/nodesHelper.ts +4 -0
  127. package/templates/src/utils/compositor/processMarkdown.ts +16 -2
  128. package/templates/src/utils/compositor/reduceNodesClassNames.ts +4 -0
  129. package/templates/src/utils/compositor/templateMarkdownStyles.ts +13 -13
  130. package/templates/src/utils/compositor/typeGuards.ts +1 -0
  131. package/templates/src/utils/customHelpers.ts +38 -0
  132. package/templates/src/utils/helpers.ts +2 -2
  133. package/templates/src/utils/layout.ts +65 -144
  134. package/utils/inject-files.ts +95 -18
  135. package/templates/src/client/analytics-events.js +0 -207
  136. package/templates/src/client/belief-events.js +0 -191
  137. package/templates/src/client/sse.js +0 -613
  138. package/templates/src/components/codehooks/FeaturedContent.astro +0 -273
  139. package/templates/src/components/codehooks/FeaturedContentSetup.tsx +0 -738
  140. package/templates/src/components/compositor/preview/FeaturedContentPreview.tsx +0 -128
  141. package/templates/src/components/edit/pane/PanePanel_slug.tsx +0 -219
@@ -1,273 +0,0 @@
1
- ---
2
- import type { FullContentMapItem } from '@/types/tractstack';
3
-
4
- export interface Props {
5
- options?: {
6
- params?: {
7
- options?: string;
8
- };
9
- };
10
- contentMap: FullContentMapItem[];
11
- }
12
-
13
- const { options, contentMap } = Astro.props;
14
-
15
- // Parse component options
16
- let parsedOptions;
17
- try {
18
- parsedOptions = JSON.parse(options?.params?.options || '{}');
19
- } catch (e) {
20
- console.error('Invalid options', e);
21
- parsedOptions = {
22
- defaultMode: 'ordered',
23
- featuredId: '',
24
- storyfragmentIds: '',
25
- };
26
- }
27
-
28
- const defaultMode = parsedOptions.defaultMode || 'ordered';
29
- const featuredId = parsedOptions.featuredId || '';
30
- const storyfragmentIdsArray = parsedOptions.storyfragmentIds
31
- ? parsedOptions.storyfragmentIds.split(',')
32
- : [];
33
-
34
- // Find the featured story from the contentMap
35
- const featuredStory = contentMap.find(
36
- (item: FullContentMapItem) =>
37
- item.id === featuredId && item.type === 'StoryFragment'
38
- );
39
- // Filter and sort the included stories, excluding the featured story
40
- let includedStories = contentMap.filter(
41
- (item: FullContentMapItem) =>
42
- storyfragmentIdsArray.includes(item.id) &&
43
- item.type === 'StoryFragment' &&
44
- item.id !== featuredId
45
- );
46
-
47
- // Sort included stories based on defaultMode ('ordered' or 'recent')
48
- // The 'popular' mode will be handled on the client-side
49
- if (defaultMode === 'ordered') {
50
- includedStories.sort(
51
- (a: FullContentMapItem, b: FullContentMapItem) =>
52
- storyfragmentIdsArray.indexOf(a.id) - storyfragmentIdsArray.indexOf(b.id)
53
- );
54
- } else if (defaultMode === 'recent') {
55
- includedStories.sort((a: FullContentMapItem, b: FullContentMapItem) => {
56
- const dateA = a.changed ? new Date(a.changed).getTime() : 0;
57
- const dateB = b.changed ? new Date(b.changed).getTime() : 0;
58
- return dateB - dateA;
59
- });
60
- }
61
-
62
- // Limit to 5 stories for display
63
- const displayedStories = includedStories.slice(0, 5);
64
-
65
- // Function to format dates
66
- function formatDate(dateString: string | null): string {
67
- if (!dateString) return 'Unknown';
68
- const date = new Date(dateString);
69
- return new Intl.DateTimeFormat('en-US', {
70
- year: 'numeric',
71
- month: 'long',
72
- day: 'numeric',
73
- }).format(date);
74
- }
75
- ---
76
-
77
- <div class="mx-auto flex max-w-7xl flex-col gap-4 py-12 md:flex-row">
78
- <div class="p-4 md:w-3/5">
79
- {
80
- featuredStory ? (
81
- <a href={`/${featuredStory.slug}`} class="group block">
82
- <div class="space-y-6 p-2 group-hover:bg-slate-50">
83
- {featuredStory.thumbSrc && (
84
- <img
85
- src={featuredStory.thumbSrc}
86
- alt={featuredStory.title}
87
- class="h-auto w-full rounded-lg object-cover"
88
- />
89
- )}
90
- <h2 class="text-2xl font-bold text-black transition-colors group-hover:text-gray-900">
91
- {featuredStory.title}
92
- </h2>
93
- {featuredStory.description && (
94
- <p class="text-base text-gray-800">{featuredStory.description}</p>
95
- )}
96
- <p class="text-sm text-gray-600">
97
- {featuredStory.changed && formatDate(featuredStory.changed)}
98
- </p>
99
- </div>
100
- </a>
101
- ) : (
102
- <p class="italic text-cyan-600">No featured story selected.</p>
103
- )
104
- }
105
- </div>
106
-
107
- <div
108
- class="border-t-2 border-slate-100 p-4 md:w-2/5 md:border-l-2 md:border-t-0"
109
- >
110
- {
111
- displayedStories.length > 0 ? (
112
- <div class="space-y-4">
113
- {displayedStories.map((story: FullContentMapItem) => (
114
- <a href={`/${story.slug}`} class="group block">
115
- <div class="flex items-start space-x-4 p-1 group-hover:bg-slate-50">
116
- {story.thumbSrc && (
117
- <img
118
- src={story.thumbSrc}
119
- alt={story.title}
120
- style="width: 100px; height: auto;"
121
- class="rounded-md"
122
- />
123
- )}
124
- <div class="flex-1">
125
- <h3 class="text-lg font-bold text-black transition-colors group-hover:text-gray-900">
126
- {story.title}
127
- </h3>
128
- {story.description && (
129
- <p class="line-clamp-2 text-sm text-gray-800">
130
- {story.description}
131
- </p>
132
- )}
133
- <p class="mt-1 text-xs text-gray-600">
134
- {story.changed && formatDate(story.changed)}
135
- </p>
136
- </div>
137
- </div>
138
- </a>
139
- ))}
140
- </div>
141
- ) : (
142
- <p class="italic text-cyan-600">Check back soon for more stories.</p>
143
- )
144
- }
145
- </div>
146
- </div>
147
-
148
- <script
149
- is:inline
150
- define:vars={{
151
- includedStories,
152
- defaultMode,
153
- }}
154
- >
155
- // Client-side script to fetch and apply "hot content" analytics
156
- let hotContent = [];
157
- let hasHotContent = false;
158
- let isLoading = false;
159
- let retryCount = 0;
160
- const maxRetries = 2;
161
-
162
- // Fetches hot content data from the analytics endpoint with polling
163
- async function fetchHotContent() {
164
- if (isLoading) return;
165
- isLoading = true;
166
-
167
- try {
168
- const goBackend = window.location.protocol + '//' + window.location.host;
169
- const tenantId = window.TRACTSTACK_CONFIG?.tenantId || 'default';
170
- const response = await fetch(
171
- `${goBackend}/api/v1/analytics/content-summary`,
172
- {
173
- method: 'GET',
174
- headers: {
175
- 'Content-Type': 'application/json',
176
- 'X-Tenant-ID': tenantId,
177
- },
178
- }
179
- );
180
-
181
- if (!response.ok) {
182
- throw new Error(`HTTP error! status: ${response.status}`);
183
- }
184
-
185
- const data = await response.json();
186
-
187
- // If data is fetched, update state and re-order content
188
- if (data.hotContent && data.hotContent.length > 0) {
189
- hotContent = data.hotContent;
190
- hasHotContent = true;
191
- updateContentOrder();
192
- } else if (retryCount < maxRetries) {
193
- retryCount++;
194
- const delayMs = retryCount === 1 ? 3000 : 6000;
195
- setTimeout(fetchHotContent, delayMs);
196
- }
197
- } catch (error) {
198
- console.warn('Could not fetch hot content:', error);
199
- if (retryCount < maxRetries) {
200
- retryCount++;
201
- const delayMs = retryCount === 1 ? 3000 : 6000;
202
- setTimeout(fetchHotContent, delayMs);
203
- }
204
- } finally {
205
- isLoading = false;
206
- }
207
- }
208
-
209
- // Re-orders stories based on popularity if mode is 'popular'
210
- function updateContentOrder() {
211
- if (hasHotContent && defaultMode === 'popular') {
212
- const viewsMap = new Map(
213
- hotContent.map((item) => [item.id, item.totalEvents])
214
- );
215
-
216
- const sortedByPopular = [...includedStories].sort((a, b) => {
217
- const aViews = viewsMap.get(a.id) || 0;
218
- const bViews = viewsMap.get(b.id) || 0;
219
- // Fallback to date sort if views are equal
220
- if (bViews === aViews) {
221
- const dateA = a.changed ? new Date(a.changed).getTime() : 0;
222
- const dateB = b.changed ? new Date(b.changed).getTime() : 0;
223
- return dateB - dateA;
224
- }
225
- return bViews - aViews;
226
- });
227
-
228
- updateDisplayedStories(sortedByPopular.slice(0, 5));
229
- }
230
- }
231
-
232
- // Updates the DOM with the new list of stories
233
- function updateDisplayedStories(stories) {
234
- const rightColumn = document.querySelector('.md\\:w-2\\/5 .space-y-4');
235
- if (!rightColumn) return;
236
-
237
- rightColumn.innerHTML = stories
238
- .map((story) => {
239
- const formattedDate = story.changed
240
- ? new Intl.DateTimeFormat('en-US', {
241
- year: 'numeric',
242
- month: 'long',
243
- day: 'numeric',
244
- }).format(new Date(story.changed))
245
- : 'Unknown';
246
- const imageHtml = story.thumbSrc
247
- ? `<img src="${story.thumbSrc}" alt="${story.title}" style="width: 100px; height: auto;" class="rounded-md">`
248
- : '';
249
- const descriptionHtml = story.description
250
- ? `<p class="line-clamp-2 text-sm text-gray-800">${story.description}</p>`
251
- : '';
252
-
253
- return `
254
- <a href="/${story.slug}" class="group block">
255
- <div class="flex items-start space-x-4 p-1 group-hover:bg-slate-50">
256
- ${imageHtml}
257
- <div class="flex-1">
258
- <h3 class="text-lg font-bold text-black transition-colors group-hover:text-gray-900">
259
- ${story.title}
260
- </h3>
261
- ${descriptionHtml}
262
- <p class="mt-1 text-xs text-gray-600">${formattedDate}</p>
263
- </div>
264
- </div>
265
- </a>
266
- `;
267
- })
268
- .join('');
269
- }
270
-
271
- // Start fetching analytics on page load
272
- document.addEventListener('DOMContentLoaded', fetchHotContent);
273
- </script>