astro-tractstack 2.0.0-rc.9 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/LICENSE +8 -97
  2. package/README.md +7 -5
  3. package/bin/create-tractstack.js +31 -8
  4. package/dist/index.js +106 -29
  5. package/package.json +10 -5
  6. package/templates/css/frontend.css +1 -1
  7. package/templates/custom/minimal/CodeHook.astro +13 -12
  8. package/templates/custom/minimal/CustomRoutes.astro +25 -31
  9. package/templates/custom/with-examples/CodeHook.astro +22 -11
  10. package/templates/custom/with-examples/CustomRoutes.astro +4 -8
  11. package/templates/custom/with-examples/ProductCard.astro +29 -0
  12. package/templates/custom/with-examples/ProductCardWrapper.astro +43 -0
  13. package/templates/custom/with-examples/ProductGrid.astro +64 -0
  14. package/templates/custom/with-examples/pages/Collections.astro +58 -98
  15. package/templates/gitignore +42 -0
  16. package/templates/prettierignore +5 -0
  17. package/templates/prettierrc +19 -0
  18. package/templates/src/client/app.js +127 -0
  19. package/templates/src/client/htmx.min.js +3519 -0
  20. package/templates/src/client/view.js +429 -0
  21. package/templates/src/components/Footer.astro +4 -9
  22. package/templates/src/components/Header.astro +67 -60
  23. package/templates/src/components/Menu.tsx +188 -52
  24. package/templates/src/components/codehooks/BunnyVideoSetup.tsx +2 -2
  25. package/templates/src/components/codehooks/EpinetDurationSelector.tsx +9 -13
  26. package/templates/src/components/codehooks/EpinetTableView.tsx +11 -7
  27. package/templates/src/components/codehooks/EpinetWrapper.tsx +1 -0
  28. package/templates/src/components/codehooks/FeaturedArticle.astro +105 -0
  29. package/templates/src/components/codehooks/FeaturedArticleSetup.tsx +318 -0
  30. package/templates/src/components/codehooks/ListContent.astro +32 -162
  31. package/templates/src/components/codehooks/ListContentSetup.tsx +43 -138
  32. package/templates/src/components/codehooks/ProductCardSetup.tsx +152 -0
  33. package/templates/src/components/codehooks/ProductGridSetup.tsx +274 -0
  34. package/templates/src/components/codehooks/SearchWidget.tsx +453 -0
  35. package/templates/src/components/compositor/Node.tsx +3 -6
  36. package/templates/src/components/compositor/PanelVisibilityWrapper.tsx +21 -11
  37. package/templates/src/components/compositor/elements/BunnyVideo.tsx +21 -20
  38. package/templates/src/components/compositor/nodes/Pane.tsx +51 -21
  39. package/templates/src/components/compositor/nodes/RenderChildren.tsx +6 -1
  40. package/templates/src/components/compositor/nodes/Widget.tsx +16 -2
  41. package/templates/src/components/compositor/preview/FeaturedArticlePreview.tsx +155 -0
  42. package/templates/src/components/compositor/preview/PaneSnapshotGenerator.tsx +20 -1
  43. package/templates/src/components/edit/Header.tsx +10 -4
  44. package/templates/src/components/edit/PanelSwitch.tsx +11 -7
  45. package/templates/src/components/edit/SettingsPanel.tsx +29 -18
  46. package/templates/src/components/edit/ToolBar.tsx +1 -28
  47. package/templates/src/components/edit/ToolMode.tsx +45 -32
  48. package/templates/src/components/edit/pane/AddPanePanel_break.tsx +12 -2
  49. package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +8 -2
  50. package/templates/src/components/edit/pane/AddPanePanel_newAICopy_modal.tsx +1 -1
  51. package/templates/src/components/edit/pane/ConfigPanePanel.tsx +17 -27
  52. package/templates/src/components/edit/pane/PageGenSelector.tsx +16 -16
  53. package/templates/src/components/edit/pane/PageGenSpecial.tsx +26 -49
  54. package/templates/src/components/edit/pane/PageGen_preview.tsx +17 -2
  55. package/templates/src/components/edit/pane/PanePanel_path.tsx +2 -4
  56. package/templates/src/components/edit/pane/PanePanel_title.tsx +243 -76
  57. package/templates/src/components/edit/panels/StyleBreakPanel.tsx +17 -19
  58. package/templates/src/components/edit/panels/StyleCodeHookPanel.tsx +48 -37
  59. package/templates/src/components/edit/panels/StyleElementPanel_add.tsx +60 -55
  60. package/templates/src/components/edit/panels/StyleImagePanel_add.tsx +56 -50
  61. package/templates/src/components/edit/panels/StyleLiElementPanel_add.tsx +54 -47
  62. package/templates/src/components/edit/panels/StyleLinkPanel_add.tsx +54 -44
  63. package/templates/src/components/edit/panels/StyleLinkPanel_config.tsx +113 -138
  64. package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +54 -40
  65. package/templates/src/components/edit/panels/StyleWidgetPanel.tsx +3 -3
  66. package/templates/src/components/edit/panels/StyleWidgetPanel_add.tsx +56 -49
  67. package/templates/src/components/edit/panels/StyleWidgetPanel_config.tsx +14 -5
  68. package/templates/src/components/edit/state/SaveModal.tsx +316 -169
  69. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_og.tsx +1 -1
  70. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_slug.tsx +56 -55
  71. package/templates/src/components/edit/widgets/BunnyWidget.tsx +538 -59
  72. package/templates/src/components/edit/widgets/InteractiveDisclosureWidget.tsx +656 -0
  73. package/templates/src/components/edit/widgets/ToggleWidget.tsx +9 -16
  74. package/templates/src/components/fields/ArtpackImage.tsx +4 -1
  75. package/templates/src/components/fields/BackgroundImage.tsx +1 -1
  76. package/templates/src/components/fields/BackgroundImageWrapper.tsx +127 -35
  77. package/templates/src/components/fields/ColorPickerCombo.tsx +66 -62
  78. package/templates/src/components/fields/ImageUpload.tsx +1 -1
  79. package/templates/src/components/fields/ViewportComboBox.tsx +59 -42
  80. package/templates/src/components/form/ActionBuilderBeliefSelector.tsx +117 -0
  81. package/templates/src/components/form/ActionBuilderField.tsx +306 -87
  82. package/templates/src/components/search/SearchModal.tsx +420 -0
  83. package/templates/src/components/search/SearchResults.tsx +367 -0
  84. package/templates/src/components/search/SearchWrapper.tsx +46 -0
  85. package/templates/src/components/storykeep/Dashboard_Advanced.tsx +1 -1
  86. package/templates/src/components/storykeep/Dashboard_Analytics.tsx +34 -8
  87. package/templates/src/components/storykeep/Dashboard_Branding.tsx +1 -1
  88. package/templates/src/components/storykeep/Dashboard_Content.tsx +6 -0
  89. package/templates/src/components/storykeep/StoryKeepBackdrop.astro +87 -0
  90. package/templates/src/components/storykeep/controls/content/BeliefForm.tsx +38 -34
  91. package/templates/src/components/storykeep/controls/content/KnownResourceForm.tsx +1 -1
  92. package/templates/src/components/storykeep/controls/content/MenuForm.tsx +56 -8
  93. package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +18 -3
  94. package/templates/src/components/storykeep/controls/content/StoryFragmentTable.tsx +5 -8
  95. package/templates/src/components/storykeep/state/FetchAnalytics.tsx +274 -228
  96. package/templates/src/components/storykeep/widgets/Wizard.tsx +14 -7
  97. package/templates/src/components/widgets/ImpressionWrapper.tsx +0 -1
  98. package/templates/src/constants/shapes.ts +9 -0
  99. package/templates/src/constants.ts +2121 -16
  100. package/templates/src/hooks/useSearch.ts +228 -0
  101. package/templates/src/layouts/Layout.astro +213 -104
  102. package/templates/src/lib/storyData.ts +4 -1
  103. package/templates/src/pages/[...slug]/edit.astro +14 -14
  104. package/templates/src/pages/[...slug].astro +82 -21
  105. package/templates/src/pages/api/orphan-analysis.ts +0 -1
  106. package/templates/src/pages/api/tailwind.ts +23 -21
  107. package/templates/src/pages/context/[...contextSlug]/edit.astro +14 -14
  108. package/templates/src/pages/context/[...contextSlug].astro +7 -2
  109. package/templates/src/pages/storykeep/advanced.astro +5 -4
  110. package/templates/src/pages/storykeep/branding.astro +5 -4
  111. package/templates/src/pages/storykeep/content.astro +5 -4
  112. package/templates/src/pages/storykeep/init.astro +40 -1
  113. package/templates/src/pages/storykeep/login.astro +1 -1
  114. package/templates/src/pages/storykeep.astro +5 -4
  115. package/templates/src/stores/nodes.ts +59 -88
  116. package/templates/src/stores/orphanAnalysis.ts +19 -21
  117. package/templates/src/stores/storykeep.ts +7 -0
  118. package/templates/src/types/compositorTypes.ts +6 -0
  119. package/templates/src/types/tractstack.ts +17 -0
  120. package/templates/src/utils/actions/lispLexer.ts +2 -2
  121. package/templates/src/utils/actions/preParse_Action.ts +3 -0
  122. package/templates/src/utils/api/beliefHelpers.ts +12 -36
  123. package/templates/src/utils/api/menuHelpers.ts +2 -2
  124. package/templates/src/utils/api.ts +26 -0
  125. package/templates/src/utils/compositor/TemplateNodes.ts +7 -0
  126. package/templates/src/utils/compositor/allowInsert.ts +5 -3
  127. package/templates/src/utils/compositor/nodesHelper.ts +4 -0
  128. package/templates/src/utils/compositor/processMarkdown.ts +16 -2
  129. package/templates/src/utils/compositor/reduceNodesClassNames.ts +4 -0
  130. package/templates/src/utils/compositor/templateMarkdownStyles.ts +13 -13
  131. package/templates/src/utils/compositor/typeGuards.ts +1 -0
  132. package/templates/src/utils/customHelpers.ts +38 -0
  133. package/templates/src/utils/helpers.ts +2 -2
  134. package/templates/src/utils/layout.ts +65 -144
  135. package/utils/inject-files.ts +95 -18
  136. package/templates/src/client/analytics-events.js +0 -207
  137. package/templates/src/client/belief-events.js +0 -191
  138. package/templates/src/client/sse.js +0 -613
  139. package/templates/src/components/codehooks/FeaturedContent.astro +0 -273
  140. package/templates/src/components/codehooks/FeaturedContentSetup.tsx +0 -738
  141. package/templates/src/components/compositor/preview/FeaturedContentPreview.tsx +0 -128
  142. package/templates/src/components/edit/pane/PanePanel_slug.tsx +0 -219
