@embeddables/cli 0.1.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/README.md +116 -0
- package/bin/embeddables.mjs +2 -0
- package/dist/auth/index.d.ts +43 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +100 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +75 -0
- package/dist/commands/build-workbench.d.ts +5 -0
- package/dist/commands/build-workbench.d.ts.map +1 -0
- package/dist/commands/build-workbench.js +122 -0
- package/dist/commands/build.d.ts +7 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +22 -0
- package/dist/commands/dev.d.ts +11 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +153 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +112 -0
- package/dist/commands/logout.d.ts +2 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +18 -0
- package/dist/commands/pull.d.ts +7 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +97 -0
- package/dist/compiler/errors.d.ts +20 -0
- package/dist/compiler/errors.d.ts.map +1 -0
- package/dist/compiler/errors.js +35 -0
- package/dist/compiler/evalStatic.d.ts +3 -0
- package/dist/compiler/evalStatic.d.ts.map +1 -0
- package/dist/compiler/evalStatic.js +57 -0
- package/dist/compiler/flatten.js +1 -0
- package/dist/compiler/helpers/duplicateIds.d.ts +9 -0
- package/dist/compiler/helpers/duplicateIds.d.ts.map +1 -0
- package/dist/compiler/helpers/duplicateIds.js +71 -0
- package/dist/compiler/index.d.ts +16 -0
- package/dist/compiler/index.d.ts.map +1 -0
- package/dist/compiler/index.js +934 -0
- package/dist/compiler/parsePage.d.ts +15 -0
- package/dist/compiler/parsePage.d.ts.map +1 -0
- package/dist/compiler/parsePage.js +562 -0
- package/dist/compiler/registry.d.ts +4 -0
- package/dist/compiler/registry.d.ts.map +1 -0
- package/dist/compiler/registry.js +44 -0
- package/dist/compiler/reverse.d.ts +17 -0
- package/dist/compiler/reverse.d.ts.map +1 -0
- package/dist/compiler/reverse.js +1632 -0
- package/dist/compiler/types.d.ts +21 -0
- package/dist/compiler/types.d.ts.map +1 -0
- package/dist/compiler/types.js +1 -0
- package/dist/components/index.d.ts +21 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +21 -0
- package/dist/components/primitives/BaseComponent.d.ts +32 -0
- package/dist/components/primitives/BaseComponent.d.ts.map +1 -0
- package/dist/components/primitives/BaseComponent.js +26 -0
- package/dist/components/primitives/BookMeeting.d.ts +18 -0
- package/dist/components/primitives/BookMeeting.d.ts.map +1 -0
- package/dist/components/primitives/BookMeeting.js +5 -0
- package/dist/components/primitives/Chart.d.ts +41 -0
- package/dist/components/primitives/Chart.d.ts.map +1 -0
- package/dist/components/primitives/Chart.js +5 -0
- package/dist/components/primitives/Container.d.ts +8 -0
- package/dist/components/primitives/Container.d.ts.map +1 -0
- package/dist/components/primitives/Container.js +5 -0
- package/dist/components/primitives/CustomButton.d.ts +37 -0
- package/dist/components/primitives/CustomButton.d.ts.map +1 -0
- package/dist/components/primitives/CustomButton.js +10 -0
- package/dist/components/primitives/CustomHTML.d.ts +8 -0
- package/dist/components/primitives/CustomHTML.d.ts.map +1 -0
- package/dist/components/primitives/CustomHTML.js +5 -0
- package/dist/components/primitives/FileUpload.d.ts +18 -0
- package/dist/components/primitives/FileUpload.d.ts.map +1 -0
- package/dist/components/primitives/FileUpload.js +16 -0
- package/dist/components/primitives/InputBox.d.ts +34 -0
- package/dist/components/primitives/InputBox.d.ts.map +1 -0
- package/dist/components/primitives/InputBox.js +25 -0
- package/dist/components/primitives/Lottie.d.ts +11 -0
- package/dist/components/primitives/Lottie.d.ts.map +1 -0
- package/dist/components/primitives/Lottie.js +5 -0
- package/dist/components/primitives/MediaEmbed.d.ts +13 -0
- package/dist/components/primitives/MediaEmbed.d.ts.map +1 -0
- package/dist/components/primitives/MediaEmbed.js +6 -0
- package/dist/components/primitives/MediaImage.d.ts +8 -0
- package/dist/components/primitives/MediaImage.d.ts.map +1 -0
- package/dist/components/primitives/MediaImage.js +5 -0
- package/dist/components/primitives/OptionSelector.d.ts +35 -0
- package/dist/components/primitives/OptionSelector.d.ts.map +1 -0
- package/dist/components/primitives/OptionSelector.js +8 -0
- package/dist/components/primitives/PaypalCheckout.d.ts +25 -0
- package/dist/components/primitives/PaypalCheckout.d.ts.map +1 -0
- package/dist/components/primitives/PaypalCheckout.js +5 -0
- package/dist/components/primitives/PlainText.d.ts +6 -0
- package/dist/components/primitives/PlainText.d.ts.map +1 -0
- package/dist/components/primitives/PlainText.js +5 -0
- package/dist/components/primitives/ProgressBar.d.ts +15 -0
- package/dist/components/primitives/ProgressBar.d.ts.map +1 -0
- package/dist/components/primitives/ProgressBar.js +5 -0
- package/dist/components/primitives/RichText.d.ts +6 -0
- package/dist/components/primitives/RichText.d.ts.map +1 -0
- package/dist/components/primitives/RichText.js +5 -0
- package/dist/components/primitives/RichTextMarkdown.d.ts +6 -0
- package/dist/components/primitives/RichTextMarkdown.d.ts.map +1 -0
- package/dist/components/primitives/RichTextMarkdown.js +5 -0
- package/dist/components/primitives/Rive.d.ts +16 -0
- package/dist/components/primitives/Rive.d.ts.map +1 -0
- package/dist/components/primitives/Rive.js +8 -0
- package/dist/components/primitives/StripeCheckout.d.ts +52 -0
- package/dist/components/primitives/StripeCheckout.d.ts.map +1 -0
- package/dist/components/primitives/StripeCheckout.js +5 -0
- package/dist/components/primitives/StripeCheckout2.d.ts +30 -0
- package/dist/components/primitives/StripeCheckout2.d.ts.map +1 -0
- package/dist/components/primitives/StripeCheckout2.js +7 -0
- package/dist/proxy/injectApiInterceptor.d.ts +6 -0
- package/dist/proxy/injectApiInterceptor.d.ts.map +1 -0
- package/dist/proxy/injectApiInterceptor.js +66 -0
- package/dist/proxy/injectReload.d.ts +2 -0
- package/dist/proxy/injectReload.d.ts.map +1 -0
- package/dist/proxy/injectReload.js +14 -0
- package/dist/proxy/injectWorkbench.d.ts +4 -0
- package/dist/proxy/injectWorkbench.d.ts.map +1 -0
- package/dist/proxy/injectWorkbench.js +16 -0
- package/dist/proxy/server.d.ts +11 -0
- package/dist/proxy/server.d.ts.map +1 -0
- package/dist/proxy/server.js +246 -0
- package/dist/proxy/sse.d.ts +5 -0
- package/dist/proxy/sse.d.ts.map +1 -0
- package/dist/proxy/sse.js +17 -0
- package/dist/types-builder.d.ts +800 -0
- package/dist/types-builder.d.ts.map +1 -0
- package/dist/types-builder.js +20 -0
- package/dist/workbench/ActionsPanel.d.ts +6 -0
- package/dist/workbench/ActionsPanel.d.ts.map +1 -0
- package/dist/workbench/ActionsPanel.js +47 -0
- package/dist/workbench/AutofillPanel.d.ts +6 -0
- package/dist/workbench/AutofillPanel.d.ts.map +1 -0
- package/dist/workbench/AutofillPanel.js +543 -0
- package/dist/workbench/ComputedFieldsPanel.d.ts +6 -0
- package/dist/workbench/ComputedFieldsPanel.d.ts.map +1 -0
- package/dist/workbench/ComputedFieldsPanel.js +31 -0
- package/dist/workbench/ExperimentsPanel.d.ts +6 -0
- package/dist/workbench/ExperimentsPanel.d.ts.map +1 -0
- package/dist/workbench/ExperimentsPanel.js +182 -0
- package/dist/workbench/FieldEditorPanel.d.ts +9 -0
- package/dist/workbench/FieldEditorPanel.d.ts.map +1 -0
- package/dist/workbench/FieldEditorPanel.js +650 -0
- package/dist/workbench/InspectorPanel.d.ts +6 -0
- package/dist/workbench/InspectorPanel.d.ts.map +1 -0
- package/dist/workbench/InspectorPanel.js +341 -0
- package/dist/workbench/PageNavigator.d.ts +6 -0
- package/dist/workbench/PageNavigator.d.ts.map +1 -0
- package/dist/workbench/PageNavigator.js +123 -0
- package/dist/workbench/SchemaPanel.d.ts +6 -0
- package/dist/workbench/SchemaPanel.d.ts.map +1 -0
- package/dist/workbench/SchemaPanel.js +222 -0
- package/dist/workbench/UserDataPanel.d.ts +6 -0
- package/dist/workbench/UserDataPanel.d.ts.map +1 -0
- package/dist/workbench/UserDataPanel.js +350 -0
- package/dist/workbench/WorkbenchApp.d.ts +6 -0
- package/dist/workbench/WorkbenchApp.d.ts.map +1 -0
- package/dist/workbench/WorkbenchApp.js +193 -0
- package/dist/workbench/cloudflare-worker/README.md +31 -0
- package/dist/workbench/cloudflare-worker/public/workbench.css +1614 -0
- package/dist/workbench/cloudflare-worker/public/workbench.js +77 -0
- package/dist/workbench/cloudflare-worker/worker.js +40 -0
- package/dist/workbench/cloudflare-worker/wrangler.toml +10 -0
- package/dist/workbench/index.d.ts +9 -0
- package/dist/workbench/index.d.ts.map +1 -0
- package/dist/workbench/index.js +44 -0
- package/dist/workbench/workbench.css +1614 -0
- package/dist/workbench/workbench.js +77 -0
- package/package.json +79 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InspectorPanel.d.ts","sourceRoot":"","sources":["../../src/workbench/InspectorPanel.tsx"],"names":[],"mappings":"AAGA,KAAK,mBAAmB,GAAG;IACzB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAmPD,wBAAgB,cAAc,CAAC,EAAE,YAAY,EAAE,EAAE,mBAAmB,2CAianE"}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
+
function getComponentIdFromElement(el) {
|
|
4
|
+
for (const cls of el.classList) {
|
|
5
|
+
if (cls.startsWith('cid-')) {
|
|
6
|
+
return cls.slice(4); // Remove 'cid-' prefix
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
function findFlowComponentAncestor(el) {
|
|
12
|
+
let current = el;
|
|
13
|
+
while (current) {
|
|
14
|
+
if (current.classList.contains('Flow-Component')) {
|
|
15
|
+
return current;
|
|
16
|
+
}
|
|
17
|
+
current = current.parentElement;
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
function findComponentById(flowJson, componentId) {
|
|
22
|
+
// Check global components
|
|
23
|
+
for (const comp of flowJson.components ?? []) {
|
|
24
|
+
if (comp.id === componentId)
|
|
25
|
+
return comp;
|
|
26
|
+
}
|
|
27
|
+
// Check page components
|
|
28
|
+
for (const page of flowJson.pages ?? []) {
|
|
29
|
+
for (const comp of page.components ?? []) {
|
|
30
|
+
if (comp.id === componentId)
|
|
31
|
+
return comp;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function findPageById(flowJson, pageId) {
|
|
37
|
+
for (const page of flowJson.pages ?? []) {
|
|
38
|
+
if (page.id === pageId)
|
|
39
|
+
return page;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Filter styles to those related to a component and/or page.
|
|
45
|
+
* Returns an object with selectors grouped by their relevance.
|
|
46
|
+
*/
|
|
47
|
+
function filterRelatedStyles(styles, component, page) {
|
|
48
|
+
const componentStyles = {};
|
|
49
|
+
const pageStyles = {};
|
|
50
|
+
if (!styles)
|
|
51
|
+
return { componentStyles, pageStyles };
|
|
52
|
+
// Build matchers for the component
|
|
53
|
+
const componentMatchers = [];
|
|
54
|
+
if (component) {
|
|
55
|
+
// Match component tags (e.g., .ComponentTag-page_wrapper)
|
|
56
|
+
for (const tag of component.tags ?? []) {
|
|
57
|
+
componentMatchers.push(`ComponentTag-${tag}`);
|
|
58
|
+
}
|
|
59
|
+
// Match component type (e.g., .ElementType-OptionSelector, .ElementType-CustomButton)
|
|
60
|
+
if (component.type) {
|
|
61
|
+
componentMatchers.push(`ElementType-${component.type}`);
|
|
62
|
+
}
|
|
63
|
+
// Match component ID (e.g., .cid-abc123)
|
|
64
|
+
if (component.id) {
|
|
65
|
+
componentMatchers.push(`cid-${component.id}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Build matchers for the page
|
|
69
|
+
const pageMatchers = [];
|
|
70
|
+
if (page) {
|
|
71
|
+
// Match page tags (e.g., .PageTag-standard_page)
|
|
72
|
+
for (const tag of page.tags ?? []) {
|
|
73
|
+
pageMatchers.push(`PageTag-${tag}`);
|
|
74
|
+
}
|
|
75
|
+
// Match page key/id in selectors
|
|
76
|
+
if (page.key) {
|
|
77
|
+
pageMatchers.push(`PageKey-${page.key}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Always include flow-level page selectors
|
|
81
|
+
pageMatchers.push('Flow-Page');
|
|
82
|
+
pageMatchers.push('Flow-EntireFlow');
|
|
83
|
+
pageMatchers.push('ElementType-PageContents');
|
|
84
|
+
for (const [selector, properties] of Object.entries(styles)) {
|
|
85
|
+
// Check if selector matches any component matchers
|
|
86
|
+
const matchesComponent = componentMatchers.some((matcher) => selector.includes(matcher));
|
|
87
|
+
// Check if selector matches any page matchers
|
|
88
|
+
const matchesPage = pageMatchers.some((matcher) => selector.includes(matcher));
|
|
89
|
+
if (matchesComponent) {
|
|
90
|
+
componentStyles[selector] = properties;
|
|
91
|
+
}
|
|
92
|
+
else if (matchesPage) {
|
|
93
|
+
pageStyles[selector] = properties;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { componentStyles, pageStyles };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Convert a FlowStyles object to CSS text for display
|
|
100
|
+
*/
|
|
101
|
+
function stylesToCss(styles) {
|
|
102
|
+
const lines = [];
|
|
103
|
+
for (const [selector, properties] of Object.entries(styles)) {
|
|
104
|
+
lines.push(`${selector} {`);
|
|
105
|
+
for (const [prop, value] of Object.entries(properties)) {
|
|
106
|
+
lines.push(` ${prop}: ${value};`);
|
|
107
|
+
}
|
|
108
|
+
lines.push('}');
|
|
109
|
+
lines.push('');
|
|
110
|
+
}
|
|
111
|
+
return lines.join('\n').trim();
|
|
112
|
+
}
|
|
113
|
+
function filterJsonByKey(obj, filterText) {
|
|
114
|
+
if (!filterText.trim())
|
|
115
|
+
return obj;
|
|
116
|
+
if (typeof obj !== 'object' || obj === null)
|
|
117
|
+
return obj;
|
|
118
|
+
const lowerFilter = filterText.toLowerCase();
|
|
119
|
+
// For arrays, filter each item and only keep non-empty results
|
|
120
|
+
if (Array.isArray(obj)) {
|
|
121
|
+
const filtered = obj
|
|
122
|
+
.map((item) => filterJsonByKey(item, filterText))
|
|
123
|
+
.filter((item) => {
|
|
124
|
+
if (typeof item !== 'object' || item === null)
|
|
125
|
+
return false;
|
|
126
|
+
if (Array.isArray(item))
|
|
127
|
+
return item.length > 0;
|
|
128
|
+
return Object.keys(item).length > 0;
|
|
129
|
+
});
|
|
130
|
+
return filtered;
|
|
131
|
+
}
|
|
132
|
+
const result = {};
|
|
133
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
134
|
+
if (key.toLowerCase().includes(lowerFilter)) {
|
|
135
|
+
// Key matches - include the entire value unfiltered
|
|
136
|
+
result[key] = value;
|
|
137
|
+
}
|
|
138
|
+
else if (typeof value === 'object' && value !== null) {
|
|
139
|
+
// Key doesn't match - recurse to find nested matches
|
|
140
|
+
const filtered = filterJsonByKey(value, filterText);
|
|
141
|
+
if (Array.isArray(filtered)) {
|
|
142
|
+
if (filtered.length > 0)
|
|
143
|
+
result[key] = filtered;
|
|
144
|
+
}
|
|
145
|
+
else if (filtered !== null && Object.keys(filtered).length > 0) {
|
|
146
|
+
result[key] = filtered;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
const USERDATA_UPDATED_EVENT = 'embeddables:userdata_updated';
|
|
153
|
+
function RelatedStylesPanel({ styles, component, page }) {
|
|
154
|
+
const { componentStyles, pageStyles } = filterRelatedStyles(styles, component, page);
|
|
155
|
+
const componentCss = stylesToCss(componentStyles);
|
|
156
|
+
const pageCss = stylesToCss(pageStyles);
|
|
157
|
+
const hasComponentStyles = Object.keys(componentStyles).length > 0;
|
|
158
|
+
const hasPageStyles = Object.keys(pageStyles).length > 0;
|
|
159
|
+
const hasAnyStyles = hasComponentStyles || hasPageStyles;
|
|
160
|
+
return (_jsxs("div", { className: "flex min-h-0 w-80 shrink-0 flex-col", children: [_jsx("div", { className: "mb-2 text-[11px] font-semibold uppercase tracking-wider text-slate-400", children: "Related Styles" }), _jsx("div", { className: "min-h-0 flex-1 overflow-auto rounded-xl bg-slate-950/60 p-3 ring-1 ring-inset ring-white/10", children: !hasAnyStyles ? (_jsx("div", { className: "text-[11px] text-slate-500 italic", children: "No related styles found for this component or page." })) : (_jsxs("div", { className: "flex flex-col gap-4", children: [hasComponentStyles && (_jsxs("div", { children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx("span", { className: "text-[10px] font-semibold uppercase tracking-wider text-teal-400", children: "Component" }), _jsxs("span", { className: "text-[10px] text-slate-500", children: ["(", Object.keys(componentStyles).length, " rules)"] })] }), _jsx("pre", { className: "font-mono text-xs leading-5 text-slate-100 whitespace-pre-wrap break-all", children: componentCss })] })), hasPageStyles && (_jsxs("div", { children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx("span", { className: "text-[10px] font-semibold uppercase tracking-wider text-sky-400", children: "Page" }), _jsxs("span", { className: "text-[10px] text-slate-500", children: ["(", Object.keys(pageStyles).length, " rules)"] })] }), _jsx("pre", { className: "font-mono text-xs leading-5 text-slate-100 whitespace-pre-wrap break-all", children: pageCss })] }))] })) })] }));
|
|
161
|
+
}
|
|
162
|
+
export function InspectorPanel({ embeddableId }) {
|
|
163
|
+
const [state, setState] = useState('idle');
|
|
164
|
+
const [selectedComponent, setSelectedComponent] = useState(null);
|
|
165
|
+
const [selectedComponentId, setSelectedComponentId] = useState(null);
|
|
166
|
+
const [error, setError] = useState(null);
|
|
167
|
+
const [keyFilter, setKeyFilter] = useState('');
|
|
168
|
+
const [currentPage, setCurrentPage] = useState(null);
|
|
169
|
+
const [flowStyles, setFlowStyles] = useState(undefined);
|
|
170
|
+
const overlayRef = useRef(null);
|
|
171
|
+
const hoveredElementRef = useRef(null);
|
|
172
|
+
const savvy = window.Savvy;
|
|
173
|
+
// Refresh page and styles info
|
|
174
|
+
const refreshPageAndStyles = useCallback(() => {
|
|
175
|
+
if (!savvy?.getFlowJson || !savvy?.getUserData)
|
|
176
|
+
return;
|
|
177
|
+
try {
|
|
178
|
+
const flowJson = savvy.getFlowJson(embeddableId);
|
|
179
|
+
if (flowJson?.styles) {
|
|
180
|
+
setFlowStyles(flowJson.styles);
|
|
181
|
+
}
|
|
182
|
+
const userData = savvy.getUserData(embeddableId);
|
|
183
|
+
if (userData && flowJson) {
|
|
184
|
+
const page = findPageById(flowJson, userData.current_page_id);
|
|
185
|
+
setCurrentPage(page);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// ignore errors
|
|
190
|
+
}
|
|
191
|
+
}, [embeddableId, savvy]);
|
|
192
|
+
// Refresh on mount and when user data changes
|
|
193
|
+
useEffect(() => {
|
|
194
|
+
const timer = setTimeout(refreshPageAndStyles, 100);
|
|
195
|
+
return () => clearTimeout(timer);
|
|
196
|
+
}, [refreshPageAndStyles]);
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
const handler = (event) => {
|
|
199
|
+
const detail = event?.detail;
|
|
200
|
+
const eventEmbeddableId = detail?.embeddableId;
|
|
201
|
+
if (typeof eventEmbeddableId === 'string' &&
|
|
202
|
+
eventEmbeddableId.length > 0 &&
|
|
203
|
+
eventEmbeddableId !== embeddableId) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
refreshPageAndStyles();
|
|
207
|
+
};
|
|
208
|
+
window.addEventListener(USERDATA_UPDATED_EVENT, handler);
|
|
209
|
+
return () => window.removeEventListener(USERDATA_UPDATED_EVENT, handler);
|
|
210
|
+
}, [embeddableId, refreshPageAndStyles]);
|
|
211
|
+
// Create or get the highlight overlay element
|
|
212
|
+
const getOverlay = useCallback(() => {
|
|
213
|
+
if (!overlayRef.current) {
|
|
214
|
+
const overlay = document.createElement('div');
|
|
215
|
+
overlay.id = 'embeddables-inspector-overlay';
|
|
216
|
+
overlay.style.cssText = `
|
|
217
|
+
position: fixed;
|
|
218
|
+
pointer-events: none;
|
|
219
|
+
background: rgba(59, 130, 246, 0.15);
|
|
220
|
+
border: 2px solid rgba(59, 130, 246, 0.8);
|
|
221
|
+
border-radius: 4px;
|
|
222
|
+
z-index: 2147483646;
|
|
223
|
+
transition: all 0.1s ease-out;
|
|
224
|
+
display: none;
|
|
225
|
+
`;
|
|
226
|
+
document.body.appendChild(overlay);
|
|
227
|
+
overlayRef.current = overlay;
|
|
228
|
+
}
|
|
229
|
+
return overlayRef.current;
|
|
230
|
+
}, []);
|
|
231
|
+
// Position the overlay over an element
|
|
232
|
+
const positionOverlay = useCallback((el) => {
|
|
233
|
+
const overlay = getOverlay();
|
|
234
|
+
if (!el) {
|
|
235
|
+
overlay.style.display = 'none';
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const rect = el.getBoundingClientRect();
|
|
239
|
+
overlay.style.display = 'block';
|
|
240
|
+
overlay.style.top = `${rect.top}px`;
|
|
241
|
+
overlay.style.left = `${rect.left}px`;
|
|
242
|
+
overlay.style.width = `${rect.width}px`;
|
|
243
|
+
overlay.style.height = `${rect.height}px`;
|
|
244
|
+
}, [getOverlay]);
|
|
245
|
+
// Handle pointer movement during inspection
|
|
246
|
+
const handlePointerOver = useCallback((e) => {
|
|
247
|
+
const target = e.target;
|
|
248
|
+
const flowComponent = findFlowComponentAncestor(target);
|
|
249
|
+
if (flowComponent && flowComponent !== hoveredElementRef.current) {
|
|
250
|
+
hoveredElementRef.current = flowComponent;
|
|
251
|
+
positionOverlay(flowComponent);
|
|
252
|
+
}
|
|
253
|
+
else if (!flowComponent && hoveredElementRef.current) {
|
|
254
|
+
hoveredElementRef.current = null;
|
|
255
|
+
positionOverlay(null);
|
|
256
|
+
}
|
|
257
|
+
}, [positionOverlay]);
|
|
258
|
+
// Handle click during inspection
|
|
259
|
+
const handleClick = useCallback((e) => {
|
|
260
|
+
const target = e.target;
|
|
261
|
+
const flowComponent = findFlowComponentAncestor(target);
|
|
262
|
+
if (flowComponent) {
|
|
263
|
+
e.preventDefault();
|
|
264
|
+
e.stopPropagation();
|
|
265
|
+
const componentId = getComponentIdFromElement(flowComponent);
|
|
266
|
+
if (!componentId) {
|
|
267
|
+
setError('Could not find component ID (cid-*) class on element.');
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (!savvy?.getFlowJson) {
|
|
271
|
+
setError('window.Savvy.getFlowJson is not available.');
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const flowJson = savvy.getFlowJson(embeddableId);
|
|
275
|
+
if (!flowJson) {
|
|
276
|
+
setError('Could not retrieve flow JSON.');
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
const component = findComponentById(flowJson, componentId);
|
|
280
|
+
if (!component) {
|
|
281
|
+
setError(`Component with ID "${componentId}" not found in flow JSON.`);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
setSelectedComponentId(componentId);
|
|
285
|
+
setSelectedComponent(component);
|
|
286
|
+
setError(null);
|
|
287
|
+
setState('selected');
|
|
288
|
+
// Hide overlay after selection
|
|
289
|
+
positionOverlay(null);
|
|
290
|
+
hoveredElementRef.current = null;
|
|
291
|
+
}
|
|
292
|
+
}, [embeddableId, positionOverlay, savvy]);
|
|
293
|
+
// Start inspection mode
|
|
294
|
+
const startInspecting = useCallback(() => {
|
|
295
|
+
setError(null);
|
|
296
|
+
setState('inspecting');
|
|
297
|
+
}, []);
|
|
298
|
+
// Stop inspection mode
|
|
299
|
+
const stopInspecting = useCallback(() => {
|
|
300
|
+
setState('idle');
|
|
301
|
+
positionOverlay(null);
|
|
302
|
+
hoveredElementRef.current = null;
|
|
303
|
+
}, [positionOverlay]);
|
|
304
|
+
// Clear selection and go back to idle
|
|
305
|
+
const clearSelection = useCallback(() => {
|
|
306
|
+
setSelectedComponent(null);
|
|
307
|
+
setSelectedComponentId(null);
|
|
308
|
+
setState('idle');
|
|
309
|
+
}, []);
|
|
310
|
+
// Inspect another component (go back to inspecting mode)
|
|
311
|
+
const inspectAnother = useCallback(() => {
|
|
312
|
+
setError(null);
|
|
313
|
+
setState('inspecting');
|
|
314
|
+
}, []);
|
|
315
|
+
// Set up and tear down event listeners
|
|
316
|
+
useEffect(() => {
|
|
317
|
+
if (state === 'inspecting') {
|
|
318
|
+
document.addEventListener('pointerover', handlePointerOver, true);
|
|
319
|
+
document.addEventListener('click', handleClick, true);
|
|
320
|
+
return () => {
|
|
321
|
+
document.removeEventListener('pointerover', handlePointerOver, true);
|
|
322
|
+
document.removeEventListener('click', handleClick, true);
|
|
323
|
+
positionOverlay(null);
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
}, [state, handlePointerOver, handleClick, positionOverlay]);
|
|
327
|
+
// Cleanup overlay on unmount
|
|
328
|
+
useEffect(() => {
|
|
329
|
+
return () => {
|
|
330
|
+
if (overlayRef.current) {
|
|
331
|
+
overlayRef.current.remove();
|
|
332
|
+
overlayRef.current = null;
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
}, []);
|
|
336
|
+
return (_jsxs("div", { className: "mx-auto flex h-full w-full max-w-6xl flex-col", children: [_jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-xs font-semibold tracking-wide text-slate-100", children: "Inspect Components" }), _jsx("div", { className: "mt-0.5 text-[11px] text-slate-400", children: state === 'inspecting'
|
|
337
|
+
? 'Hover over a component and click to inspect its JSON.'
|
|
338
|
+
: 'Click a component on the page to view its full JSON configuration.' })] }), _jsxs("div", { className: "flex flex-wrap items-center justify-start gap-2 sm:justify-end", children: [state === 'idle' && (_jsxs("button", { type: "button", onClick: startInspecting, className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg bg-sky-600 px-2.5 py-1.5 text-xs font-semibold text-white ring-1 ring-inset ring-sky-500 hover:bg-sky-500", children: [_jsx("span", { className: "text-sm mb-0.5", children: "\u2316" }), "Start Inspecting"] })), state === 'inspecting' && (_jsx("button", { type: "button", onClick: stopInspecting, className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg bg-rose-600 px-2.5 py-1.5 text-xs font-semibold text-white ring-1 ring-inset ring-rose-500 hover:bg-rose-500", children: "Stop Inspecting" })), state === 'selected' && (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: inspectAnother, className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg bg-sky-600 px-2.5 py-1.5 text-xs font-semibold text-white ring-1 ring-inset ring-sky-500 hover:bg-sky-500", children: [_jsx("span", { className: "text-sm", children: "\u2316" }), "Inspect Another"] }), _jsx("button", { type: "button", onClick: clearSelection, className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg bg-slate-700 px-2.5 py-1.5 text-xs font-semibold text-slate-200 ring-1 ring-inset ring-slate-600 hover:bg-slate-600 hover:text-white", children: "Clear" })] }))] })] }), error && (_jsx("div", { className: "mt-3 rounded-xl bg-rose-500/10 px-3 py-2 text-xs text-rose-200 ring-1 ring-inset ring-rose-500/20", children: error })), state === 'inspecting' && (_jsxs("div", { className: "mt-4 flex items-center gap-2 rounded-xl bg-sky-500/10 px-3 py-2 text-xs text-sky-200 ring-1 ring-inset ring-sky-500/20", children: [_jsx("span", { className: "inline-block h-2 w-2 animate-pulse rounded-full bg-sky-400" }), "Inspection mode active. Click any component with the", ' ', _jsx("code", { className: "rounded bg-white/10 px-1 py-0.5 font-mono", children: "Flow-Component" }), " class."] })), state === 'selected' && selectedComponent && (_jsxs("div", { className: "mt-4 flex min-h-0 flex-1 flex-col gap-3 overflow-hidden", children: [_jsx("div", { className: "rounded-xl bg-white/5 p-3 ring-1 ring-inset ring-white/10", children: _jsxs("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-[10px] font-medium uppercase tracking-wider text-slate-300 -mb-0.5", children: "Type" }), _jsx("span", { className: "text-xs font-semibold text-teal-300", children: selectedComponent.type })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-[10px] font-medium uppercase tracking-wider text-slate-300 -mb-0.5", children: "ID" }), _jsx("code", { className: "rounded bg-white/10 px-1.5 py-0.5 font-mono text-xs text-slate-200", children: selectedComponentId })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-[10px] font-medium uppercase tracking-wider text-slate-300 -mb-0.5", children: "Key" }), _jsx("code", { className: "rounded bg-white/10 px-1.5 py-0.5 font-mono text-xs text-slate-200", children: selectedComponent.key })] }), selectedComponent.tags && selectedComponent.tags.length > 0 && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-[10px] font-medium uppercase tracking-wider text-slate-300 -mb-0.5", children: "Tags" }), _jsx("div", { className: "flex flex-wrap gap-1", children: selectedComponent.tags.map((tag) => (_jsx("code", { className: "rounded bg-amber-500/20 px-1.5 py-0.5 font-mono text-xs text-amber-200", children: tag }, tag))) })] }))] }) }), _jsxs("div", { className: "flex min-h-0 flex-1 gap-3", children: [_jsxs("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [_jsx("div", { className: "text-[11px] font-semibold uppercase tracking-wider text-slate-400", children: "Component JSON" }), _jsx("input", { type: "text", value: keyFilter, onChange: (e) => setKeyFilter(e.target.value), placeholder: "Filter by key...", className: "w-32 rounded-lg bg-slate-800 px-2 py-1.5 text-xs text-slate-100 ring-1 ring-inset ring-slate-600 placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-sky-500/60" })] }), _jsx("pre", { className: "min-h-0 flex-1 overflow-auto rounded-xl bg-slate-950/60 p-3 font-mono text-xs leading-5 text-slate-100 ring-1 ring-inset ring-white/10", children: JSON.stringify(keyFilter.trim()
|
|
339
|
+
? filterJsonByKey(selectedComponent, keyFilter)
|
|
340
|
+
: selectedComponent, null, 2) })] }), _jsx(RelatedStylesPanel, { styles: flowStyles, component: selectedComponent, page: currentPage })] })] })), state === 'idle' && !error && (_jsxs("div", { className: "mt-4 flex min-h-0 flex-1 flex-col gap-3 overflow-hidden", children: [_jsx("div", { className: "text-[11px] text-slate-400", children: "Click \"Start Inspecting\" to begin selecting components." }), currentPage && (_jsxs("div", { className: "flex min-h-0 flex-1 gap-3", children: [_jsxs("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [_jsx("div", { className: "mb-2 text-[11px] font-semibold uppercase tracking-wider text-slate-400", children: "Current Page" }), _jsx("div", { className: "rounded-xl bg-white/5 p-3 ring-1 ring-inset ring-white/10", children: _jsxs("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-[10px] font-medium uppercase tracking-wider text-slate-300 -mb-0.5", children: "Key" }), _jsx("code", { className: "rounded bg-white/10 px-1.5 py-0.5 font-mono text-xs text-slate-200", children: currentPage.key })] }), currentPage.tags && currentPage.tags.length > 0 && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-[10px] font-medium uppercase tracking-wider text-slate-300 -mb-0.5", children: "Tags" }), _jsx("div", { className: "flex flex-wrap gap-1", children: currentPage.tags.map((tag) => (_jsx("code", { className: "rounded bg-sky-500/20 px-1.5 py-0.5 font-mono text-xs text-sky-200", children: tag }, tag))) })] }))] }) })] }), _jsx(RelatedStylesPanel, { styles: flowStyles, component: null, page: currentPage })] }))] }))] }));
|
|
341
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageNavigator.d.ts","sourceRoot":"","sources":["../../src/workbench/PageNavigator.tsx"],"names":[],"mappings":"AAGA,KAAK,kBAAkB,GAAG;IACxB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AA2BD,wBAAgB,aAAa,CAAC,EAAE,YAAY,EAAE,EAAE,kBAAkB,kDAkMjE"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useState, useRef } from 'react';
|
|
3
|
+
const USERDATA_UPDATED_EVENT = 'embeddables:userdata_updated';
|
|
4
|
+
export function PageNavigator({ embeddableId }) {
|
|
5
|
+
const [pages, setPages] = useState([]);
|
|
6
|
+
const [currentPageKey, setCurrentPageKey] = useState('');
|
|
7
|
+
const [currentPageIndex, setCurrentPageIndex] = useState(0);
|
|
8
|
+
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
|
9
|
+
const dropdownRef = useRef(null);
|
|
10
|
+
const dropdownListRef = useRef(null);
|
|
11
|
+
const savvy = window.Savvy;
|
|
12
|
+
const refresh = useCallback(() => {
|
|
13
|
+
if (!savvy?.getFlowJson || !savvy?.getUserData)
|
|
14
|
+
return;
|
|
15
|
+
try {
|
|
16
|
+
const flowJson = savvy.getFlowJson(embeddableId);
|
|
17
|
+
if (flowJson?.pages) {
|
|
18
|
+
setPages(flowJson.pages.map((p) => ({ id: p.id, key: p.key })));
|
|
19
|
+
}
|
|
20
|
+
const userData = savvy.getUserData(embeddableId);
|
|
21
|
+
if (userData) {
|
|
22
|
+
setCurrentPageKey(userData.current_page_key || '');
|
|
23
|
+
setCurrentPageIndex(userData.current_page_index ?? 0);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// ignore errors
|
|
28
|
+
}
|
|
29
|
+
}, [embeddableId, savvy]);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const timer = setTimeout(refresh, 100);
|
|
32
|
+
return () => clearTimeout(timer);
|
|
33
|
+
}, [refresh]);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const handler = (event) => {
|
|
36
|
+
const detail = event?.detail;
|
|
37
|
+
const eventEmbeddableId = detail?.embeddableId;
|
|
38
|
+
if (typeof eventEmbeddableId === 'string' &&
|
|
39
|
+
eventEmbeddableId.length > 0 &&
|
|
40
|
+
eventEmbeddableId !== embeddableId) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
refresh();
|
|
44
|
+
};
|
|
45
|
+
window.addEventListener(USERDATA_UPDATED_EVENT, handler);
|
|
46
|
+
return () => window.removeEventListener(USERDATA_UPDATED_EVENT, handler);
|
|
47
|
+
}, [embeddableId, refresh]);
|
|
48
|
+
// Close dropdown when clicking outside
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const handleClickOutside = (event) => {
|
|
51
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
52
|
+
setIsDropdownOpen(false);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
if (isDropdownOpen) {
|
|
56
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
57
|
+
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
58
|
+
}
|
|
59
|
+
}, [isDropdownOpen]);
|
|
60
|
+
// Scroll to current page when dropdown opens
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (isDropdownOpen && dropdownListRef.current) {
|
|
63
|
+
const currentIndex = pages.findIndex((p) => p.key === currentPageKey);
|
|
64
|
+
if (currentIndex >= 0) {
|
|
65
|
+
const listEl = dropdownListRef.current;
|
|
66
|
+
const items = listEl.querySelectorAll('button');
|
|
67
|
+
const currentItem = items[currentIndex];
|
|
68
|
+
if (currentItem) {
|
|
69
|
+
const listHeight = listEl.clientHeight;
|
|
70
|
+
const itemTop = currentItem.offsetTop;
|
|
71
|
+
const itemHeight = currentItem.offsetHeight;
|
|
72
|
+
// Center the item in the list
|
|
73
|
+
const scrollTop = itemTop - listHeight / 2 + itemHeight / 2;
|
|
74
|
+
listEl.scrollTop = Math.max(0, scrollTop);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}, [isDropdownOpen, pages, currentPageKey]);
|
|
79
|
+
const handlePrevPage = (e) => {
|
|
80
|
+
e.stopPropagation();
|
|
81
|
+
// Cmd (Mac) or Ctrl (Windows) + click: jump directly by page ID
|
|
82
|
+
if ((e.metaKey || e.ctrlKey) && savvy?.goToPage) {
|
|
83
|
+
const prevPage = pages[currentPageIndex - 1];
|
|
84
|
+
if (prevPage) {
|
|
85
|
+
savvy.goToPage(embeddableId, prevPage.id);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else if (savvy?.goToPrevPage) {
|
|
89
|
+
savvy.goToPrevPage(embeddableId);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const handleNextPage = (e) => {
|
|
93
|
+
e.stopPropagation();
|
|
94
|
+
// Cmd (Mac) or Ctrl (Windows) + click: jump directly by page ID
|
|
95
|
+
if ((e.metaKey || e.ctrlKey) && savvy?.goToPage) {
|
|
96
|
+
const nextPage = pages[currentPageIndex + 1];
|
|
97
|
+
if (nextPage) {
|
|
98
|
+
savvy.goToPage(embeddableId, nextPage.id);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (savvy?.goToNextPage) {
|
|
102
|
+
savvy.goToNextPage(embeddableId);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const handleSelectPage = (pageId) => {
|
|
106
|
+
if (savvy?.goToPage) {
|
|
107
|
+
savvy.goToPage(embeddableId, pageId);
|
|
108
|
+
}
|
|
109
|
+
setIsDropdownOpen(false);
|
|
110
|
+
};
|
|
111
|
+
const toggleDropdown = (e) => {
|
|
112
|
+
e.stopPropagation();
|
|
113
|
+
setIsDropdownOpen(!isDropdownOpen);
|
|
114
|
+
};
|
|
115
|
+
if (pages.length === 0)
|
|
116
|
+
return null;
|
|
117
|
+
const isFirstPage = currentPageIndex === 0;
|
|
118
|
+
const isLastPage = currentPageIndex >= pages.length - 1;
|
|
119
|
+
const absolutePageIndex = pages.findIndex((p) => p.key === currentPageKey);
|
|
120
|
+
return (_jsxs("div", { className: "flex items-center gap-1", ref: dropdownRef, children: [_jsx("button", { type: "button", onClick: handlePrevPage, disabled: isFirstPage, title: "Previous page (Cmd/Ctrl+click to jump by ID)", className: "grid h-6 w-6 cursor-pointer place-items-center rounded-md bg-white/5 text-slate-300 ring-1 ring-inset ring-white/10 transition-colors hover:bg-white/10 hover:text-white disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-white/5 disabled:hover:text-slate-300", children: _jsx("span", { className: "text-[10px] leading-none", children: "\u25C0" }) }), _jsxs("div", { className: "relative", children: [_jsxs("button", { type: "button", onClick: toggleDropdown, title: currentPageKey, className: "flex h-6 cursor-pointer items-center gap-1 rounded-md bg-white/5 px-2 text-[11px] text-slate-300 ring-1 ring-inset ring-white/10 transition-colors hover:bg-white/10 hover:text-white", children: [_jsxs("span", { className: "text-slate-400", children: [absolutePageIndex + 1, "."] }), _jsx("span", { className: "max-w-[120px] truncate", children: currentPageKey || 'Loading...' }), _jsx("span", { className: "text-[8px] leading-none", children: isDropdownOpen ? '▲' : '▼' })] }), isDropdownOpen && (_jsx("div", { ref: dropdownListRef, className: "absolute right-0 bottom-full z-50 mb-1 max-h-64 min-w-[180px] overflow-auto rounded-lg bg-slate-900 py-1 shadow-xl ring-1 ring-white/10", children: pages.map((page, index) => (_jsxs("button", { type: "button", onClick: () => handleSelectPage(page.id), className: `w-full cursor-pointer px-3 py-1.5 whitespace-nowrap text-left text-[11px] transition-colors ${page.key === currentPageKey
|
|
121
|
+
? 'bg-white/30 text-white'
|
|
122
|
+
: 'text-slate-300 hover:bg-white/5 hover:text-white'}`, children: [_jsx("span", { className: "mr-2 inline-block w-4 text-right text-[10px] text-slate-400", children: index + 1 }), _jsx("span", { className: "truncate", children: page.key })] }, page.id))) }))] }), _jsx("button", { type: "button", onClick: handleNextPage, disabled: isLastPage, title: "Next page (Cmd/Ctrl+click to jump by ID)", className: "grid h-6 w-6 cursor-pointer place-items-center rounded-md bg-white/5 text-slate-300 ring-1 ring-inset ring-white/10 transition-colors hover:bg-white/10 hover:text-white disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-white/5 disabled:hover:text-slate-300", children: _jsx("span", { className: "text-[10px] leading-none", children: "\u25B6" }) })] }));
|
|
123
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaPanel.d.ts","sourceRoot":"","sources":["../../src/workbench/SchemaPanel.tsx"],"names":[],"mappings":"AAGA,KAAK,gBAAgB,GAAG;IACtB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AA4DD,wBAAgB,WAAW,CAAC,EAAE,YAAY,EAAE,EAAE,gBAAgB,2CA6O7D"}
|