astro-tractstack 2.0.0-rc.11 → 2.0.0-rc.13
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/package.json +7 -2
- package/templates/src/components/codehooks/EpinetDurationSelector.tsx +6 -3
- package/templates/src/components/edit/SettingsPanel.tsx +4 -1
- package/templates/src/components/edit/pane/AddPanePanel_newAICopy_modal.tsx +1 -1
- package/templates/src/components/edit/pane/PanePanel_path.tsx +2 -2
- package/templates/src/components/edit/panels/StyleElementPanel_add.tsx +1 -1
- package/templates/src/components/edit/panels/StyleImagePanel_add.tsx +1 -1
- package/templates/src/components/edit/panels/StyleLiElementPanel_add.tsx +1 -1
- package/templates/src/components/edit/panels/StyleLinkPanel_add.tsx +1 -1
- package/templates/src/components/edit/panels/StyleLinkPanel_config.tsx +1 -1
- package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +1 -1
- package/templates/src/components/edit/panels/StyleWidgetPanel_add.tsx +1 -1
- package/templates/src/components/fields/BackgroundImageWrapper.tsx +1 -1
- package/templates/src/components/fields/ViewportComboBox.tsx +10 -3
- package/templates/src/components/storykeep/Dashboard_Analytics.tsx +1 -1
- package/templates/src/pages/[...slug]/edit.astro +1 -1
- package/templates/src/pages/storykeep/advanced.astro +1 -1
- package/templates/src/pages/storykeep/branding.astro +1 -1
- package/templates/src/pages/storykeep/content.astro +1 -1
- package/templates/src/pages/storykeep/init.astro +3 -1
- package/templates/src/pages/storykeep.astro +1 -1
- package/templates/src/stores/nodes.ts +32 -1
- package/templates/src/stores/storykeep.ts +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro-tractstack",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.13",
|
|
4
4
|
"description": "Astro integration for TractStack - redeeming the web from boring experiences",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -85,5 +85,10 @@
|
|
|
85
85
|
"engines": {
|
|
86
86
|
"node": ">=18.14.1"
|
|
87
87
|
},
|
|
88
|
-
"packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0"
|
|
88
|
+
"packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0",
|
|
89
|
+
"pnpm": {
|
|
90
|
+
"overrides": {
|
|
91
|
+
"esbuild@<=0.24.2": ">=0.25.0"
|
|
92
|
+
}
|
|
93
|
+
}
|
|
89
94
|
}
|
|
@@ -185,7 +185,7 @@ const EpinetDurationSelector = ({
|
|
|
185
185
|
const startUTCTime = createUTCDateTime(startDate, localFilters.startHour);
|
|
186
186
|
const endUTCTime = createUTCDateTime(endDate, localFilters.endHour);
|
|
187
187
|
|
|
188
|
-
if (endUTCTime
|
|
188
|
+
if (endUTCTime < startUTCTime) {
|
|
189
189
|
setErrorMessage('End time must be after start time.');
|
|
190
190
|
return;
|
|
191
191
|
}
|
|
@@ -549,7 +549,7 @@ const EpinetDurationSelector = ({
|
|
|
549
549
|
|
|
550
550
|
return (
|
|
551
551
|
<>
|
|
552
|
-
<div className="space-y-4">
|
|
552
|
+
<div className="space-y-4 overflow-visible">
|
|
553
553
|
{$epinetCustomFilters.enabled && (
|
|
554
554
|
<div
|
|
555
555
|
className={`space-y-4 rounded-lg border-2 border-dashed border-gray-200 bg-gray-50 p-4`}
|
|
@@ -865,7 +865,10 @@ const EpinetDurationSelector = ({
|
|
|
865
865
|
</Select.Control>
|
|
866
866
|
<Portal>
|
|
867
867
|
<Select.Positioner>
|
|
868
|
-
<Select.Content
|
|
868
|
+
<Select.Content
|
|
869
|
+
className="z-10 mt-2 max-h-96 overflow-auto rounded-md bg-white text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
|
|
870
|
+
style={{ width: 'var(--trigger-width)' }}
|
|
871
|
+
>
|
|
869
872
|
{paginatedUserCounts.length > 0 ? (
|
|
870
873
|
[
|
|
871
874
|
<Select.Item
|
|
@@ -42,7 +42,10 @@ const SettingsPanel = ({ config, availableCodeHooks }: SettingsPanelProps) => {
|
|
|
42
42
|
100% { opacity: var(--fade-end, 1); }
|
|
43
43
|
}
|
|
44
44
|
`}</style>
|
|
45
|
-
<div
|
|
45
|
+
<div
|
|
46
|
+
className="w-full rounded-lg border border-gray-200 bg-white p-1.5 shadow-xl md:p-2.5"
|
|
47
|
+
style={{ maxWidth: '90vw' }}
|
|
48
|
+
>
|
|
46
49
|
<div className="mb-4 flex items-center justify-between">
|
|
47
50
|
<h3 className="text-myblue text-lg font-bold">{panelTitle}</h3>
|
|
48
51
|
<button
|
|
@@ -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>
|
|
@@ -222,7 +222,7 @@ const PaneMagicPathPanel = ({ nodeId, setMode }: PaneMagicPathPanelProps) => {
|
|
|
222
222
|
</div>
|
|
223
223
|
|
|
224
224
|
<div className="flex w-full flex-wrap gap-8">
|
|
225
|
-
<div className="
|
|
225
|
+
<div className="flex-1">
|
|
226
226
|
<MagicPathBuilder
|
|
227
227
|
paths={heldPaths}
|
|
228
228
|
setPaths={handleHeldPathsChange}
|
|
@@ -232,7 +232,7 @@ const PaneMagicPathPanel = ({ nodeId, setMode }: PaneMagicPathPanelProps) => {
|
|
|
232
232
|
/>
|
|
233
233
|
</div>
|
|
234
234
|
|
|
235
|
-
<div className="
|
|
235
|
+
<div className="flex-1">
|
|
236
236
|
<MagicPathBuilder
|
|
237
237
|
paths={withheldPaths}
|
|
238
238
|
setPaths={handleWithheldPathsChange}
|
|
@@ -249,7 +249,7 @@ const StyleElementPanelAdd = ({
|
|
|
249
249
|
`;
|
|
250
250
|
|
|
251
251
|
return (
|
|
252
|
-
<div className="
|
|
252
|
+
<div className="max-w-md space-y-4">
|
|
253
253
|
<style>{comboboxItemStyles}</style>
|
|
254
254
|
|
|
255
255
|
<div className="flex flex-row flex-nowrap justify-between">
|
|
@@ -195,7 +195,7 @@ const StyleImagePanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
195
195
|
`;
|
|
196
196
|
|
|
197
197
|
return (
|
|
198
|
-
<div className="
|
|
198
|
+
<div className="max-w-md space-y-4">
|
|
199
199
|
<style>{comboboxItemStyles}</style>
|
|
200
200
|
|
|
201
201
|
<div className="flex flex-row flex-nowrap justify-between">
|
|
@@ -200,7 +200,7 @@ const StyleLiElementAddPanel = ({
|
|
|
200
200
|
`;
|
|
201
201
|
|
|
202
202
|
return (
|
|
203
|
-
<div className="
|
|
203
|
+
<div className="max-w-md space-y-4">
|
|
204
204
|
<style>{comboboxItemStyles}</style>
|
|
205
205
|
|
|
206
206
|
<div className="flex flex-row flex-nowrap justify-between">
|
|
@@ -164,7 +164,7 @@ const StyleLinkPanelAdd = ({ node }: BasePanelProps) => {
|
|
|
164
164
|
`;
|
|
165
165
|
|
|
166
166
|
return (
|
|
167
|
-
<div className="
|
|
167
|
+
<div className="max-w-md space-y-4">
|
|
168
168
|
<style>{comboboxItemStyles}</style>
|
|
169
169
|
|
|
170
170
|
<div className="flex flex-row flex-nowrap justify-between">
|
|
@@ -221,7 +221,7 @@ const StyleLinkConfigPanel = ({ node, config }: StyleLinkConfigPanelProps) => {
|
|
|
221
221
|
</div>
|
|
222
222
|
|
|
223
223
|
<div className="space-y-2">
|
|
224
|
-
<div className="relative
|
|
224
|
+
<div className="relative overflow-y-auto">
|
|
225
225
|
<div className="absolute inset-x-0">
|
|
226
226
|
<label className="text-mydarkgrey mb-2 block text-sm">
|
|
227
227
|
{actionType === 'goto'
|
|
@@ -174,7 +174,7 @@ const StyleParentPanelAdd = ({ node, layer }: BasePanelProps) => {
|
|
|
174
174
|
`;
|
|
175
175
|
|
|
176
176
|
return (
|
|
177
|
-
<div className="
|
|
177
|
+
<div className="max-w-md space-y-4">
|
|
178
178
|
<style>{comboboxItemStyles}</style>
|
|
179
179
|
|
|
180
180
|
<div className="flex flex-row flex-nowrap justify-between">
|
|
@@ -191,7 +191,7 @@ const StyleWidgetPanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
191
191
|
`;
|
|
192
192
|
|
|
193
193
|
return (
|
|
194
|
-
<div className="
|
|
194
|
+
<div className="max-w-md space-y-4">
|
|
195
195
|
<style>{comboboxItemStyles}</style>
|
|
196
196
|
|
|
197
197
|
<div className="flex flex-row flex-nowrap justify-between">
|
|
@@ -13,7 +13,7 @@ import CheckIcon from '@heroicons/react/24/outline/CheckIcon';
|
|
|
13
13
|
import DevicePhoneMobileIcon from '@heroicons/react/24/outline/DevicePhoneMobileIcon';
|
|
14
14
|
import DeviceTabletIcon from '@heroicons/react/24/outline/DeviceTabletIcon';
|
|
15
15
|
import ComputerDesktopIcon from '@heroicons/react/24/outline/ComputerDesktopIcon';
|
|
16
|
-
import { classNames } from '@/utils/helpers';
|
|
16
|
+
import { classNames, useDropdownDirection } from '@/utils/helpers';
|
|
17
17
|
import { tailwindToHex, colorValues } from '@/utils/compositor/tailwindColors';
|
|
18
18
|
import type { BrandConfig } from '@/types/tractstack';
|
|
19
19
|
|
|
@@ -46,6 +46,8 @@ const ViewportComboBox = ({
|
|
|
46
46
|
const [query, setQuery] = useState('');
|
|
47
47
|
const [isNowNegative, setIsNowNegative] = useState(isNegative);
|
|
48
48
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
49
|
+
const comboboxRef = useRef<HTMLDivElement>(null);
|
|
50
|
+
const { openAbove, maxHeight } = useDropdownDirection(comboboxRef);
|
|
49
51
|
|
|
50
52
|
const Icon =
|
|
51
53
|
viewport === 'mobile'
|
|
@@ -155,7 +157,7 @@ const ViewportComboBox = ({
|
|
|
155
157
|
openOnKeyPress={true}
|
|
156
158
|
composite={true}
|
|
157
159
|
>
|
|
158
|
-
<div className="relative">
|
|
160
|
+
<div ref={comboboxRef} className="relative">
|
|
159
161
|
<div className="relative flex items-center">
|
|
160
162
|
{isColorValue && (
|
|
161
163
|
<div
|
|
@@ -187,7 +189,12 @@ const ViewportComboBox = ({
|
|
|
187
189
|
</Combobox.Trigger>
|
|
188
190
|
</div>
|
|
189
191
|
</div>
|
|
190
|
-
<Combobox.Content
|
|
192
|
+
<Combobox.Content
|
|
193
|
+
className={`absolute z-50 mt-1 w-full overflow-auto rounded-md bg-white py-1 text-xl shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none ${
|
|
194
|
+
openAbove ? 'bottom-full mb-1' : 'top-full'
|
|
195
|
+
}`}
|
|
196
|
+
style={{ maxHeight: `${maxHeight}px` }}
|
|
197
|
+
>
|
|
191
198
|
{collection.items.length === 0 ? (
|
|
192
199
|
<div className="text-mydarkgrey relative cursor-default select-none px-4 py-2">
|
|
193
200
|
Nothing found.
|
|
@@ -369,7 +369,7 @@ export default function StoryKeepDashboard_Analytics({
|
|
|
369
369
|
</div>
|
|
370
370
|
|
|
371
371
|
{/* User Journey Section */}
|
|
372
|
-
<div className="mb-6 overflow-
|
|
372
|
+
<div className="mb-6 overflow-visible">
|
|
373
373
|
<h3 className="mb-4 text-lg font-bold text-gray-900">
|
|
374
374
|
User Journey Analytics
|
|
375
375
|
</h3>
|
|
@@ -201,7 +201,7 @@ for (const [key, value] of Astro.url.searchParams) {
|
|
|
201
201
|
<!-- Floating Controls (Settings Panel & HUD OR ToolBar) -->
|
|
202
202
|
<aside
|
|
203
203
|
id="settingsControls"
|
|
204
|
-
class="z-101 pointer-events-none fixed bottom-24 right-0 flex max-h-screen flex-col items-end gap-2 overflow-
|
|
204
|
+
class="z-101 pointer-events-none fixed bottom-24 right-0 flex max-h-screen flex-col items-end gap-2 overflow-visible p-4 md:bottom-0"
|
|
205
205
|
>
|
|
206
206
|
<div class="pointer-events-auto">
|
|
207
207
|
<StoryKeepToolBar client:only="react" />
|
|
@@ -54,7 +54,7 @@ try {
|
|
|
54
54
|
|
|
55
55
|
<Layout title={title} slug="storykeep" isStoryKeep={true}>
|
|
56
56
|
<main id="main-content" class="min-h-screen w-full">
|
|
57
|
-
<div class="max-w-5xl p-8">
|
|
57
|
+
<div class="max-w-5xl p-3.5 md:p-8">
|
|
58
58
|
<StoryKeepDashboard
|
|
59
59
|
client:only="react"
|
|
60
60
|
fullContentMap={fullContentMap}
|
|
@@ -43,7 +43,7 @@ try {
|
|
|
43
43
|
|
|
44
44
|
<Layout title={title} slug="storykeep" isStoryKeep={true}>
|
|
45
45
|
<main id="main-content" class="min-h-screen w-full">
|
|
46
|
-
<div class="max-w-5xl p-8">
|
|
46
|
+
<div class="max-w-5xl p-3.5 md:p-8">
|
|
47
47
|
<BrandingPageWrapper
|
|
48
48
|
client:only="react"
|
|
49
49
|
fullContentMap={fullContentMap}
|
|
@@ -50,7 +50,7 @@ try {
|
|
|
50
50
|
|
|
51
51
|
<Layout title={title} slug="storykeep" isStoryKeep={true}>
|
|
52
52
|
<main id="main-content" class="min-h-screen w-full">
|
|
53
|
-
<div class="max-w-5xl p-8">
|
|
53
|
+
<div class="max-w-5xl p-3.5 md:p-8">
|
|
54
54
|
<StoryKeepDashboard
|
|
55
55
|
client:only="react"
|
|
56
56
|
fullContentMap={fullContentMap}
|
|
@@ -31,6 +31,8 @@ const mainStylesUrl = isDev
|
|
|
31
31
|
<link rel="stylesheet" href={mainStylesUrl} />
|
|
32
32
|
</head>
|
|
33
33
|
<body class="h-full">
|
|
34
|
-
<
|
|
34
|
+
<div class="max-w-5xl p-3.5 md:p-8">
|
|
35
|
+
<RegistrationForm client:load isInitMode={true} />
|
|
36
|
+
</div>
|
|
35
37
|
</body>
|
|
36
38
|
</html>
|
|
@@ -52,7 +52,7 @@ try {
|
|
|
52
52
|
|
|
53
53
|
<Layout title={title} isStoryKeep={true} slug="storykeep">
|
|
54
54
|
<main id="main-content" class="min-h-screen w-full">
|
|
55
|
-
<div class="p-3.5 md:p-8">
|
|
55
|
+
<div class="max-w-5xl p-3.5 md:p-8">
|
|
56
56
|
<StoryKeepDashboard
|
|
57
57
|
client:only="react"
|
|
58
58
|
fullContentMap={fullContentMap}
|
|
@@ -2316,10 +2316,41 @@ export class NodesContext {
|
|
|
2316
2316
|
|
|
2317
2317
|
getDirtyNodesClassData(): { dirtyPaneIds: string[]; classes: string[] } {
|
|
2318
2318
|
const dirtyNodes = this.getDirtyNodes();
|
|
2319
|
+
|
|
2319
2320
|
const dirtyPaneIds = dirtyNodes
|
|
2320
2321
|
.filter((node) => node.nodeType === 'Pane')
|
|
2321
2322
|
.map((node) => node.id);
|
|
2322
|
-
|
|
2323
|
+
|
|
2324
|
+
// Collect all nodes that need class extraction
|
|
2325
|
+
const allNodesToExtract: BaseNode[] = [];
|
|
2326
|
+
|
|
2327
|
+
// Find root dirty nodes (dirty nodes whose parents are NOT dirty)
|
|
2328
|
+
const dirtyNodeIds = new Set(dirtyNodes.map((n) => n.id));
|
|
2329
|
+
const rootDirtyNodes = dirtyNodes.filter(
|
|
2330
|
+
(node) => !node.parentId || !dirtyNodeIds.has(node.parentId)
|
|
2331
|
+
);
|
|
2332
|
+
|
|
2333
|
+
// For each root dirty node, traverse all descendants
|
|
2334
|
+
rootDirtyNodes.forEach((rootNode) => {
|
|
2335
|
+
// Add the root node itself
|
|
2336
|
+
allNodesToExtract.push(rootNode);
|
|
2337
|
+
|
|
2338
|
+
// Traverse all descendants using breadth-first
|
|
2339
|
+
const queue = [...this.getChildNodeIDs(rootNode.id)];
|
|
2340
|
+
while (queue.length > 0) {
|
|
2341
|
+
const currentId = queue.shift();
|
|
2342
|
+
if (!currentId) continue;
|
|
2343
|
+
|
|
2344
|
+
const currentNode = this.allNodes.get().get(currentId);
|
|
2345
|
+
if (currentNode) {
|
|
2346
|
+
allNodesToExtract.push(currentNode);
|
|
2347
|
+
const childrenIds = this.getChildNodeIDs(currentId);
|
|
2348
|
+
queue.push(...childrenIds);
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
});
|
|
2352
|
+
|
|
2353
|
+
const classes = extractClassesFromNodes(allNodesToExtract);
|
|
2323
2354
|
|
|
2324
2355
|
return { dirtyPaneIds, classes };
|
|
2325
2356
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { atom, map } from 'nanostores';
|
|
2
2
|
import { persistentAtom } from '@nanostores/persistent';
|
|
3
3
|
import { handleSettingsPanelMobile } from '@/utils/layout';
|
|
4
|
+
import { getCtx, ROOT_NODE_NAME } from '@/stores/nodes';
|
|
4
5
|
import type {
|
|
5
6
|
FullContentMapItem,
|
|
6
7
|
Theme,
|
|
@@ -116,6 +117,10 @@ export const setViewportMode = (mode: ViewportKey) => {
|
|
|
116
117
|
} else {
|
|
117
118
|
viewportKeyStore.setKey('value', mode);
|
|
118
119
|
}
|
|
120
|
+
|
|
121
|
+
// Notify root node to trigger coordinated re-render
|
|
122
|
+
const ctx = getCtx();
|
|
123
|
+
ctx.notifyNode(ROOT_NODE_NAME);
|
|
119
124
|
};
|
|
120
125
|
|
|
121
126
|
export const toggleShowAnalytics = () => {
|