@@ -1,5 +1,5 @@
1
- import { useState, useCallback, useMemo } from 'react';
2
- import { Combobox } from '@ark-ui/react';
1
+ import { useState, useCallback, useMemo, useRef } from 'react';
2
+ import { Combobox, Portal } from '@ark-ui/react';
3
3
  import { createListCollection } from '@ark-ui/react/collection';
4
4
  import ChevronUpDownIcon from '@heroicons/react/24/outline/ChevronUpDownIcon';
5
5
  import CheckIcon from '@heroicons/react/24/outline/CheckIcon';
@@ -7,6 +7,7 @@ import { settingsPanelStore } from '@/stores/storykeep';
7
7
  import { getCtx } from '@/stores/nodes';
8
8
  import { tailwindClasses } from '@/utils/compositor/tailwindClasses';
9
9
  import { isMarkdownPaneFragmentNode } from '@/utils/compositor/typeGuards';
10
+ import { useDropdownDirection } from '@/utils/helpers';
10
11
  import type { BasePanelProps } from '@/types/compositorTypes';
11
12
 
12
13
  // Recommended styles for widget containers (li)
@@ -68,6 +69,8 @@ const StyleWidgetPanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
68
69
  const [query, setQuery] = useState('');
69
70
  const [showAdvanced, setShowAdvanced] = useState(false);
