astro-tractstack 2.0.0-rc.8 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -97
- package/README.md +7 -5
- package/bin/create-tractstack.js +35 -11
- package/dist/index.js +106 -29
- package/package.json +10 -5
- package/templates/css/frontend.css +1 -1
- package/templates/custom/minimal/CodeHook.astro +13 -12
- package/templates/custom/minimal/CustomRoutes.astro +25 -31
- package/templates/custom/with-examples/CodeHook.astro +22 -11
- package/templates/custom/with-examples/CustomRoutes.astro +4 -8
- package/templates/custom/with-examples/ProductCard.astro +29 -0
- package/templates/custom/with-examples/ProductCardWrapper.astro +43 -0
- package/templates/custom/with-examples/ProductGrid.astro +64 -0
- package/templates/custom/with-examples/pages/Collections.astro +58 -98
- package/templates/gitignore +42 -0
- package/templates/prettierignore +5 -0
- package/templates/prettierrc +19 -0
- package/templates/src/client/app.js +127 -0
- package/templates/src/client/htmx.min.js +3519 -0
- package/templates/src/client/view.js +429 -0
- package/templates/src/components/Footer.astro +4 -9
- package/templates/src/components/Header.astro +67 -60
- package/templates/src/components/Menu.tsx +188 -52
- package/templates/src/components/codehooks/BunnyVideoSetup.tsx +2 -2
- package/templates/src/components/codehooks/EpinetDurationSelector.tsx +9 -13
- package/templates/src/components/codehooks/EpinetTableView.tsx +11 -7
- package/templates/src/components/codehooks/EpinetWrapper.tsx +1 -0
- package/templates/src/components/codehooks/FeaturedArticle.astro +105 -0
- package/templates/src/components/codehooks/FeaturedArticleSetup.tsx +318 -0
- package/templates/src/components/codehooks/ListContent.astro +32 -162
- package/templates/src/components/codehooks/ListContentSetup.tsx +43 -138
- package/templates/src/components/codehooks/ProductCardSetup.tsx +152 -0
- package/templates/src/components/codehooks/ProductGridSetup.tsx +274 -0
- package/templates/src/components/codehooks/SearchWidget.tsx +453 -0
- package/templates/src/components/compositor/Node.tsx +3 -6
- package/templates/src/components/compositor/PanelVisibilityWrapper.tsx +21 -11
- package/templates/src/components/compositor/elements/BunnyVideo.tsx +21 -20
- package/templates/src/components/compositor/nodes/Pane.tsx +51 -21
- package/templates/src/components/compositor/nodes/RenderChildren.tsx +6 -1
- package/templates/src/components/compositor/nodes/Widget.tsx +16 -2
- package/templates/src/components/compositor/preview/FeaturedArticlePreview.tsx +155 -0
- package/templates/src/components/compositor/preview/PaneSnapshotGenerator.tsx +20 -1
- package/templates/src/components/edit/Header.tsx +10 -4
- package/templates/src/components/edit/PanelSwitch.tsx +11 -7
- package/templates/src/components/edit/SettingsPanel.tsx +29 -18
- package/templates/src/components/edit/ToolBar.tsx +1 -28
- package/templates/src/components/edit/ToolMode.tsx +45 -32
- package/templates/src/components/edit/pane/AddPanePanel_break.tsx +12 -2
- package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +8 -2
- package/templates/src/components/edit/pane/AddPanePanel_newAICopy_modal.tsx +1 -1
- package/templates/src/components/edit/pane/ConfigPanePanel.tsx +17 -27
- package/templates/src/components/edit/pane/PageGenSelector.tsx +16 -16
- package/templates/src/components/edit/pane/PageGenSpecial.tsx +26 -49
- package/templates/src/components/edit/pane/PageGen_preview.tsx +17 -2
- package/templates/src/components/edit/pane/PanePanel_path.tsx +2 -4
- package/templates/src/components/edit/pane/PanePanel_title.tsx +243 -76
- package/templates/src/components/edit/panels/StyleBreakPanel.tsx +17 -19
- package/templates/src/components/edit/panels/StyleCodeHookPanel.tsx +48 -37
- package/templates/src/components/edit/panels/StyleElementPanel_add.tsx +60 -55
- package/templates/src/components/edit/panels/StyleImagePanel_add.tsx +56 -50
- package/templates/src/components/edit/panels/StyleLiElementPanel_add.tsx +54 -47
- package/templates/src/components/edit/panels/StyleLinkPanel_add.tsx +54 -44
- package/templates/src/components/edit/panels/StyleLinkPanel_config.tsx +113 -138
- package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +54 -40
- package/templates/src/components/edit/panels/StyleWidgetPanel.tsx +3 -3
- package/templates/src/components/edit/panels/StyleWidgetPanel_add.tsx +56 -49
- package/templates/src/components/edit/panels/StyleWidgetPanel_config.tsx +14 -5
- package/templates/src/components/edit/state/SaveModal.tsx +316 -169
- package/templates/src/components/edit/storyfragment/StoryFragmentPanel_og.tsx +1 -1
- package/templates/src/components/edit/storyfragment/StoryFragmentPanel_slug.tsx +56 -55
- package/templates/src/components/edit/widgets/BunnyWidget.tsx +538 -59
- package/templates/src/components/edit/widgets/InteractiveDisclosureWidget.tsx +656 -0
- package/templates/src/components/edit/widgets/ToggleWidget.tsx +9 -16
- package/templates/src/components/fields/ArtpackImage.tsx +4 -1
- package/templates/src/components/fields/BackgroundImage.tsx +1 -1
- package/templates/src/components/fields/BackgroundImageWrapper.tsx +127 -35
- package/templates/src/components/fields/ColorPickerCombo.tsx +66 -62
- package/templates/src/components/fields/ImageUpload.tsx +1 -1
- package/templates/src/components/fields/ViewportComboBox.tsx +59 -42
- package/templates/src/components/form/ActionBuilderBeliefSelector.tsx +117 -0
- package/templates/src/components/form/ActionBuilderField.tsx +306 -87
- package/templates/src/components/search/SearchModal.tsx +420 -0
- package/templates/src/components/search/SearchResults.tsx +367 -0
- package/templates/src/components/search/SearchWrapper.tsx +46 -0
- package/templates/src/components/storykeep/Dashboard_Advanced.tsx +1 -1
- package/templates/src/components/storykeep/Dashboard_Analytics.tsx +34 -8
- package/templates/src/components/storykeep/Dashboard_Content.tsx +6 -0
- package/templates/src/components/storykeep/StoryKeepBackdrop.astro +87 -0
- package/templates/src/components/storykeep/controls/content/BeliefForm.tsx +37 -33
- package/templates/src/components/storykeep/controls/content/MenuForm.tsx +55 -7
- package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +17 -2
- package/templates/src/components/storykeep/controls/content/StoryFragmentTable.tsx +5 -8
- package/templates/src/components/storykeep/state/FetchAnalytics.tsx +274 -228
- package/templates/src/components/storykeep/widgets/Wizard.tsx +14 -7
- package/templates/src/components/tenant/RegistrationForm.tsx +1 -1
- package/templates/src/components/widgets/ImpressionWrapper.tsx +0 -1
- package/templates/src/constants/shapes.ts +9 -0
- package/templates/src/constants.ts +2121 -16
- package/templates/src/hooks/useSearch.ts +228 -0
- package/templates/src/layouts/Layout.astro +213 -104
- package/templates/src/lib/storyData.ts +4 -1
- package/templates/src/pages/[...slug]/edit.astro +14 -14
- package/templates/src/pages/[...slug].astro +82 -21
- package/templates/src/pages/api/orphan-analysis.ts +0 -1
- package/templates/src/pages/api/tailwind.ts +23 -21
- package/templates/src/pages/context/[...contextSlug]/edit.astro +14 -14
- package/templates/src/pages/context/[...contextSlug].astro +7 -2
- package/templates/src/pages/storykeep/advanced.astro +5 -4
- package/templates/src/pages/storykeep/branding.astro +5 -4
- package/templates/src/pages/storykeep/content.astro +5 -4
- package/templates/src/pages/storykeep/init.astro +40 -1
- package/templates/src/pages/storykeep/login.astro +1 -1
- package/templates/src/pages/storykeep.astro +5 -4
- package/templates/src/stores/nodes.ts +59 -88
- package/templates/src/stores/orphanAnalysis.ts +19 -21
- package/templates/src/stores/storykeep.ts +7 -0
- package/templates/src/types/compositorTypes.ts +6 -0
- package/templates/src/types/tractstack.ts +17 -0
- package/templates/src/utils/actions/lispLexer.ts +2 -2
- package/templates/src/utils/actions/preParse_Action.ts +3 -0
- package/templates/src/utils/api/beliefHelpers.ts +12 -36
- package/templates/src/utils/api/menuHelpers.ts +2 -2
- package/templates/src/utils/api.ts +26 -0
- package/templates/src/utils/compositor/TemplateNodes.ts +7 -0
- package/templates/src/utils/compositor/allowInsert.ts +5 -3
- package/templates/src/utils/compositor/nodesHelper.ts +4 -0
- package/templates/src/utils/compositor/processMarkdown.ts +16 -2
- package/templates/src/utils/compositor/reduceNodesClassNames.ts +4 -0
- package/templates/src/utils/compositor/templateMarkdownStyles.ts +13 -13
- package/templates/src/utils/compositor/typeGuards.ts +1 -0
- package/templates/src/utils/customHelpers.ts +38 -0
- package/templates/src/utils/helpers.ts +2 -2
- package/templates/src/utils/layout.ts +65 -144
- package/utils/inject-files.ts +95 -18
- package/templates/src/client/analytics-events.js +0 -207
- package/templates/src/client/belief-events.js +0 -191
- package/templates/src/client/sse.js +0 -613
- package/templates/src/components/codehooks/FeaturedContent.astro +0 -273
- package/templates/src/components/codehooks/FeaturedContentSetup.tsx +0 -738
- package/templates/src/components/compositor/preview/FeaturedContentPreview.tsx +0 -128
- package/templates/src/components/edit/pane/PanePanel_slug.tsx +0 -219
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { useRef, useEffect } from 'react';
|
|
2
2
|
import { useStore } from '@nanostores/react';
|
|
3
3
|
import PencilSquareIcon from '@heroicons/react/24/outline/PencilSquareIcon';
|
|
4
4
|
import PaintBrushIcon from '@heroicons/react/24/outline/PaintBrushIcon';
|
|
@@ -41,12 +41,6 @@ const storykeepToolModes = [
|
|
|
41
41
|
title: 'Move',
|
|
42
42
|
description: 'Keyboard accessible re-order',
|
|
43
43
|
},
|
|
44
|
-
{
|
|
45
|
-
key: 'debug' as const,
|
|
46
|
-
Icon: BugAntIcon,
|
|
47
|
-
title: 'Debug',
|
|
48
|
-
description: 'Debug node ids',
|
|
49
|
-
},
|
|
50
44
|
] as const;
|
|
51
45
|
|
|
52
46
|
interface StoryKeepToolModeProps {
|
|
@@ -54,9 +48,10 @@ interface StoryKeepToolModeProps {
|
|
|
54
48
|
}
|
|
55
49
|
|
|
56
50
|
const StoryKeepToolMode = ({ isContext }: StoryKeepToolModeProps) => {
|
|
57
|
-
//const signal = useStore(settingsPanelStore);
|
|
58
51
|
const ctx = getCtx();
|
|
59
52
|
const { value: toolModeVal } = useStore(ctx.toolModeValStore);
|
|
53
|
+
const showGuids = useStore(ctx.showGuids);
|
|
54
|
+
const navRef = useRef<HTMLElement>(null);
|
|
60
55
|
|
|
61
56
|
const hasTitle = useStore(ctx.hasTitle);
|
|
62
57
|
const hasPanes = useStore(ctx.hasPanes);
|
|
@@ -64,6 +59,8 @@ const StoryKeepToolMode = ({ isContext }: StoryKeepToolModeProps) => {
|
|
|
64
59
|
const className =
|
|
65
60
|
'w-8 h-8 py-1 rounded-xl bg-white text-myblue hover:bg-mygreen/20 hover:text-black hover:rotate-3 cursor-pointer transition-all';
|
|
66
61
|
const classNameActive = 'w-8 h-8 py-1.5 rounded-md bg-myblue text-white';
|
|
62
|
+
const classNameDebugActive =
|
|
63
|
+
'w-8 h-8 py-1.5 rounded-md bg-orange-500 text-white';
|
|
67
64
|
|
|
68
65
|
const currentToolMode =
|
|
69
66
|
storykeepToolModes.find((mode) => mode.key === toolModeVal) ??
|
|
@@ -72,49 +69,65 @@ const StoryKeepToolMode = ({ isContext }: StoryKeepToolModeProps) => {
|
|
|
72
69
|
const handleClick = (mode: ToolModeVal) => {
|
|
73
70
|
settingsPanelStore.set(null);
|
|
74
71
|
ctx.toolModeValStore.set({ value: mode });
|
|
75
|
-
ctx.showGuids.set(mode === `debug`);
|
|
76
72
|
ctx.notifyNode('root');
|
|
77
73
|
};
|
|
78
74
|
|
|
79
|
-
|
|
75
|
+
const handleDebugToggle = () => {
|
|
76
|
+
ctx.showGuids.set(!showGuids);
|
|
77
|
+
ctx.notifyNode('root');
|
|
78
|
+
};
|
|
79
|
+
|
|
80
80
|
useEffect(() => {
|
|
81
81
|
const handleEscapeKey = (event: KeyboardEvent) => {
|
|
82
82
|
if (event.key === 'Escape') {
|
|
83
83
|
ctx.toolModeValStore.set({ value: 'text' });
|
|
84
|
-
|
|
84
|
+
ctx.notifyNode('root');
|
|
85
85
|
}
|
|
86
86
|
};
|
|
87
|
+
|
|
87
88
|
document.addEventListener('keydown', handleEscapeKey);
|
|
89
|
+
|
|
88
90
|
return () => {
|
|
89
91
|
document.removeEventListener('keydown', handleEscapeKey);
|
|
90
92
|
};
|
|
91
93
|
}, [ctx]);
|
|
92
94
|
|
|
93
|
-
if (!hasTitle || (!hasPanes && !isContext))
|
|
95
|
+
if (!hasTitle || (!hasPanes && !isContext)) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
94
98
|
|
|
95
99
|
return (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<div className="
|
|
104
|
-
|
|
100
|
+
<>
|
|
101
|
+
<nav
|
|
102
|
+
id="mainNav"
|
|
103
|
+
ref={navRef}
|
|
104
|
+
className="z-102 bg-mywhite md:bg-mywhite/70 fixed bottom-0 left-0 right-0 p-1.5 md:bottom-2 md:right-auto md:h-auto md:w-auto md:rounded-r-xl md:border md:border-black/5 md:p-2 md:shadow-lg md:backdrop-blur-sm"
|
|
105
|
+
>
|
|
106
|
+
<div className="flex flex-wrap justify-around gap-4 py-0.5 md:flex-nowrap md:justify-start md:gap-4 md:p-0">
|
|
107
|
+
<div className="text-mydarkgrey text-center text-sm font-bold">
|
|
108
|
+
mode:
|
|
109
|
+
<div className="font-action text-myblue pt-1.5 text-center text-xs">
|
|
110
|
+
{currentToolMode.title}
|
|
111
|
+
</div>
|
|
105
112
|
</div>
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
{storykeepToolModes.map(({ key, Icon, description }) => (
|
|
114
|
+
<div title={description} key={key}>
|
|
115
|
+
{key === toolModeVal ? (
|
|
116
|
+
<Icon className={classNameActive} />
|
|
117
|
+
) : (
|
|
118
|
+
<Icon className={className} onClick={() => handleClick(key)} />
|
|
119
|
+
)}
|
|
120
|
+
</div>
|
|
121
|
+
))}
|
|
122
|
+
<div title="Toggle debug node ids" key="debug">
|
|
123
|
+
<BugAntIcon
|
|
124
|
+
className={showGuids ? classNameDebugActive : className}
|
|
125
|
+
onClick={handleDebugToggle}
|
|
126
|
+
/>
|
|
114
127
|
</div>
|
|
115
|
-
|
|
116
|
-
</
|
|
117
|
-
|
|
128
|
+
</div>
|
|
129
|
+
</nav>
|
|
130
|
+
</>
|
|
118
131
|
);
|
|
119
132
|
};
|
|
120
133
|
|
|
@@ -14,7 +14,9 @@ import {
|
|
|
14
14
|
type SnapshotData,
|
|
15
15
|
} from '@/components/compositor/preview/PaneSnapshotGenerator';
|
|
16
16
|
import { createEmptyStorykeep } from '@/utils/compositor/nodesHelper';
|
|
17
|
+
import { tailwindToHex } from '@/utils/compositor/tailwindColors';
|
|
17
18
|
import { getTemplateVisualBreakPane } from '@/utils/compositor/TemplatePanes';
|
|
19
|
+
import { SvgBreaks } from '@/constants/shapes';
|
|
18
20
|
import {
|
|
19
21
|
PaneAddMode,
|
|
20
22
|
type PaneNode,
|
|
@@ -243,8 +245,16 @@ const AddPaneBreakPanel = ({
|
|
|
243
245
|
}
|
|
244
246
|
}
|
|
245
247
|
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
+
const shapeName = `kCz${variant}`;
|
|
249
|
+
const isFlipped = SvgBreaks[shapeName]?.flipped || false;
|
|
250
|
+
template.bgColour = tailwindToHex(
|
|
251
|
+
isFlipped ? aboveColor : belowColor,
|
|
252
|
+
null
|
|
253
|
+
);
|
|
254
|
+
const svgFill = tailwindToHex(
|
|
255
|
+
isFlipped ? belowColor : aboveColor === belowColor ? 'black' : aboveColor,
|
|
256
|
+
null
|
|
257
|
+
);
|
|
248
258
|
|
|
249
259
|
if (template.bgPane) {
|
|
250
260
|
if (template.bgPane.type === 'visual-break') {
|
|
@@ -62,7 +62,12 @@ const AddPaneCodeHookPanel = ({
|
|
|
62
62
|
}, [filteredHooks]);
|
|
63
63
|
|
|
64
64
|
const isHookAvailable = (hookName: string) => {
|
|
65
|
-
if (
|
|
65
|
+
if (
|
|
66
|
+
(hookName === 'featured-content' ||
|
|
67
|
+
hookName === 'list-content' ||
|
|
68
|
+
hookName === 'featured-article') &&
|
|
69
|
+
!hasStoryFragments
|
|
70
|
+
) {
|
|
66
71
|
return hasStoryFragments;
|
|
67
72
|
}
|
|
68
73
|
return true;
|
|
@@ -153,7 +158,8 @@ const AddPaneCodeHookPanel = ({
|
|
|
153
158
|
font-weight: bold;
|
|
154
159
|
}
|
|
155
160
|
.hook-item-available:hover {
|
|
156
|
-
background-color:
|
|
161
|
+
background-color: #0891b2;
|
|
162
|
+
color: #fff;
|
|
157
163
|
}
|
|
158
164
|
.hook-item-disabled {
|
|
159
165
|
background-color: #f9fafb; /* bg-gray-50 */
|
|
@@ -165,7 +165,7 @@ ${additionalInstructions}`;
|
|
|
165
165
|
Content has been generated successfully! Click "Apply
|
|
166
166
|
Content" to use this content with your selected design.
|
|
167
167
|
</p>
|
|
168
|
-
<div className="
|
|
168
|
+
<div className="overflow-y-auto rounded-md border border-gray-200 bg-gray-50 p-4">
|
|
169
169
|
<pre className="whitespace-pre-wrap font-mono text-sm text-gray-800">
|
|
170
170
|
{generatedContent}
|
|
171
171
|
</pre>
|
|
@@ -9,10 +9,13 @@ import {
|
|
|
9
9
|
isContextPaneNode,
|
|
10
10
|
hasBeliefPayload,
|
|
11
11
|
} from '@/utils/compositor/typeGuards';
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
settingsPanelStore,
|
|
14
|
+
viewportKeyStore,
|
|
15
|
+
fullContentMapStore,
|
|
16
|
+
} from '@/stores/storykeep';
|
|
13
17
|
import { getCtx } from '@/stores/nodes';
|
|
14
18
|
import PaneTitlePanel from './PanePanel_title';
|
|
15
|
-
import PaneSlugPanel from './PanePanel_slug';
|
|
16
19
|
import PaneMagicPathPanel from './PanePanel_path';
|
|
17
20
|
import PaneImpressionPanel from './PanePanel_impression';
|
|
18
21
|
import { PaneConfigMode, type PaneNode } from '@/types/compositorTypes';
|
|
@@ -30,7 +33,7 @@ const ConfigPanePanel = ({ nodeId }: ConfigPanePanelProps) => {
|
|
|
30
33
|
const reorderMode = toolMode.value === `move`;
|
|
31
34
|
const isActiveMode =
|
|
32
35
|
activePaneMode.panel === 'settings' && activePaneMode.paneId === nodeId;
|
|
33
|
-
|
|
36
|
+
const $contentMap = useStore(fullContentMapStore);
|
|
34
37
|
const $viewportKey = useStore(viewportKeyStore);
|
|
35
38
|
const isMobile = $viewportKey.value === `mobile`;
|
|
36
39
|
|
|
@@ -68,6 +71,7 @@ const ConfigPanePanel = ({ nodeId }: ConfigPanePanelProps) => {
|
|
|
68
71
|
};
|
|
69
72
|
|
|
70
73
|
const handleCodeHookConfig = () => {
|
|
74
|
+
ctx.toolModeValStore.set({ value: 'styles' });
|
|
71
75
|
settingsPanelStore.set({
|
|
72
76
|
action: 'setup-codehook',
|
|
73
77
|
nodeId: nodeId,
|
|
@@ -103,8 +107,6 @@ const ConfigPanePanel = ({ nodeId }: ConfigPanePanelProps) => {
|
|
|
103
107
|
|
|
104
108
|
if (mode === PaneConfigMode.TITLE) {
|
|
105
109
|
return <PaneTitlePanel nodeId={nodeId} setMode={setSaveMode} />;
|
|
106
|
-
} else if (mode === PaneConfigMode.SLUG) {
|
|
107
|
-
return <PaneSlugPanel nodeId={nodeId} setMode={setSaveMode} />;
|
|
108
110
|
} else if (mode === PaneConfigMode.PATH) {
|
|
109
111
|
return <PaneMagicPathPanel nodeId={nodeId} setMode={setSaveMode} />;
|
|
110
112
|
} else if (mode === PaneConfigMode.IMPRESSION) {
|
|
@@ -136,28 +138,16 @@ const ConfigPanePanel = ({ nodeId }: ConfigPanePanelProps) => {
|
|
|
136
138
|
<>
|
|
137
139
|
{!isTemplate && (
|
|
138
140
|
<>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
</button>
|
|
150
|
-
<button
|
|
151
|
-
onClick={() => setSaveMode(PaneConfigMode.SLUG)}
|
|
152
|
-
className={buttonClass}
|
|
153
|
-
>
|
|
154
|
-
Slug
|
|
155
|
-
{!isMobile && (
|
|
156
|
-
<>
|
|
157
|
-
: <strong>{paneNode.slug}</strong>
|
|
158
|
-
</>
|
|
159
|
-
)}
|
|
160
|
-
</button>
|
|
141
|
+
{$contentMap.some(
|
|
142
|
+
(item) => item.type === 'Pane' && item.id === nodeId
|
|
143
|
+
) && (
|
|
144
|
+
<button
|
|
145
|
+
onClick={() => setSaveMode(PaneConfigMode.TITLE)}
|
|
146
|
+
className={buttonClass}
|
|
147
|
+
>
|
|
148
|
+
ID
|
|
149
|
+
</button>
|
|
150
|
+
)}
|
|
161
151
|
<button
|
|
162
152
|
onClick={() => setSaveMode(PaneConfigMode.IMPRESSION)}
|
|
163
153
|
className={buttonClass}
|
|
@@ -4,7 +4,7 @@ import { RadioGroup } from '@ark-ui/react/radio-group';
|
|
|
4
4
|
import CheckCircleIcon from '@heroicons/react/20/solid/CheckCircleIcon';
|
|
5
5
|
import CubeTransparentIcon from '@heroicons/react/24/outline/CubeTransparentIcon';
|
|
6
6
|
import DocumentIcon from '@heroicons/react/24/outline/DocumentIcon';
|
|
7
|
-
import NewspaperIcon from '@heroicons/react/24/outline/NewspaperIcon';
|
|
7
|
+
//import NewspaperIcon from '@heroicons/react/24/outline/NewspaperIcon';
|
|
8
8
|
import ExclamationTriangleIcon from '@heroicons/react/24/outline/ExclamationTriangleIcon';
|
|
9
9
|
import AddPanePanel from './AddPanePanel';
|
|
10
10
|
import PageCreationGen from './PageGen';
|
|
@@ -75,21 +75,21 @@ export const PageCreationSelector = ({
|
|
|
75
75
|
: []),
|
|
76
76
|
];
|
|
77
77
|
|
|
78
|
-
const featuredMode = {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
return [...baseModesWithoutFeature
|
|
78
|
+
//const featuredMode = {
|
|
79
|
+
// id: 'featured',
|
|
80
|
+
// name: 'Featured Content home page',
|
|
81
|
+
// description:
|
|
82
|
+
// 'A layout with a prominent hero section showcasing a featured article and grid of additional top articles',
|
|
83
|
+
// icon: NewspaperIcon,
|
|
84
|
+
// active: true,
|
|
85
|
+
// disabled: validPagesCount < 3,
|
|
86
|
+
// disabledReason:
|
|
87
|
+
// validPagesCount === 0
|
|
88
|
+
// ? 'Not yet available; no pages with SEO metadata found.'
|
|
89
|
+
// : `Not yet available; requires at least 3 pages with SEO metadata (currently ${validPagesCount}).`,
|
|
90
|
+
//};
|
|
91
|
+
|
|
92
|
+
return [...baseModesWithoutFeature /*, featuredMode */] as CreationMode[];
|
|
93
93
|
}, [validPagesCount]);
|
|
94
94
|
|
|
95
95
|
const handleContinue = () => {
|
|
@@ -2,13 +2,13 @@ import { useState } from 'react';
|
|
|
2
2
|
import type { ReactNode } from 'react';
|
|
3
3
|
import { RadioGroup } from '@ark-ui/react/radio-group';
|
|
4
4
|
import { ulid } from 'ulid';
|
|
5
|
-
import FeaturedContentPreview from '@/components/compositor/preview/FeaturedContentPreview';
|
|
6
|
-
import ListContentPreview from '@/components/compositor/preview/ListContentPreview';
|
|
7
5
|
import VisualBreakPreview from '@/components/compositor/preview/VisualBreakPreview';
|
|
8
6
|
import { getTemplateVisualBreakPane } from '@/utils/compositor/TemplatePanes';
|
|
9
7
|
import { fullContentMapStore } from '@/stores/storykeep';
|
|
10
8
|
import type { NodesContext } from '@/stores/nodes';
|
|
11
9
|
import { findUniqueSlug } from '@/utils/helpers';
|
|
10
|
+
import { tailwindToHex } from '@/utils/compositor/tailwindColors';
|
|
11
|
+
import { SvgBreaks } from '@/constants/shapes';
|
|
12
12
|
import type { StoryFragmentNode, TemplatePane } from '@/types/compositorTypes';
|
|
13
13
|
|
|
14
14
|
// Layout options with IDs, labels, and descriptions
|
|
@@ -95,19 +95,14 @@ const PageCreationSpecial = ({
|
|
|
95
95
|
const featuredContentPane: TemplatePane = {
|
|
96
96
|
id: ulid(),
|
|
97
97
|
nodeType: 'Pane',
|
|
98
|
-
title: 'Featured
|
|
99
|
-
slug: findUniqueSlug(`featured-
|
|
98
|
+
title: 'Featured Article',
|
|
99
|
+
slug: findUniqueSlug(`featured-article`, existingSlugs),
|
|
100
100
|
isDecorative: false,
|
|
101
101
|
parentId: nodeId,
|
|
102
|
-
codeHookTarget: 'featured-
|
|
102
|
+
codeHookTarget: 'featured-article',
|
|
103
103
|
codeHookPayload: {
|
|
104
104
|
options: JSON.stringify({
|
|
105
|
-
title: 'Featured
|
|
106
|
-
featured: true,
|
|
107
|
-
slugs: '',
|
|
108
|
-
category: '',
|
|
109
|
-
limit: '6',
|
|
110
|
-
showDate: 'true',
|
|
105
|
+
title: 'Featured Article',
|
|
111
106
|
}),
|
|
112
107
|
},
|
|
113
108
|
};
|
|
@@ -128,24 +123,36 @@ const PageCreationSpecial = ({
|
|
|
128
123
|
const bgColor = breakVariant?.odd ? 'white' : 'gray-50';
|
|
129
124
|
const fillColor = breakVariant?.odd ? 'gray-50' : 'white';
|
|
130
125
|
|
|
126
|
+
const shapeName = `kCz${selectedBreak}`;
|
|
127
|
+
const isFlipped = SvgBreaks[shapeName]?.flipped || false;
|
|
128
|
+
|
|
129
|
+
const finalBgColor = tailwindToHex(
|
|
130
|
+
isFlipped ? fillColor : bgColor,
|
|
131
|
+
null
|
|
132
|
+
);
|
|
133
|
+
const finalFillColor = tailwindToHex(
|
|
134
|
+
isFlipped ? bgColor : fillColor,
|
|
135
|
+
null
|
|
136
|
+
);
|
|
137
|
+
|
|
131
138
|
// 2. Create Visual Break pane
|
|
132
139
|
const visualBreakTemplate = getTemplateVisualBreakPane(selectedBreak);
|
|
133
140
|
visualBreakTemplate.id = ulid();
|
|
134
141
|
visualBreakTemplate.title = 'Visual Break';
|
|
135
142
|
visualBreakTemplate.slug = `${storyfragment.slug}-visual-break`;
|
|
136
|
-
visualBreakTemplate.bgColour =
|
|
143
|
+
visualBreakTemplate.bgColour = finalBgColor;
|
|
137
144
|
|
|
138
145
|
// Configure the SVG fill color
|
|
139
146
|
if (visualBreakTemplate.bgPane) {
|
|
140
147
|
if (visualBreakTemplate.bgPane.type === 'visual-break') {
|
|
141
148
|
if (visualBreakTemplate.bgPane.breakDesktop) {
|
|
142
|
-
visualBreakTemplate.bgPane.breakDesktop.svgFill =
|
|
149
|
+
visualBreakTemplate.bgPane.breakDesktop.svgFill = finalFillColor;
|
|
143
150
|
}
|
|
144
151
|
if (visualBreakTemplate.bgPane.breakTablet) {
|
|
145
|
-
visualBreakTemplate.bgPane.breakTablet.svgFill =
|
|
152
|
+
visualBreakTemplate.bgPane.breakTablet.svgFill = finalFillColor;
|
|
146
153
|
}
|
|
147
154
|
if (visualBreakTemplate.bgPane.breakMobile) {
|
|
148
|
-
visualBreakTemplate.bgPane.breakMobile.svgFill =
|
|
155
|
+
visualBreakTemplate.bgPane.breakMobile.svgFill = finalFillColor;
|
|
149
156
|
}
|
|
150
157
|
}
|
|
151
158
|
}
|
|
@@ -171,7 +178,10 @@ const PageCreationSpecial = ({
|
|
|
171
178
|
isDecorative: false,
|
|
172
179
|
parentId: nodeId,
|
|
173
180
|
// For complete-home layout, match the background color with the visual break
|
|
174
|
-
bgColour:
|
|
181
|
+
bgColour: tailwindToHex(
|
|
182
|
+
selectedLayout === 'complete-home' ? 'gray-50' : 'white',
|
|
183
|
+
null
|
|
184
|
+
),
|
|
175
185
|
codeHookTarget: 'list-content',
|
|
176
186
|
codeHookPayload: {
|
|
177
187
|
options: JSON.stringify({
|
|
@@ -299,39 +309,6 @@ const PageCreationSpecial = ({
|
|
|
299
309
|
)}
|
|
300
310
|
</div>
|
|
301
311
|
|
|
302
|
-
<div className="mt-8 rounded-lg border bg-white p-4 shadow-md">
|
|
303
|
-
<h3 className="mb-4 text-lg font-bold">Preview</h3>
|
|
304
|
-
|
|
305
|
-
{selectedLayout === 'featured-only' && <FeaturedContentPreview />}
|
|
306
|
-
|
|
307
|
-
{selectedLayout === 'featured-list' && (
|
|
308
|
-
<div>
|
|
309
|
-
<FeaturedContentPreview />
|
|
310
|
-
<ListContentPreview bgColour="#ffffff" />
|
|
311
|
-
</div>
|
|
312
|
-
)}
|
|
313
|
-
|
|
314
|
-
{selectedLayout === 'complete-home' && (
|
|
315
|
-
<div>
|
|
316
|
-
<FeaturedContentPreview />
|
|
317
|
-
<VisualBreakPreview
|
|
318
|
-
bgColour={
|
|
319
|
-
breakVariants.find((b) => b.id === selectedBreak)?.odd
|
|
320
|
-
? '#ffffff'
|
|
321
|
-
: '#f1f5f9'
|
|
322
|
-
}
|
|
323
|
-
fillColour={
|
|
324
|
-
breakVariants.find((b) => b.id === selectedBreak)?.odd
|
|
325
|
-
? '#f1f5f9'
|
|
326
|
-
: '#ffffff'
|
|
327
|
-
}
|
|
328
|
-
variant={selectedBreak}
|
|
329
|
-
/>
|
|
330
|
-
<ListContentPreview bgColour="#f1f5f9" />
|
|
331
|
-
</div>
|
|
332
|
-
)}
|
|
333
|
-
</div>
|
|
334
|
-
|
|
335
312
|
<div className="mt-6 flex justify-end gap-3">
|
|
336
313
|
<button
|
|
337
314
|
onClick={() => {
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
getIntroDesign,
|
|
13
13
|
getWithArtpackImageDesign,
|
|
14
14
|
} from '@/utils/compositor/templateMarkdownStyles';
|
|
15
|
+
import { tailwindToHex } from '@/utils/compositor/tailwindColors';
|
|
16
|
+
import { SvgBreaks } from '@/constants/shapes';
|
|
15
17
|
import {
|
|
16
18
|
parsePageMarkdown,
|
|
17
19
|
validatePageMarkdown,
|
|
@@ -243,8 +245,21 @@ export const PageCreationPreview = ({
|
|
|
243
245
|
? design.visualBreaks.odd()
|
|
244
246
|
: design.visualBreaks.even();
|
|
245
247
|
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
+
const breakData = breakTemplate.bgPane?.breakDesktop;
|
|
249
|
+
const shapeName = breakData
|
|
250
|
+
? `${breakData.collection}${breakData.image}`
|
|
251
|
+
: '';
|
|
252
|
+
const isFlipped =
|
|
253
|
+
(shapeName && SvgBreaks[shapeName]?.flipped) || false;
|
|
254
|
+
|
|
255
|
+
breakTemplate.bgColour = tailwindToHex(
|
|
256
|
+
isFlipped ? belowColor : aboveColor,
|
|
257
|
+
null
|
|
258
|
+
);
|
|
259
|
+
const svgFill = tailwindToHex(
|
|
260
|
+
isFlipped ? aboveColor : belowColor,
|
|
261
|
+
null
|
|
262
|
+
);
|
|
248
263
|
if (breakTemplate.bgPane) {
|
|
249
264
|
if (breakTemplate.bgPane.breakDesktop) {
|
|
250
265
|
breakTemplate.bgPane.breakDesktop.svgFill = svgFill;
|
|
@@ -60,7 +60,6 @@ const PaneMagicPathPanel = ({ nodeId, setMode }: PaneMagicPathPanelProps) => {
|
|
|
60
60
|
if (!idsResponse.ok) throw new Error('Failed to fetch belief IDs');
|
|
61
61
|
|
|
62
62
|
const idsResult = await idsResponse.json();
|
|
63
|
-
// CORRECTED: The key from the backend is "beliefIds", not "beliefs"
|
|
64
63
|
if (!idsResult.beliefIds || idsResult.beliefIds.length === 0) {
|
|
65
64
|
setAvailableBeliefs([]);
|
|
66
65
|
setIsLoading(false);
|
|
@@ -74,7 +73,6 @@ const PaneMagicPathPanel = ({ nodeId, setMode }: PaneMagicPathPanelProps) => {
|
|
|
74
73
|
'Content-Type': 'application/json',
|
|
75
74
|
'X-Tenant-ID': tenantId,
|
|
76
75
|
},
|
|
77
|
-
// CORRECTED: Pass the array from the correct key "beliefIds"
|
|
78
76
|
body: JSON.stringify({ beliefIds: idsResult.beliefIds }),
|
|
79
77
|
});
|
|
80
78
|
|
|
@@ -222,7 +220,7 @@ const PaneMagicPathPanel = ({ nodeId, setMode }: PaneMagicPathPanelProps) => {
|
|
|
222
220
|
</div>
|
|
223
221
|
|
|
224
222
|
<div className="flex w-full flex-wrap gap-8">
|
|
225
|
-
<div className="
|
|
223
|
+
<div className="flex-1">
|
|
226
224
|
<MagicPathBuilder
|
|
227
225
|
paths={heldPaths}
|
|
228
226
|
setPaths={handleHeldPathsChange}
|
|
@@ -232,7 +230,7 @@ const PaneMagicPathPanel = ({ nodeId, setMode }: PaneMagicPathPanelProps) => {
|
|
|
232
230
|
/>
|
|
233
231
|
</div>
|
|
234
232
|
|
|
235
|
-
<div className="
|
|
233
|
+
<div className="flex-1">
|
|
236
234
|
<MagicPathBuilder
|
|
237
235
|
paths={withheldPaths}
|
|
238
236
|
setPaths={handleWithheldPathsChange}
|