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,638 @@
1
+ import { useId, useMemo, useState, useEffect } from 'react';
2
+ import { DatePicker } from '@ark-ui/react/date-picker';
3
+ import { Select } from '@ark-ui/react/select';
4
+ import { Portal } from '@ark-ui/react/portal';
5
+ import { createListCollection } from '@ark-ui/react/collection';
6
+ import { CalendarDate, type DateValue } from '@internationalized/date';
7
+ import CalendarDaysIcon from '@heroicons/react/24/outline/CalendarDaysIcon';
8
+ import ChevronLeftIcon from '@heroicons/react/24/outline/ChevronLeftIcon';
9
+ import ChevronRightIcon from '@heroicons/react/24/outline/ChevronRightIcon';
10
+ import ChevronUpDownIcon from '@heroicons/react/24/outline/ChevronUpDownIcon';
11
+ import CheckIcon from '@heroicons/react/24/outline/CheckIcon';
12
+ import { classNames } from '@/utils/helpers';
13
+ import type { BaseFormComponentProps } from '@/types/formTypes';
14
+
15
+ export interface DateTimeInputProps extends BaseFormComponentProps<number> {
16
+ displayFormat?: 'date' | 'datetime' | 'time';
17
+ min?: number;
18
+ max?: number;
19
+ withTime?: boolean;
20
+ timeStep?: number;
21
+ }
22
+
23
+ // Hour options (1-12 for 12-hour format)
24
+ const hourOptions = Array.from({ length: 12 }, (_, i) => ({
25
+ value: (i + 1).toString(),
26
+ label: (i + 1).toString().padStart(2, '0'),
27
+ }));
28
+
29
+ // Minute options (00, 15, 30, 45)
30
+ const minuteOptions = [
31
+ { value: '0', label: '00' },
32
+ { value: '15', label: '15' },
33
+ { value: '30', label: '30' },
34
+ { value: '45', label: '45' },
35
+ ];
36
+
37
+ // AM/PM options
38
+ const ampmOptions = [
39
+ { value: 'AM', label: 'AM' },
40
+ { value: 'PM', label: 'PM' },
41
+ ];
42
+
43
+ const DateTimeInput = ({
44
+ value,
45
+ onChange,
46
+ label,
47
+ error,
48
+ disabled = false,
49
+ required = false,
50
+ className,
51
+ displayFormat = 'datetime',
52
+ min,
53
+ max,
54
+ withTime = true,
55
+ }: DateTimeInputProps) => {
56
+ const id = useId();
57
+ const errorId = `${id}-error`;
58
+ const helpTextId = `${id}-help`;
59
+
60
+ // Local state for date and time components
61
+ const [selectedDate, setSelectedDate] = useState<CalendarDate | null>(null);
62
+ const [selectedHour, setSelectedHour] = useState<string>('7'); // Default 7 PM
63
+ const [selectedMinute, setSelectedMinute] = useState<string>('0'); // Default :00
64
+ const [selectedAmPm, setSelectedAmPm] = useState<string>('PM'); // Default PM
65
+
66
+ // Create collections for Ark UI Select components
67
+ const hourCollection = useMemo(
68
+ () => createListCollection({ items: hourOptions }),
69
+ []
70
+ );
71
+ const minuteCollection = useMemo(
72
+ () => createListCollection({ items: minuteOptions }),
73
+ []
74
+ );
75
+ const ampmCollection = useMemo(
76
+ () => createListCollection({ items: ampmOptions }),
77
+ []
78
+ );
79
+
80
+ // Sync local state with incoming UTC timestamp value
81
+ useEffect(() => {
82
+ if (value && value > 0) {
83
+ const localDate = new Date(value * 1000);
84
+
85
+ // Set date
86
+ const newDate = new CalendarDate(
87
+ localDate.getFullYear(),
88
+ localDate.getMonth() + 1,
89
+ localDate.getDate()
90
+ );
91
+
92
+ // Set time components in local timezone
93
+ const hour24 = localDate.getHours();
94
+ const minute = localDate.getMinutes();
95
+
96
+ // Convert to 12-hour format
97
+ const hour12 = hour24 === 0 ? 12 : hour24 > 12 ? hour24 - 12 : hour24;
98
+ const isPM = hour24 >= 12;
99
+
100
+ // Only update if different to prevent loops
101
+ setSelectedDate(newDate);
102
+ setSelectedHour(hour12.toString());
103
+ setSelectedMinute(minute.toString());
104
+ setSelectedAmPm(isPM ? 'PM' : 'AM');
105
+ }
106
+ }, [value]); // Remove selectedDate from dependencies
107
+
108
+ // Helper to calculate UTC timestamp from local date/time components
109
+ const calculateUtcTimestamp = (
110
+ date: CalendarDate,
111
+ hour: string,
112
+ minute: string,
113
+ ampm: string
114
+ ): number => {
115
+ // Convert 12-hour to 24-hour
116
+ let hour24 = parseInt(hour, 10);
117
+ if (ampm === 'PM' && hour24 !== 12) {
118
+ hour24 += 12;
119
+ } else if (ampm === 'AM' && hour24 === 12) {
120
+ hour24 = 0;
121
+ }
122
+
123
+ // Create local date object
124
+ const localDateTime = new Date(
125
+ date.year,
126
+ date.month - 1, // JavaScript months are 0-indexed
127
+ date.day,
128
+ hour24,
129
+ parseInt(minute, 10),
130
+ 0, // seconds
131
+ 0 // milliseconds
132
+ );
133
+
134
+ // Convert to UTC timestamp
135
+ return Math.floor(localDateTime.getTime() / 1000);
136
+ };
137
+
138
+ // Update UTC timestamp when any component changes
139
+ const updateTimestamp = (
140
+ date?: CalendarDate,
141
+ hour?: string,
142
+ minute?: string,
143
+ ampm?: string
144
+ ) => {
145
+ const currentDate = date || selectedDate;
146
+ const currentHour = hour || selectedHour;
147
+ const currentMinute = minute || selectedMinute;
148
+ const currentAmPm = ampm || selectedAmPm;
149
+
150
+ if (currentDate) {
151
+ const utcTimestamp = calculateUtcTimestamp(
152
+ currentDate,
153
+ currentHour,
154
+ currentMinute,
155
+ currentAmPm
156
+ );
157
+ onChange(utcTimestamp);
158
+ }
159
+ };
160
+
161
+ // Handle date selection
162
+ const handleDateChange = (details: { value: DateValue[] }) => {
163
+ if (details.value && details.value.length > 0) {
164
+ const newDate = details.value[0] as CalendarDate;
165
+ setSelectedDate(newDate);
166
+
167
+ // If this is the first time selecting a date, set default time
168
+ if (!selectedDate) {
169
+ setSelectedHour('7');
170
+ setSelectedMinute('0');
171
+ setSelectedAmPm('PM');
172
+ updateTimestamp(newDate, '7', '0', 'PM');
173
+ } else {
174
+ updateTimestamp(newDate);
175
+ }
176
+ } else {
177
+ setSelectedDate(null);
178
+ onChange(0);
179
+ }
180
+ };
181
+
182
+ // Handle hour selection
183
+ const handleHourChange = (details: { value: string[] }) => {
184
+ if (details.value && details.value.length > 0) {
185
+ const newHour = details.value[0];
186
+ setSelectedHour(newHour);
187
+ updateTimestamp(undefined, newHour);
188
+ }
189
+ };
190
+
191
+ // Handle minute selection
192
+ const handleMinuteChange = (details: { value: string[] }) => {
193
+ if (details.value && details.value.length > 0) {
194
+ const newMinute = details.value[0];
195
+ setSelectedMinute(newMinute);
196
+ updateTimestamp(undefined, undefined, newMinute);
197
+ }
198
+ };
199
+
200
+ // Handle AM/PM selection
201
+ const handleAmPmChange = (details: { value: string[] }) => {
202
+ if (details.value && details.value.length > 0) {
203
+ const newAmPm = details.value[0];
204
+ setSelectedAmPm(newAmPm);
205
+ updateTimestamp(undefined, undefined, undefined, newAmPm);
206
+ }
207
+ };
208
+
209
+ // Calculate min/max dates for DatePicker
210
+ const minDate = useMemo((): CalendarDate | undefined => {
211
+ if (!min) return undefined;
212
+ const date = new Date(min * 1000);
213
+ return new CalendarDate(
214
+ date.getFullYear(),
215
+ date.getMonth() + 1,
216
+ date.getDate()
217
+ );
218
+ }, [min]);
219
+
220
+ const maxDate = useMemo((): CalendarDate | undefined => {
221
+ if (!max) return undefined;
222
+ const date = new Date(max * 1000);
223
+ return new CalendarDate(
224
+ date.getFullYear(),
225
+ date.getMonth() + 1,
226
+ date.getDate()
227
+ );
228
+ }, [max]);
229
+
230
+ // Format display value for current selection
231
+ const getDisplaySummary = () => {
232
+ if (!selectedDate) {
233
+ return 'No date selected';
234
+ }
235
+
236
+ const dateStr = `${selectedDate.month}/${selectedDate.day}/${selectedDate.year}`;
237
+
238
+ if (withTime && displayFormat !== 'date') {
239
+ const timeStr = `${selectedHour.padStart(2, '0')}:${selectedMinute.padStart(2, '0')} ${selectedAmPm}`;
240
+ return `${dateStr} at ${timeStr}`;
241
+ }
242
+
243
+ return dateStr;
244
+ };
245
+
246
+ return (
247
+ <div className={classNames('space-y-4', className || '')}>
248
+ {/* Label */}
249
+ {label && (
250
+ <label className="block text-sm font-bold text-gray-700">
251
+ {label}
252
+ {required && <span className="ml-1 text-red-500">*</span>}
253
+ </label>
254
+ )}
255
+
256
+ {/* Date Picker Section */}
257
+ <div className="space-y-2">
258
+ <div className="text-xs font-bold text-gray-600">Date</div>
259
+ <DatePicker.Root
260
+ value={selectedDate ? [selectedDate] : []}
261
+ onValueChange={handleDateChange}
262
+ min={minDate}
263
+ max={maxDate}
264
+ disabled={disabled}
265
+ closeOnSelect={true}
266
+ positioning={{ sameWidth: false }}
267
+ >
268
+ <DatePicker.Control className="relative w-fit">
269
+ <DatePicker.Input
270
+ placeholder="Select date"
271
+ className={classNames(
272
+ 'w-40 rounded-md border px-3 py-2 text-sm shadow-sm transition-colors',
273
+ 'focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500',
274
+ error
275
+ ? 'border-red-300 focus:border-red-500 focus:ring-red-500'
276
+ : 'border-gray-300',
277
+ disabled ? 'cursor-not-allowed bg-gray-50 text-gray-500' : ''
278
+ )}
279
+ disabled={disabled}
280
+ readOnly
281
+ />
282
+ <DatePicker.Trigger
283
+ className={classNames(
284
+ 'absolute right-2 top-1/2 -translate-y-1/2 rounded p-1',
285
+ 'text-gray-400 transition-colors hover:text-gray-600',
286
+ disabled ? 'cursor-not-allowed opacity-50' : ''
287
+ )}
288
+ disabled={disabled}
289
+ >
290
+ <CalendarDaysIcon className="h-4 w-4" />
291
+ </DatePicker.Trigger>
292
+ </DatePicker.Control>
293
+
294
+ <Portal>
295
+ <DatePicker.Positioner>
296
+ <DatePicker.Content className="z-50 rounded-lg border border-gray-200 bg-white p-4 shadow-lg">
297
+ <DatePicker.View view="day">
298
+ <DatePicker.Context>
299
+ {(api) => (
300
+ <>
301
+ <DatePicker.ViewControl className="mb-4 flex items-center justify-between">
302
+ <DatePicker.PrevTrigger className="rounded p-1 hover:bg-gray-100">
303
+ <ChevronLeftIcon className="h-4 w-4" />
304
+ </DatePicker.PrevTrigger>
305
+ <DatePicker.ViewTrigger className="rounded px-3 py-1 text-sm font-bold hover:bg-gray-100">
306
+ <DatePicker.RangeText />
307
+ </DatePicker.ViewTrigger>
308
+ <DatePicker.NextTrigger className="rounded p-1 hover:bg-gray-100">
309
+ <ChevronRightIcon className="h-4 w-4" />
310
+ </DatePicker.NextTrigger>
311
+ </DatePicker.ViewControl>
312
+
313
+ <DatePicker.Table className="w-full">
314
+ <DatePicker.TableHead>
315
+ <DatePicker.TableRow>
316
+ {api.weekDays.map((weekDay, id) => (
317
+ <DatePicker.TableHeader
318
+ key={id}
319
+ className="p-2 text-center text-xs font-bold text-gray-500"
320
+ >
321
+ {weekDay.short}
322
+ </DatePicker.TableHeader>
323
+ ))}
324
+ </DatePicker.TableRow>
325
+ </DatePicker.TableHead>
326
+ <DatePicker.TableBody>
327
+ {api.weeks.map((week, id) => (
328
+ <DatePicker.TableRow key={id}>
329
+ {week.map((day, id) => (
330
+ <DatePicker.TableCell key={id} value={day}>
331
+ <DatePicker.TableCellTrigger
332
+ className={classNames(
333
+ 'h-8 w-8 rounded p-0 text-sm transition-colors',
334
+ 'hover:bg-blue-50 focus:outline-none focus:ring-2 focus:ring-blue-500',
335
+ 'data-[selected]:bg-blue-600 data-[selected]:text-white',
336
+ 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-40',
337
+ 'data-[outside-range]:text-gray-400'
338
+ )}
339
+ >
340
+ {day.day}
341
+ </DatePicker.TableCellTrigger>
342
+ </DatePicker.TableCell>
343
+ ))}
344
+ </DatePicker.TableRow>
345
+ ))}
346
+ </DatePicker.TableBody>
347
+ </DatePicker.Table>
348
+ </>
349
+ )}
350
+ </DatePicker.Context>
351
+ </DatePicker.View>
352
+
353
+ <DatePicker.View view="month">
354
+ <DatePicker.Context>
355
+ {(api) => (
356
+ <>
357
+ <DatePicker.ViewControl className="mb-4 flex items-center justify-between">
358
+ <DatePicker.PrevTrigger className="rounded p-1 hover:bg-gray-100">
359
+ <ChevronLeftIcon className="h-4 w-4" />
360
+ </DatePicker.PrevTrigger>
361
+ <DatePicker.ViewTrigger className="rounded px-3 py-1 text-sm font-bold hover:bg-gray-100">
362
+ <DatePicker.RangeText />
363
+ </DatePicker.ViewTrigger>
364
+ <DatePicker.NextTrigger className="rounded p-1 hover:bg-gray-100">
365
+ <ChevronRightIcon className="h-4 w-4" />
366
+ </DatePicker.NextTrigger>
367
+ </DatePicker.ViewControl>
368
+
369
+ <DatePicker.Table>
370
+ <DatePicker.TableBody>
371
+ {api
372
+ .getMonthsGrid({ columns: 4 })
373
+ .map((months, id) => (
374
+ <DatePicker.TableRow key={id}>
375
+ {months.map((month, id) => (
376
+ <DatePicker.TableCell
377
+ key={id}
378
+ value={month.value}
379
+ >
380
+ <DatePicker.TableCellTrigger
381
+ className={classNames(
382
+ 'w-full rounded p-2 text-sm transition-colors hover:bg-blue-50',
383
+ 'data-[selected]:bg-blue-600 data-[selected]:text-white'
384
+ )}
385
+ >
386
+ {month.label}
387
+ </DatePicker.TableCellTrigger>
388
+ </DatePicker.TableCell>
389
+ ))}
390
+ </DatePicker.TableRow>
391
+ ))}
392
+ </DatePicker.TableBody>
393
+ </DatePicker.Table>
394
+ </>
395
+ )}
396
+ </DatePicker.Context>
397
+ </DatePicker.View>
398
+
399
+ <DatePicker.View view="year">
400
+ <DatePicker.Context>
401
+ {(api) => (
402
+ <>
403
+ <DatePicker.ViewControl className="mb-4 flex items-center justify-between">
404
+ <DatePicker.PrevTrigger className="rounded p-1 hover:bg-gray-100">
405
+ <ChevronLeftIcon className="h-4 w-4" />
406
+ </DatePicker.PrevTrigger>
407
+ <DatePicker.ViewTrigger className="rounded px-3 py-1 text-sm font-bold hover:bg-gray-100">
408
+ <DatePicker.RangeText />
409
+ </DatePicker.ViewTrigger>
410
+ <DatePicker.NextTrigger className="rounded p-1 hover:bg-gray-100">
411
+ <ChevronRightIcon className="h-4 w-4" />
412
+ </DatePicker.NextTrigger>
413
+ </DatePicker.ViewControl>
414
+
415
+ <DatePicker.Table>
416
+ <DatePicker.TableBody>
417
+ {api
418
+ .getYearsGrid({ columns: 4 })
419
+ .map((years, id) => (
420
+ <DatePicker.TableRow key={id}>
421
+ {years.map((year, id) => (
422
+ <DatePicker.TableCell
423
+ key={id}
424
+ value={year.value}
425
+ >
426
+ <DatePicker.TableCellTrigger
427
+ className={classNames(
428
+ 'w-full rounded p-2 text-sm transition-colors hover:bg-blue-50',
429
+ 'data-[selected]:bg-blue-600 data-[selected]:text-white'
430
+ )}
431
+ >
432
+ {year.label}
433
+ </DatePicker.TableCellTrigger>
434
+ </DatePicker.TableCell>
435
+ ))}
436
+ </DatePicker.TableRow>
437
+ ))}
438
+ </DatePicker.TableBody>
439
+ </DatePicker.Table>
440
+ </>
441
+ )}
442
+ </DatePicker.Context>
443
+ </DatePicker.View>
444
+ </DatePicker.Content>
445
+ </DatePicker.Positioner>
446
+ </Portal>
447
+ </DatePicker.Root>
448
+ </div>
449
+
450
+ {/* Time Picker Section (only show if withTime is true and not date-only) */}
451
+ {withTime && displayFormat !== 'date' && (
452
+ <div className="space-y-2">
453
+ <div className="text-xs font-bold text-gray-600">
454
+ Time (Local Timezone)
455
+ </div>
456
+ <div className="flex items-center space-x-2">
457
+ {/* Hour Select */}
458
+ <div className="w-16">
459
+ <Select.Root
460
+ collection={hourCollection}
461
+ value={[selectedHour]}
462
+ onValueChange={handleHourChange}
463
+ disabled={disabled}
464
+ positioning={{ sameWidth: true }}
465
+ >
466
+ <Select.Control>
467
+ <Select.Trigger
468
+ className={classNames(
469
+ 'flex w-full items-center justify-between rounded-md border px-3 py-2 text-sm',
470
+ 'focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500',
471
+ error
472
+ ? 'border-red-300 focus:border-red-500 focus:ring-red-500'
473
+ : 'border-gray-300',
474
+ disabled
475
+ ? 'cursor-not-allowed bg-gray-50 text-gray-500'
476
+ : ''
477
+ )}
478
+ disabled={disabled}
479
+ >
480
+ <Select.ValueText placeholder="Hr" />
481
+ <ChevronUpDownIcon className="h-4 w-4 text-gray-400" />
482
+ </Select.Trigger>
483
+ </Select.Control>
484
+
485
+ <Portal>
486
+ <Select.Positioner>
487
+ <Select.Content className="z-50 max-h-60 overflow-auto rounded-md border border-gray-200 bg-white py-1 shadow-lg">
488
+ {hourOptions.map((option) => (
489
+ <Select.Item
490
+ key={option.value}
491
+ item={option}
492
+ className="flex cursor-pointer items-center justify-between px-3 py-2 text-sm hover:bg-blue-50 data-[highlighted]:bg-blue-50"
493
+ >
494
+ <Select.ItemText>{option.label}</Select.ItemText>
495
+ <Select.ItemIndicator>
496
+ <CheckIcon className="h-4 w-4" />
497
+ </Select.ItemIndicator>
498
+ </Select.Item>
499
+ ))}
500
+ </Select.Content>
501
+ </Select.Positioner>
502
+ </Portal>
503
+ </Select.Root>
504
+ </div>
505
+
506
+ <span className="text-gray-500">:</span>
507
+
508
+ {/* Minute Select */}
509
+ <div className="w-16">
510
+ <Select.Root
511
+ collection={minuteCollection}
512
+ value={[selectedMinute]}
513
+ onValueChange={handleMinuteChange}
514
+ disabled={disabled}
515
+ positioning={{ sameWidth: true }}
516
+ >
517
+ <Select.Control>
518
+ <Select.Trigger
519
+ className={classNames(
520
+ 'flex w-full items-center justify-between rounded-md border px-3 py-2 text-sm',
521
+ 'focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500',
522
+ error
523
+ ? 'border-red-300 focus:border-red-500 focus:ring-red-500'
524
+ : 'border-gray-300',
525
+ disabled
526
+ ? 'cursor-not-allowed bg-gray-50 text-gray-500'
527
+ : ''
528
+ )}
529
+ disabled={disabled}
530
+ >
531
+ <Select.ValueText placeholder="Min" />
532
+ <ChevronUpDownIcon className="h-4 w-4 text-gray-400" />
533
+ </Select.Trigger>
534
+ </Select.Control>
535
+
536
+ <Portal>
537
+ <Select.Positioner>
538
+ <Select.Content className="z-50 max-h-60 overflow-auto rounded-md border border-gray-200 bg-white py-1 shadow-lg">
539
+ {minuteOptions.map((option) => (
540
+ <Select.Item
541
+ key={option.value}
542
+ item={option}
543
+ className="flex cursor-pointer items-center justify-between px-3 py-2 text-sm hover:bg-blue-50 data-[highlighted]:bg-blue-50"
544
+ >
545
+ <Select.ItemText>{option.label}</Select.ItemText>
546
+ <Select.ItemIndicator>
547
+ <CheckIcon className="h-4 w-4" />
548
+ </Select.ItemIndicator>
549
+ </Select.Item>
550
+ ))}
551
+ </Select.Content>
552
+ </Select.Positioner>
553
+ </Portal>
554
+ </Select.Root>
555
+ </div>
556
+
557
+ {/* AM/PM Select */}
558
+ <div className="w-20">
559
+ <Select.Root
560
+ collection={ampmCollection}
561
+ value={[selectedAmPm]}
562
+ onValueChange={handleAmPmChange}
563
+ disabled={disabled}
564
+ positioning={{ sameWidth: true }}
565
+ >
566
+ <Select.Control>
567
+ <Select.Trigger
568
+ className={classNames(
569
+ 'flex w-full items-center justify-between rounded-md border px-3 py-2 text-sm',
570
+ 'focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500',
571
+ error
572
+ ? 'border-red-300 focus:border-red-500 focus:ring-red-500'
573
+ : 'border-gray-300',
574
+ disabled
575
+ ? 'cursor-not-allowed bg-gray-50 text-gray-500'
576
+ : ''
577
+ )}
578
+ disabled={disabled}
579
+ >
580
+ <Select.ValueText placeholder="AM/PM" />
581
+ <ChevronUpDownIcon className="h-4 w-4 text-gray-400" />
582
+ </Select.Trigger>
583
+ </Select.Control>
584
+
585
+ <Portal>
586
+ <Select.Positioner>
587
+ <Select.Content className="z-50 max-h-60 overflow-auto rounded-md border border-gray-200 bg-white py-1 shadow-lg">
588
+ {ampmOptions.map((option) => (
589
+ <Select.Item
590
+ key={option.value}
591
+ item={option}
592
+ className="flex cursor-pointer items-center justify-between px-3 py-2 text-sm hover:bg-blue-50 data-[highlighted]:bg-blue-50"
593
+ >
594
+ <Select.ItemText>{option.label}</Select.ItemText>
595
+ <Select.ItemIndicator>
596
+ <CheckIcon className="h-4 w-4" />
597
+ </Select.ItemIndicator>
598
+ </Select.Item>
599
+ ))}
600
+ </Select.Content>
601
+ </Select.Positioner>
602
+ </Portal>
603
+ </Select.Root>
604
+ </div>
605
+ </div>
606
+ </div>
607
+ )}
608
+
609
+ {/* Current Selection Summary */}
610
+ <div className="rounded-md bg-gray-50 p-3">
611
+ <div className="mb-1 text-xs font-bold text-gray-600">
612
+ Current Selection:
613
+ </div>
614
+ <div className="text-sm text-gray-900">{getDisplaySummary()}</div>
615
+ {value > 0 && (
616
+ <div className="mt-1 text-xs text-gray-500">
617
+ UTC Timestamp: {value}
618
+ </div>
619
+ )}
620
+ </div>
621
+
622
+ {/* Error Message */}
623
+ {error && (
624
+ <p id={errorId} className="text-sm text-red-600" role="alert">
625
+ {error}
626
+ </p>
627
+ )}
628
+
629
+ {/* Help Text */}
630
+ <p id={helpTextId} className="text-xs text-gray-500">
631
+ <strong>⚠️ Timezone Info:</strong> All times are displayed in your local
632
+ timezone but stored as UTC timestamps for consistency across time zones.
633
+ </p>
634
+ </div>
635
+ );
636
+ };
637
+
638
+ export default DateTimeInput;