@sanmid/flux 0.1.4 → 0.1.7
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 +7 -18
- package/dist/index.cjs +8031 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +240 -0
- package/dist/index.js +157 -41
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
type DesignEditorProps = {
|
|
4
|
+
/**
|
|
5
|
+
* When true, the editor mounts in production builds.
|
|
6
|
+
* Default is **development only** (`process.env.NODE_ENV === "development"`).
|
|
7
|
+
*/
|
|
8
|
+
force?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Classic margin / border / padding overlay bands on the selected node.
|
|
11
|
+
* Default **false** — only the mint selection ring is shown unless you opt in.
|
|
12
|
+
*/
|
|
13
|
+
showBoxModel?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* When the overlay is active, block default actions on interactive page nodes (buttons, links, inputs, …)
|
|
16
|
+
* via capture-phase listeners. Opt-in for host apps (e.g. playgrounds); default **false**.
|
|
17
|
+
*/
|
|
18
|
+
blockPageInteractions?: boolean;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Visual design editor overlay. **Does not render in production** unless `force` is set.
|
|
22
|
+
*/
|
|
23
|
+
declare function DesignEditor({ force, showBoxModel, blockPageInteractions, }: DesignEditorProps): react_jsx_runtime.JSX.Element | null;
|
|
24
|
+
|
|
25
|
+
/** Persisted for copy prompt after a successful DOM reorder. */
|
|
26
|
+
type FluxStructuralReorder = {
|
|
27
|
+
type: "reorder";
|
|
28
|
+
containerSelector: string;
|
|
29
|
+
containerComponents: string[];
|
|
30
|
+
originalOrder: string[];
|
|
31
|
+
newOrder: string[];
|
|
32
|
+
childrenType: "array" | "static";
|
|
33
|
+
containerSourceFile: {
|
|
34
|
+
fileName: string;
|
|
35
|
+
lineNumber: number;
|
|
36
|
+
columnNumber?: number;
|
|
37
|
+
} | null;
|
|
38
|
+
childSources?: {
|
|
39
|
+
label: string;
|
|
40
|
+
sourceFile: {
|
|
41
|
+
fileName: string;
|
|
42
|
+
lineNumber: number;
|
|
43
|
+
columnNumber?: number;
|
|
44
|
+
};
|
|
45
|
+
}[];
|
|
46
|
+
timestamp: number;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Live preview engine using Constructable Stylesheets when supported,
|
|
51
|
+
* otherwise a single <style> tag in document.head.
|
|
52
|
+
*
|
|
53
|
+
* Applies CSS changes without mutating the host element's inline styles.
|
|
54
|
+
*/
|
|
55
|
+
interface AppliedRule {
|
|
56
|
+
selector: string;
|
|
57
|
+
property: string;
|
|
58
|
+
value: string;
|
|
59
|
+
}
|
|
60
|
+
declare class PreviewEngine {
|
|
61
|
+
private sheet;
|
|
62
|
+
private fallbackStyle;
|
|
63
|
+
private rules;
|
|
64
|
+
private attached;
|
|
65
|
+
constructor();
|
|
66
|
+
attach(): void;
|
|
67
|
+
detach(): void;
|
|
68
|
+
applyChange(selector: string, property: string, value: string): void;
|
|
69
|
+
removeChange(selector: string, property: string): void;
|
|
70
|
+
removeAllChanges(selector: string): void;
|
|
71
|
+
clearAll(): void;
|
|
72
|
+
getChanges(): readonly AppliedRule[];
|
|
73
|
+
/** Last preview value applied for this selector + property (e.g. `100%` when Fill), or undefined. */
|
|
74
|
+
getPreviewValue(selector: string, property: string): string | undefined;
|
|
75
|
+
destroy(): void;
|
|
76
|
+
private flush;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Generate a unique CSS selector for an element using @medv/finder.
|
|
80
|
+
* Falls back to a manual path if finder throws (e.g., SVG elements).
|
|
81
|
+
*/
|
|
82
|
+
declare function getUniqueSelector(el: Element): string;
|
|
83
|
+
/**
|
|
84
|
+
* `parent > :nth-child(n)` so preview rules (e.g. `order`) target the exact direct child.
|
|
85
|
+
* Finder-only selectors often collide for sibling elements; this stays stable for flex/grid children.
|
|
86
|
+
*/
|
|
87
|
+
declare function getDirectChildSelector(parent: Element, child: Element): string;
|
|
88
|
+
/**
|
|
89
|
+
* Selector used for {@link PreviewEngine} rules. Verifies each candidate with
|
|
90
|
+
* `querySelectorAll(sel).length === 1` and that node is `el`, so injected rules
|
|
91
|
+
* cannot hit multiple elements (e.g. all `button`s). Last resort: a temporary
|
|
92
|
+
* `data-flux-preview-target` id — call {@link removePreviewTargetAttribute} when deselecting.
|
|
93
|
+
*/
|
|
94
|
+
declare function getReliableSelectorForPreview(el: Element): {
|
|
95
|
+
selector: string;
|
|
96
|
+
usedAttrFallback: boolean;
|
|
97
|
+
};
|
|
98
|
+
declare function removePreviewTargetAttribute(el: Element | null | undefined): void;
|
|
99
|
+
|
|
100
|
+
interface StyleSnapshot {
|
|
101
|
+
fontFamily: string;
|
|
102
|
+
fontSize: string;
|
|
103
|
+
fontWeight: string;
|
|
104
|
+
lineHeight: string;
|
|
105
|
+
letterSpacing: string;
|
|
106
|
+
color: string;
|
|
107
|
+
textAlign: string;
|
|
108
|
+
width: string;
|
|
109
|
+
height: string;
|
|
110
|
+
padding: string;
|
|
111
|
+
margin: string;
|
|
112
|
+
paddingTop: string;
|
|
113
|
+
paddingRight: string;
|
|
114
|
+
paddingBottom: string;
|
|
115
|
+
paddingLeft: string;
|
|
116
|
+
marginTop: string;
|
|
117
|
+
marginRight: string;
|
|
118
|
+
marginBottom: string;
|
|
119
|
+
marginLeft: string;
|
|
120
|
+
/** CSS `position` (static, relative, absolute, fixed, sticky). */
|
|
121
|
+
position: string;
|
|
122
|
+
/** Inset offsets for positioned layout (`top` / `right` / `bottom` / `left`). */
|
|
123
|
+
top: string;
|
|
124
|
+
right: string;
|
|
125
|
+
bottom: string;
|
|
126
|
+
left: string;
|
|
127
|
+
/** CSS `align-self` — item alignment in flex/grid. */
|
|
128
|
+
alignSelf: string;
|
|
129
|
+
/** CSS `justify-self` — grid item alignment on row axis. */
|
|
130
|
+
justifySelf: string;
|
|
131
|
+
overflow: string;
|
|
132
|
+
display: string;
|
|
133
|
+
flexDirection: string;
|
|
134
|
+
justifyContent: string;
|
|
135
|
+
alignItems: string;
|
|
136
|
+
gap: string;
|
|
137
|
+
rowGap: string;
|
|
138
|
+
columnGap: string;
|
|
139
|
+
gridTemplateColumns: string;
|
|
140
|
+
gridTemplateRows: string;
|
|
141
|
+
backgroundColor: string;
|
|
142
|
+
/** Computed `background-image` (gradients count as fill for `hasFill`-style checks). */
|
|
143
|
+
backgroundImage: string;
|
|
144
|
+
borderTopWidth: string;
|
|
145
|
+
borderRightWidth: string;
|
|
146
|
+
borderBottomWidth: string;
|
|
147
|
+
borderLeftWidth: string;
|
|
148
|
+
borderTopLeftRadius: string;
|
|
149
|
+
borderTopRightRadius: string;
|
|
150
|
+
borderBottomRightRadius: string;
|
|
151
|
+
borderBottomLeftRadius: string;
|
|
152
|
+
borderTopColor: string;
|
|
153
|
+
borderRightColor: string;
|
|
154
|
+
borderBottomColor: string;
|
|
155
|
+
borderLeftColor: string;
|
|
156
|
+
borderTopStyle: string;
|
|
157
|
+
borderRightStyle: string;
|
|
158
|
+
borderBottomStyle: string;
|
|
159
|
+
borderLeftStyle: string;
|
|
160
|
+
borderColor: string;
|
|
161
|
+
borderRadius: string;
|
|
162
|
+
borderStyle: string;
|
|
163
|
+
boxShadow: string;
|
|
164
|
+
opacity: string;
|
|
165
|
+
}
|
|
166
|
+
type DesignEditorElement = Element & {
|
|
167
|
+
style: CSSStyleDeclaration;
|
|
168
|
+
};
|
|
169
|
+
declare function isStyleableElement(target: EventTarget | null): target is DesignEditorElement;
|
|
170
|
+
declare function getComputedSnapshot(el: Element): StyleSnapshot;
|
|
171
|
+
declare function getElementPath(el: Element): string;
|
|
172
|
+
declare function getElementSelector(el: Element): string;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Border-box dimensions in viewport CSS pixels, rounded for the overlay label.
|
|
176
|
+
*/
|
|
177
|
+
declare function formatSelectionDimensions(width: number, height: number): string;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* React fiber traversal for extracting component hierarchy and source file locations.
|
|
181
|
+
* Works with React 18+ dev builds that attach `__reactFiber$` to DOM nodes.
|
|
182
|
+
*/
|
|
183
|
+
interface ReactComponentInfo {
|
|
184
|
+
components: string[];
|
|
185
|
+
sourceFile: {
|
|
186
|
+
fileName: string;
|
|
187
|
+
lineNumber: number;
|
|
188
|
+
columnNumber?: number;
|
|
189
|
+
} | null;
|
|
190
|
+
}
|
|
191
|
+
declare function getExactSourceLocation(el: Element): string | null;
|
|
192
|
+
declare function getReactComponentStack(el: Element): string | null;
|
|
193
|
+
declare function getReactComponentInfo(el: Element): ReactComponentInfo;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Lazy token scanner — walks document.styleSheets to discover CSS custom properties
|
|
197
|
+
* and utility class tokens. Scans on-demand per category, cached until stylesheet count changes.
|
|
198
|
+
*/
|
|
199
|
+
type TokenCategory = "colors" | "spacing" | "typography" | "borders" | "effects" | "layout";
|
|
200
|
+
type CssFramework = "tailwind" | "css-modules" | "custom" | "unknown";
|
|
201
|
+
interface DesignToken {
|
|
202
|
+
className: string;
|
|
203
|
+
property: string;
|
|
204
|
+
value: string;
|
|
205
|
+
category: TokenCategory;
|
|
206
|
+
}
|
|
207
|
+
interface CssVariable {
|
|
208
|
+
name: string;
|
|
209
|
+
value: string;
|
|
210
|
+
category: TokenCategory;
|
|
211
|
+
}
|
|
212
|
+
interface TokenScanResult {
|
|
213
|
+
tokens: DesignToken[];
|
|
214
|
+
variables: CssVariable[];
|
|
215
|
+
framework: CssFramework;
|
|
216
|
+
}
|
|
217
|
+
declare function scanTokens(): TokenScanResult;
|
|
218
|
+
/** One-line summary for AI prompts (design-token preamble). */
|
|
219
|
+
declare function summarizeTokenSystem(): string | null;
|
|
220
|
+
declare function detectFramework(): CssFramework;
|
|
221
|
+
declare function getTokensForProperty(cssProperty: string): DesignToken[];
|
|
222
|
+
declare function getVariablesForProperty(cssProperty: string): CssVariable[];
|
|
223
|
+
/**
|
|
224
|
+
* Variables that appear in real CSS rules for this property first, then category fallback.
|
|
225
|
+
*/
|
|
226
|
+
declare function getVariablesForPropertySmart(cssPropertyKebab: string): CssVariable[];
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Maps CSS property names (kebab-case) to custom property names that appear
|
|
230
|
+
* in stylesheet values via var(--name), so pickers can prefer vars actually
|
|
231
|
+
* used for that property in the host app.
|
|
232
|
+
*/
|
|
233
|
+
declare function invalidateVariableUsageCache(): void;
|
|
234
|
+
/** Custom property names (--foo) that appear in rules for this CSS property. */
|
|
235
|
+
declare function getVariablesUsedForCssProperty(kebabProperty: string): string[];
|
|
236
|
+
|
|
237
|
+
/** Collect `font-family` values from parsed stylesheets (best-effort; skips cross-origin). */
|
|
238
|
+
declare function scanStylesheetFontFamilies(): string[];
|
|
239
|
+
|
|
240
|
+
export { type CssFramework, type CssVariable, DesignEditor, type DesignEditorElement, type DesignEditorProps, type DesignToken, type FluxStructuralReorder, PreviewEngine, type ReactComponentInfo, type StyleSnapshot, type TokenCategory, type TokenScanResult, detectFramework, formatSelectionDimensions, getComputedSnapshot, getDirectChildSelector, getElementPath, getElementSelector, getExactSourceLocation, getReactComponentInfo, getReactComponentStack, getReliableSelectorForPreview, getTokensForProperty, getUniqueSelector, getVariablesForProperty, getVariablesForPropertySmart, getVariablesUsedForCssProperty, invalidateVariableUsageCache, isStyleableElement, removePreviewTargetAttribute, scanStylesheetFontFamilies, scanTokens, summarizeTokenSystem };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
import { createContext, useState, useRef, useCallback, useEffect, useLayoutEffect, useMemo, useContext } from 'react';
|
|
3
3
|
import { flushSync, createPortal } from 'react-dom';
|
|
4
|
-
import { jsx,
|
|
4
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
5
5
|
import { X, CornerUpLeft, Check, Copy, AlignHorizontalJustifyStart, AlignHorizontalJustifyCenter, AlignHorizontalJustifyEnd, AlignVerticalJustifyStart, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, Rows3, SquareSquare, AlignVerticalSpaceAround, AlignHorizontalSpaceAround, ArrowUpDown, ArrowLeftRight, AlignLeft, AlignCenter, AlignRight, ArrowUpToLine, FoldVertical, ArrowDownToLine, SunDim, Minus, Plus, Eye, Ruler, SquareDashed, ChevronDown, Link2, Square, MoveDown, MoveRight } from 'lucide-react';
|
|
6
6
|
import { clsx } from 'clsx';
|
|
7
7
|
import { twMerge } from 'tailwind-merge';
|
|
@@ -149,10 +149,23 @@ function BoxModelOverlay({ enabled, target }) {
|
|
|
149
149
|
/* @__PURE__ */ jsx("div", { ref: contentRef, className: band, "aria-hidden": true })
|
|
150
150
|
] });
|
|
151
151
|
}
|
|
152
|
+
function usePrefersReducedMotion() {
|
|
153
|
+
const [reduced, setReduced] = useState(false);
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
156
|
+
const sync = () => setReduced(mq.matches);
|
|
157
|
+
sync();
|
|
158
|
+
mq.addEventListener("change", sync);
|
|
159
|
+
return () => mq.removeEventListener("change", sync);
|
|
160
|
+
}, []);
|
|
161
|
+
return reduced;
|
|
162
|
+
}
|
|
152
163
|
var MONO = "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace";
|
|
153
164
|
var PROMPT_MS = 22;
|
|
154
165
|
var LINE_GAP_MS = 300;
|
|
155
166
|
var AFTER_LAST_MS = 450;
|
|
167
|
+
var EASE_OUT = "cubic-bezier(0.4, 0, 0.2, 1)";
|
|
168
|
+
var DIALOG_EASE = "cubic-bezier(0.34, 1.3, 0.64, 1)";
|
|
156
169
|
function TrafficLightsSvg() {
|
|
157
170
|
return /* @__PURE__ */ jsxs("svg", { width: "52", height: "12", viewBox: "0 0 52 12", "aria-hidden": true, className: "shrink-0", children: [
|
|
158
171
|
/* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "5", fill: "#FF5F57" }),
|
|
@@ -293,11 +306,12 @@ function TerminalTyping({
|
|
|
293
306
|
}
|
|
294
307
|
);
|
|
295
308
|
}
|
|
296
|
-
var EASE_OUT = [0.4, 0, 0.2, 1];
|
|
297
309
|
var DISMISS_AFTER_TYPING_MS = 5200;
|
|
298
310
|
function CopySuccessOverlay({ open, onClose }) {
|
|
299
|
-
const reduceMotion =
|
|
311
|
+
const reduceMotion = usePrefersReducedMotion();
|
|
300
312
|
const [typingComplete, setTypingComplete] = useState(false);
|
|
313
|
+
const [mounted, setMounted] = useState(false);
|
|
314
|
+
const [animIn, setAnimIn] = useState(false);
|
|
301
315
|
const handleTypingComplete = useCallback(() => setTypingComplete(true), []);
|
|
302
316
|
useEffect(() => {
|
|
303
317
|
if (!open) {
|
|
@@ -320,36 +334,57 @@ function CopySuccessOverlay({ open, onClose }) {
|
|
|
320
334
|
const t = window.setTimeout(onClose, DISMISS_AFTER_TYPING_MS);
|
|
321
335
|
return () => window.clearTimeout(t);
|
|
322
336
|
}, [open, typingComplete, onClose]);
|
|
337
|
+
useLayoutEffect(() => {
|
|
338
|
+
if (open) setMounted(true);
|
|
339
|
+
}, [open]);
|
|
340
|
+
useEffect(() => {
|
|
341
|
+
if (!open) {
|
|
342
|
+
setAnimIn(false);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
setAnimIn(false);
|
|
346
|
+
const id = requestAnimationFrame(() => {
|
|
347
|
+
requestAnimationFrame(() => setAnimIn(true));
|
|
348
|
+
});
|
|
349
|
+
return () => cancelAnimationFrame(id);
|
|
350
|
+
}, [open]);
|
|
351
|
+
const onBackdropTransitionEnd = useCallback((e) => {
|
|
352
|
+
if (e.target !== e.currentTarget) return;
|
|
353
|
+
if (e.propertyName !== "opacity") return;
|
|
354
|
+
if (!open) setMounted(false);
|
|
355
|
+
}, [open]);
|
|
323
356
|
if (typeof document === "undefined") return null;
|
|
324
357
|
const running = open && !typingComplete && !reduceMotion;
|
|
358
|
+
const backdropStyle = {
|
|
359
|
+
opacity: animIn ? 1 : 0,
|
|
360
|
+
transition: reduceMotion ? "none" : `opacity 220ms ${EASE_OUT}`
|
|
361
|
+
};
|
|
362
|
+
const dialogStyle = reduceMotion ? {
|
|
363
|
+
opacity: animIn ? 1 : 0,
|
|
364
|
+
transition: `opacity 180ms ${EASE_OUT}`
|
|
365
|
+
} : {
|
|
366
|
+
opacity: animIn ? 1 : 0,
|
|
367
|
+
transform: animIn ? "scale(1) translateY(0)" : "scale(0.94) translateY(14px)",
|
|
368
|
+
transition: `opacity 240ms ${EASE_OUT}, transform 450ms ${DIALOG_EASE}`
|
|
369
|
+
};
|
|
325
370
|
return createPortal(
|
|
326
|
-
/* @__PURE__ */ jsx(
|
|
327
|
-
|
|
371
|
+
/* @__PURE__ */ jsx(Fragment, { children: mounted && /* @__PURE__ */ jsx(
|
|
372
|
+
"div",
|
|
328
373
|
{
|
|
329
374
|
className: "fixed inset-0 z-[10020] flex items-center justify-center bg-black/50 p-4 backdrop-blur-[3px]",
|
|
330
|
-
style: { fontFamily: MONO },
|
|
331
|
-
initial: { opacity: 0 },
|
|
332
|
-
animate: { opacity: 1 },
|
|
333
|
-
exit: { opacity: 0 },
|
|
334
|
-
transition: { duration: 0.22, ease: EASE_OUT },
|
|
375
|
+
style: { ...backdropStyle, fontFamily: MONO },
|
|
335
376
|
onClick: onClose,
|
|
377
|
+
onTransitionEnd: onBackdropTransitionEnd,
|
|
336
378
|
role: "presentation",
|
|
337
379
|
children: /* @__PURE__ */ jsxs(
|
|
338
|
-
|
|
380
|
+
"div",
|
|
339
381
|
{
|
|
340
382
|
role: "dialog",
|
|
341
383
|
"aria-modal": "true",
|
|
342
384
|
"aria-labelledby": "flux-copy-success-title",
|
|
343
385
|
className: "max-h-[min(90vh,640px)] w-full max-w-[520px] overflow-hidden rounded-xl border border-zinc-200 bg-white shadow-[0_24px_80px_rgba(0,0,0,0.2)]",
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
animate: reduceMotion ? { opacity: 1 } : { opacity: 1, scale: 1, y: 0 },
|
|
347
|
-
exit: reduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.97, y: 8 },
|
|
348
|
-
transition: reduceMotion ? { duration: 0.18, ease: EASE_OUT } : {
|
|
349
|
-
opacity: { duration: 0.24, ease: EASE_OUT },
|
|
350
|
-
scale: { type: "spring", stiffness: 420, damping: 32, mass: 0.85 },
|
|
351
|
-
y: { type: "spring", stiffness: 420, damping: 34, mass: 0.85 }
|
|
352
|
-
},
|
|
386
|
+
style: dialogStyle,
|
|
387
|
+
onClick: (ev) => ev.stopPropagation(),
|
|
353
388
|
children: [
|
|
354
389
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 border-b border-zinc-200/90 bg-zinc-50/90 px-3 py-2", children: [
|
|
355
390
|
/* @__PURE__ */ jsx(TrafficLightsSvg, {}),
|
|
@@ -374,8 +409,7 @@ function CopySuccessOverlay({ open, onClose }) {
|
|
|
374
409
|
]
|
|
375
410
|
}
|
|
376
411
|
)
|
|
377
|
-
}
|
|
378
|
-
"flux-copy-success-overlay"
|
|
412
|
+
}
|
|
379
413
|
) }),
|
|
380
414
|
document.body
|
|
381
415
|
);
|
|
@@ -7366,6 +7400,9 @@ async function writeTextToClipboard(text) {
|
|
|
7366
7400
|
async function copyCombinedPromptToClipboard(items, structuralReorders) {
|
|
7367
7401
|
return writeTextToClipboard(buildCombinedCopyPrompt(items, structuralReorders));
|
|
7368
7402
|
}
|
|
7403
|
+
|
|
7404
|
+
// src/host-styles.ts
|
|
7405
|
+
var fluxHostStyles = ".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-right-0{right:0}.-right-1{right:-.25rem}.-top-0{top:0}.-top-1{top:-.25rem}.bottom-2{bottom:.5rem}.left-0{left:0}.right-0{right:0}.right-1{right:.25rem}.right-2{right:.5rem}.right-4{right:1rem}.right-8{right:2rem}.top-0{top:0}.top-1{top:.25rem}.top-2{top:.5rem}.top-4{top:1rem}.top-full{top:100%}.z-10{z-index:10}.z-20{z-index:20}.z-\\[10003\\]{z-index:10003}.z-\\[10020\\]{z-index:10020}.z-\\[1\\]{z-index:1}.z-\\[9997\\]{z-index:9997}.z-\\[9998\\]{z-index:9998}.m-0{margin:0}.mx-auto{margin-left:auto;margin-right:auto}.-mt-px{margin-top:-1px}.mb-2{margin-bottom:.5rem}.ml-px{margin-left:1px}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.box-border{box-sizing:border-box}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.inline-grid{display:inline-grid}.hidden{display:none}.size-10{width:2.5rem;height:2.5rem}.size-11{width:2.75rem;height:2.75rem}.size-3{width:.75rem;height:.75rem}.size-3\\.5{width:.875rem;height:.875rem}.size-4{width:1rem;height:1rem}.size-9{width:2.25rem;height:2.25rem}.size-\\[14px\\]{width:14px;height:14px}.size-\\[5px\\]{width:5px;height:5px}.h-3{height:.75rem}.h-4{height:1rem}.h-9{height:2.25rem}.h-full{height:100%}.max-h-48{max-height:12rem}.max-h-\\[min\\(90vh\\2c 640px\\)\\]{max-height:min(90vh,640px)}.min-h-0{min-height:0}.w-0{width:0}.w-0\\.5{width:.125rem}.w-1{width:.25rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-\\[4\\.5rem\\]{width:4.5rem}.w-\\[5\\.5rem\\]{width:5.5rem}.w-\\[52px\\]{width:52px}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\\[2rem\\]{min-width:2rem}.min-w-full{min-width:100%}.max-w-\\[520px\\]{max-width:520px}.max-w-\\[5rem\\]{max-width:5rem}.max-w-\\[min\\(18rem\\2c calc\\(100vw-20px\\)\\)\\]{max-width:min(18rem,calc(100vw - 20px))}.max-w-full{max-width:100%}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-y-1{--tw-translate-y:-0.25rem}.-translate-y-1,.scale-\\[0\\.92\\]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-\\[0\\.92\\]{--tw-scale-x:0.92;--tw-scale-y:0.92}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-col-resize{cursor:col-resize}.cursor-ew-resize{cursor:ew-resize}.cursor-grab{cursor:grab}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-rows-3{grid-template-rows:repeat(3,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0}.gap-0\\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-\\[13px\\]{gap:13px}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.self-start{align-self:flex-start}.self-end{align-self:flex-end}.self-stretch{align-self:stretch}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.rounded-small{border-radius:8px}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-\\[\\#202020\\]{--tw-border-opacity:1;border-color:rgb(32 32 32/var(--tw-border-opacity,1))}.border-\\[\\#444\\]{--tw-border-opacity:1;border-color:rgb(68 68 68/var(--tw-border-opacity,1))}.border-\\[\\#555\\]{--tw-border-opacity:1;border-color:rgb(85 85 85/var(--tw-border-opacity,1))}.border-amber-800{--tw-border-opacity:1;border-color:rgb(146 64 14/var(--tw-border-opacity,1))}.border-amber-800\\/35{border-color:rgba(146,64,14,.35)}.border-zinc-100{--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1))}.border-zinc-200{--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1))}.border-zinc-200\\/90{border-color:hsla(240,6%,90%,.9)}.bg-\\[\\#202020\\]{--tw-bg-opacity:1;background-color:rgb(32 32 32/var(--tw-bg-opacity,1))}.bg-\\[\\#2a2a2a\\]{--tw-bg-opacity:1;background-color:rgb(42 42 42/var(--tw-bg-opacity,1))}.bg-\\[\\#333333\\]{--tw-bg-opacity:1;background-color:rgb(51 51 51/var(--tw-bg-opacity,1))}.bg-\\[\\#555\\]{--tw-bg-opacity:1;background-color:rgb(85 85 85/var(--tw-bg-opacity,1))}.bg-\\[\\#F3F3F3\\]{--tw-bg-opacity:1;background-color:rgb(243 243 243/var(--tw-bg-opacity,1))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.bg-black\\/50{background-color:rgba(0,0,0,.5)}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-zinc-300{--tw-bg-opacity:1;background-color:rgb(212 212 216/var(--tw-bg-opacity,1))}.bg-zinc-400{--tw-bg-opacity:1;background-color:rgb(161 161 170/var(--tw-bg-opacity,1))}.bg-zinc-50{--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity,1))}.bg-zinc-50\\/90{background-color:hsla(0,0%,98%,.9)}.\\!fill-none{fill:none!important}.p-0{padding:0}.p-0\\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\\.5{padding:.375rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-0{padding-left:0;padding-right:0}.px-0\\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0{padding-top:0;padding-bottom:0}.py-0\\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-0{padding-left:0}.pl-0\\.5{padding-left:.125rem}.pr-0{padding-right:0}.pr-10{padding-right:2.5rem}.pr-11{padding-right:2.75rem}.pr-6{padding-right:1.5rem}.pr-7{padding-right:1.75rem}.pt-0{padding-top:0}.pt-1{padding-top:.25rem}.pt-3{padding-top:.75rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.font-\\[\\'Inter\\'\\2c system-ui\\2c sans-serif\\]{font-family:Inter,system-ui,sans-serif}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.text-\\[12px\\]{font-size:12px}.text-\\[15px\\]{font-size:15px}.text-\\[7px\\]{font-size:7px}.text-base{font-size:1rem;line-height:1.5rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-\\[14px\\]{line-height:14px}.leading-\\[15\\.6px\\]{line-height:15.6px}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.tracking-tight{letter-spacing:-.025em}.text-\\[\\#202020\\]{--tw-text-opacity:1;color:rgb(32 32 32/var(--tw-text-opacity,1))}.text-\\[\\#333333\\]{--tw-text-opacity:1;color:rgb(51 51 51/var(--tw-text-opacity,1))}.text-\\[\\#71717a\\]{--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.text-\\[\\#7C7C7C\\]{--tw-text-opacity:1;color:rgb(124 124 124/var(--tw-text-opacity,1))}.text-\\[\\#93c47d\\]{--tw-text-opacity:1;color:rgb(147 196 125/var(--tw-text-opacity,1))}.text-\\[\\#D9D9D9\\]{--tw-text-opacity:1;color:rgb(217 217 217/var(--tw-text-opacity,1))}.text-\\[\\#b45309\\]{--tw-text-opacity:1;color:rgb(180 83 9/var(--tw-text-opacity,1))}.text-\\[\\#c2410c\\]{--tw-text-opacity:1;color:rgb(194 65 12/var(--tw-text-opacity,1))}.text-\\[\\#d9d9d9\\]{--tw-text-opacity:1;color:rgb(217 217 217/var(--tw-text-opacity,1))}.text-emerald-600{--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-zinc-400{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.text-zinc-500{--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.text-zinc-700{--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.text-zinc-800{--tw-text-opacity:1;color:rgb(39 39 42/var(--tw-text-opacity,1))}.text-zinc-900{--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-\\[0_24px_80px_rgba\\(0\\2c 0\\2c 0\\2c 0\\.2\\)\\]{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\\[0_24px_80px_rgba\\(0\\2c 0\\2c 0\\2c 0\\.2\\)\\]{--tw-shadow:0 24px 80px rgba(0,0,0,.2);--tw-shadow-colored:0 24px 80px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.outline-none{outline:2px solid transparent;outline-offset:2px}.\\!outline{outline-style:solid!important}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-\\[3px\\]{--tw-backdrop-blur:blur(3px);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[transform\\]{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150,.transition-opacity{transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\\[font-synthesis\\:none\\]{font-synthesis:none}.hover\\:bg-\\[\\#2a2a2a\\]:hover{--tw-bg-opacity:1;background-color:rgb(42 42 42/var(--tw-bg-opacity,1))}.hover\\:bg-\\[\\#333333\\]:hover{--tw-bg-opacity:1;background-color:rgb(51 51 51/var(--tw-bg-opacity,1))}.hover\\:text-\\[\\#D9D9D9\\]:hover{--tw-text-opacity:1;color:rgb(217 217 217/var(--tw-text-opacity,1))}.hover\\:brightness-110:hover{--tw-brightness:brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus-visible\\:outline:focus-visible{outline-style:solid}.focus-visible\\:outline-2:focus-visible{outline-width:2px}.focus-visible\\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\\:outline-\\[\\#D9D9D9\\]\\/40:focus-visible{outline-color:hsla(0,0%,85%,.4)}.active\\:scale-95:active{--tw-scale-x:.95;--tw-scale-y:.95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:focus-within .group-focus-within\\:opacity-100{opacity:1}.group:hover .group-hover\\:opacity-100{opacity:1}@media (min-width:640px){.sm\\:max-w-\\[200px\\]{max-width:200px}.sm\\:flex-row{flex-direction:row}.sm\\:items-start{align-items:flex-start}.sm\\:justify-between{justify-content:space-between}.sm\\:gap-6{gap:1.5rem}.sm\\:px-4{padding-left:1rem;padding-right:1rem}.sm\\:px-5{padding-left:1.25rem;padding-right:1.25rem}.sm\\:pt-4{padding-top:1rem}}.\\[\\&\\:\\:-webkit-details-marker\\]\\:hidden::-webkit-details-marker{display:none}.\\[\\&_svg\\]\\:-mt-px svg{margin-top:-1px}.\\[\\&_svg\\]\\:\\!fill-none svg{fill:none!important}";
|
|
7369
7406
|
var MIN_WIDTH = 240;
|
|
7370
7407
|
var MAX_WIDTH = 560;
|
|
7371
7408
|
var DEFAULT_WIDTH = 277;
|
|
@@ -7459,6 +7496,7 @@ function DesignEditorImpl({
|
|
|
7459
7496
|
blockPageInteractions
|
|
7460
7497
|
}) {
|
|
7461
7498
|
const [enabled, setEnabled] = useState(false);
|
|
7499
|
+
const [isExiting, setIsExiting] = useState(false);
|
|
7462
7500
|
const [width, setWidth] = useState(DEFAULT_WIDTH);
|
|
7463
7501
|
const [layoutW, setLayoutW] = useState(0);
|
|
7464
7502
|
const resizeRef = useRef(null);
|
|
@@ -7484,6 +7522,15 @@ function DesignEditorImpl({
|
|
|
7484
7522
|
setMenuPortalTarget(null);
|
|
7485
7523
|
};
|
|
7486
7524
|
}, []);
|
|
7525
|
+
useEffect(() => {
|
|
7526
|
+
const id = "flux-host-tailwind";
|
|
7527
|
+
if (typeof document === "undefined" || document.getElementById(id)) return;
|
|
7528
|
+
const el = document.createElement("style");
|
|
7529
|
+
el.id = id;
|
|
7530
|
+
el.setAttribute("data-flux-host-tailwind", "");
|
|
7531
|
+
el.textContent = fluxHostStyles;
|
|
7532
|
+
document.head.appendChild(el);
|
|
7533
|
+
}, []);
|
|
7487
7534
|
useEffect(() => {
|
|
7488
7535
|
const id = "flux-floating-toggle-host-styles";
|
|
7489
7536
|
if (document.getElementById(id)) return;
|
|
@@ -7572,6 +7619,9 @@ button[data-flux-floating-toggle]:hover {
|
|
|
7572
7619
|
flushSync(() => {
|
|
7573
7620
|
setExitClipVp(getEditorToggleViewportCenter());
|
|
7574
7621
|
});
|
|
7622
|
+
flushSync(() => {
|
|
7623
|
+
setIsExiting(true);
|
|
7624
|
+
});
|
|
7575
7625
|
flushSync(() => {
|
|
7576
7626
|
setEnabled(false);
|
|
7577
7627
|
});
|
|
@@ -7695,7 +7745,11 @@ button[data-flux-floating-toggle]:hover {
|
|
|
7695
7745
|
}
|
|
7696
7746
|
return copyCombinedPromptToClipboard(items, structuralReorders);
|
|
7697
7747
|
}, [getCopyBatchItems, structuralReorders]);
|
|
7698
|
-
const reduceMotion =
|
|
7748
|
+
const reduceMotion = usePrefersReducedMotion();
|
|
7749
|
+
const panelRef = useRef(null);
|
|
7750
|
+
const panelVisible = enabled || isExiting;
|
|
7751
|
+
const irisOpenDoneRef = useRef(false);
|
|
7752
|
+
const exitAnimStartedRef = useRef(false);
|
|
7699
7753
|
const themeRevealDuration = useMemo(() => readThemeTransitionDurationSeconds(), []);
|
|
7700
7754
|
const effectiveWidth = useMemo(() => {
|
|
7701
7755
|
const lw = layoutW > 0 ? layoutW : layoutViewportWidth();
|
|
@@ -7706,10 +7760,80 @@ button[data-flux-floating-toggle]:hover {
|
|
|
7706
7760
|
const openO = viewportToPanelClipOrigin(openClipVpRef.current.x, openClipVpRef.current.y, effectiveWidth);
|
|
7707
7761
|
const exitVpForClip = exitClipVp ?? defaultExitViewport();
|
|
7708
7762
|
const closeO = viewportToPanelClipOrigin(exitVpForClip.x, exitVpForClip.y, effectiveWidth);
|
|
7709
|
-
const
|
|
7710
|
-
const
|
|
7711
|
-
|
|
7763
|
+
const easeReveal = `cubic-bezier(${THEME_REVEAL_EASE.join(",")})`;
|
|
7764
|
+
const easeExit = `cubic-bezier(${IRIS_EXIT_EASE.join(",")})`;
|
|
7765
|
+
useEffect(() => {
|
|
7766
|
+
if (!enabled) irisOpenDoneRef.current = false;
|
|
7767
|
+
}, [enabled]);
|
|
7768
|
+
useEffect(() => {
|
|
7769
|
+
if (!isExiting) exitAnimStartedRef.current = false;
|
|
7770
|
+
}, [isExiting]);
|
|
7771
|
+
useLayoutEffect(() => {
|
|
7772
|
+
if (!panelVisible || !enabled || isExiting) return;
|
|
7773
|
+
if (irisOpenDoneRef.current) return;
|
|
7774
|
+
const el = panelRef.current;
|
|
7775
|
+
if (!el) return;
|
|
7776
|
+
irisOpenDoneRef.current = true;
|
|
7777
|
+
if (reduceMotion) {
|
|
7778
|
+
el.style.transition = "";
|
|
7779
|
+
el.style.clipPath = "none";
|
|
7780
|
+
return;
|
|
7781
|
+
}
|
|
7782
|
+
el.style.transition = "none";
|
|
7783
|
+
el.style.clipPath = `circle(0px at ${openO.ox}px ${openO.oy}px)`;
|
|
7784
|
+
const id = requestAnimationFrame(() => {
|
|
7785
|
+
requestAnimationFrame(() => {
|
|
7786
|
+
el.style.transition = `clip-path ${themeRevealDuration}s ${easeReveal}`;
|
|
7787
|
+
el.style.clipPath = `circle(150vmax at ${openO.ox}px ${openO.oy}px)`;
|
|
7788
|
+
});
|
|
7789
|
+
});
|
|
7790
|
+
return () => cancelAnimationFrame(id);
|
|
7791
|
+
}, [
|
|
7792
|
+
panelVisible,
|
|
7793
|
+
enabled,
|
|
7794
|
+
isExiting,
|
|
7795
|
+
reduceMotion,
|
|
7796
|
+
themeRevealDuration,
|
|
7797
|
+
easeReveal,
|
|
7798
|
+
openO.ox,
|
|
7799
|
+
openO.oy
|
|
7800
|
+
]);
|
|
7801
|
+
useLayoutEffect(() => {
|
|
7802
|
+
if (!isExiting || enabled) return;
|
|
7803
|
+
if (exitAnimStartedRef.current) return;
|
|
7804
|
+
const el = panelRef.current;
|
|
7805
|
+
if (!el) return;
|
|
7806
|
+
exitAnimStartedRef.current = true;
|
|
7807
|
+
if (reduceMotion) {
|
|
7808
|
+
el.style.transition = "";
|
|
7809
|
+
el.style.clipPath = `circle(0px at ${closeO.ox}px ${closeO.oy}px)`;
|
|
7810
|
+
queueMicrotask(() => {
|
|
7811
|
+
setIsExiting(false);
|
|
7812
|
+
setExitClipVp(null);
|
|
7813
|
+
});
|
|
7814
|
+
return;
|
|
7815
|
+
}
|
|
7816
|
+
el.style.transition = "none";
|
|
7817
|
+
el.style.clipPath = `circle(150vmax at ${openO.ox}px ${openO.oy}px)`;
|
|
7818
|
+
void el.offsetHeight;
|
|
7819
|
+
el.style.transition = `clip-path ${themeRevealDuration}s ${easeExit}`;
|
|
7820
|
+
el.style.clipPath = `circle(0px at ${closeO.ox}px ${closeO.oy}px)`;
|
|
7821
|
+
}, [isExiting, enabled, reduceMotion, themeRevealDuration, easeExit, openO.ox, openO.oy, closeO.ox, closeO.oy]);
|
|
7822
|
+
const onPanelTransitionEnd = useCallback(
|
|
7823
|
+
(e) => {
|
|
7824
|
+
if (e.propertyName !== "clip-path") return;
|
|
7825
|
+
if (!isExiting || enabled || reduceMotion) return;
|
|
7826
|
+
setIsExiting(false);
|
|
7827
|
+
setExitClipVp(null);
|
|
7828
|
+
},
|
|
7829
|
+
[isExiting, enabled, reduceMotion]
|
|
7830
|
+
);
|
|
7831
|
+
const panelContent = /* @__PURE__ */ jsx(Fragment, { children: panelVisible && /* @__PURE__ */ jsxs(
|
|
7832
|
+
"div",
|
|
7712
7833
|
{
|
|
7834
|
+
ref: panelRef,
|
|
7835
|
+
"data-flux-ui": true,
|
|
7836
|
+
onTransitionEnd: onPanelTransitionEnd,
|
|
7713
7837
|
style: {
|
|
7714
7838
|
position: "fixed",
|
|
7715
7839
|
top: 8,
|
|
@@ -7726,18 +7850,8 @@ button[data-flux-floating-toggle]:hover {
|
|
|
7726
7850
|
color: "#D9D9D9",
|
|
7727
7851
|
colorScheme: "dark",
|
|
7728
7852
|
WebkitFontSmoothing: "antialiased",
|
|
7729
|
-
pointerEvents: "auto"
|
|
7730
|
-
|
|
7731
|
-
initial: reduceMotion === true ? { clipPath: "none" } : { clipPath: `circle(0px at ${openO.ox}px ${openO.oy}px)` },
|
|
7732
|
-
animate: reduceMotion === true ? { clipPath: "none" } : { clipPath: `circle(150vmax at ${irisAt.ox}px ${irisAt.oy}px)` },
|
|
7733
|
-
exit: reduceMotion === true ? { clipPath: "none", transition: { duration: 0 } } : {
|
|
7734
|
-
clipPath: `circle(0px at ${closeO.ox}px ${closeO.oy}px)`,
|
|
7735
|
-
transition: {
|
|
7736
|
-
clipPath: { duration: themeRevealDuration, ease: IRIS_EXIT_EASE }
|
|
7737
|
-
}
|
|
7738
|
-
},
|
|
7739
|
-
transition: reduceMotion === true ? { duration: 0 } : {
|
|
7740
|
-
clipPath: { duration: themeRevealDuration, ease: THEME_REVEAL_EASE }
|
|
7853
|
+
pointerEvents: "auto",
|
|
7854
|
+
willChange: reduceMotion ? void 0 : "clip-path"
|
|
7741
7855
|
},
|
|
7742
7856
|
children: [
|
|
7743
7857
|
/* @__PURE__ */ jsx(
|
|
@@ -7764,6 +7878,9 @@ button[data-flux-floating-toggle]:hover {
|
|
|
7764
7878
|
flushSync(() => {
|
|
7765
7879
|
setExitClipVp(getEditorToggleViewportCenter());
|
|
7766
7880
|
});
|
|
7881
|
+
flushSync(() => {
|
|
7882
|
+
setIsExiting(true);
|
|
7883
|
+
});
|
|
7767
7884
|
flushSync(() => {
|
|
7768
7885
|
setEnabled(false);
|
|
7769
7886
|
});
|
|
@@ -7794,8 +7911,7 @@ button[data-flux-floating-toggle]:hover {
|
|
|
7794
7911
|
selectedElement ? getElementPath(selectedElement) : "none"
|
|
7795
7912
|
) })
|
|
7796
7913
|
]
|
|
7797
|
-
}
|
|
7798
|
-
"flux-panel"
|
|
7914
|
+
}
|
|
7799
7915
|
) });
|
|
7800
7916
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7801
7917
|
!enabled && /* @__PURE__ */ jsx(
|