astro-tractstack 2.0.0-rc.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 (427) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +56 -0
  3. package/astro.d.ts +64 -0
  4. package/bin/create-tractstack.js +483 -0
  5. package/dist/config.js +80 -0
  6. package/dist/index.js +2129 -0
  7. package/package.json +89 -0
  8. package/templates/artpacks/kCz/captainBreakfast_1080px.webp +0 -0
  9. package/templates/artpacks/kCz/captainBreakfast_1920px.webp +0 -0
  10. package/templates/artpacks/kCz/captainBreakfast_600px.webp +0 -0
  11. package/templates/artpacks/kCz/cleanDrips_1080px.webp +0 -0
  12. package/templates/artpacks/kCz/cleanDrips_1920px.webp +0 -0
  13. package/templates/artpacks/kCz/cleanDrips_600px.webp +0 -0
  14. package/templates/artpacks/kCz/crispwaves_1080px.webp +0 -0
  15. package/templates/artpacks/kCz/crispwaves_1920px.webp +0 -0
  16. package/templates/artpacks/kCz/crispwaves_600px.webp +0 -0
  17. package/templates/artpacks/kCz/dragonSkin_1080px.webp +0 -0
  18. package/templates/artpacks/kCz/dragonSkin_1920px.webp +0 -0
  19. package/templates/artpacks/kCz/dragonSkin_600px.webp +0 -0
  20. package/templates/artpacks/kCz/dragon_1080px.webp +0 -0
  21. package/templates/artpacks/kCz/dragon_1920px.webp +0 -0
  22. package/templates/artpacks/kCz/dragon_600px.webp +0 -0
  23. package/templates/artpacks/kCz/nightcity_1080px.webp +0 -0
  24. package/templates/artpacks/kCz/nightcity_1920px.webp +0 -0
  25. package/templates/artpacks/kCz/nightcity_600px.webp +0 -0
  26. package/templates/artpacks/kCz/pattern1_1080px.webp +0 -0
  27. package/templates/artpacks/kCz/pattern1_1920px.webp +0 -0
  28. package/templates/artpacks/kCz/pattern1_600px.webp +0 -0
  29. package/templates/artpacks/kCz/pattern2_1080px.webp +0 -0
  30. package/templates/artpacks/kCz/pattern2_1920px.webp +0 -0
  31. package/templates/artpacks/kCz/pattern2_600px.webp +0 -0
  32. package/templates/artpacks/kCz/skindrips_1080px.webp +0 -0
  33. package/templates/artpacks/kCz/skindrips_1920px.webp +0 -0
  34. package/templates/artpacks/kCz/skindrips_600px.webp +0 -0
  35. package/templates/artpacks/kCz/slimetime_1080px.webp +0 -0
  36. package/templates/artpacks/kCz/slimetime_1920px.webp +0 -0
  37. package/templates/artpacks/kCz/slimetime_600px.webp +0 -0
  38. package/templates/artpacks/kCz/snake_1080px.webp +0 -0
  39. package/templates/artpacks/kCz/snake_1920px.webp +0 -0
  40. package/templates/artpacks/kCz/snake_600px.webp +0 -0
  41. package/templates/artpacks/kCz/toxicshock_1080px.webp +0 -0
  42. package/templates/artpacks/kCz/toxicshock_1920px.webp +0 -0
  43. package/templates/artpacks/kCz/toxicshock_600px.webp +0 -0
  44. package/templates/artpacks/kCz/tractstack_1080px.webp +0 -0
  45. package/templates/artpacks/kCz/tractstack_1920px.webp +0 -0
  46. package/templates/artpacks/kCz/tractstack_600px.webp +0 -0
  47. package/templates/artpacks/kCz/tripdrips_1080px.webp +0 -0
  48. package/templates/artpacks/kCz/tripdrips_1920px.webp +0 -0
  49. package/templates/artpacks/kCz/tripdrips_600px.webp +0 -0
  50. package/templates/artpacks/kCz/wavedrips_1080px.webp +0 -0
  51. package/templates/artpacks/kCz/wavedrips_1920px.webp +0 -0
  52. package/templates/artpacks/kCz/wavedrips_600px.webp +0 -0
  53. package/templates/artpacks/t8k/beach_1080px.webp +0 -0
  54. package/templates/artpacks/t8k/beach_1920px.webp +0 -0
  55. package/templates/artpacks/t8k/beach_600px.webp +0 -0
  56. package/templates/artpacks/t8k/blast_1080px.webp +0 -0
  57. package/templates/artpacks/t8k/blast_1920px.webp +0 -0
  58. package/templates/artpacks/t8k/blast_600px.webp +0 -0
  59. package/templates/artpacks/t8k/bokeh_1080px.webp +0 -0
  60. package/templates/artpacks/t8k/bokeh_1920px.webp +0 -0
  61. package/templates/artpacks/t8k/bokeh_600px.webp +0 -0
  62. package/templates/artpacks/t8k/cartoon_1080px.webp +0 -0
  63. package/templates/artpacks/t8k/cartoon_1920px.webp +0 -0
  64. package/templates/artpacks/t8k/cartoon_600px.webp +0 -0
  65. package/templates/artpacks/t8k/darkeggshell_1080px.webp +0 -0
  66. package/templates/artpacks/t8k/darkeggshell_1920px.webp +0 -0
  67. package/templates/artpacks/t8k/darkeggshell_600px.webp +0 -0
  68. package/templates/artpacks/t8k/explosion_1080px.webp +0 -0
  69. package/templates/artpacks/t8k/explosion_1920px.webp +0 -0
  70. package/templates/artpacks/t8k/explosion_600px.webp +0 -0
  71. package/templates/artpacks/t8k/floral_1080px.webp +0 -0
  72. package/templates/artpacks/t8k/floral_1920px.webp +0 -0
  73. package/templates/artpacks/t8k/floral_600px.webp +0 -0
  74. package/templates/artpacks/t8k/flower_1080px.webp +0 -0
  75. package/templates/artpacks/t8k/flower_1920px.webp +0 -0
  76. package/templates/artpacks/t8k/flower_600px.webp +0 -0
  77. package/templates/artpacks/t8k/foliage_1080px.webp +0 -0
  78. package/templates/artpacks/t8k/foliage_1920px.webp +0 -0
  79. package/templates/artpacks/t8k/foliage_600px.webp +0 -0
  80. package/templates/artpacks/t8k/mist_1080px.webp +0 -0
  81. package/templates/artpacks/t8k/mist_1920px.webp +0 -0
  82. package/templates/artpacks/t8k/mist_600px.webp +0 -0
  83. package/templates/artpacks/t8k/portal_1080px.webp +0 -0
  84. package/templates/artpacks/t8k/portal_1920px.webp +0 -0
  85. package/templates/artpacks/t8k/portal_600px.webp +0 -0
  86. package/templates/artpacks/t8k/storytime_1080px.webp +0 -0
  87. package/templates/artpacks/t8k/storytime_1920px.webp +0 -0
  88. package/templates/artpacks/t8k/storytime_600px.webp +0 -0
  89. package/templates/artpacks/t8k/tacky_1080px.webp +0 -0
  90. package/templates/artpacks/t8k/tacky_1920px.webp +0 -0
  91. package/templates/artpacks/t8k/tacky_600px.webp +0 -0
  92. package/templates/artpacks/t8k/wallpaper_1080px.webp +0 -0
  93. package/templates/artpacks/t8k/wallpaper_1920px.webp +0 -0
  94. package/templates/artpacks/t8k/wallpaper_600px.webp +0 -0
  95. package/templates/brand/favicon.ico +0 -0
  96. package/templates/brand/logo.svg +19 -0
  97. package/templates/brand/static.jpg +0 -0
  98. package/templates/brand/wordmark.svg +4 -0
  99. package/templates/css/custom.css +51 -0
  100. package/templates/css/frontend.css +3519 -0
  101. package/templates/css/storykeep.css +92872 -0
  102. package/templates/custom/minimal/CodeHook.astro +53 -0
  103. package/templates/custom/minimal/CustomRoutes.astro +46 -0
  104. package/templates/custom/with-examples/CodeHook.astro +49 -0
  105. package/templates/custom/with-examples/CustomHero.astro +13 -0
  106. package/templates/custom/with-examples/CustomRoutes.astro +39 -0
  107. package/templates/custom/with-examples/pages/Collections.astro +110 -0
  108. package/templates/env.example +8 -0
  109. package/templates/fonts/Inter-Black.woff2 +0 -0
  110. package/templates/fonts/Inter-Bold.woff2 +0 -0
  111. package/templates/fonts/Inter-Regular.woff2 +0 -0
  112. package/templates/icons/h2.svg +1 -0
  113. package/templates/icons/h3.svg +1 -0
  114. package/templates/icons/h4.svg +1 -0
  115. package/templates/icons/h5.svg +1 -0
  116. package/templates/icons/image.svg +7 -0
  117. package/templates/icons/text.svg +6 -0
  118. package/templates/socials/codepen.svg +1 -0
  119. package/templates/socials/discord.svg +1 -0
  120. package/templates/socials/facebook.svg +1 -0
  121. package/templates/socials/github.svg +1 -0
  122. package/templates/socials/instagram.svg +1 -0
  123. package/templates/socials/linkedin.svg +1 -0
  124. package/templates/socials/mail.svg +1 -0
  125. package/templates/socials/rumble.svg +1 -0
  126. package/templates/socials/tiktok.svg +1 -0
  127. package/templates/socials/twitch.svg +1 -0
  128. package/templates/socials/twitter.svg +1 -0
  129. package/templates/socials/x.svg +1 -0
  130. package/templates/socials/youtube.svg +1 -0
  131. package/templates/src/client/analytics-events.ts +213 -0
  132. package/templates/src/client/belief-events.ts +205 -0
  133. package/templates/src/client/sse.ts +667 -0
  134. package/templates/src/components/Footer.astro +246 -0
  135. package/templates/src/components/Fragment.astro +70 -0
  136. package/templates/src/components/Header.astro +458 -0
  137. package/templates/src/components/Menu.tsx +196 -0
  138. package/templates/src/components/codehooks/BunnyVideoSetup.tsx +692 -0
  139. package/templates/src/components/codehooks/BunnyVideoWrapper.astro +78 -0
  140. package/templates/src/components/codehooks/EpinetDurationSelector.tsx +1020 -0
  141. package/templates/src/components/codehooks/EpinetTableView.tsx +594 -0
  142. package/templates/src/components/codehooks/EpinetWrapper.tsx +424 -0
  143. package/templates/src/components/codehooks/FeaturedContent.astro +273 -0
  144. package/templates/src/components/codehooks/FeaturedContentSetup.tsx +738 -0
  145. package/templates/src/components/codehooks/ListContent.astro +460 -0
  146. package/templates/src/components/codehooks/ListContentSetup.tsx +649 -0
  147. package/templates/src/components/codehooks/SankeyDiagram.tsx +359 -0
  148. package/templates/src/components/compositor/Compositor.tsx +144 -0
  149. package/templates/src/components/compositor/Node.tsx +415 -0
  150. package/templates/src/components/compositor/NodeWithGuid.tsx +25 -0
  151. package/templates/src/components/compositor/PanelVisibilityWrapper.tsx +87 -0
  152. package/templates/src/components/compositor/elements/Belief.tsx +148 -0
  153. package/templates/src/components/compositor/elements/BgImage.tsx +118 -0
  154. package/templates/src/components/compositor/elements/BgVisualBreak.tsx +102 -0
  155. package/templates/src/components/compositor/elements/BunnyVideo.tsx +63 -0
  156. package/templates/src/components/compositor/elements/IdentifyAs.tsx +66 -0
  157. package/templates/src/components/compositor/elements/PlayButton.tsx +19 -0
  158. package/templates/src/components/compositor/elements/SignUp.tsx +179 -0
  159. package/templates/src/components/compositor/elements/Svg.tsx +33 -0
  160. package/templates/src/components/compositor/elements/ToggleBelief.tsx +36 -0
  161. package/templates/src/components/compositor/elements/YouTubeWrapper.tsx +33 -0
  162. package/templates/src/components/compositor/nodes/BgPaneWrapper.tsx +35 -0
  163. package/templates/src/components/compositor/nodes/GhostInsertBlock.tsx +189 -0
  164. package/templates/src/components/compositor/nodes/Markdown.tsx +179 -0
  165. package/templates/src/components/compositor/nodes/Pane.tsx +277 -0
  166. package/templates/src/components/compositor/nodes/Pane_eraser.tsx +69 -0
  167. package/templates/src/components/compositor/nodes/Pane_layout.tsx +77 -0
  168. package/templates/src/components/compositor/nodes/RenderChildren.tsx +19 -0
  169. package/templates/src/components/compositor/nodes/StoryFragment.tsx +35 -0
  170. package/templates/src/components/compositor/nodes/TagElement.tsx +14 -0
  171. package/templates/src/components/compositor/nodes/Widget.tsx +115 -0
  172. package/templates/src/components/compositor/nodes/tagElements/NodeA.tsx +4 -0
  173. package/templates/src/components/compositor/nodes/tagElements/NodeA_eraser.tsx +26 -0
  174. package/templates/src/components/compositor/nodes/tagElements/NodeAnchorComponent.tsx +248 -0
  175. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag.tsx +684 -0
  176. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_eraser.tsx +62 -0
  177. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_insert.tsx +120 -0
  178. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_settings.tsx +62 -0
  179. package/templates/src/components/compositor/nodes/tagElements/NodeButton.tsx +5 -0
  180. package/templates/src/components/compositor/nodes/tagElements/NodeButton_eraser.tsx +26 -0
  181. package/templates/src/components/compositor/nodes/tagElements/NodeImg.tsx +28 -0
  182. package/templates/src/components/compositor/nodes/tagElements/NodeText.tsx +18 -0
  183. package/templates/src/components/compositor/nodes/tagElements/TabIndicator.tsx +51 -0
  184. package/templates/src/components/compositor/preview/FeaturedContentPreview.tsx +128 -0
  185. package/templates/src/components/compositor/preview/ListContentPreview.tsx +213 -0
  186. package/templates/src/components/compositor/preview/OgImagePreview.tsx +223 -0
  187. package/templates/src/components/compositor/preview/PaneSnapshotGenerator.tsx +199 -0
  188. package/templates/src/components/compositor/preview/PanesPreviewGenerator.tsx +123 -0
  189. package/templates/src/components/compositor/preview/VisualBreakPreview.tsx +154 -0
  190. package/templates/src/components/edit/Header.tsx +181 -0
  191. package/templates/src/components/edit/PanelSwitch.tsx +446 -0
  192. package/templates/src/components/edit/SettingsPanel.tsx +70 -0
  193. package/templates/src/components/edit/ToolBar.tsx +101 -0
  194. package/templates/src/components/edit/ToolMode.tsx +121 -0
  195. package/templates/src/components/edit/context/ContextPaneConfig.tsx +91 -0
  196. package/templates/src/components/edit/context/ContextPaneConfig_slug.tsx +174 -0
  197. package/templates/src/components/edit/context/ContextPaneConfig_title.tsx +186 -0
  198. package/templates/src/components/edit/pane/AddPanePanel.tsx +136 -0
  199. package/templates/src/components/edit/pane/AddPanePanel_break.tsx +470 -0
  200. package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +264 -0
  201. package/templates/src/components/edit/pane/AddPanePanel_new.tsx +623 -0
  202. package/templates/src/components/edit/pane/AddPanePanel_newAICopy.tsx +107 -0
  203. package/templates/src/components/edit/pane/AddPanePanel_newAICopy_modal.tsx +217 -0
  204. package/templates/src/components/edit/pane/AddPanePanel_newCopyMode.tsx +109 -0
  205. package/templates/src/components/edit/pane/AddPanePanel_newCustomCopy.tsx +39 -0
  206. package/templates/src/components/edit/pane/AddPanePanel_reuse.tsx +445 -0
  207. package/templates/src/components/edit/pane/ConfigPanePanel.tsx +245 -0
  208. package/templates/src/components/edit/pane/PageGen.tsx +485 -0
  209. package/templates/src/components/edit/pane/PageGenSelector.tsx +238 -0
  210. package/templates/src/components/edit/pane/PageGenSpecial.tsx +362 -0
  211. package/templates/src/components/edit/pane/PageGen_preview.tsx +495 -0
  212. package/templates/src/components/edit/pane/PanePanel_impression.tsx +258 -0
  213. package/templates/src/components/edit/pane/PanePanel_path.tsx +268 -0
  214. package/templates/src/components/edit/pane/PanePanel_slug.tsx +219 -0
  215. package/templates/src/components/edit/pane/PanePanel_title.tsx +142 -0
  216. package/templates/src/components/edit/panels/StyleBreakPanel.tsx +182 -0
  217. package/templates/src/components/edit/panels/StyleCodeHookPanel.tsx +439 -0
  218. package/templates/src/components/edit/panels/StyleElementPanel.tsx +177 -0
  219. package/templates/src/components/edit/panels/StyleElementPanel_add.tsx +349 -0
  220. package/templates/src/components/edit/panels/StyleElementPanel_remove.tsx +159 -0
  221. package/templates/src/components/edit/panels/StyleElementPanel_update.tsx +320 -0
  222. package/templates/src/components/edit/panels/StyleImagePanel.tsx +460 -0
  223. package/templates/src/components/edit/panels/StyleImagePanel_add.tsx +296 -0
  224. package/templates/src/components/edit/panels/StyleImagePanel_remove.tsx +153 -0
  225. package/templates/src/components/edit/panels/StyleImagePanel_update.tsx +312 -0
  226. package/templates/src/components/edit/panels/StyleLiElementPanel.tsx +273 -0
  227. package/templates/src/components/edit/panels/StyleLiElementPanel_add.tsx +301 -0
  228. package/templates/src/components/edit/panels/StyleLiElementPanel_remove.tsx +132 -0
  229. package/templates/src/components/edit/panels/StyleLiElementPanel_update.tsx +313 -0
  230. package/templates/src/components/edit/panels/StyleLinkPanel.tsx +346 -0
  231. package/templates/src/components/edit/panels/StyleLinkPanel_add.tsx +265 -0
  232. package/templates/src/components/edit/panels/StyleLinkPanel_config.tsx +240 -0
  233. package/templates/src/components/edit/panels/StyleLinkPanel_remove.tsx +94 -0
  234. package/templates/src/components/edit/panels/StyleLinkPanel_update.tsx +110 -0
  235. package/templates/src/components/edit/panels/StyleParentPanel.tsx +263 -0
  236. package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +275 -0
  237. package/templates/src/components/edit/panels/StyleParentPanel_deleteLayer.tsx +112 -0
  238. package/templates/src/components/edit/panels/StyleParentPanel_remove.tsx +87 -0
  239. package/templates/src/components/edit/panels/StyleParentPanel_update.tsx +141 -0
  240. package/templates/src/components/edit/panels/StyleWidgetPanel.tsx +428 -0
  241. package/templates/src/components/edit/panels/StyleWidgetPanel_add.tsx +292 -0
  242. package/templates/src/components/edit/panels/StyleWidgetPanel_config.tsx +190 -0
  243. package/templates/src/components/edit/panels/StyleWidgetPanel_remove.tsx +152 -0
  244. package/templates/src/components/edit/panels/StyleWidgetPanel_update.tsx +308 -0
  245. package/templates/src/components/edit/state/SaveModal.tsx +811 -0
  246. package/templates/src/components/edit/state/StylesMemory.tsx +310 -0
  247. package/templates/src/components/edit/storyfragment/StoryFragmentConfigPanel.tsx +289 -0
  248. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_menu.tsx +320 -0
  249. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_og.tsx +888 -0
  250. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_slug.tsx +269 -0
  251. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_title.tsx +190 -0
  252. package/templates/src/components/edit/widgets/BeliefWidget.tsx +183 -0
  253. package/templates/src/components/edit/widgets/BunnyWidget.tsx +134 -0
  254. package/templates/src/components/edit/widgets/IdentifyAsWidget.tsx +193 -0
  255. package/templates/src/components/edit/widgets/SignupWidget.tsx +177 -0
  256. package/templates/src/components/edit/widgets/ToggleWidget.tsx +152 -0
  257. package/templates/src/components/edit/widgets/YouTubeWidget.tsx +65 -0
  258. package/templates/src/components/fields/ActionBuilderTimeSelector.tsx +353 -0
  259. package/templates/src/components/fields/ArtpackImage.tsx +480 -0
  260. package/templates/src/components/fields/BackgroundImage.tsx +530 -0
  261. package/templates/src/components/fields/BackgroundImageWrapper.tsx +192 -0
  262. package/templates/src/components/fields/BooleanParam.tsx +67 -0
  263. package/templates/src/components/fields/BunnyMomentSelector.tsx +56 -0
  264. package/templates/src/components/fields/ColorPickerCombo.tsx +284 -0
  265. package/templates/src/components/fields/ImageUpload.tsx +405 -0
  266. package/templates/src/components/fields/MultiParam.tsx +75 -0
  267. package/templates/src/components/fields/PaneBreakCollectionSelector.tsx +97 -0
  268. package/templates/src/components/fields/PaneBreakShapeSelector.tsx +134 -0
  269. package/templates/src/components/fields/SelectedTailwindClass.tsx +44 -0
  270. package/templates/src/components/fields/SingleParam.tsx +73 -0
  271. package/templates/src/components/fields/ViewportComboBox.tsx +252 -0
  272. package/templates/src/components/form/ActionBuilderField.tsx +282 -0
  273. package/templates/src/components/form/ActionBuilderSlugSelector.tsx +182 -0
  274. package/templates/src/components/form/BooleanToggle.tsx +94 -0
  275. package/templates/src/components/form/ColorPicker.tsx +153 -0
  276. package/templates/src/components/form/DateTimeInput.tsx +638 -0
  277. package/templates/src/components/form/EnumSelect.tsx +88 -0
  278. package/templates/src/components/form/FileUpload.tsx +465 -0
  279. package/templates/src/components/form/MagicPathBuilder.tsx +546 -0
  280. package/templates/src/components/form/NumberInput.tsx +101 -0
  281. package/templates/src/components/form/ParagraphArrayInput.tsx +207 -0
  282. package/templates/src/components/form/StringArrayInput.tsx +163 -0
  283. package/templates/src/components/form/StringInput.tsx +88 -0
  284. package/templates/src/components/form/UnsavedChangesBar.tsx +295 -0
  285. package/templates/src/components/form/advanced/APIConfigSection.tsx +69 -0
  286. package/templates/src/components/form/advanced/AuthConfigSection.tsx +97 -0
  287. package/templates/src/components/form/brand/BrandAssetsSection.tsx +93 -0
  288. package/templates/src/components/form/brand/BrandColorsSection.tsx +201 -0
  289. package/templates/src/components/form/brand/SEOSection.tsx +101 -0
  290. package/templates/src/components/form/brand/SiteConfigSection.tsx +61 -0
  291. package/templates/src/components/form/brand/SocialLinksSection.tsx +393 -0
  292. package/templates/src/components/profile/ProfileConsent.tsx +65 -0
  293. package/templates/src/components/profile/ProfileCreate.tsx +462 -0
  294. package/templates/src/components/profile/ProfileEdit.tsx +409 -0
  295. package/templates/src/components/profile/ProfileSwitch.tsx +255 -0
  296. package/templates/src/components/profile/ProfileUnlock.tsx +221 -0
  297. package/templates/src/components/storykeep/Dashboard.tsx +160 -0
  298. package/templates/src/components/storykeep/Dashboard_Activity.tsx +56 -0
  299. package/templates/src/components/storykeep/Dashboard_Advanced.tsx +165 -0
  300. package/templates/src/components/storykeep/Dashboard_Analytics.tsx +451 -0
  301. package/templates/src/components/storykeep/Dashboard_Branding.tsx +95 -0
  302. package/templates/src/components/storykeep/Dashboard_Content.tsx +191 -0
  303. package/templates/src/components/storykeep/controls/UsageCell.tsx +71 -0
  304. package/templates/src/components/storykeep/controls/content/BeliefForm.tsx +378 -0
  305. package/templates/src/components/storykeep/controls/content/BeliefTable.tsx +329 -0
  306. package/templates/src/components/storykeep/controls/content/ContentBrowser.tsx +385 -0
  307. package/templates/src/components/storykeep/controls/content/ContentSummary.tsx +149 -0
  308. package/templates/src/components/storykeep/controls/content/KnownResourceForm.tsx +397 -0
  309. package/templates/src/components/storykeep/controls/content/KnownResourceTable.tsx +260 -0
  310. package/templates/src/components/storykeep/controls/content/ManageContent.tsx +439 -0
  311. package/templates/src/components/storykeep/controls/content/MenuForm.tsx +239 -0
  312. package/templates/src/components/storykeep/controls/content/MenuTable.tsx +332 -0
  313. package/templates/src/components/storykeep/controls/content/ResourceBulkIngest.tsx +724 -0
  314. package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +355 -0
  315. package/templates/src/components/storykeep/controls/content/ResourceTable.tsx +222 -0
  316. package/templates/src/components/storykeep/controls/content/StoryFragmentTable.tsx +482 -0
  317. package/templates/src/components/storykeep/state/BrandingWrapper.tsx +42 -0
  318. package/templates/src/components/storykeep/state/FetchAnalytics.tsx +350 -0
  319. package/templates/src/components/storykeep/widgets/ResponsiveLine.tsx +319 -0
  320. package/templates/src/components/storykeep/widgets/Wizard.tsx +278 -0
  321. package/templates/src/components/tenant/RegistrationForm.tsx +447 -0
  322. package/templates/src/components/widgets/BunnyVideoHero.astro +775 -0
  323. package/templates/src/components/widgets/Impression.tsx +102 -0
  324. package/templates/src/components/widgets/ImpressionWrapper.tsx +214 -0
  325. package/templates/src/constants/beliefs.ts +61 -0
  326. package/templates/src/constants/brandThemes.ts +133 -0
  327. package/templates/src/constants/prompts.json +55 -0
  328. package/templates/src/constants/shapes.ts +556 -0
  329. package/templates/src/constants/stopWords.ts +116 -0
  330. package/templates/src/constants/tailwindColors.json +344 -0
  331. package/templates/src/constants.ts +274 -0
  332. package/templates/src/hooks/useFormState.ts +203 -0
  333. package/templates/src/layouts/Layout.astro +290 -0
  334. package/templates/src/lib/session.ts +126 -0
  335. package/templates/src/lib/storyData.ts +56 -0
  336. package/templates/src/middleware.ts +52 -0
  337. package/templates/src/pages/404.astro +54 -0
  338. package/templates/src/pages/[...slug]/edit.astro +216 -0
  339. package/templates/src/pages/[...slug].astro +148 -0
  340. package/templates/src/pages/api/auth/decode.ts +101 -0
  341. package/templates/src/pages/api/auth/login.ts +122 -0
  342. package/templates/src/pages/api/auth/logout.ts +37 -0
  343. package/templates/src/pages/api/auth/profile.ts +76 -0
  344. package/templates/src/pages/api/orphan-analysis.ts +106 -0
  345. package/templates/src/pages/api/tailwind.ts +116 -0
  346. package/templates/src/pages/collections/[param1].astro +65 -0
  347. package/templates/src/pages/context/[...contextSlug]/edit.astro +207 -0
  348. package/templates/src/pages/context/[...contextSlug].astro +161 -0
  349. package/templates/src/pages/llms.txt.ts +122 -0
  350. package/templates/src/pages/maint.astro +183 -0
  351. package/templates/src/pages/media/[...slug].astro +67 -0
  352. package/templates/src/pages/robots.txt.ts +36 -0
  353. package/templates/src/pages/sandbox/activate.astro +258 -0
  354. package/templates/src/pages/sandbox/register.astro +44 -0
  355. package/templates/src/pages/sandbox/success.astro +179 -0
  356. package/templates/src/pages/sitemap.xml.ts +119 -0
  357. package/templates/src/pages/storykeep/advanced.astro +69 -0
  358. package/templates/src/pages/storykeep/branding.astro +57 -0
  359. package/templates/src/pages/storykeep/content.astro +71 -0
  360. package/templates/src/pages/storykeep/init.astro +36 -0
  361. package/templates/src/pages/storykeep/login.astro +266 -0
  362. package/templates/src/pages/storykeep/logout.astro +84 -0
  363. package/templates/src/pages/storykeep/profile.astro +98 -0
  364. package/templates/src/pages/storykeep.astro +81 -0
  365. package/templates/src/stores/analytics.ts +171 -0
  366. package/templates/src/stores/backend.ts +16 -0
  367. package/templates/src/stores/navigation.ts +149 -0
  368. package/templates/src/stores/nodes.ts +2390 -0
  369. package/templates/src/stores/nodesHistory.ts +85 -0
  370. package/templates/src/stores/notificationSystem.ts +41 -0
  371. package/templates/src/stores/orphanAnalysis.ts +409 -0
  372. package/templates/src/stores/storykeep.ts +247 -0
  373. package/templates/src/types/astro.ts +86 -0
  374. package/templates/src/types/compositorTypes.ts +456 -0
  375. package/templates/src/types/formTypes.ts +281 -0
  376. package/templates/src/types/multiTenant.ts +77 -0
  377. package/templates/src/types/nodeProps.ts +66 -0
  378. package/templates/src/types/tractstack.ts +445 -0
  379. package/templates/src/utils/aai/getTitleSlug.ts +72 -0
  380. package/templates/src/utils/actions/actionButton.ts +101 -0
  381. package/templates/src/utils/actions/lispLexer.ts +57 -0
  382. package/templates/src/utils/actions/preParse_Action.ts +85 -0
  383. package/templates/src/utils/actions/preParse_Bunny.ts +50 -0
  384. package/templates/src/utils/actions/preParse_Clicked.ts +87 -0
  385. package/templates/src/utils/actions/preParse_Impression.ts +71 -0
  386. package/templates/src/utils/api/advancedConfig.ts +66 -0
  387. package/templates/src/utils/api/advancedHelpers.ts +134 -0
  388. package/templates/src/utils/api/beliefConfig.ts +87 -0
  389. package/templates/src/utils/api/beliefHelpers.ts +196 -0
  390. package/templates/src/utils/api/brandConfig.ts +126 -0
  391. package/templates/src/utils/api/brandHelpers.ts +155 -0
  392. package/templates/src/utils/api/fileHelpers.ts +306 -0
  393. package/templates/src/utils/api/menuConfig.ts +57 -0
  394. package/templates/src/utils/api/menuHelpers.ts +156 -0
  395. package/templates/src/utils/api/resourceConfig.ts +158 -0
  396. package/templates/src/utils/api/resourceHelpers.ts +72 -0
  397. package/templates/src/utils/api/tenantConfig.ts +97 -0
  398. package/templates/src/utils/api/tenantHelpers.ts +172 -0
  399. package/templates/src/utils/api.ts +183 -0
  400. package/templates/src/utils/auth.ts +150 -0
  401. package/templates/src/utils/backend.ts +243 -0
  402. package/templates/src/utils/compositor/TemplateMarkdowns.ts +118 -0
  403. package/templates/src/utils/compositor/TemplateNodes.ts +138 -0
  404. package/templates/src/utils/compositor/TemplatePanes.ts +100 -0
  405. package/templates/src/utils/compositor/allowInsert.ts +100 -0
  406. package/templates/src/utils/compositor/domHelpers.ts +37 -0
  407. package/templates/src/utils/compositor/handleClickEvent.ts +131 -0
  408. package/templates/src/utils/compositor/nodesHelper.ts +491 -0
  409. package/templates/src/utils/compositor/nodesMarkdownGenerator.ts +292 -0
  410. package/templates/src/utils/compositor/processMarkdown.ts +431 -0
  411. package/templates/src/utils/compositor/reduceNodesClassNames.ts +192 -0
  412. package/templates/src/utils/compositor/tailwindClasses.ts +1795 -0
  413. package/templates/src/utils/compositor/tailwindColors.ts +227 -0
  414. package/templates/src/utils/compositor/templateMarkdownStyles.ts +1265 -0
  415. package/templates/src/utils/compositor/typeGuards.ts +193 -0
  416. package/templates/src/utils/etl/extractor.ts +119 -0
  417. package/templates/src/utils/etl/index.ts +88 -0
  418. package/templates/src/utils/etl/loader.ts +36 -0
  419. package/templates/src/utils/etl/transformer.ts +286 -0
  420. package/templates/src/utils/helpers.ts +435 -0
  421. package/templates/src/utils/layout.ts +209 -0
  422. package/templates/src/utils/profileStorage.ts +306 -0
  423. package/templates/src/utils/useInterval.ts +27 -0
  424. package/templates/tailwind.config.cjs +169 -0
  425. package/utils/create-resolver.ts +10 -0
  426. package/utils/inject-files.ts +2140 -0
  427. package/utils/validate-config.ts +43 -0
