astro-tractstack 2.1.3 → 2.2.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 (128) hide show
  1. package/README.md +54 -266
  2. package/bin/create-tractstack.js +9 -6
  3. package/dist/index.js +109 -71
  4. package/package.json +4 -2
  5. package/templates/css/custom.css +5 -0
  6. package/templates/icons/code.svg +18 -0
  7. package/templates/icons/li.svg +4 -0
  8. package/templates/icons/link.svg +22 -0
  9. package/templates/icons/p.svg +3 -0
  10. package/templates/src/client/app.js +80 -1
  11. package/templates/src/components/Footer.astro +1 -1
  12. package/templates/src/components/codehooks/BunnyVideoSetup.tsx +6 -6
  13. package/templates/src/components/codehooks/EpinetDurationSelector.tsx +3 -3
  14. package/templates/src/components/codehooks/FeaturedArticleSetup.tsx +1 -1
  15. package/templates/src/components/codehooks/ListContentSetup.tsx +2 -2
  16. package/templates/src/components/codehooks/ProductCardSetup.tsx +1 -1
  17. package/templates/src/components/codehooks/ProductGridSetup.tsx +2 -2
  18. package/templates/src/components/codehooks/SandboxRegisterForm.tsx +3 -3
  19. package/templates/src/components/compositor/Compositor.tsx +25 -9
  20. package/templates/src/components/compositor/Node.tsx +168 -496
  21. package/templates/src/components/compositor/PanelVisibilityWrapper.tsx +1 -0
  22. package/templates/src/components/compositor/elements/SignUp.tsx +1 -1
  23. package/templates/src/components/compositor/elements/YouTubeWrapper.tsx +2 -0
  24. package/templates/src/components/compositor/nodes/CreativePane.tsx +262 -0
  25. package/templates/src/components/compositor/nodes/GhostInsertBlock.tsx +4 -6
  26. package/templates/src/components/compositor/nodes/GridLayout.tsx +4 -2
  27. package/templates/src/components/compositor/nodes/Markdown.tsx +18 -3
  28. package/templates/src/components/compositor/nodes/Pane.tsx +11 -5
  29. package/templates/src/components/compositor/nodes/RenderChildren.tsx +1 -1
  30. package/templates/src/components/compositor/nodes/tagElements/NodeAnchorComponent.tsx +5 -5
  31. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag.tsx +90 -42
  32. package/templates/src/components/compositor/nodes/tagElements/NodeImg.tsx +2 -0
  33. package/templates/src/components/compositor/nodes/tagElements/NodeText.tsx +27 -1
  34. package/templates/src/components/compositor/preview/PaneSnapshotGenerator.tsx +10 -8
  35. package/templates/src/components/compositor/tools/NodeOverlay.tsx +224 -0
  36. package/templates/src/components/compositor/tools/PaneOverlay.tsx +122 -0
  37. package/templates/src/components/edit/Header.tsx +68 -9
  38. package/templates/src/components/edit/PanelSwitch.tsx +42 -4
  39. package/templates/src/components/edit/SettingsPanel.tsx +2 -3
  40. package/templates/src/components/edit/ToolMode.tsx +1 -31
  41. package/templates/src/components/edit/pane/AddPanePanel_break.tsx +2 -2
  42. package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +1 -1
  43. package/templates/src/components/edit/pane/AddPanePanel_new.tsx +193 -659
  44. package/templates/src/components/edit/pane/AddPanePanel_reuse.tsx +15 -82
  45. package/templates/src/components/edit/pane/AiRestylePaneModal.tsx +95 -45
  46. package/templates/src/components/edit/pane/ConfigPanePanel.tsx +137 -49
  47. package/templates/src/components/edit/pane/RestylePaneModal.tsx +1 -1
  48. package/templates/src/components/edit/pane/steps/AiCreativeDesignStep.tsx +375 -0
  49. package/templates/src/components/edit/pane/steps/AiDesignStep.tsx +1 -23
  50. package/templates/src/components/edit/pane/steps/AiLibraryCopyStep.tsx +327 -0
  51. package/templates/src/components/edit/pane/steps/AiRefineDesignStep.tsx +267 -0
  52. package/templates/src/components/edit/pane/steps/AiStandardDesignStep.tsx +371 -0
  53. package/templates/src/components/edit/pane/steps/CopyInputStep.tsx +201 -76
  54. package/templates/src/components/edit/pane/steps/CreativeInjectStep.tsx +141 -0
  55. package/templates/src/components/edit/panels/CreativeImagePanel.tsx +435 -0
  56. package/templates/src/components/edit/panels/CreativeLinkPanel.tsx +110 -0
  57. package/templates/src/components/edit/panels/StyleCodeHookPanel.tsx +1 -1
  58. package/templates/src/components/edit/panels/StyleParentPanel.tsx +118 -126
  59. package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +3 -2
  60. package/templates/src/components/edit/panels/StyleParentPanel_deleteLayer.tsx +1 -0
  61. package/templates/src/components/edit/panels/StyleParentPanel_remove.tsx +3 -1
  62. package/templates/src/components/edit/panels/StyleParentPanel_update.tsx +3 -1
  63. package/templates/src/components/edit/panels/StyleWidgetPanel.tsx +1 -1
  64. package/templates/src/components/edit/state/SaveModal.tsx +19 -787
  65. package/templates/src/components/edit/state/SaveToLibraryModal.tsx +2 -2
  66. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_menu.tsx +1 -1
  67. package/templates/src/components/edit/widgets/BunnyWidget.tsx +5 -5
  68. package/templates/src/components/edit/widgets/InteractiveDisclosureWidget.tsx +1 -1
  69. package/templates/src/components/edit/widgets/SignupWidget.tsx +1 -1
  70. package/templates/src/components/fields/ActionBuilderTimeSelector.tsx +1 -1
  71. package/templates/src/components/fields/ArtpackImage.tsx +11 -3
  72. package/templates/src/components/fields/BackgroundImage.tsx +8 -0
  73. package/templates/src/components/fields/BackgroundImageWrapper.tsx +15 -9
  74. package/templates/src/components/fields/ImageUpload.tsx +6 -0
  75. package/templates/src/components/form/ActionBuilderField.tsx +15 -5
  76. package/templates/src/components/form/ActionBuilderSlugSelector.tsx +1 -1
  77. package/templates/src/components/form/ColorPicker.tsx +1 -1
  78. package/templates/src/components/form/EnumSelect.tsx +1 -1
  79. package/templates/src/components/form/NumberInput.tsx +1 -1
  80. package/templates/src/components/form/StringArrayInput.tsx +1 -1
  81. package/templates/src/components/form/StringInput.tsx +1 -1
  82. package/templates/src/components/form/UnsavedChangesBar.tsx +1 -1
  83. package/templates/src/components/form/advanced/APIConfigSection.tsx +2 -2
  84. package/templates/src/components/form/advanced/AuthConfigSection.tsx +2 -2
  85. package/templates/src/components/profile/ProfileCreate.tsx +1 -1
  86. package/templates/src/components/profile/ProfileEdit.tsx +1 -1
  87. package/templates/src/components/storykeep/Dashboard_Advanced.tsx +2 -2
  88. package/templates/src/components/storykeep/controls/content/BeliefForm.tsx +1 -1
  89. package/templates/src/components/storykeep/controls/content/ContentSummary.tsx +2 -2
  90. package/templates/src/components/storykeep/controls/content/KnownResourceTable.tsx +1 -1
  91. package/templates/src/components/storykeep/controls/content/ManageContent.tsx +6 -6
  92. package/templates/src/components/storykeep/controls/content/MenuForm.tsx +1 -1
  93. package/templates/src/components/storykeep/controls/content/PaneTable.tsx +358 -0
  94. package/templates/src/components/storykeep/controls/content/ResourceTable.tsx +1 -1
  95. package/templates/src/constants/prompts.json +18 -10
  96. package/templates/src/constants.ts +3 -0
  97. package/templates/src/hooks/usePaneFragments.ts +60 -0
  98. package/templates/src/lib/session.ts +71 -16
  99. package/templates/src/pages/[...slug].astro +4 -46
  100. package/templates/src/pages/api/css.ts +149 -0
  101. package/templates/src/pages/maint.astro +1 -1
  102. package/templates/src/pages/storykeep/login.astro +2 -2
  103. package/templates/src/stores/nodes.ts +162 -49
  104. package/templates/src/stores/orphanAnalysis.ts +6 -30
  105. package/templates/src/stores/previews.ts +7 -0
  106. package/templates/src/stores/storykeep.ts +0 -8
  107. package/templates/src/types/compositorTypes.ts +53 -10
  108. package/templates/src/utils/compositor/aiGeneration.ts +93 -0
  109. package/templates/src/utils/compositor/allowInsert.ts +2 -0
  110. package/templates/src/utils/compositor/htmlAst.ts +704 -0
  111. package/templates/src/utils/compositor/nodesHelper.ts +281 -102
  112. package/templates/src/utils/compositor/savePipeline.ts +893 -0
  113. package/templates/src/utils/etl/index.ts +3 -0
  114. package/templates/src/utils/etl/transformer.ts +10 -0
  115. package/templates/src/utils/helpers.ts +101 -0
  116. package/utils/inject-files.ts +100 -62
  117. package/templates/icons/text.svg +0 -6
  118. package/templates/src/components/compositor/NodeWithGuid.tsx +0 -69
  119. package/templates/src/components/compositor/nodes/GridLayout_eraser.tsx +0 -33
  120. package/templates/src/components/compositor/nodes/Markdown_eraser.tsx +0 -56
  121. package/templates/src/components/compositor/nodes/Pane_DesignLibrary.tsx +0 -269
  122. package/templates/src/components/compositor/nodes/Pane_eraser.tsx +0 -186
  123. package/templates/src/components/compositor/nodes/Pane_layout.tsx +0 -79
  124. package/templates/src/components/compositor/nodes/tagElements/NodeA_eraser.tsx +0 -26
  125. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_eraser.tsx +0 -61
  126. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_insert.tsx +0 -120
  127. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_settings.tsx +0 -62
  128. package/templates/src/components/compositor/nodes/tagElements/NodeButton_eraser.tsx +0 -26
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { fileURLToPath as d } from "node:url";
2
2
  import { dirname as i, resolve as l } from "node:path";
