astro-tractstack 2.0.17 → 2.0.19

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 (63) hide show
  1. package/dist/index.js +18 -0
  2. package/package.json +1 -1
  3. package/templates/src/components/codehooks/FeaturedArticleSetup.tsx +1 -1
  4. package/templates/src/components/codehooks/ListContentSetup.tsx +1 -1
  5. package/templates/src/components/compositor/Compositor.tsx +1 -0
  6. package/templates/src/components/compositor/Node.tsx +41 -17
  7. package/templates/src/components/compositor/nodes/GhostInsertBlock.tsx +9 -6
  8. package/templates/src/components/compositor/nodes/GridLayout.tsx +124 -0
  9. package/templates/src/components/compositor/nodes/GridLayout_eraser.tsx +33 -0
  10. package/templates/src/components/compositor/nodes/Markdown.tsx +67 -37
  11. package/templates/src/components/compositor/nodes/Markdown_eraser.tsx +56 -0
  12. package/templates/src/components/compositor/preview/FeaturedArticlePreview.tsx +8 -2
  13. package/templates/src/components/edit/PanelSwitch.tsx +232 -75
  14. package/templates/src/components/edit/SettingsPanel.tsx +0 -1
  15. package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +3 -3
  16. package/templates/src/components/edit/pane/AddPanePanel_new.tsx +402 -167
  17. package/templates/src/components/edit/pane/AddPanePanel_reuse.tsx +2 -2
  18. package/templates/src/components/edit/pane/ConfigPanePanel.tsx +1 -7
  19. package/templates/src/components/edit/pane/PanePanel_impression.tsx +1 -1
  20. package/templates/src/components/edit/pane/RestylePaneModal.tsx +8 -5
  21. package/templates/src/components/edit/pane/steps/AiDesignStep.tsx +6 -6
  22. package/templates/src/components/edit/pane/steps/CopyInputStep.tsx +3 -3
  23. package/templates/src/components/edit/pane/steps/DesignLibraryStep.tsx +4 -4
  24. package/templates/src/components/edit/panels/StyleElementPanel.tsx +11 -4
  25. package/templates/src/components/edit/panels/StyleElementPanel_add.tsx +8 -8
  26. package/templates/src/components/edit/panels/StyleElementPanel_remove.tsx +14 -4
  27. package/templates/src/components/edit/panels/StyleElementPanel_update.tsx +16 -4
  28. package/templates/src/components/edit/panels/StyleImagePanel.tsx +7 -3
  29. package/templates/src/components/edit/panels/StyleImagePanel_add.tsx +9 -2
  30. package/templates/src/components/edit/panels/StyleImagePanel_remove.tsx +5 -2
  31. package/templates/src/components/edit/panels/StyleImagePanel_update.tsx +5 -2
  32. package/templates/src/components/edit/panels/StyleLiElementPanel.tsx +7 -3
  33. package/templates/src/components/edit/panels/StyleLiElementPanel_add.tsx +9 -2
  34. package/templates/src/components/edit/panels/StyleLiElementPanel_remove.tsx +5 -2
  35. package/templates/src/components/edit/panels/StyleLiElementPanel_update.tsx +5 -2
  36. package/templates/src/components/edit/panels/StyleParentPanel.tsx +530 -171
  37. package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +77 -42
  38. package/templates/src/components/edit/panels/StyleParentPanel_deleteLayer.tsx +38 -22
  39. package/templates/src/components/edit/panels/StyleParentPanel_remove.tsx +171 -66
  40. package/templates/src/components/edit/panels/StyleParentPanel_update.tsx +166 -98
  41. package/templates/src/components/edit/panels/StyleWidgetPanel.tsx +7 -3
  42. package/templates/src/components/edit/panels/StyleWidgetPanel_add.tsx +9 -2
  43. package/templates/src/components/edit/panels/StyleWidgetPanel_remove.tsx +5 -2
  44. package/templates/src/components/edit/panels/StyleWidgetPanel_update.tsx +6 -2
  45. package/templates/src/components/edit/state/SaveModal.tsx +10 -2
  46. package/templates/src/components/edit/state/SaveToLibraryModal.tsx +6 -6
  47. package/templates/src/components/fields/PaneBreakShapeSelector.tsx +1 -1
  48. package/templates/src/components/widgets/ImpressionWrapper.tsx +4 -1
  49. package/templates/src/constants/prompts.json +23 -2
  50. package/templates/src/stores/nodes.ts +356 -212
  51. package/templates/src/stores/storykeep.ts +3 -1
  52. package/templates/src/types/compositorTypes.ts +56 -3
  53. package/templates/src/types/tractstack.ts +1 -0
  54. package/templates/src/utils/compositor/TemplateNodes.ts +8 -0
  55. package/templates/src/utils/compositor/aiPaneParser.ts +263 -83
  56. package/templates/src/utils/compositor/designLibraryHelper.ts +12 -9
  57. package/templates/src/utils/compositor/nodesHelper.ts +229 -0
  58. package/templates/src/utils/compositor/reduceNodesClassNames.ts +40 -1
  59. package/templates/src/utils/compositor/typeGuards.ts +7 -0
  60. package/templates/src/utils/etl/extractor.ts +1 -5
  61. package/templates/src/utils/etl/index.ts +1 -0
  62. package/templates/src/utils/etl/transformer.ts +70 -25
  63. package/utils/inject-files.ts +18 -0