@@ -0,0 +1,451 @@
1
+ import { useState, useCallback, useMemo, Component } from 'react';
2
+ import type { ReactNode } from 'react';
3
+ import { useStore } from '@nanostores/react';
4
+ import { epinetCustomFilters } from '@/stores/analytics';
5
+ import { classNames } from '@/utils/helpers';
6
+ import { ArrowDownTrayIcon } from '@heroicons/react/24/outline';
7
+ import DashboardActivity from './Dashboard_Activity';
8
+ import SankeyDiagram from '../codehooks/SankeyDiagram';
9
+ import EpinetDurationSelector from '../codehooks/EpinetDurationSelector';
10
+ import FetchAnalytics from './state/FetchAnalytics';
11
+ import type { FullContentMapItem } from '@/types/tractstack';
12
+
13
+ interface StoryKeepDashboardAnalyticsProps {
14
+ fullContentMap: FullContentMapItem[];
15
+ initializing?: boolean;
16
+ }
17
+
18
+ // Helper component for error boundary
19
+ class ErrorBoundary extends Component<
20
+ { children: ReactNode; fallback: ReactNode },
21
+ { hasError: boolean }
22
+ > {
23
+ constructor(props: any) {
24
+ super(props);
25
+ this.state = { hasError: false };
26
+ }
27
+
28
+ static getDerivedStateFromError() {
29
+ return { hasError: true };
30
+ }
31
+
32
+ render() {
33
+ if (this.state.hasError) {
34
+ return this.props.fallback;
35
+ }
36
+ return this.props.children;
37
+ }
38
+ }
39
+
40
+ const DurationSelector = ({
41
+ currentDurationHelper,
42
+ setStandardDuration,
43
+ }: {
44
+ currentDurationHelper: 'daily' | 'weekly' | 'monthly' | 'custom';
45
+ setStandardDuration: (duration: 'daily' | 'weekly' | 'monthly') => void;
46
+ }) => {
47
+ const periods = [
48
+ { value: 'daily', label: '24 Hours' },
49
+ { value: 'weekly', label: '7 Days' },
50
+ { value: 'monthly', label: '28 Days' },
51
+ ] as const;
52
+
53
+ return (
54
+ <div className="mb-6 flex flex-wrap items-center gap-2">
55
+ <span className="text-sm font-bold text-gray-900">Time Range:</span>
56
+ {periods.map((period) => (
57
+ <button
58
+ key={period.value}
59
+ onClick={() => setStandardDuration(period.value)}
60
+ className={classNames(
61
+ 'rounded px-3 py-1 text-sm transition-colors',
62
+ currentDurationHelper === period.value
63
+ ? 'bg-cyan-600 font-bold text-white shadow-sm'
64
+ : 'bg-gray-100 text-gray-700 hover:bg-cyan-100 hover:text-cyan-800'
65
+ )}
66
+ >
67
+ {period.label}
68
+ </button>
69
+ ))}
70
+ {currentDurationHelper === 'custom' && (
71
+ <span className="px-3 py-1 text-sm italic text-gray-600">
72
+ Custom range active
73
+ </span>
74
+ )}
75
+ </div>
76
+ );
77
+ };
78
+
79
+ export default function StoryKeepDashboard_Analytics({
80
+ fullContentMap,
81
+ initializing = false,
82
+ }: StoryKeepDashboardAnalyticsProps) {
83
+ const $epinetCustomFilters = useStore(epinetCustomFilters);
84
+ const [isDownloading, setIsDownloading] = useState(false);
85
+
86
+ // Analytics data state
87
+ const [analytics, setAnalytics] = useState<{
88
+ dashboard: any;
89
+ leads: any;
90
+ epinet: any;
91
+ userCounts: any[];
92
+ hourlyNodeActivity: any;
93
+ isLoading: boolean;
94
+ status: string;
95
+ error: string | null;
96
+ }>({
97
+ dashboard: null,
98
+ leads: null,
99
+ epinet: null,
100
+ userCounts: [],
101
+ hourlyNodeActivity: {},
102
+ isLoading: false,
103
+ status: 'idle',
104
+ error: null,
105
+ });
106
+
107
+ // Duration helper for UI
108
+ const currentDurationHelper = useMemo(():
109
+ | 'daily'
110
+ | 'weekly'
111
+ | 'monthly'
112
+ | 'custom' => {
113
+ const { startTimeUTC, endTimeUTC } = $epinetCustomFilters;
114
+
115
+ if (startTimeUTC && endTimeUTC) {
116
+ const startTime = new Date(startTimeUTC);
117
+ const endTime = new Date(endTimeUTC);
118
+ const diffMs = endTime.getTime() - startTime.getTime();
119
+ const diffHours = diffMs / (1000 * 60 * 60);
120
+
121
+ if (Math.abs(diffHours - 24) <= 1) return 'daily';
122
+ if (Math.abs(diffHours - 168) <= 1) return 'weekly';
123
+ if (Math.abs(diffHours - 672) <= 1) return 'monthly';
124
+ return 'custom';
125
+ }
126
+
127
+ return 'monthly';
128
+ }, [$epinetCustomFilters.startTimeUTC, $epinetCustomFilters.endTimeUTC]);
129
+
130
+ // Standard duration setter helper
131
+ const setStandardDuration = useCallback(
132
+ (newValue: 'daily' | 'weekly' | 'monthly') => {
133
+ const nowUTC = new Date();
134
+ const hoursBack: number =
135
+ newValue === 'daily' ? 24 : newValue === 'weekly' ? 168 : 672;
136
+ const startTimeUTC = new Date(
137
+ nowUTC.getTime() - hoursBack * 60 * 60 * 1000
138
+ );
139
+
140
+ epinetCustomFilters.set(window.TRACTSTACK_CONFIG?.tenantId || 'default', {
141
+ ...$epinetCustomFilters,
142
+ enabled: true,
143
+ startTimeUTC: startTimeUTC.toISOString(),
144
+ endTimeUTC: nowUTC.toISOString(),
145
+ });
146
+ },
147
+ [$epinetCustomFilters]
148
+ );
149
+
150
+ // Download leads CSV
151
+ const downloadLeadsCSV = async () => {
152
+ if (isDownloading) return;
153
+ try {
154
+ setIsDownloading(true);
155
+
156
+ const config = window.TRACTSTACK_CONFIG;
157
+ const response = await fetch(
158
+ `${config?.backendUrl || ''}/api/v1/admin/leads/download`,
159
+ {
160
+ method: 'GET',
161
+ headers: {
162
+ 'X-Tenant-ID': config?.tenantId || 'default',
163
+ },
164
+ credentials: 'include', // Include cookies for auth
165
+ }
166
+ );
167
+
168
+ if (!response.ok) {
169
+ throw new Error('Download failed');
170
+ }
171
+
172
+ const blob = await response.blob();
173
+ const url = window.URL.createObjectURL(blob);
174
+ const a = document.createElement('a');
175
+ a.href = url;
176
+ a.download = 'leads.csv';
177
+ document.body.appendChild(a);
178
+ a.click();
179
+ window.URL.revokeObjectURL(url);
180
+ document.body.removeChild(a);
181
+ } catch (error) {
182
+ console.error('Error downloading leads:', error);
183
+ alert('Failed to download leads. Please try again.');
184
+ } finally {
185
+ setIsDownloading(false);
186
+ }
187
+ };
188
+
189
+ // Helper function for number formatting
190
+ const formatNumber = (num: number) => {
191
+ return new Intl.NumberFormat().format(num);
192
+ };
193
+
194
+ // Prepare stats data for display
195
+ const stats = [
196
+ {
197
+ name: 'Past 24 Hours',
198
+ events: analytics.dashboard?.stats?.daily ?? 0,
199
+ period: '24h',
200
+ },
201
+ {
202
+ name: 'Past 7 Days',
203
+ events: analytics.dashboard?.stats?.weekly ?? 0,
204
+ period: '7d',
205
+ },
206
+ {
207
+ name: 'Past 28 Days',
208
+ events: analytics.dashboard?.stats?.monthly ?? 0,
209
+ period: '28d',
210
+ },
211
+ ];
212
+
213
+ if (initializing) return null;
214
+
215
+ return (
216
+ <div className="w-full">
217
+ <FetchAnalytics onAnalyticsUpdate={setAnalytics} />
218
+
219
+ <div className="mb-6">
220
+ <h2 className="font-action text-2xl font-bold text-gray-900">
221
+ Analytics Dashboard
222
+ {(analytics.isLoading || analytics.status === 'loading') && (
223
+ <span className="ml-2 text-sm font-normal text-gray-500">
224
+ (Loading data...)
225
+ </span>
226
+ )}
227
+ </h2>
228
+ <p className="mt-1 text-sm text-gray-600">
229
+ Comprehensive analytics for your StoryKeep content and user engagement
230
+ </p>
231
+ </div>
232
+
233
+ {analytics.error && (
234
+ <div className="mb-6 rounded-lg bg-red-50 p-4 text-red-800">
235
+ <h4 className="font-bold">Analytics Error</h4>
236
+ <p>{analytics.error}</p>
237
+ </div>
238
+ )}
239
+
240
+ {/* Stats Cards Grid */}
241
+ <div className="mb-6 grid grid-cols-1 gap-4 md:grid-cols-3">
242
+ {stats.map((item) => {
243
+ const period = item.period;
244
+ let firstTimeValue = 0,
245
+ returningValue = 0;
246
+ switch (period) {
247
+ case '24h':
248
+ firstTimeValue = analytics.dashboard?.dailyAnonymous ?? 0;
249
+ returningValue = analytics.dashboard?.dailyKnown ?? 0;
250
+ break;
251
+ case '7d':
252
+ firstTimeValue = analytics.dashboard?.weeklyAnonymous ?? 0;
253
+ returningValue = analytics.dashboard?.weeklyKnown ?? 0;
254
+ break;
255
+ case '28d':
256
+ firstTimeValue = analytics.dashboard?.monthlyAnonymous ?? 0;
257
+ returningValue = analytics.dashboard?.monthlyKnown ?? 0;
258
+ break;
259
+ }
260
+
261
+ return (
262
+ <div
263
+ key={item.period}
264
+ className="rounded-lg border border-gray-100 bg-white px-4 py-3 shadow-sm transition-colors hover:border-cyan-100"
265
+ >
266
+ <dt className="text-sm font-bold text-gray-800">{item.name}</dt>
267
+
268
+ <dd className="mt-2">
269
+ <div className="flex items-end justify-between">
270
+ <div className="flex-1">
271
+ <div className="text-sm text-gray-600">Events</div>
272
+ <div className="text-2xl font-bold tracking-tight text-cyan-700">
273
+ {item.events === 0 ? '-' : formatNumber(item.events)}
274
+ </div>
275
+ </div>
276
+ </div>
277
+ </dd>
278
+
279
+ <hr className="my-3.5 border-gray-100" />
280
+
281
+ <dd>
282
+ <div className="flex items-end justify-between">
283
+ <div className="flex-1">
284
+ <div className="text-sm text-gray-600">
285
+ Anonymous Visitors
286
+ </div>
287
+ <div className="text-2xl font-bold tracking-tight text-cyan-700">
288
+ {firstTimeValue === 0
289
+ ? '-'
290
+ : formatNumber(firstTimeValue)}
291
+ </div>
292
+ </div>
293
+ <div className="flex-1 text-right">
294
+ <div className="text-sm text-gray-600">Known Leads</div>
295
+ <div className="text-2xl font-bold tracking-tight text-cyan-700">
296
+ {returningValue === 0
297
+ ? '-'
298
+ : formatNumber(returningValue)}
299
+ </div>
300
+ </div>
301
+ </div>
302
+ </dd>
303
+ </div>
304
+ );
305
+ })}
306
+
307
+ {/* Total Leads Card */}
308
+ <div className="rounded-lg border border-gray-100 bg-white px-4 py-3 shadow-sm transition-colors hover:border-cyan-100 md:col-span-3">
309
+ <div className="flex items-center justify-between">
310
+ <dt className="text-sm font-bold text-gray-800">Total Leads</dt>
311
+ <div className="flex items-center gap-2">
312
+ <button
313
+ onClick={downloadLeadsCSV}
314
+ disabled={isDownloading}
315
+ className="inline-flex items-center gap-1 rounded bg-cyan-600 px-2 py-1 text-xs font-bold text-white hover:bg-cyan-700 disabled:opacity-50"
316
+ >
317
+ <ArrowDownTrayIcon className="h-3 w-3" />
318
+ {isDownloading ? 'Downloading...' : 'Download'}
319
+ </button>
320
+ </div>
321
+ </div>
322
+ <dd className="mt-2">
323
+ <div className="text-2xl font-bold tracking-tight text-cyan-700">
324
+ {!analytics.leads?.totalLeads || analytics.leads?.totalLeads === 0
325
+ ? '-'
326
+ : formatNumber(analytics.leads?.totalLeads)}
327
+ </div>
328
+ <div className="mt-1 text-sm text-gray-600">
329
+ Registered leads (emails collected)
330
+ </div>
331
+ </dd>
332
+ </div>
333
+ </div>
334
+
335
+ {/* Duration Selector */}
336
+ <DurationSelector
337
+ currentDurationHelper={currentDurationHelper}
338
+ setStandardDuration={setStandardDuration}
339
+ />
340
+
341
+ {/* Dashboard Activity Chart */}
342
+ <div className="mb-6 overflow-hidden">
343
+ <h3 className="mb-4 text-lg font-bold text-gray-900">
344
+ Activity Over Time
345
+ </h3>
346
+ {analytics.dashboard &&
347
+ analytics.dashboard.line &&
348
+ analytics.dashboard.line.length > 0 ? (
349
+ <DashboardActivity data={analytics.dashboard.line} />
350
+ ) : (
351
+ <div className="flex h-64 w-full items-center justify-center rounded-lg bg-gray-100">
352
+ <div className="text-center text-gray-500">
353
+ {analytics.isLoading || analytics.status === 'loading' ? (
354
+ <div className="flex flex-col items-center">
355
+ <div className="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-blue-600 border-r-transparent"></div>
356
+ <p className="mt-4">Loading activity data...</p>
357
+ </div>
358
+ ) : (
359
+ 'No activity data available yet'
360
+ )}
361
+ </div>
362
+ </div>
363
+ )}
364
+ </div>
365
+
366
+ {/* Separator */}
367
+ <div className="my-8">
368
+ <hr className="border-gray-200" />
369
+ </div>
370
+
371
+ {/* User Journey Section */}
372
+ <div className="mb-6 overflow-hidden">
373
+ <h3 className="mb-4 text-lg font-bold text-gray-900">
374
+ User Journey Analytics
375
+ </h3>
376
+
377
+ {analytics.isLoading || analytics.status === 'loading' ? (
378
+ <div className="flex h-96 w-full items-center justify-center rounded bg-gray-100">
379
+ <div className="text-center">
380
+ <div className="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-blue-600 border-r-transparent"></div>
381
+ <p className="mt-4 text-sm text-gray-600">
382
+ Computing user journey data...
383
+ </p>
384
+ </div>
385
+ </div>
386
+ ) : analytics.epinet &&
387
+ analytics.epinet.nodes &&
388
+ analytics.epinet.links ? (
389
+ analytics.epinet.nodes.length > 0 &&
390
+ analytics.epinet.links.length > 0 ? (
391
+ <ErrorBoundary
392
+ fallback={
393
+ <div className="rounded-lg bg-red-50 p-4 text-red-800">
394
+ Error rendering user flow diagram. Please check the data and
395
+ try again.
396
+ </div>
397
+ }
398
+ >
399
+ <div className="relative">
400
+ {analytics.status === 'loading' && (
401
+ <div className="absolute right-0 top-0 rounded bg-white px-2 py-1 text-xs text-gray-500 shadow-sm">
402
+ Updating...
403
+ </div>
404
+ )}
405
+ <SankeyDiagram
406
+ data={{
407
+ nodes: analytics.epinet.nodes,
408
+ links: analytics.epinet.links,
409
+ }}
410
+ isLoading={
411
+ analytics.isLoading || analytics.status === 'loading'
412
+ }
413
+ />
414
+ <EpinetDurationSelector
415
+ fullContentMap={fullContentMap}
416
+ isLoading={
417
+ analytics.isLoading || analytics.status === 'loading'
418
+ }
419
+ />
420
+ </div>
421
+ </ErrorBoundary>
422
+ ) : (
423
+ <>
424
+ <div className="mt-4 rounded-lg bg-gray-50 p-4 text-gray-800">
425
+ No matching data found with current filters. Try different
426
+ filter settings or time ranges.
427
+ </div>
428
+ <EpinetDurationSelector
429
+ fullContentMap={fullContentMap}
430
+ isLoading={
431
+ analytics.isLoading || analytics.status === 'loading'
432
+ }
433
+ />
434
+ </>
435
+ )
436
+ ) : (
437
+ <>
438
+ <div className="rounded-lg bg-gray-50 p-4 text-gray-800">
439
+ User Journey data will appear here once there's visitor activity.
440
+ Check back after some page views have been recorded.
441
+ </div>
442
+ <EpinetDurationSelector
443
+ fullContentMap={fullContentMap}
444
+ isLoading={analytics.isLoading || analytics.status === 'loading'}
445
+ />
446
+ </>
447
+ )}
448
+ </div>
449
+ </div>
450
+ );
451
+ }
@@ -0,0 +1,95 @@
1
+ import { useState } from 'react';
2
+ import { navigate } from 'astro:transitions/client';
3
+ import { useFormState } from '@/hooks/useFormState';
4
+ import {
5
+ convertToLocalState,
6
+ convertToBackendFormat,
7
+ validateBrandConfig,
8
+ } from '@/utils/api/brandHelpers';
9
+ import { saveBrandConfigWithStateUpdate } from '@/utils/api/brandConfig';
10
+ import BrandColorsSection from '@/components/form/brand/BrandColorsSection';
11
+ import BrandAssetsSection from '@/components/form/brand/BrandAssetsSection';
12
+ import SiteConfigSection from '@/components/form/brand/SiteConfigSection';
13
+ import SocialLinksSection from '@/components/form/brand/SocialLinksSection';
14
+ import SEOSection from '@/components/form/brand/SEOSection';
15
+ import UnsavedChangesBar from '@/components/form/UnsavedChangesBar';
16
+ import type { BrandConfig, BrandConfigState } from '@/types/tractstack';
17
+
18
+ interface StoryKeepDashboardBrandingProps {
19
+ brandConfig: BrandConfig;
20
+ onBrandConfigUpdate?: (config: BrandConfig) => void;
21
+ }
22
+
23
+ export default function StoryKeepDashboard_Branding({
24
+ brandConfig,
25
+ onBrandConfigUpdate,
26
+ }: StoryKeepDashboardBrandingProps) {
27
+ const [currentBrandConfig, setCurrentBrandConfig] = useState(brandConfig);
28
+ const initialState: BrandConfigState =
29
+ convertToLocalState(currentBrandConfig);
30
+
31
+ const formState = useFormState({
32
+ initialData: initialState,
33
+ validator: validateBrandConfig,
34
+ onSave: async (data) => {
35
+ try {
36
+ const isFirstSave = !currentBrandConfig.SITE_INIT;
37
+
38
+ const updatedState = await saveBrandConfigWithStateUpdate(
39
+ window.TRACTSTACK_CONFIG?.tenantId || 'default',
40
+ data
41
+ );
42
+
43
+ // Preserve existing paths when updating parent state
44
+ const updatedBrandConfig = {
45
+ ...currentBrandConfig,
46
+ ...convertToBackendFormat(updatedState),
47
+ };
48
+
49
+ // Update local state
50
+ setCurrentBrandConfig(updatedBrandConfig);
51
+
52
+ if (onBrandConfigUpdate) {
53
+ onBrandConfigUpdate(updatedBrandConfig);
54
+ }
55
+
56
+ if (isFirstSave) {
57
+ navigate('/storykeep');
58
+ }
59
+ } catch (error) {
60
+ console.error('Save failed:', error);
61
+ throw error;
62
+ }
63
+ },
64
+ unsavedChanges: {
65
+ enableBrowserWarning: true,
66
+ browserWarningMessage: 'Your brand configuration changes will be lost!',
67
+ },
68
+ });
69
+
70
+ return (
71
+ <div className="space-y-8">
72
+ <div className="border-b border-gray-200 pb-4">
73
+ <h2 className="text-2xl font-bold text-gray-900">
74
+ Brand Configuration
75
+ </h2>
76
+ <p className="mt-2 text-sm text-gray-600">
77
+ Configure your site's branding, colors, assets, and social presence.
78
+ </p>
79
+ </div>
80
+
81
+ <SiteConfigSection formState={formState} />
82
+ <BrandColorsSection formState={formState} />
83
+ <BrandAssetsSection formState={formState} />
84
+ <SEOSection formState={formState} />
85
+ <SocialLinksSection formState={formState} />
86
+
87
+ <UnsavedChangesBar
88
+ formState={formState}
89
+ message="You have unsaved brand configuration changes"
90
+ saveLabel="Save Brand Config"
91
+ cancelLabel="Discard Changes"
92
+ />
93
+ </div>
94
+ );
95
+ }