3
- import { existsSync as n, mkdirSync as x, copyFileSync as k, writeFileSync as u } from "node:fs";
3
+ import { existsSync as o, mkdirSync as x, copyFileSync as k, writeFileSync as u } from "node:fs";
4
4
  import { resolve as a } from "path";
5
5
  function b(t) {
6
6
  const e = i(d(t));
@@ -95,8 +95,16 @@ async function w(t, e, c) {
95
95
  dest: "src/components/compositor/Node.tsx"
96
96
  },
97
97
  {
98
- src: t("../templates/src/components/compositor/NodeWithGuid.tsx"),
99
- dest: "src/components/compositor/NodeWithGuid.tsx"
98
+ src: t(
99
+ "../templates/src/components/compositor/tools/NodeOverlay.tsx"
100
+ ),
101
+ dest: "src/components/compositor/tools/NodeOverlay.tsx"
102
+ },
103
+ {
104
+ src: t(
105
+ "../templates/src/components/compositor/tools/PaneOverlay.tsx"
106
+ ),
107
+ dest: "src/components/compositor/tools/PaneOverlay.tsx"
100
108
  },
101
109
  {
102
110
  src: t(
@@ -106,15 +114,15 @@ async function w(t, e, c) {
106
114
  },
107
115
  {
108
116
  src: t(
109
- "../templates/src/components/compositor/nodes/GridLayout.tsx"
117
+ "../templates/src/components/compositor/nodes/CreativePane.tsx"
110
118
  ),
111
- dest: "src/components/compositor/nodes/GridLayout.tsx"
119
+ dest: "src/components/compositor/nodes/CreativePane.tsx"
112
120
  },
113
121
  {
114
122
  src: t(
115
- "../templates/src/components/compositor/nodes/GridLayout_eraser.tsx"
123
+ "../templates/src/components/compositor/nodes/GridLayout.tsx"
116
124
  ),
117
- dest: "src/components/compositor/nodes/GridLayout_eraser.tsx"
125
+ dest: "src/components/compositor/nodes/GridLayout.tsx"
118
126
  },
119
127
  {
120
128
  src: t(
@@ -132,24 +140,6 @@ async function w(t, e, c) {
132
140
  src: t("../templates/src/components/compositor/nodes/Pane.tsx"),
133
141
  dest: "src/components/compositor/nodes/Pane.tsx"
134
142
  },
135
- {
136
- src: t(
137
- "../templates/src/components/compositor/nodes/Pane_eraser.tsx"
138
- ),
139
- dest: "src/components/compositor/nodes/Pane_eraser.tsx"
140
- },
141
- {
142
- src: t(
143
- "../templates/src/components/compositor/nodes/Pane_DesignLibrary.tsx"
144
- ),
145
- dest: "src/components/compositor/nodes/Pane_DesignLibrary.tsx"
146
- },
147
- {
148
- src: t(
149
- "../templates/src/components/compositor/nodes/Pane_layout.tsx"
150
- ),
151
- dest: "src/components/compositor/nodes/Pane_layout.tsx"
152
- },
153
143
  {
154
144
  src: t(
155
145
  "../templates/src/components/codehooks/SandboxRegisterForm.tsx"
@@ -160,12 +150,6 @@ async function w(t, e, c) {
160
150
  src: t("../templates/src/components/compositor/nodes/Markdown.tsx"),
161
151
  dest: "src/components/compositor/nodes/Markdown.tsx"
162
152
  },
163
- {
164
- src: t(
165
- "../templates/src/components/compositor/nodes/Markdown_eraser.tsx"
166
- ),
167
- dest: "src/components/compositor/nodes/Markdown_eraser.tsx"
168
- },
169
153
  {
170
154
  src: t(
171
155
  "../templates/src/components/compositor/nodes/BgPaneWrapper.tsx"
@@ -194,24 +178,6 @@ async function w(t, e, c) {
194
178
  ),
195
179
  dest: "src/components/compositor/nodes/tagElements/NodeBasicTag.tsx"
196
180
  },
197
- {
198
- src: t(
199
- "../templates/src/components/compositor/nodes/tagElements/NodeBasicTag_insert.tsx"
200
- ),
201
- dest: "src/components/compositor/nodes/tagElements/NodeBasicTag_insert.tsx"
202
- },
203
- {
204
- src: t(
205
- "../templates/src/components/compositor/nodes/tagElements/NodeBasicTag_eraser.tsx"
206
- ),
207
- dest: "src/components/compositor/nodes/tagElements/NodeBasicTag_eraser.tsx"
208
- },
209
- {
210
- src: t(
211
- "../templates/src/components/compositor/nodes/tagElements/NodeBasicTag_settings.tsx"
212
- ),
213
- dest: "src/components/compositor/nodes/tagElements/NodeBasicTag_settings.tsx"
214
- },
215
181
  {
216
182
  src: t(
217
183
  "../templates/src/components/compositor/nodes/tagElements/NodeText.tsx"
@@ -230,24 +196,12 @@ async function w(t, e, c) {
230
196
  ),
231
197
  dest: "src/components/compositor/nodes/tagElements/NodeA.tsx"
232
198
  },
233
- {
234
- src: t(
235
- "../templates/src/components/compositor/nodes/tagElements/NodeA_eraser.tsx"
236
- ),
237
- dest: "src/components/compositor/nodes/tagElements/NodeA_eraser.tsx"
238
- },
239
199
  {
240
200
  src: t(
241
201
  "../templates/src/components/compositor/nodes/tagElements/NodeButton.tsx"
242
202
  ),
243
203
  dest: "src/components/compositor/nodes/tagElements/NodeButton.tsx"
244
204
  },
245
- {
246
- src: t(
247
- "../templates/src/components/compositor/nodes/tagElements/NodeButton_eraser.tsx"
248
- ),
249
- dest: "src/components/compositor/nodes/tagElements/NodeButton_eraser.tsx"
250
- },
251
205
  {
252
206
  src: t(
253
207
  "../templates/src/components/compositor/nodes/tagElements/NodeImg.tsx"
@@ -482,6 +436,30 @@ async function w(t, e, c) {
482
436
  ),
483
437
  dest: "src/components/edit/pane/steps/CopyInputStep.tsx"
484
438
  },
439
+ {
440
+ src: t(
441
+ "../templates/src/components/edit/pane/steps/AiCreativeDesignStep.tsx"
442
+ ),
443
+ dest: "src/components/edit/pane/steps/AiCreativeDesignStep.tsx"
444
+ },
445
+ {
446
+ src: t(
447
+ "../templates/src/components/edit/pane/steps/AiStandardDesignStep.tsx"
448
+ ),
449
+ dest: "src/components/edit/pane/steps/AiStandardDesignStep.tsx"
450
+ },
451
+ {
452
+ src: t(
453
+ "../templates/src/components/edit/pane/steps/AiLibraryCopyStep.tsx"
454
+ ),
455
+ dest: "src/components/edit/pane/steps/AiLibraryCopyStep.tsx"
456
+ },
457
+ {
458
+ src: t(
459
+ "../templates/src/components/edit/pane/steps/AiRefineDesignStep.tsx"
460
+ ),
461
+ dest: "src/components/edit/pane/steps/AiRefineDesignStep.tsx"
462
+ },
485
463
  {
486
464
  src: t(
487
465
  "../templates/src/components/edit/pane/steps/DesignLibraryStep.tsx"
@@ -500,6 +478,12 @@ async function w(t, e, c) {
500
478
  ),
501
479
  dest: "src/components/edit/pane/steps/DirectInjectStep.tsx"
502
480
  },
481
+ {
482
+ src: t(
483
+ "../templates/src/components/edit/pane/steps/CreativeInjectStep.tsx"
484
+ ),
485
+ dest: "src/components/edit/pane/steps/CreativeInjectStep.tsx"
486
+ },
503
487
  {
504
488
  src: t(
505
489
  "../templates/src/components/edit/pane/AddPanePanel_newCustomCopy.tsx"
@@ -629,10 +613,22 @@ async function w(t, e, c) {
629
613
  dest: "src/utils/etl/loader.ts"
630
614
  },
631
615
  // Compositor utils
616
+ {
617
+ src: t("../templates/src/utils/compositor/savePipeline.ts"),
618
+ dest: "src/utils/compositor/savePipeline.ts"
619
+ },
632
620
  {
633
621
  src: t("../templates/src/utils/compositor/aiPaneParser.ts"),
634
622
  dest: "src/utils/compositor/aiPaneParser.ts"
635
623
  },
624
+ {
625
+ src: t("../templates/src/utils/compositor/aiGeneration.ts"),
626
+ dest: "src/utils/compositor/aiGeneration.ts"
627
+ },
628
+ {
629
+ src: t("../templates/src/utils/compositor/htmlAst.ts"),
630
+ dest: "src/utils/compositor/htmlAst.ts"
631
+ },
636
632
  {
637
633
  src: t(
638
634
  "../templates/src/utils/compositor/nodesMarkdownGenerator.ts"
@@ -710,6 +706,10 @@ async function w(t, e, c) {
710
706
  src: t("../templates/src/stores/storykeep.ts"),
711
707
  dest: "src/stores/storykeep.ts"
712
708
  },
709
+ {
710
+ src: t("../templates/src/stores/previews.ts"),
711
+ dest: "src/stores/previews.ts"
712
+ },
713
713
  {
714
714
  src: t("../templates/src/stores/analytics.ts"),
715
715
  dest: "src/stores/analytics.ts"
@@ -879,6 +879,10 @@ async function w(t, e, c) {
879
879
  src: t("../templates/src/pages/api/tailwind.ts"),
880
880
  dest: "src/pages/api/tailwind.ts"
881
881
  },
882
+ {
883
+ src: t("../templates/src/pages/api/css.ts"),
884
+ dest: "src/pages/api/css.ts"
885
+ },
882
886
  {
883
887
  src: t("../templates/src/pages/api/sandbox.ts"),
884
888
  dest: "src/pages/api/sandbox.ts"
@@ -947,6 +951,10 @@ async function w(t, e, c) {
947
951
  src: t("../templates/src/components/search/SearchResults.tsx"),
948
952
  dest: "src/components/search/SearchResults.tsx"
949
953
  },
954
+ {
955
+ src: t("../templates/src/hooks/usePaneFragments.ts"),
956
+ dest: "src/hooks/usePaneFragments.ts"
957
+ },
950
958
  {
951
959
  src: t("../templates/src/hooks/useSearch.ts"),
952
960
  dest: "src/hooks/useSearch.ts"
@@ -1169,6 +1177,12 @@ async function w(t, e, c) {
1169
1177
  ),
1170
1178
  dest: "src/components/storykeep/controls/content/StoryFragmentTable.tsx"
1171
1179
  },
1180
+ {
1181
+ src: t(
1182
+ "../templates/src/components/storykeep/controls/content/PaneTable.tsx"
1183
+ ),
1184
+ dest: "src/components/storykeep/controls/content/PaneTable.tsx"
1185
+ },
1172
1186
  {
1173
1187
  src: t(
1174
1188
  "../templates/src/components/storykeep/controls/content/ContentBrowser.tsx"
@@ -1394,6 +1408,18 @@ async function w(t, e, c) {
1394
1408
  src: t("../templates/src/components/edit/state/StylesMemory.tsx"),
1395
1409
  dest: "src/components/edit/state/StylesMemory.tsx"
1396
1410
  },
1411
+ {
1412
+ src: t(
1413
+ "../templates/src/components/edit/panels/CreativeImagePanel.tsx"
1414
+ ),
1415
+ dest: "src/components/edit/panels/CreativeImagePanel.tsx"
1416
+ },
1417
+ {
1418
+ src: t(
1419
+ "../templates/src/components/edit/panels/CreativeLinkPanel.tsx"
1420
+ ),
1421
+ dest: "src/components/edit/panels/CreativeLinkPanel.tsx"
1422
+ },
1397
1423
  {
1398
1424
  src: t(
1399
1425
  "../templates/src/components/edit/panels/StyleWordCarouselPanel.tsx"
@@ -1997,8 +2023,20 @@ async function w(t, e, c) {
1997
2023
  dest: "public/icons/image.svg"
1998
2024
  },
1999
2025
  {
2000
- src: t("../templates/icons/text.svg"),
2001
- dest: "public/icons/text.svg"
2026
+ src: t("../templates/icons/link.svg"),
2027
+ dest: "public/icons/link.svg"
2028
+ },
2029
+ {
2030
+ src: t("../templates/icons/p.svg"),
2031
+ dest: "public/icons/p.svg"
2032
+ },
2033
+ {
2034
+ src: t("../templates/icons/li.svg"),
2035
+ dest: "public/icons/li.svg"
2036
+ },
2037
+ {
2038
+ src: t("../templates/icons/code.svg"),
2039
+ dest: "public/icons/code.svg"
2002
2040
  },
2003
2041
  // Social Icons
2004
2042
  {
@@ -2157,22 +2195,22 @@ async function w(t, e, c) {
2157
2195
  for (const s of r)
2158
2196
  try {
2159
2197
  const p = i(s.dest);
2160
- n(p) || x(p, { recursive: !0 });
2161
- const o = !s.protected && (s.dest === "tailwind.config.cjs" || s.dest.startsWith("src/components/codehooks/") || s.dest.startsWith("src/components/widgets/") || s.dest.startsWith("src/") || s.dest.startsWith("public/client/") || s.dest === ".gitignore");
2162
- if (!n(s.dest) || o)
2163
- if (n(s.src))
2198
+ o(p) || x(p, { recursive: !0 });
2199
+ const n = !s.protected && (s.dest === "tailwind.config.cjs" || s.dest.startsWith("src/components/codehooks/") || s.dest.startsWith("src/components/widgets/") || s.dest.startsWith("src/") || s.dest.startsWith("public/client/") || s.dest === ".gitignore");
2200
+ if (!o(s.dest) || n)
2201
+ if (o(s.src))
2164
2202
  k(s.src, s.dest), e.info(`Updated ${s.dest}`);
2165
2203
  else {
2166
- const m = _(s.dest);
2204
+ const m = y(s.dest);
2167
2205
  u(s.dest, m), e.info(`Created placeholder ${s.dest}`);
2168
2206
  }
2169
2207
  else s.protected ? e.info(`Protected: ${s.dest} (skipped overwrite)`) : e.info(`Skipped existing ${s.dest}`);
2170
2208
  } catch (p) {
2171
- const o = p instanceof Error ? p.message : String(p);
2172
- e.error(`Failed to create ${s.dest}: ${o}`);
2209
+ const n = p instanceof Error ? p.message : String(p);
2210
+ e.error(`Failed to create ${s.dest}: ${n}`);
2173
2211
  }
2174
2212
  }
2175
- function _(t) {
2213
+ function y(t) {
2176
2214
  return t.endsWith(".astro") ? `---
2177
2215
  // TractStack placeholder component
2178
2216
  ---
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "astro-tractstack",
3
- "version": "2.1.3",
4
- "description": "Astro integration for TractStack - the digital experience platform (DXP) for the missing middle",
3
+ "version": "2.2.0",
4
+ "description": "Astro integration for TractStack - the free web press by At Risk Media",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
@@ -74,6 +74,8 @@
74
74
  "html-to-image": "^1.11.13",
75
75
  "nanostores": "^1.1.0",
76
76
  "player.js": "^0.1.0",
77
+ "postcss": "^8.5.6",
78
+ "postcss-selector-parser": "^7.1.1",
77
79
  "prettier": "3.7.4",
78
80
  "prettier-plugin-astro": "0.14.1",
79
81
  "prettier-plugin-tailwindcss": "0.7.2",
@@ -43,3 +43,8 @@ body {
43
43
  @media (prefers-reduced-motion) {
44
44
  scroll-behavior: auto;
45
45
  }
46
+
47
+ /* Force lite-youtube to fill the container, overriding the 720px library limit */
48
+ lite-youtube {
49
+ max-width: 100% !important;
50
+ }
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
3
+ viewBox="0 0 122.88 122.151" width="512" height="273.292" preserveAspectRatio="xMidYMid meet">
4
+ <g>
5
+ <path fill-rule="evenodd" clip-rule="evenodd" d="
6
+ M8.676,0h105.529c2.405,0,4.557,0.984,6.124,2.552c1.567,1.567,2.551,3.754,2.551,6.124v104.8
7
+ c0,2.405-0.983,4.557-2.551,6.124c-1.568,1.567-3.755,2.552-6.124,2.552H8.676
8
+ c-2.406,0-4.557-0.984-6.124-2.553C0.984,118.032,0,115.845,0,113.476V8.675
9
+ C0,6.27,0.984,4.119,2.552,2.552C4.12,0.984,6.307,0,8.676,0L8.676,0z
10
+
11
+ M11,11 h100.88 v100.15 h-100.88 z
12
+
13
+ M40,35 L20,61 L40,87 L48,80 L32,61 L48,42 Z
14
+ M82,35 L102,61 L82,87 L74,80 L90,61 L74,42 Z
15
+ M66,30 L56,92 H64 L74,30 Z
16
+ "/>
17
+ </g>
18
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 330 276">
2
+ <path fill-rule="nonzero" d="M0 6.464h86.198v183.162h103.802v86.198H0z"/>
3
+ <path fill-rule="nonzero" d="M235 6.464h86.198v269.36H235z"/>
4
+ </svg>
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
3
+ viewBox="0 0 122.88 122.151" width="512" height="273.292" preserveAspectRatio="xMidYMid meet">
4
+ <g>
5
+ <path fill-rule="evenodd" clip-rule="evenodd" d="
6
+ M8.676,0h105.529c2.405,0,4.557,0.984,6.124,2.552c1.567,1.567,2.551,3.754,2.551,6.124v104.8
7
+ c0,2.405-0.983,4.557-2.551,6.124c-1.568,1.567-3.755,2.552-6.124,2.552H8.676
8
+ c-2.406,0-4.557-0.984-6.124-2.553C0.984,118.032,0,115.845,0,113.476V8.675
9
+ C0,6.27,0.984,4.119,2.552,2.552C4.12,0.984,6.307,0,8.676,0L8.676,0z
10
+
11
+ M11,11 h100.88 v100.15 h-100.88 z
12
+
13
+ M78.5,33.5 l-10,10 l6,6 l10-10 c4.4-4.4,4.4-11.6,0-16 c-4.4-4.4-11.6-4.4-16,0
14
+ L58.5,33.5 l6,6 l10-10 C76,28,77,28,78.5,29.5 C80,31,80,32,78.5,33.5 z
15
+
16
+ M67.5,42.5 l-6,6 l16,16 l6-6 L67.5,42.5 z
17
+
18
+ M44.5,67.5 l10-10 l-6-6 l-10,10 c-4.4,4.4-4.4,11.6,0,16 c4.4,4.4,11.6,4.4,16,0
19
+ l10-10 l-6-6 l-10,10 C47,73,46,73,44.5,71.5 C43,70,43,69,44.5,67.5 z
20
+ "/>
21
+ </g>
22
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 260 276">
2
+ <path fill="black" fill-rule="evenodd" d="M0 275.824V0h160c45 0 85 20 85 90.29 0 70.29-40 90.29-85 90.29H86.198v95.244H0z M86.198 58v64.58h65c15 0 25-10 25-32.29 0-22.29-10-32.29-25-32.29h-65z"/>
3
+ </svg>
@@ -27,8 +27,69 @@ if (!window.TractStackApp) {
27
27
 
28
28
  initialize(config) {
29
29
  log('Initializing with config from first page load.', config);
30
+
31
+ // 1. Capture the existing local session BEFORE we potentially overwrite it
32
+ // This is the "Memory" the Healer uses.
33
+ const localSessionId = localStorage.getItem('tractstack_session_id');
34
+
30
35
  this.config = config;
31
- if (config.sessionId && !this.eventSource) {
36
+
37
+ // 2. Pass the captured local ID into the reconciliation logic
38
+ this.reconcileAndStart(localSessionId);
39
+ },
40
+
41
+ async reconcileAndStart(lsSession) {
42
+ const ssrSession = this.config.sessionId;
43
+
44
+ // Check for Split-Brain (LocalStorage has an ID that doesn't match what Astro sent)
45
+ if (lsSession && lsSession !== ssrSession) {
46
+ log(
47
+ 'Session mismatch detected (Split-Brain). Attempting reconciliation.',
48
+ {
49
+ local: lsSession,
50
+ server: ssrSession,
51
+ }
52
+ );
53
+
54
+ try {
55
+ const response = await fetch(
56
+ `${this.config.backendUrl}/api/v1/auth/visit`,
57
+ {
58
+ method: 'POST',
59
+ headers: {
60
+ 'X-Tenant-ID': this.config.tenantId,
61
+ 'Content-Type': 'application/json',
62
+ },
63
+ body: JSON.stringify({ sessionId: lsSession }),
64
+ }
65
+ );
66
+
67
+ if (response.ok) {
68
+ const data = await response.json();
69
+ log('Reconciliation successful. Switching to local session.', data);
70
+
71
+ // This function handles updating Cookies AND LocalStorage
72
+ this.updateSession(data.sessionId, data.fingerprint);
73
+ return; // EXIT HERE so we don't overwrite with the server session below
74
+ } else {
75
+ log(
76
+ 'Reconciliation failed (session likely expired). Adopting server session.'
77
+ );
78
+ }
79
+ } catch (e) {
80
+ logError('Reconciliation network error.', e);
81
+ }
82
+ }
83
+
84
+ // 3. Finalize state: Persist the "Winner" to LocalStorage
85
+ // This runs if:
86
+ // A) There was no mismatch (Clean Start) -> Seeds the storage
87
+ // B) Reconciliation failed -> Resets storage to new Server ID
88
+ if (ssrSession) {
89
+ localStorage.setItem('tractstack_session_id', ssrSession);
90
+ }
91
+
92
+ if (this.config.sessionId && !this.eventSource) {
32
93
  this.startSSE();
33
94
  } else {
34
95
  log(
@@ -37,6 +98,24 @@ if (!window.TractStackApp) {
37
98
  }
38
99
  },
39
100
 
101
+ updateSession(sessionId, fingerprintId) {
102
+ document.cookie = `tractstack_session_id=${sessionId}; path=/; SameSite=Lax; max-age=86400`;
103
+ if (fingerprintId) {
104
+ document.cookie = `tractstack_fingerprint=${fingerprintId}; path=/; SameSite=Lax; max-age=31536000`;
105
+ }
106
+
107
+ this.config.sessionId = sessionId;
108
+ if (fingerprintId) this.config.fingerprintId = fingerprintId;
109
+
110
+ localStorage.setItem('tractstack_session_id', sessionId);
111
+
112
+ if (this.eventSource) {
113
+ this.eventSource.close();
114
+ this.eventSource = null;
115
+ }
116
+ this.startSSE();
117
+ },
118
+
40
119
  updateConfig(newConfig) {
41
120
  const oldStoryfragmentId = this.config.storyfragmentId;
42
121
  this.config = { ...this.config, ...newConfig };
@@ -171,7 +171,7 @@ const createdDate = created ? new Date(created) : new Date();
171
171
  >
172
172
  Tract Stack</a
173
173
  >
174
- &ndash; the &#8220;free web press&#8221; by{` `}
174
+ &ndash; the &#8220;free web&#8221; press by{` `}
175
175
  <a
176
176
  href="https://atriskmedia.com/?utm_source=tractstack&utm_medium=www&utm_campaign=community"
177
177
  class="font-bold underline hover:text-black"
@@ -353,7 +353,7 @@ const BunnyVideoSetup = ({ nodeId, params }: BunnyVideoSetupProps) => {
353
353
  <input
354
354
  type="text"
355
355
  id="videoUrl"
356
- className={`sm:text-sm block w-full rounded-md border-gray-300 px-2.5 py-1.5 pr-10 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 ${videoUrl && !isValidBunnyUrl(videoUrl) ? 'border-red-300 focus:border-red-500 focus:ring-red-500' : ''}`}
356
+ className={`block w-full rounded-md border-gray-300 px-2.5 py-1.5 pr-10 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 md:text-sm ${videoUrl && !isValidBunnyUrl(videoUrl) ? 'border-red-300 focus:border-red-500 focus:ring-red-500' : ''}`}
357
357
  value={videoUrl}
358
358
  onChange={(e) => setVideoUrl(e.target.value)}
359
359
  onKeyDown={(e) => {
@@ -396,7 +396,7 @@ const BunnyVideoSetup = ({ nodeId, params }: BunnyVideoSetupProps) => {
396
396
  <input
397
397
  type="text"
398
398
  id="videoTitle"
399
- className="sm:text-sm mt-1 block w-full rounded-md border-gray-300 px-2.5 py-1.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500"
399
+ className="mt-1 block w-full rounded-md border-gray-300 px-2.5 py-1.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 md:text-sm"
400
400
  value={videoTitle}
401
401
  onChange={(e) => setVideoTitle(e.target.value)}
402
402
  onKeyDown={(e) => {
@@ -524,7 +524,7 @@ const BunnyVideoSetup = ({ nodeId, params }: BunnyVideoSetupProps) => {
524
524
  }
525
525
  }}
526
526
  onBlur={() => saveChanges()}
527
- className={`sm:text-sm mt-1 block w-full rounded-md border-gray-300 px-2.5 py-1.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 ${
527
+ className={`mt-1 block w-full rounded-md border-gray-300 px-2.5 py-1.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 md:text-sm ${
528
528
  formErrors[`title-${index}`] ? 'border-red-300' : ''
529
529
  }`}
530
530
  />
@@ -551,7 +551,7 @@ const BunnyVideoSetup = ({ nodeId, params }: BunnyVideoSetupProps) => {
551
551
  }
552
552
  }}
553
553
  onBlur={() => saveChanges()}
554
- className="sm:text-sm mt-1 block w-full rounded-md border-gray-300 px-2.5 py-1.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500"
554
+ className="mt-1 block w-full rounded-md border-gray-300 px-2.5 py-1.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 md:text-sm"
555
555
  />
556
556
  </div>
557
557
  </div>
@@ -577,7 +577,7 @@ const BunnyVideoSetup = ({ nodeId, params }: BunnyVideoSetupProps) => {
577
577
  e.currentTarget.blur();
578
578
  }
579
579
  }}
580
- className={`sm:text-sm mt-1 block w-full rounded-md border-gray-300 px-2.5 py-1.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 ${
580
+ className={`mt-1 block w-full rounded-md border-gray-300 px-2.5 py-1.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 md:text-sm ${
581
581
  formErrors[`startTime-${index}`]
582
582
  ? 'border-red-300'
583
583
  : ''
@@ -611,7 +611,7 @@ const BunnyVideoSetup = ({ nodeId, params }: BunnyVideoSetupProps) => {
611
611
  e.currentTarget.blur();
612
612
  }
613
613
  }}
614
- className={`sm:text-sm mt-1 block w-full rounded-md border-gray-300 px-2.5 py-1.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 ${
614
+ className={`mt-1 block w-full rounded-md border-gray-300 px-2.5 py-1.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 md:text-sm ${
615
615
  formErrors[`endTime-${index}`] ? 'border-red-300' : ''
616
616
  }`}
617
617
  placeholder="60"
@@ -607,7 +607,7 @@ const EpinetDurationSelector = ({
607
607
  : 'Select date range'}
608
608
  </button>
609
609
  {isDatePickerOpen && (
610
- <div className="sm:w-auto absolute z-10 mt-1 w-full rounded-md bg-white p-2 shadow-lg">
610
+ <div className="absolute z-10 mt-1 w-full rounded-md bg-white p-2 shadow-lg md:w-auto">
611
611
  <div className="mb-2 flex flex-wrap justify-between gap-2">
612
612
  <button
613
613
  className="rounded-md p-1 text-sm hover:bg-gray-100"
@@ -642,7 +642,7 @@ const EpinetDurationSelector = ({
642
642
  End date: {formatDateDisplay(endDate)}
643
643
  </p>
644
644
  </div>
645
- <div className="sm:flex-row flex flex-col gap-4">
645
+ <div className="flex flex-col gap-4 md:flex-row">
646
646
  <div className="flex-1">
647
647
  <label
648
648
  htmlFor="start-date"
@@ -884,7 +884,7 @@ const EpinetDurationSelector = ({
884
884
  className={`fixed bottom-0 left-0 right-0 z-50 transform pr-12 transition-all duration-300 ease-in-out ${isAnimating ? 'translate-y-0 opacity-100' : 'translate-y-full opacity-0'}`}
885
885
  >
886
886
  <div className="absolute inset-0 bg-black/10 backdrop-blur-sm" />
887
- <div className="sm:px-6 lg:px-8 relative mx-auto max-w-7xl px-4 py-4">
887
+ <div className="relative mx-auto max-w-7xl px-4 py-4 md:px-6 xl:px-8">
888
888
  <div
889
889
  className={`flex items-center justify-between rounded-lg border px-6 py-4 shadow-lg ${styling.bgColor} ${styling.borderColor}`}
890
890
  >
@@ -264,7 +264,7 @@ const FeaturedArticleSetup = ({
264
264
  />
265
265
  </Combobox.Trigger>
266
266
  </div>
267
- <Combobox.Content className="sm:text-sm absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
267
+ <Combobox.Content className="absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none md:text-sm">
268
268
  {collection.items.map((item) => (
269
269
  <Combobox.Item
270
270
  key={item.slug}
@@ -288,7 +288,7 @@ const ListContentSetup = ({ params, nodeId }: ListContentSetupProps) => {
288
288
  <input
289
289
  type="text"
290
290
  id="list-title"
291
- className="sm:text-sm mt-1 block w-full rounded-md border-gray-300 px-3 py-2 shadow-sm focus:border-cyan-600 focus:ring-cyan-600"
291
+ className="mt-1 block w-full rounded-md border-gray-300 px-3 py-2 shadow-sm focus:border-cyan-600 focus:ring-cyan-600 md:text-sm"
292
292
  value={title}
293
293
  onChange={(e) => setTitle(e.target.value)}
294
294
  placeholder="e.g., Recent Articles"
@@ -305,7 +305,7 @@ const ListContentSetup = ({ params, nodeId }: ListContentSetupProps) => {
305
305
  <select
306
306
  id="page-size"
307
307
  name="page-size"
308
- className="sm:text-sm mt-1 block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-base focus:border-cyan-600 focus:outline-none focus:ring-cyan-600"
308
+ className="mt-1 block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-base focus:border-cyan-600 focus:outline-none focus:ring-cyan-600 md:text-sm"
309
309
  value={pageSize}
310
310
  onChange={(e) => handlePageSizeChange(parseInt(e.target.value))}
311
311
  >
@@ -121,7 +121,7 @@ export const ProductCardSetup = (props: ProductCardSetupProps) => {
121
121
  </Combobox.Label>
122
122
  <Combobox.Control>
123
123
  <Combobox.Input
124
- className="sm:text-sm w-full rounded-md border-gray-300 px-3 py-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500"
124
+ className="w-full rounded-md border-gray-300 px-3 py-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 md:text-sm"
125
125
  placeholder="Search products..."
126
126
  />
127
127
  </Combobox.Control>
@@ -198,7 +198,7 @@ export const ProductGridSetup = (props: ProductGridSetupProps) => {
198
198
  value={productType}
199
199
  onChange={(e) => setProductType(e.target.value)}
200
200
  placeholder="e.g., 'electronics'"
201
- className="sm:text-sm w-full rounded-md border-gray-300 px-3 py-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500"
201
+ className="w-full rounded-md border-gray-300 px-3 py-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 md:text-sm"
202
202
  />
203
203
  </div>
204
204
  )}
@@ -238,7 +238,7 @@ export const ProductGridSetup = (props: ProductGridSetupProps) => {
238
238
  </Combobox.Label>
239
239
  <Combobox.Control>
240
240
  <Combobox.Input
241
- className="sm:text-sm w-full rounded-md border-gray-300 px-3 py-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500"
241
+ className="w-full rounded-md border-gray-300 px-3 py-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 md:text-sm"
242
242
  placeholder="Search products..."
243
243
  />
244
244
  </Combobox.Control>