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,5 +1,5 @@
|
|
|
1
|
-
import { useEffect, useState, useCallback, useMemo } from 'react';
|
|
2
|
-
import { Combobox } from '@ark-ui/react';
|
|
1
|
+
import { useEffect, 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';
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from '@/stores/storykeep';
|
|
11
11
|
import { tailwindClasses } from '@/utils/compositor/tailwindClasses';
|
|
12
12
|
import { isMarkdownPaneFragmentNode } from '@/utils/compositor/typeGuards';
|
|
13
|
+
import { useDropdownDirection } from '@/utils/helpers';
|
|
13
14
|
import {
|
|
14
15
|
tagTitles,
|
|
15
16
|
type Tag,
|
|
@@ -126,6 +127,8 @@ const StyleElementPanelAdd = ({
|
|
|
126
127
|
const [query, setQuery] = useState('');
|
|
127
128
|
const [showAdvanced, setShowAdvanced] = useState(false);
|
|
128
129
|
const [selectedStyle, setSelectedStyle] = useState<string | null>(null);
|
|
130
|
+
const comboboxRef = useRef<HTMLDivElement>(null);
|
|
131
|
+
const { openAbove } = useDropdownDirection(comboboxRef);
|
|
129
132
|
|
|
130
133
|
if (
|
|
131
134
|
!node ||
|
|
@@ -138,7 +141,6 @@ const StyleElementPanelAdd = ({
|
|
|
138
141
|
|
|
139
142
|
const currentClasses = new Set<string>();
|
|
140
143
|
|
|
141
|
-
// Get existing classes from default classes in parent
|
|
142
144
|
if (parentNode.defaultClasses?.[node.tagName]) {
|
|
143
145
|
const defaults = parentNode.defaultClasses[node.tagName];
|
|
144
146
|
Object.keys(defaults.mobile).forEach((key) => currentClasses.add(key));
|
|
@@ -148,33 +150,26 @@ const StyleElementPanelAdd = ({
|
|
|
148
150
|
Object.keys(defaults.desktop).forEach((key) => currentClasses.add(key));
|
|
149
151
|
}
|
|
150
152
|
|
|
151
|
-
// Get existing classes from override classes in node
|
|
152
153
|
if (node.overrideClasses) {
|
|
153
154
|
Object.values(node.overrideClasses).forEach((viewportClasses) => {
|
|
154
155
|
Object.keys(viewportClasses).forEach((key) => currentClasses.add(key));
|
|
155
156
|
});
|
|
156
157
|
}
|
|
157
158
|
|
|
158
|
-
// Get filtered styles based on query and existing classes
|
|
159
159
|
const styles = getFilteredStyles(showAdvanced, currentClasses);
|
|
160
|
-
const filteredStyles =
|
|
161
|
-
query === ''
|
|
162
|
-
? styles
|
|
163
|
-
: styles.filter(
|
|
164
|
-
(style) =>
|
|
165
|
-
style.title.toLowerCase().includes(query.toLowerCase()) ||
|
|
166
|
-
style.key.toLowerCase().includes(query.toLowerCase())
|
|
167
|
-
);
|
|
168
160
|
|
|
169
|
-
// Create collection for Ark UI Combobox
|
|
170
161
|
const collection = useMemo(
|
|
171
162
|
() =>
|
|
172
163
|
createListCollection({
|
|
173
|
-
items:
|
|
164
|
+
items: styles.filter(
|
|
165
|
+
(style) =>
|
|
166
|
+
style.title.toLowerCase().includes(query.toLowerCase()) ||
|
|
167
|
+
style.key.toLowerCase().includes(query.toLowerCase())
|
|
168
|
+
),
|
|
174
169
|
itemToValue: (item: StyleOption) => item.key,
|
|
175
170
|
itemToString: (item: StyleOption) => item.title,
|
|
176
171
|
}),
|
|
177
|
-
[
|
|
172
|
+
[styles, query]
|
|
178
173
|
);
|
|
179
174
|
|
|
180
175
|
const availableRecommendedStyles =
|
|
@@ -228,7 +223,6 @@ const StyleElementPanelAdd = ({
|
|
|
228
223
|
};
|
|
229
224
|
}, [parentNode.id, node.tagName]);
|
|
230
225
|
|
|
231
|
-
// CSS to properly style the combobox items with hover and selection
|
|
232
226
|
const comboboxItemStyles = `
|
|
233
227
|
.style-item[data-highlighted] {
|
|
234
228
|
background-color: #0891b2; /* bg-cyan-600 */
|
|
@@ -249,7 +243,7 @@ const StyleElementPanelAdd = ({
|
|
|
249
243
|
`;
|
|
250
244
|
|
|
251
245
|
return (
|
|
252
|
-
<div className="
|
|
246
|
+
<div className="max-w-md space-y-4">
|
|
253
247
|
<style>{comboboxItemStyles}</style>
|
|
254
248
|
|
|
255
249
|
<div className="flex flex-row flex-nowrap justify-between">
|
|
@@ -283,46 +277,57 @@ const StyleElementPanelAdd = ({
|
|
|
283
277
|
loopFocus={true}
|
|
284
278
|
openOnKeyPress={true}
|
|
285
279
|
composite={true}
|
|
280
|
+
positioning={{
|
|
281
|
+
placement: openAbove ? 'top' : 'bottom',
|
|
282
|
+
gutter: 4,
|
|
283
|
+
sameWidth: true,
|
|
284
|
+
}}
|
|
286
285
|
>
|
|
287
|
-
<
|
|
288
|
-
<
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
<Combobox.Trigger className="absolute inset-y-0 right-0 flex items-center pr-2">
|
|
294
|
-
<ChevronUpDownIcon
|
|
295
|
-
className="text-mydarkgrey h-5 w-5"
|
|
296
|
-
aria-hidden="true"
|
|
286
|
+
<Combobox.Control ref={comboboxRef}>
|
|
287
|
+
<div className="relative">
|
|
288
|
+
<Combobox.Input
|
|
289
|
+
className="border-mydarkgrey focus:border-myblue focus:ring-myblue w-full rounded-md py-2 pl-3 pr-10 text-xl shadow-sm"
|
|
290
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
291
|
+
placeholder="Search styles..."
|
|
297
292
|
/>
|
|
298
|
-
|
|
299
|
-
|
|
293
|
+
<Combobox.Trigger className="absolute inset-y-0 right-0 flex items-center pr-2">
|
|
294
|
+
<ChevronUpDownIcon
|
|
295
|
+
className="text-mydarkgrey h-5 w-5"
|
|
296
|
+
aria-hidden="true"
|
|
297
|
+
/>
|
|
298
|
+
</Combobox.Trigger>
|
|
299
|
+
</div>
|
|
300
|
+
</Combobox.Control>
|
|
300
301
|
|
|
301
|
-
<
|
|
302
|
-
|
|
303
|
-
<
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
302
|
+
<Portal>
|
|
303
|
+
<Combobox.Positioner style={{ zIndex: 1002 }}>
|
|
304
|
+
<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">
|
|
305
|
+
{collection.items.length === 0 ? (
|
|
306
|
+
<div className="text-mydarkgrey relative cursor-default select-none px-4 py-2">
|
|
307
|
+
Nothing found.
|
|
308
|
+
</div>
|
|
309
|
+
) : (
|
|
310
|
+
collection.items.map((style) => (
|
|
311
|
+
<Combobox.Item
|
|
312
|
+
key={style.key}
|
|
313
|
+
item={style}
|
|
314
|
+
className="style-item relative cursor-default select-none py-2 pl-10 pr-4 text-black"
|
|
315
|
+
>
|
|
316
|
+
<span className="block truncate">
|
|
317
|
+
{style.title}
|
|
318
|
+
<span className="ml-2 text-sm opacity-60">
|
|
319
|
+
{style.className}
|
|
320
|
+
</span>
|
|
321
|
+
</span>
|
|
322
|
+
<span className="style-indicator absolute inset-y-0 left-0 flex items-center pl-3 text-cyan-600">
|
|
323
|
+
<CheckIcon className="h-5 w-5" aria-hidden="true" />
|
|
324
|
+
</span>
|
|
325
|
+
</Combobox.Item>
|
|
326
|
+
))
|
|
327
|
+
)}
|
|
328
|
+
</Combobox.Content>
|
|
329
|
+
</Combobox.Positioner>
|
|
330
|
+
</Portal>
|
|
326
331
|
</Combobox.Root>
|
|
327
332
|
</div>
|
|
328
333
|
|
|
@@ -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 images
|
|
@@ -73,6 +74,8 @@ const StyleImagePanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
73
74
|
const [query, setQuery] = useState('');
|
|
74
75
|
const [showAdvanced, setShowAdvanced] = useState(false);
|
|
75
76
|
const [selectedStyle, setSelectedStyle] = useState<string | null>(null);
|
|
77
|
+
const comboboxRef = useRef<HTMLDivElement>(null);
|
|
78
|
+
const { openAbove } = useDropdownDirection(comboboxRef);
|
|
76
79
|
|
|
77
80
|
if (!node?.tagName || !parentNode || !isMarkdownPaneFragmentNode(parentNode))
|
|
78
81
|
return null;
|
|
@@ -84,13 +87,11 @@ const StyleImagePanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
84
87
|
const ctx = getCtx();
|
|
85
88
|
const allNodes = ctx.allNodes.get();
|
|
86
89
|
|
|
87
|
-
// When styling container or outer container, use their IDs directly
|
|
88
90
|
const targetNode = allNodes.get(node.id);
|
|
89
91
|
if (!targetNode) return null;
|
|
90
92
|
|
|
91
93
|
const currentClasses = new Set<string>();
|
|
92
94
|
|
|
93
|
-
// Get existing classes from default classes in parent for THIS element type
|
|
94
95
|
if (parentNode.defaultClasses?.[node.tagName]) {
|
|
95
96
|
const defaults = parentNode.defaultClasses[node.tagName];
|
|
96
97
|
Object.keys(defaults.mobile).forEach((key) => currentClasses.add(key));
|
|
@@ -100,14 +101,12 @@ const StyleImagePanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
100
101
|
Object.keys(defaults.desktop).forEach((key) => currentClasses.add(key));
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
// Get existing override classes for THIS element
|
|
104
104
|
if (`overrideClasses` in targetNode && targetNode.overrideClasses) {
|
|
105
105
|
Object.values(targetNode.overrideClasses).forEach((viewportClasses) => {
|
|
106
106
|
Object.keys(viewportClasses).forEach((key) => currentClasses.add(key));
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
// Create collection for combobox with filtered styles
|
|
111
110
|
const styles = getFilteredStyles(showAdvanced, currentClasses);
|
|
112
111
|
const filteredStyles =
|
|
113
112
|
query === ''
|
|
@@ -118,7 +117,6 @@ const StyleImagePanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
118
117
|
style.key.toLowerCase().includes(query.toLowerCase())
|
|
119
118
|
);
|
|
120
119
|
|
|
121
|
-
// Create collection for Ark UI Combobox
|
|
122
120
|
const collection = useMemo(() => {
|
|
123
121
|
return createListCollection({
|
|
124
122
|
items: filteredStyles,
|
|
@@ -127,7 +125,6 @@ const StyleImagePanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
127
125
|
});
|
|
128
126
|
}, [filteredStyles]);
|
|
129
127
|
|
|
130
|
-
// Get appropriate recommended styles based on element type
|
|
131
128
|
const recommendedStyles = isOuterContainer
|
|
132
129
|
? OUTER_CONTAINER_STYLES
|
|
133
130
|
: isContainer
|
|
@@ -151,7 +148,7 @@ const StyleImagePanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
151
148
|
? 'style-img-container-update'
|
|
152
149
|
: 'style-img-update',
|
|
153
150
|
nodeId: node.id,
|
|
154
|
-
childId,
|
|
151
|
+
childId,
|
|
155
152
|
className: styleKey,
|
|
156
153
|
expanded: true,
|
|
157
154
|
});
|
|
@@ -160,10 +157,9 @@ const StyleImagePanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
160
157
|
);
|
|
161
158
|
|
|
162
159
|
const handleCancel = () => {
|
|
163
|
-
// Return to main panel with correct context
|
|
164
160
|
settingsPanelStore.set({
|
|
165
161
|
action: 'style-image',
|
|
166
|
-
nodeId: childId || node.id,
|
|
162
|
+
nodeId: childId || node.id,
|
|
167
163
|
expanded: true,
|
|
168
164
|
});
|
|
169
165
|
};
|
|
@@ -174,7 +170,6 @@ const StyleImagePanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
174
170
|
? 'Container'
|
|
175
171
|
: 'Image';
|
|
176
172
|
|
|
177
|
-
// CSS to properly style the combobox items with hover and selection
|
|
178
173
|
const comboboxItemStyles = `
|
|
179
174
|
.style-item[data-highlighted] {
|
|
180
175
|
background-color: #0891b2; /* bg-cyan-600 */
|
|
@@ -195,7 +190,7 @@ const StyleImagePanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
195
190
|
`;
|
|
196
191
|
|
|
197
192
|
return (
|
|
198
|
-
<div className="
|
|
193
|
+
<div className="max-w-md space-y-4">
|
|
199
194
|
<style>{comboboxItemStyles}</style>
|
|
200
195
|
|
|
201
196
|
<div className="flex flex-row flex-nowrap justify-between">
|
|
@@ -230,46 +225,57 @@ const StyleImagePanelAdd = ({ node, parentNode, childId }: BasePanelProps) => {
|
|
|
230
225
|
loopFocus={true}
|
|
231
226
|
openOnKeyPress={true}
|
|
232
227
|
composite={true}
|
|
228
|
+
positioning={{
|
|
229
|
+
placement: openAbove ? 'top' : 'bottom',
|
|
230
|
+
gutter: 4,
|
|
231
|
+
sameWidth: true,
|
|
232
|
+
}}
|
|
233
233
|
>
|
|
234
|
-
<
|
|
235
|
-
<
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
<Combobox.Trigger className="absolute inset-y-0 right-0 flex items-center pr-2">
|
|
241
|
-
<ChevronUpDownIcon
|
|
242
|
-
className="text-mydarkgrey h-5 w-5"
|
|
243
|
-
aria-hidden="true"
|
|
234
|
+
<Combobox.Control ref={comboboxRef}>
|
|
235
|
+
<div className="relative">
|
|
236
|
+
<Combobox.Input
|
|
237
|
+
className="border-mydarkgrey focus:border-myblue focus:ring-myblue w-full rounded-md py-2 pl-3 pr-10 text-xl shadow-sm"
|
|
238
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
239
|
+
placeholder="Search styles..."
|
|
244
240
|
/>
|
|
245
|
-
|
|
246
|
-
|
|
241
|
+
<Combobox.Trigger className="absolute inset-y-0 right-0 flex items-center pr-2">
|
|
242
|
+
<ChevronUpDownIcon
|
|
243
|
+
className="text-mydarkgrey h-5 w-5"
|
|
244
|
+
aria-hidden="true"
|
|
245
|
+
/>
|
|
246
|
+
</Combobox.Trigger>
|
|
247
|
+
</div>
|
|
248
|
+
</Combobox.Control>
|
|
247
249
|
|
|
248
|
-
<
|
|
249
|
-
|
|
250
|
-
<
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
250
|
+
<Portal>
|
|
251
|
+
<Combobox.Positioner style={{ zIndex: 1002 }}>
|
|
252
|
+
<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">
|
|
253
|
+
{collection.items.length === 0 ? (
|
|
254
|
+
<div className="text-mydarkgrey relative cursor-default select-none px-4 py-2">
|
|
255
|
+
Nothing found.
|
|
256
|
+
</div>
|
|
257
|
+
) : (
|
|
258
|
+
collection.items.map((style) => (
|
|
259
|
+
<Combobox.Item
|
|
260
|
+
key={style.key}
|
|
261
|
+
item={style}
|
|
262
|
+
className="style-item relative cursor-default select-none py-2 pl-10 pr-4 text-black"
|
|
263
|
+
>
|
|
264
|
+
<span className="block truncate">
|
|
265
|
+
{style.title}
|
|
266
|
+
<span className="ml-2 text-sm opacity-60">
|
|
267
|
+
{style.className}
|
|
268
|
+
</span>
|
|
269
|
+
</span>
|
|
270
|
+
<span className="style-indicator absolute inset-y-0 left-0 flex items-center pl-3 text-cyan-600">
|
|
271
|
+
<CheckIcon className="h-5 w-5" aria-hidden="true" />
|
|
272
|
+
</span>
|
|
273
|
+
</Combobox.Item>
|
|
274
|
+
))
|
|
275
|
+
)}
|
|
276
|
+
</Combobox.Content>
|
|
277
|
+
</Combobox.Positioner>
|
|
278
|
+
</Portal>
|
|
273
279
|
</Combobox.Root>
|
|
274
280
|
</div>
|
|
275
281
|
|
|
@@ -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, FlatNode } from '@/types/compositorTypes';
|
|
11
12
|
|
|
12
13
|
// Recommended styles for list items
|
|
@@ -66,17 +67,17 @@ const StyleLiElementAddPanel = ({
|
|
|
66
67
|
const [query, setQuery] = useState('');
|
|
67
68
|
const [showAdvanced, setShowAdvanced] = useState(false);
|
|
68
69
|
const [selectedStyle, setSelectedStyle] = useState<string | null>(null);
|
|
70
|
+
const comboboxRef = useRef<HTMLDivElement>(null);
|
|
71
|
+
const { openAbove } = useDropdownDirection(comboboxRef);
|
|
69
72
|
|
|
70
73
|
if (!node?.tagName || !parentNode || !isMarkdownPaneFragmentNode(parentNode))
|
|
71
74
|
return null;
|
|
72
75
|
|
|
73
|
-
// Determine if we're styling a container or list item
|
|
74
76
|
const isContainer = node.tagName === 'ul' || node.tagName === 'ol';
|
|
75
77
|
|
|
76
78
|
const ctx = getCtx();
|
|
77
79
|
const allNodes = ctx.allNodes.get();
|
|
78
80
|
|
|
79
|
-
// Get the correct node based on what we're styling
|
|
80
81
|
const targetNodeId = isContainer ? node.id : childId || node.id;
|
|
81
82
|
const targetNode = allNodes.get(targetNodeId) as FlatNode;
|
|
82
83
|
|
|
@@ -84,7 +85,6 @@ const StyleLiElementAddPanel = ({
|
|
|
84
85
|
|
|
85
86
|
const currentClasses = new Set<string>();
|
|
86
87
|
|
|
87
|
-
// Get existing classes from default classes in parent
|
|
88
88
|
if (parentNode.defaultClasses?.[targetNode.tagName]) {
|
|
89
89
|
const defaults = parentNode.defaultClasses[targetNode.tagName];
|
|
90
90
|
Object.keys(defaults.mobile).forEach((key) => currentClasses.add(key));
|
|
@@ -94,7 +94,6 @@ const StyleLiElementAddPanel = ({
|
|
|
94
94
|
Object.keys(defaults.desktop).forEach((key) => currentClasses.add(key));
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
// Get existing classes from override classes in node
|
|
98
97
|
if (targetNode.overrideClasses) {
|
|
99
98
|
Object.values(targetNode.overrideClasses).forEach((viewportClasses) => {
|
|
100
99
|
Object.keys(viewportClasses).forEach((key) => currentClasses.add(key));
|
|
@@ -103,7 +102,6 @@ const StyleLiElementAddPanel = ({
|
|
|
103
102
|
|
|
104
103
|
const styles = getFilteredStyles(showAdvanced, currentClasses);
|
|
105
104
|
|
|
106
|
-
// Create collection for combobox
|
|
107
105
|
const collection = useMemo(() => {
|
|
108
106
|
const filteredStyles =
|
|
109
107
|
query === ''
|
|
@@ -121,7 +119,6 @@ const StyleLiElementAddPanel = ({
|
|
|
121
119
|
});
|
|
122
120
|
}, [styles, query]);
|
|
123
121
|
|
|
124
|
-
// Get appropriate recommended styles based on element type
|
|
125
122
|
const recommendedStyles = isContainer
|
|
126
123
|
? LIST_CONTAINER_STYLES
|
|
127
124
|
: LIST_ITEM_STYLES;
|
|
@@ -179,7 +176,6 @@ const StyleLiElementAddPanel = ({
|
|
|
179
176
|
});
|
|
180
177
|
};
|
|
181
178
|
|
|
182
|
-
// CSS to properly style the combobox items with hover and selection
|
|
183
179
|
const comboboxItemStyles = `
|
|
184
180
|
.style-item[data-highlighted] {
|
|
185
181
|
background-color: #0891b2; /* bg-cyan-600 */
|
|
@@ -200,7 +196,7 @@ const StyleLiElementAddPanel = ({
|
|
|
200
196
|
`;
|
|
201
197
|
|
|
202
198
|
return (
|
|
203
|
-
<div className="
|
|
199
|
+
<div className="max-w-md space-y-4">
|
|
204
200
|
<style>{comboboxItemStyles}</style>
|
|
205
201
|
|
|
206
202
|
<div className="flex flex-row flex-nowrap justify-between">
|
|
@@ -235,46 +231,57 @@ const StyleLiElementAddPanel = ({
|
|
|
235
231
|
loopFocus={true}
|
|
236
232
|
openOnKeyPress={true}
|
|
237
233
|
composite={true}
|
|
234
|
+
positioning={{
|
|
235
|
+
placement: openAbove ? 'top' : 'bottom',
|
|
236
|
+
gutter: 4,
|
|
237
|
+
sameWidth: true,
|
|
238
|
+
}}
|
|
238
239
|
>
|
|
239
|
-
<
|
|
240
|
-
<
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
<Combobox.Trigger className="absolute inset-y-0 right-0 flex items-center pr-2">
|
|
246
|
-
<ChevronUpDownIcon
|
|
247
|
-
className="text-mydarkgrey h-5 w-5"
|
|
248
|
-
aria-hidden="true"
|
|
240
|
+
<Combobox.Control ref={comboboxRef}>
|
|
241
|
+
<div className="relative">
|
|
242
|
+
<Combobox.Input
|
|
243
|
+
className="border-mydarkgrey focus:border-myblue focus:ring-myblue w-full rounded-md py-2 pl-3 pr-10 text-xl shadow-sm"
|
|
244
|
+
placeholder="Search styles..."
|
|
245
|
+
autoComplete="off"
|
|
249
246
|
/>
|
|
250
|
-
|
|
251
|
-
|
|
247
|
+
<Combobox.Trigger className="absolute inset-y-0 right-0 flex items-center pr-2">
|
|
248
|
+
<ChevronUpDownIcon
|
|
249
|
+
className="text-mydarkgrey h-5 w-5"
|
|
250
|
+
aria-hidden="true"
|
|
251
|
+
/>
|
|
252
|
+
</Combobox.Trigger>
|
|
253
|
+
</div>
|
|
254
|
+
</Combobox.Control>
|
|
252
255
|
|
|
253
|
-
<
|
|
254
|
-
|
|
255
|
-
<
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
256
|
+
<Portal>
|
|
257
|
+
<Combobox.Positioner style={{ zIndex: 1002 }}>
|
|
258
|
+
<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">
|
|
259
|
+
{collection.items.length === 0 ? (
|
|
260
|
+
<div className="text-mydarkgrey relative cursor-default select-none px-4 py-2">
|
|
261
|
+
Nothing found.
|
|
262
|
+
</div>
|
|
263
|
+
) : (
|
|
264
|
+
collection.items.map((item) => (
|
|
265
|
+
<Combobox.Item
|
|
266
|
+
key={item.key}
|
|
267
|
+
item={item}
|
|
268
|
+
className="style-item relative cursor-default select-none py-2 pl-10 pr-4"
|
|
269
|
+
>
|
|
270
|
+
<span className="block truncate">
|
|
271
|
+
{item.title}
|
|
272
|
+
<span className="ml-2 text-sm opacity-60">
|
|
273
|
+
{item.className}
|
|
274
|
+
</span>
|
|
275
|
+
</span>
|
|
276
|
+
<span className="style-indicator absolute inset-y-0 left-0 flex items-center pl-3 text-cyan-600">
|
|
277
|
+
<CheckIcon className="h-5 w-5" aria-hidden="true" />
|
|
278
|
+
</span>
|
|
279
|
+
</Combobox.Item>
|
|
280
|
+
))
|
|
281
|
+
)}
|
|
282
|
+
</Combobox.Content>
|
|
283
|
+
</Combobox.Positioner>
|
|
284
|
+
</Portal>
|
|
278
285
|
</Combobox.Root>
|
|
279
286
|
</div>
|
|
280
287
|
|