70
71
  const [selectedStyle, setSelectedStyle] = useState<string | null>(null);
72
+ const comboboxRef = useRef<HTMLDivElement>(null);
73
+ const { openAbove } = useDropdownDirection(comboboxRef);
71
74
 
72
75
  if (!node?.tagName || !parentNode || !isMarkdownPaneFragmentNode(parentNode))
73
76
  return null;
@@ -79,13 +82,11 @@ const StyleWidgetPanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
79
82
  const ctx = getCtx();
80
83
  const allNodes = ctx.allNodes.get();
81
84
 
82
- // When styling container or outer container, use their IDs directly
83
85
  const targetNode = allNodes.get(node.id);
84
86
  if (!targetNode) return null;
85
87
 
86
88
  const currentClasses = new Set<string>();
87
89
 
88
- // Get existing classes from default classes in parent for THIS element type
89
90
  if (parentNode.defaultClasses?.[node.tagName]) {
90
91
  const defaults = parentNode.defaultClasses[node.tagName];
91
92
  Object.keys(defaults.mobile).forEach((key) => currentClasses.add(key));
@@ -95,7 +96,6 @@ const StyleWidgetPanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
95
96
  Object.keys(defaults.desktop).forEach((key) => currentClasses.add(key));
96
97
  }
97
98
 