@@ -5,9 +5,17 @@ import ChevronUpDownIcon from '@heroicons/react/24/outline/ChevronUpDownIcon';
5
5
  import CheckIcon from '@heroicons/react/24/outline/CheckIcon';
6
6
  import { settingsPanelStore } from '@/stores/storykeep';
7
7
  import { tailwindClasses } from '@/utils/compositor/tailwindClasses';
8
- import { isMarkdownPaneFragmentNode } from '@/utils/compositor/typeGuards';
8
+ import {
9
+ isMarkdownPaneFragmentNode,
10
+ isGridLayoutNode,
11
+ } from '@/utils/compositor/typeGuards';
9
12
  import { useDropdownDirection } from '@/utils/helpers';
10
- import type { BasePanelProps, PaneFragmentNode } from '@/types/compositorTypes';
13
+ import type {
14
+ ParentBasePanelProps,
15
+ MarkdownPaneFragmentNode,
16
+ GridLayoutNode,
17
+ DefaultClassValue,
18
+ } from '@/types/compositorTypes';
11
19
 
12
20
  const RECOMMENDED_STYLES = [
13
21
  { key: 'bgCOLOR', title: 'Background Color' },
@@ -54,41 +62,66 @@ interface StyleOption {
54
62
  values: string[];
55
63
  }
56
64
 
57
- const StyleParentPanelAdd = ({ node, layer }: BasePanelProps) => {
65
+ type StyleableNode = MarkdownPaneFragmentNode | GridLayoutNode;
66
+
67
+ // This custom prop is passed via the settingsPanelStore signal.
68
+ type CustomPanelProps = ParentBasePanelProps & {
69
+ targetProperty: 'parentClasses' | 'gridClasses';
70
+ };
71
+
72
+ const StyleParentPanelAdd = ({
73
+ node,
74
+ layer,
75
+ targetProperty,
76
+ }: CustomPanelProps) => {
58
77
  const [query, setQuery] = useState('');
59
78
  const [showAdvanced, setShowAdvanced] = useState(false);
60
79
  const [selectedStyle, setSelectedStyle] = useState<string | null>(null);
61
80
  const comboboxRef = useRef<HTMLDivElement>(null);
62
81
  const { openAbove } = useDropdownDirection(comboboxRef);
63
82
 
64
- const paneFragmentNode = node as PaneFragmentNode | null;
83
+ const styleableNode = node as StyleableNode | null;
65
84
 
66
85
  if (
67
- !paneFragmentNode ||
68
- !isMarkdownPaneFragmentNode(paneFragmentNode) ||
69
- !layer
86
+ !styleableNode ||
87
+ (!isMarkdownPaneFragmentNode(styleableNode) &&
88
+ !isGridLayoutNode(styleableNode))
70
89
  ) {
71
90
  return null;
72
91
  }
73
92
 
74
- const currentLayerClasses = new Set<string>();
93
+ const currentClassesSet = useMemo(() => {
94
+ const classSet = new Set<string>();
95
+ if (!styleableNode) return classSet;
75
96
 
76
- if (paneFragmentNode.parentClasses?.[layer - 1]) {
77
- const layerClasses = paneFragmentNode.parentClasses[layer - 1];
78
- Object.keys(layerClasses.mobile || {}).forEach((key) =>
79
- currentLayerClasses.add(key)
80
- );
81
- Object.keys(layerClasses.tablet || {}).forEach((key) =>
82
- currentLayerClasses.add(key)
83
- );
84
- Object.keys(layerClasses.desktop || {}).forEach((key) =>
85
- currentLayerClasses.add(key)
86
- );
87
- }
97
+ let classesSource: DefaultClassValue | undefined;
98
+
99
+ if (targetProperty === 'parentClasses' && layer) {
100
+ const layerIndex = layer - 1;
101
+ classesSource = styleableNode.parentClasses?.[layerIndex];
102
+ } else if (targetProperty === 'gridClasses') {
103
+ if (isMarkdownPaneFragmentNode(styleableNode)) {
104
+ classesSource = styleableNode.gridClasses;
105
+ }
106
+ }
107
+
108
+ if (classesSource) {
109
+ Object.keys(classesSource.mobile || {}).forEach((key) =>
110
+ classSet.add(key)
111
+ );
112
+ Object.keys(classesSource.tablet || {}).forEach((key) =>
113
+ classSet.add(key)
114
+ );
115
+ Object.keys(classesSource.desktop || {}).forEach((key) =>
116
+ classSet.add(key)
117
+ );
118
+ }
88
119
 
89
- const styles = getFilteredStyles(showAdvanced, currentLayerClasses);
120
+ return classSet;
121
+ }, [styleableNode, layer, targetProperty]);
122
+
123
+ const styles = getFilteredStyles(showAdvanced, currentClassesSet);
90
124
 
91
- // Create collection for Ark UI Combobox
92
125
  const collection = useMemo(() => {
93
126
  const filteredStyles =
94
127
  query === ''
@@ -107,24 +140,32 @@ const StyleParentPanelAdd = ({ node, layer }: BasePanelProps) => {
107
140
  }, [styles, query]);
108
141
 
109
142
  const availableRecommendedStyles = RECOMMENDED_STYLES.filter(
110
- (style) => !currentLayerClasses.has(style.key)
143
+ (style) => !currentClassesSet.has(style.key)
111
144
  );
112
145
 
113
- const handleValueChange = useCallback(
114
- (details: { value: string[] }) => {
115
- const styleKey = details.value[0] || '';
116
- if (!styleKey) return;
117
-
118
- setSelectedStyle(styleKey);
146
+ const dispatchUpdate = useCallback(
147
+ (styleKey: string) => {
148
+ if (!styleableNode) return;
119
149
  settingsPanelStore.set({
120
- nodeId: paneFragmentNode.id,
150
+ nodeId: styleableNode.id,
121
151
  layer: layer,
122
152
  className: styleKey,
123
153
  action: 'style-parent-update',
154
+ targetProperty: targetProperty,
124
155
  expanded: true,
125
156
  });
126
157
  },
127
- [paneFragmentNode.id, layer]
158
+ [styleableNode, layer, targetProperty]
159
+ );
160
+
161
+ const handleValueChange = useCallback(
162
+ (details: { value: string[] }) => {
163
+ const styleKey = details.value[0] || '';
164
+ if (!styleKey) return;
165
+ setSelectedStyle(styleKey);
166
+ dispatchUpdate(styleKey);
167
+ },
168
+ [dispatchUpdate]
128
169
  );
129
170
 
130
171
  const handleInputChange = useCallback(
@@ -136,30 +177,24 @@ const StyleParentPanelAdd = ({ node, layer }: BasePanelProps) => {
136
177
 
137
178
  const handleStyleClick = useCallback(
138
179
  (styleKey: string) => {
139
- settingsPanelStore.set({
140
- nodeId: paneFragmentNode.id,
141
- layer: layer,
142
- className: styleKey,
143
- action: 'style-parent-update',
144
- expanded: true,
145
- });
180
+ dispatchUpdate(styleKey);
146
181
  },
147
- [paneFragmentNode.id, layer]
182
+ [dispatchUpdate]
148
183
  );
149
184
 
150
185
  const handleCancel = () => {
186
+ if (!styleableNode) return;
151
187
  settingsPanelStore.set({
152
- nodeId: paneFragmentNode.id,
188
+ nodeId: styleableNode.id,
153
189
  layer: layer,
154
190
  action: 'style-parent',
155
191
  expanded: true,
156
192
  });
157
193
  };
158
194
 
159
- // CSS to properly style the combobox items with hover and selection
160
195
  const comboboxItemStyles = `
161
196
  .style-item[data-highlighted] {
162
- background-color: #0891b2; /* bg-cyan-600 */
197
+ background-color: #0891b2;
163
198
  color: white;
164
199
  }
165
200
  .style-item[data-highlighted] .style-indicator {
@@ -1,21 +1,37 @@
1
1
  import { settingsPanelStore } from '@/stores/storykeep';
2
2
  import { getCtx } from '@/stores/nodes';
3
- import { isMarkdownPaneFragmentNode } from '@/utils/compositor/typeGuards';
3
+ import {
4
+ isMarkdownPaneFragmentNode,
5
+ isGridLayoutNode,
6
+ } from '@/utils/compositor/typeGuards';
4
7
  import { cloneDeep } from '@/utils/helpers';
5
8
  import type {
6
- BasePanelProps,
9
+ ParentBasePanelProps,
7
10
  MarkdownPaneFragmentNode,
11
+ GridLayoutNode,
8
12
  } from '@/types/compositorTypes';
9
13
 
10
- const StyleParentDeleteLayerPanel = ({ node, layer }: BasePanelProps) => {
11
- if (!layer) return null;
12
- if (!node || !isMarkdownPaneFragmentNode(node)) return null;
13
- if (!node.parentClasses) return null;
14
+ type StyleableNode = MarkdownPaneFragmentNode | GridLayoutNode;
15
+
16
+ const StyleParentDeleteLayerPanel = ({ node, layer }: ParentBasePanelProps) => {
17
+ const styleableNode = node as StyleableNode | null;
18
+
19
+ if (
20
+ !layer ||
21
+ !styleableNode ||
22
+ !(
23
+ isMarkdownPaneFragmentNode(styleableNode) ||
24
+ isGridLayoutNode(styleableNode)
25
+ )
26
+ ) {
27
+ return null;
28
+ }
29
+ if (!styleableNode.parentClasses) return null;
14
30
 
15
31
  const layerIndex = layer - 1;
16
- if (layerIndex >= node.parentClasses.length) return null;
32
+ if (layerIndex >= styleableNode.parentClasses.length) return null;
17
33
 
18
- const currentLayer = node.parentClasses[layerIndex];
34
+ const currentLayer = styleableNode.parentClasses[layerIndex];
19
35
  const allKeys = new Set([
20
36
  ...Object.keys(currentLayer.mobile || {}),
21
37
  ...Object.keys(currentLayer.tablet || {}),
@@ -25,7 +41,7 @@ const StyleParentDeleteLayerPanel = ({ node, layer }: BasePanelProps) => {
25
41
 
26
42
  const resetStore = () => {
27
43
  settingsPanelStore.set({
28
- nodeId: node.id,
44
+ nodeId: styleableNode.id,
29
45
  action: 'style-parent',
30
46
  expanded: true,
31
47
  });
@@ -33,25 +49,25 @@ const StyleParentDeleteLayerPanel = ({ node, layer }: BasePanelProps) => {
33
49
 
34
50
  const handleYesClick = () => {
35
51
  const ctx = getCtx();
36
- const allNodes = ctx.allNodes.get();
37
- const markdownNode = allNodes.get(node.id) as MarkdownPaneFragmentNode;
52
+ const nodeToUpdate = cloneDeep(
53
+ ctx.allNodes.get().get(styleableNode.id)
54
+ ) as StyleableNode;
38
55
 
39
- if (!markdownNode || !isMarkdownPaneFragmentNode(markdownNode)) return;
40
- if (!markdownNode.parentClasses) return;
56
+ if (!nodeToUpdate.parentClasses) return;
41
57
 
42
58
  // If this is the last layer, replace with empty classes instead of removing
43
- if (markdownNode.parentClasses.length === 1) {
59
+ if (nodeToUpdate.parentClasses.length === 1) {
44
60
  const emptyLayer = {
45
61
  mobile: {},
46
62
  tablet: {},
47
63
  desktop: {},
48
64
  };
49
65
 
50
- const updatedNode: MarkdownPaneFragmentNode = cloneDeep({
51
- ...markdownNode,
66
+ const updatedNode = {
67
+ ...nodeToUpdate,
52
68
  parentClasses: [emptyLayer],
53
69
  isChanged: true,
54
- });
70
+ };
55
71
 
56
72
  ctx.modifyNodes([updatedNode]);
57
73
  resetStore();
@@ -60,15 +76,15 @@ const StyleParentDeleteLayerPanel = ({ node, layer }: BasePanelProps) => {
60
76
 
61
77
  // Otherwise remove the layer
62
78
  const newParentClasses = [
63
- ...markdownNode.parentClasses.slice(0, layerIndex),
64
- ...markdownNode.parentClasses.slice(layerIndex + 1),
79
+ ...nodeToUpdate.parentClasses.slice(0, layerIndex),
80
+ ...nodeToUpdate.parentClasses.slice(layerIndex + 1),
65
81
  ];
66
82
 
67
- const updatedNode: MarkdownPaneFragmentNode = cloneDeep({
68
- ...markdownNode,
83
+ const updatedNode = {
84
+ ...nodeToUpdate,
69
85
  parentClasses: newParentClasses,
70
86
  isChanged: true,
71
- });
87
+ };
72
88
 
73
89
  ctx.modifyNodes([updatedNode]);
74
90
  resetStore();
@@ -1,87 +1,192 @@
1
+ import { useState, useCallback, useMemo } from 'react';
1
2
  import { settingsPanelStore } from '@/stores/storykeep';
2
3
  import { getCtx } from '@/stores/nodes';
3
- import { tailwindClasses } from '@/utils/compositor/tailwindClasses';
4
- import { isMarkdownPaneFragmentNode } from '@/utils/compositor/typeGuards';
5
4
  import { cloneDeep } from '@/utils/helpers';
5
+ import {
6
+ isMarkdownPaneFragmentNode,
7
+ isGridLayoutNode,
8
+ } from '@/utils/compositor/typeGuards';
6
9
  import type {
7
- BasePanelProps,
10
+ ParentBasePanelProps,
8
11
  MarkdownPaneFragmentNode,
12
+ GridLayoutNode,
13
+ DefaultClassValue,
9
14
  } from '@/types/compositorTypes';
10
15
 
11
- const StyleParentRemovePanel = ({ node, layer, className }: BasePanelProps) => {
12
- if (!className) return null;
16
+ type StyleableNode = MarkdownPaneFragmentNode | GridLayoutNode;
13
17
 
14
- const friendlyName = tailwindClasses[className]?.title || className;
18
+ // This custom prop is passed via the settingsPanelStore signal.
19
+ type CustomPanelProps = ParentBasePanelProps & {
20
+ targetProperty: 'parentClasses' | 'gridClasses';
21
+ };
15
22
 
16
- const resetStore = () => {
17
- if (node?.id)
18
- settingsPanelStore.set({
19
- nodeId: node.id,
20
- layer: layer,
21
- action: `style-parent`,
22
- expanded: true,
23
- });
24
- };
23
+ const StyleParentPanelRemove = ({
24
+ node,
25
+ layer,
26
+ className,
27
+ targetProperty,
28
+ }: CustomPanelProps) => {
29
+ const [confirm, setConfirm] = useState(false);
30
+ const ctx = getCtx();
25
31
 
26
- const handleYesClick = () => {
27
- if (!node || !className || !layer) {
28
- console.error('Missing required properties for class removal');
29
- return;
32
+ const styleableNode = node as StyleableNode | null;
33
+
34
+ if (
35
+ !styleableNode ||
36
+ (!isMarkdownPaneFragmentNode(styleableNode) &&
37
+ !isGridLayoutNode(styleableNode))
38
+ ) {
39
+ return null;
40
+ }
41
+
42
+ const values = useMemo(() => {
43
+ if (!styleableNode || !layer || !className) {
44
+ return { mobile: '', tablet: '', desktop: '' };
30
45
  }
31
- const ctx = getCtx();
32
- const allNodes = ctx.allNodes.get();
33
- const markdownNode = cloneDeep(
34
- allNodes.get(node.id) as MarkdownPaneFragmentNode
35
- );
36
- if (!markdownNode || !isMarkdownPaneFragmentNode(markdownNode)) return;
37
- const layerIndex = layer - 1;
38
- const layerClasses = markdownNode?.parentClasses?.[layerIndex];
39
- if (!layerClasses) return;
40
- // Remove the class from each viewport if it exists
41
- if (className in layerClasses.mobile) delete layerClasses.mobile[className];
42
- if (className in layerClasses.tablet) delete layerClasses.tablet[className];
43
- if (className in layerClasses.desktop)
44
- delete layerClasses.desktop[className];
45
- // Update the node in the store
46
- const newData = { ...markdownNode, isChanged: true };
47
- ctx.modifyNodes([newData]);
48
- resetStore();
49
- };
50
46
 
51
- const handleNoClick = () => {
52
- resetStore();
47
+ let classesSource: DefaultClassValue | undefined;
48
+
49
+ if (targetProperty === 'parentClasses') {
50
+ const layerIndex = layer - 1;
51
+ classesSource = styleableNode.parentClasses?.[layerIndex];
52
+ } else if (
53
+ targetProperty === 'gridClasses' &&
54
+ isMarkdownPaneFragmentNode(styleableNode)
55
+ ) {
56
+ classesSource = styleableNode.gridClasses;
57
+ }
58
+
59
+ if (!classesSource) {
60
+ return { mobile: '', tablet: '', desktop: '' };
61
+ }
62
+
63
+ return {
64
+ mobile: classesSource.mobile?.[className] || '',
65
+ tablet: classesSource.tablet?.[className] || '',
66
+ desktop: classesSource.desktop?.[className] || '',
67
+ };
68
+ }, [styleableNode, layer, className, targetProperty]);
69
+
70
+ const handleCancel = () => {
71
+ settingsPanelStore.set({
72
+ nodeId: styleableNode.id,
73
+ layer: layer,
74
+ action: 'style-parent',
75
+ expanded: true,
76
+ });
53
77
  };
54
78
 
79
+ const handleRemove = useCallback(() => {
80
+ if (!styleableNode || !layer || !className) return;
81
+
82
+ const updatedNode = cloneDeep(styleableNode);
83
+ let wasModified = false;
84
+
85
+ if (targetProperty === 'parentClasses') {
86
+ const layerIndex = layer - 1;
87
+ if (updatedNode.parentClasses?.[layerIndex]) {
88
+ if (updatedNode.parentClasses[layerIndex].mobile?.[className]) {
89
+ delete updatedNode.parentClasses[layerIndex].mobile[className];
90
+ wasModified = true;
91
+ }
92
+ if (updatedNode.parentClasses[layerIndex].tablet?.[className]) {
93
+ delete updatedNode.parentClasses[layerIndex].tablet[className];
94
+ wasModified = true;
95
+ }
96
+ if (updatedNode.parentClasses[layerIndex].desktop?.[className]) {
97
+ delete updatedNode.parentClasses[layerIndex].desktop[className];
98
+ wasModified = true;
99
+ }
100
+ }
101
+ } else if (
102
+ targetProperty === 'gridClasses' &&
103
+ isMarkdownPaneFragmentNode(updatedNode)
104
+ ) {
105
+ if (updatedNode.gridClasses) {
106
+ if (updatedNode.gridClasses.mobile?.[className]) {
107
+ delete updatedNode.gridClasses.mobile[className];
108
+ wasModified = true;
109
+ }
110
+ if (updatedNode.gridClasses.tablet?.[className]) {
111
+ delete updatedNode.gridClasses.tablet[className];
112
+ wasModified = true;
113
+ }
114
+ if (updatedNode.gridClasses.desktop?.[className]) {
115
+ delete updatedNode.gridClasses.desktop[className];
116
+ wasModified = true;
117
+ }
118
+ }
119
+ }
120
+
121
+ if (wasModified) {
122
+ updatedNode.isChanged = true;
123
+ ctx.modifyNodes([updatedNode]);
124
+ ctx.notifyNode('root');
125
+ }
126
+
127
+ settingsPanelStore.set({
128
+ nodeId: styleableNode.id,
129
+ layer: layer,
130
+ action: 'style-parent',
131
+ expanded: true,
132
+ });
133
+ }, [styleableNode, layer, className, targetProperty, ctx]);
134
+
135
+ if (!className) return null;
136
+
55
137
  return (
56
138
  <div className="space-y-4">
57
- <h3 className="text-xl font-bold">
58
- Remove <span className="font-bold">{friendlyName}</span>?
59
- </h3>
60
- <div className="space-y-4 rounded bg-slate-50 p-6">
61
- <ul className="text-mydarkgrey flex flex-wrap gap-x-4 gap-y-1">
62
- <li>
63
- <em>Are you sure?</em>
64
- </li>
65
- <li>
66
- <button
67
- onClick={handleYesClick}
68
- className="font-bold underline hover:text-black"
69
- >
70
- Yes
71
- </button>
72
- </li>
73
- <li>
74
- <button
75
- onClick={handleNoClick}
76
- className="font-bold underline hover:text-black"
77
- >
78
- No / Cancel
79
- </button>
80
- </li>
81
- </ul>
139
+ <div className="flex flex-row flex-nowrap justify-between">
140
+ <button
141
+ title="Return to preview pane"
142
+ onClick={handleCancel}
143
+ className="text-myblue hover:text-black"
144
+ >
145
+ Go Back
146
+ </button>
147
+ </div>
148
+ <div>
149
+ <h3 className="text-xl font-bold">Remove Style</h3>
150
+ <p className="text-mydarkgrey mt-2">
151
+ Are you sure you want to remove this style?
152
+ </p>
153
+ <div className="my-4 rounded-md bg-slate-100 p-4">
154
+ <p className="font-mono text-sm font-bold">{className}</p>
155
+ <div className="mt-2 space-y-1 text-sm">
156
+ <p>
157
+ <span className="font-bold">Mobile:</span>{' '}
158
+ {values.mobile || 'N/A'}
159
+ </p>
160
+ <p>
161
+ <span className="font-bold">Tablet:</span>{' '}
162
+ {values.tablet || 'N/A'}
163
+ </p>
164
+ <p>
165
+ <span className="font-bold">Desktop:</span>{' '}
166
+ {values.desktop || 'N/A'}
167
+ </p>
168
+ </div>
169
+ </div>
170
+ </div>
171
+ <div className="flex items-center justify-end space-x-3">
172
+ {!confirm ? (
173
+ <button
174
+ onClick={() => setConfirm(true)}
175
+ className="rounded-md bg-red-600 px-4 py-2 text-sm font-bold text-white shadow-sm hover:bg-red-700"
176
+ >
177
+ Remove
178
+ </button>
179
+ ) : (
180
+ <button
181
+ onClick={handleRemove}
182
+ className="rounded-md bg-red-700 px-4 py-2 text-sm font-bold text-white shadow-sm ring-2 ring-red-800 ring-offset-2"
183
+ >
184
+ Confirm Removal
185
+ </button>
186
+ )}
82
187
  </div>
83
188
  </div>
84
189
  );
85
190
  };
86
191
 
87
- export default StyleParentRemovePanel;
192
+ export default StyleParentPanelRemove;