98
- // Get existing override classes for THIS element
99
99
  if (`overrideClasses` in targetNode && targetNode.overrideClasses) {
100
100
  Object.values(targetNode.overrideClasses).forEach((viewportClasses) => {
101
101
  Object.keys(viewportClasses).forEach((key) => currentClasses.add(key));
@@ -112,7 +112,6 @@ const StyleWidgetPanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
112
112
  style.key.toLowerCase().includes(query.toLowerCase())
113
113
  );
114
114
 
115
- // Create collection for Ark UI Combobox
116
115
  const collection = useMemo(
117
116
  () =>
118
117
  createListCollection({
@@ -123,7 +122,6 @@ const StyleWidgetPanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
123
122
  [filteredStyles]
124
123
  );
125
124
 
126
- // Get appropriate recommended styles based on element type
127
125
  const recommendedStyles = isOuterContainer
128
126
  ? OUTER_CONTAINER_STYLES
129
127
  : isContainer
@@ -147,7 +145,7 @@ const StyleWidgetPanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
147
145
  ? 'style-code-container-update'
148
146
  : 'style-code-update',
149
147
  nodeId: node.id,
150
- childId, // Preserve childId for container context
148
+ childId,
151
149
  className: styleKey,
152
150
  expanded: true,
153
151
  });
@@ -156,10 +154,9 @@ const StyleWidgetPanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
156
154
  );
157
155
 
158
156
  const handleCancel = () => {
159
- // Return to main panel with correct context
160
157
  settingsPanelStore.set({
161
158
  action: 'style-widget',
162
- nodeId: childId || node.id, // Use childId when available for context
159
+ nodeId: childId || node.id,
163
160
  expanded: true,
164
161
  });
165
162
  };
@@ -170,7 +167,6 @@ const StyleWidgetPanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
170
167
  ? 'Container'
171
168
  : 'Widget';
172
169
 
173
- // CSS to properly style the combobox items with hover and selection
174
170
  const comboboxItemStyles = `
175
171
  .style-item[data-highlighted] {
176
172
  background-color: #0891b2; /* bg-cyan-600 */
@@ -191,7 +187,7 @@ const StyleWidgetPanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
191
187
  `;
192
188
 
193
189
  return (
194
- <div className="min-h-[400px] max-w-md space-y-4">
190
+ <div className="max-w-md space-y-4">
195
191
  <style>{comboboxItemStyles}</style>
196
192
 
197
193
  <div className="flex flex-row flex-nowrap justify-between">
@@ -226,46 +222,57 @@ const StyleWidgetPanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
226
222
  loopFocus={true}
227
223
  openOnKeyPress={true}
228
224
  composite={true}
225
+ positioning={{
226
+ placement: openAbove ? 'top' : 'bottom',
227
+ gutter: 4,
228
+ sameWidth: true,
229
+ }}
229
230
  >
230
- <div className="relative">
231
- <Combobox.Input
232
- className="border-mydarkgrey focus:border-myblue focus:ring-myblue w-full rounded-md py-2 pl-3 pr-10 text-xl shadow-sm"
233
- onChange={(e) => setQuery(e.target.value)}
234
- placeholder="Search styles..."
235
- />
236
- <Combobox.Trigger className="absolute inset-y-0 right-0 flex items-center pr-2">
237
- <ChevronUpDownIcon
238
- className="text-mydarkgrey h-5 w-5"
239
- aria-hidden="true"
231
+ <Combobox.Control ref={comboboxRef}>
232
+ <div className="relative">
233
+ <Combobox.Input
234
+ className="border-mydarkgrey focus:border-myblue focus:ring-myblue w-full rounded-md py-2 pl-3 pr-10 text-xl shadow-sm"
235
+ onChange={(e) => setQuery(e.target.value)}
236
+ placeholder="Search styles..."
240
237
  />
241
- </Combobox.Trigger>
242
- </div>
238
+ <Combobox.Trigger className="absolute inset-y-0 right-0 flex items-center pr-2">
239
+ <ChevronUpDownIcon
240
+ className="text-mydarkgrey h-5 w-5"
241
+ aria-hidden="true"
242
+ />
243
+ </Combobox.Trigger>
244
+ </div>
245
+ </Combobox.Control>
243
246
 
244
- <Combobox.Content className="absolute z-50 mt-1 max-h-64 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
245
- {collection.items.length === 0 ? (
246
- <div className="text-mydarkgrey relative cursor-default select-none px-4 py-2">
247
- Nothing found.
248
- </div>
249
- ) : (
250
- collection.items.map((style) => (
251
- <Combobox.Item
252
- key={style.key}
253
- item={style}
254
- className="style-item relative cursor-default select-none py-2 pl-10 pr-4 text-black"
255
- >
256
- <span className="block truncate">
257
- {style.title}
258
- <span className="ml-2 text-sm opacity-60">
259
- {style.className}
260
- </span>
261
- </span>
262
- <span className="style-indicator absolute inset-y-0 left-0 flex items-center pl-3 text-cyan-600">
263
- <CheckIcon className="h-5 w-5" aria-hidden="true" />
264
- </span>
265
- </Combobox.Item>
266
- ))
267
- )}
268
- </Combobox.Content>
247
+ <Portal>
248
+ <Combobox.Positioner style={{ zIndex: 1002 }}>
249
+ <Combobox.Content className="max-h-64 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
250
+ {collection.items.length === 0 ? (
251
+ <div className="text-mydarkgrey relative cursor-default select-none px-4 py-2">
252
+ Nothing found.
253
+ </div>
254
+ ) : (
255
+ collection.items.map((style) => (
256
+ <Combobox.Item
257
+ key={style.key}
258
+ item={style}
259
+ className="style-item relative cursor-default select-none py-2 pl-10 pr-4 text-black"
260
+ >
261
+ <span className="block truncate">
262
+ {style.title}
263
+ <span className="ml-2 text-sm opacity-60">
264
+ {style.className}
265
+ </span>
266
+ </span>
267
+ <span className="style-indicator absolute inset-y-0 left-0 flex items-center pl-3 text-cyan-600">
268
+ <CheckIcon className="h-5 w-5" aria-hidden="true" />
269
+ </span>
270
+ </Combobox.Item>
271
+ ))
272
+ )}
273
+ </Combobox.Content>
274
+ </Combobox.Positioner>
275
+ </Portal>
269
276
  </Combobox.Root>
270
277
  </div>
271
278
 
@@ -1,7 +1,7 @@
1
1
  import { useEffect, useState } from 'react';
2
2
  import { getCtx } from '@/stores/nodes';
3
3
  import { cloneDeep } from '@/utils/helpers';
4
- import { widgetMeta } from '@/constants';
4
+ import { regexpHook, widgetMeta } from '@/constants';
5
5
  import SingleParam from '@/components/fields/SingleParam';
6
6
  import BooleanParam from '@/components/fields/BooleanParam';
7
7
  import MultiParam from '@/components/fields/MultiParam';
@@ -11,13 +11,16 @@ import IdentifyAsWidget from '@/components/edit/widgets/IdentifyAsWidget';
11
11
  import SignupWidget from '@/components/edit/widgets/SignupWidget';
12
12
  import ToggleWidget from '@/components/edit/widgets/ToggleWidget';
13
13
  import YouTubeWidget from '@/components/edit/widgets/YouTubeWidget';
14
+ import InteractiveDisclosureWidget from '@/components/edit/widgets/InteractiveDisclosureWidget';
14
15
  import type { FlatNode } from '@/types/compositorTypes';
16
+ import type { BrandConfig } from '@/types/tractstack';
15
17
 
16
18
  interface StyleWidgetConfigPanelProps {
17
19
  node: FlatNode;
20
+ config: BrandConfig;
18
21
  }
19
22
 
20
- function StyleWidgetConfigPanel({ node }: StyleWidgetConfigPanelProps) {
23
+ function StyleWidgetConfigPanel({ node, config }: StyleWidgetConfigPanelProps) {
21
24
  const [init, setInit] = useState(false);
22
25
 
23
26
  useEffect(() => {
@@ -27,8 +30,6 @@ function StyleWidgetConfigPanel({ node }: StyleWidgetConfigPanelProps) {
27
30
  if (!node || !('copy' in node) || typeof node.copy !== 'string') return null;
28
31
 
29
32
  // Extract the widget type from the node's copy
30
- const regexpHook =
31
- /^(identifyAs|youtube|bunny|bunnyContext|toggle|resource|belief|signup)\((.*)\)$/;
32
33
  const hookMatch = node.copy?.match(regexpHook);
33
34
  if (!hookMatch) return null;
34
35
 
@@ -75,7 +76,8 @@ function StyleWidgetConfigPanel({ node }: StyleWidgetConfigPanelProps) {
75
76
  newNode.codeHookParams = stringParams;
76
77
 
77
78
  // Update the copy field to match the new params
78
- newNode.copy = `${widgetType}(${stringParams.join('|')})`;
79
+ const paramsForCopy = stringParams.slice(0, widgetInfo.parameters.length);
80
+ newNode.copy = `${widgetType}(${paramsForCopy.join('|')})`;
79
81
 
80
82
  // Mark the node as changed
81
83
  newNode.isChanged = true;
@@ -94,6 +96,13 @@ function StyleWidgetConfigPanel({ node }: StyleWidgetConfigPanelProps) {
94
96
  signup: () => <SignupWidget node={node} onUpdate={handleParamUpdate} />,
95
97
  toggle: () => <ToggleWidget node={node} onUpdate={handleParamUpdate} />,
96
98
  youtube: () => <YouTubeWidget node={node} onUpdate={handleParamUpdate} />,
99
+ interactiveDisclosure: () => (
100
+ <InteractiveDisclosureWidget
101
+ node={node}
102
+ onUpdate={handleParamUpdate}
103
+ config={config}
104
+ />
105
+ ),
97
106
  };
98
107
 
99
108
  // Generic parameter editor for widget types without specific editors