hyperframes 0.7.21 → 0.7.23
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/dist/cli.js +1384 -510
- package/dist/commands/contrast-audit.browser.js +40 -0
- package/dist/commands/layout-audit.browser.js +91 -3
- package/dist/hyperframe-runtime.js +25 -25
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +25 -25
- package/dist/hyperframes-player.global.js +2 -2
- package/dist/skills/hyperframes/SKILL.md +17 -17
- package/dist/skills/hyperframes-cli/references/preview-render.md +2 -0
- package/dist/studio/assets/hyperframes-player-BGuumSiM.js +459 -0
- package/dist/studio/assets/{index-jbPe1Dih.js → index-B8XMgbWF.js} +157 -157
- package/dist/studio/assets/{index-pAaVqALC.js → index-BRZTrsSs.js} +1 -1
- package/dist/studio/assets/{index-gFA786gK.js → index-DPO5Gw_v.js} +1 -1
- package/dist/studio/{chunk-SBGXX7WY.js → chunk-AN2EWWK3.js} +59 -108
- package/dist/studio/chunk-AN2EWWK3.js.map +1 -0
- package/dist/studio/{domEditingLayers-VZMLL4AP.js → domEditingLayers-EK7R7R4G.js} +4 -2
- package/dist/studio/index.html +1 -1
- package/dist/studio/index.js +163 -99
- package/dist/studio/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/studio/assets/hyperframes-player-DNLS_l47.js +0 -459
- package/dist/studio/chunk-SBGXX7WY.js.map +0 -1
- /package/dist/studio/{domEditingLayers-VZMLL4AP.js.map → domEditingLayers-EK7R7R4G.js.map} +0 -0
package/dist/studio/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
buildDomEditStylePatchOperation,
|
|
5
5
|
buildDomEditTextPatchOperation,
|
|
6
6
|
collectDomEditLayerItems,
|
|
7
|
+
domEditSelectionToFacts,
|
|
7
8
|
findElementForSelection,
|
|
8
9
|
findElementForTimelineElement,
|
|
9
10
|
getDomEditLayerKey,
|
|
@@ -17,7 +18,7 @@ import {
|
|
|
17
18
|
resolveDomEditSelection,
|
|
18
19
|
serializeDomEditTextFields,
|
|
19
20
|
setCompositionSourceMap
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-AN2EWWK3.js";
|
|
21
22
|
|
|
22
23
|
// src/components/nle/NLELayout.tsx
|
|
23
24
|
import {
|
|
@@ -1469,6 +1470,72 @@ function generateId() {
|
|
|
1469
1470
|
return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
1470
1471
|
}
|
|
1471
1472
|
|
|
1473
|
+
// src/utils/safeStorage.ts
|
|
1474
|
+
function safeLocalStorage() {
|
|
1475
|
+
try {
|
|
1476
|
+
return typeof localStorage === "undefined" ? null : localStorage;
|
|
1477
|
+
} catch {
|
|
1478
|
+
return null;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
function safeSessionStorage() {
|
|
1482
|
+
try {
|
|
1483
|
+
return typeof sessionStorage === "undefined" ? null : sessionStorage;
|
|
1484
|
+
} catch {
|
|
1485
|
+
return null;
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
// src/telemetry/distinctId.ts
|
|
1490
|
+
var DISTINCT_ID_KEY = "hyperframes-studio:anonymousId";
|
|
1491
|
+
var LEGACY_STUDIO_ANON_ID_KEY = "hf-studio-anon-id";
|
|
1492
|
+
var cachedId = null;
|
|
1493
|
+
function getCliDistinctId() {
|
|
1494
|
+
try {
|
|
1495
|
+
const id = typeof window === "undefined" ? void 0 : window.__HF_CLI_DISTINCT_ID;
|
|
1496
|
+
return typeof id === "string" && id.length > 0 ? id : null;
|
|
1497
|
+
} catch {
|
|
1498
|
+
return null;
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
function persist(ls, id) {
|
|
1502
|
+
for (const key of [DISTINCT_ID_KEY, LEGACY_STUDIO_ANON_ID_KEY]) {
|
|
1503
|
+
try {
|
|
1504
|
+
ls.setItem(key, id);
|
|
1505
|
+
} catch {
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
function resolveStudioDistinctId() {
|
|
1510
|
+
if (cachedId) return cachedId;
|
|
1511
|
+
const ls = safeLocalStorage();
|
|
1512
|
+
const cliId = getCliDistinctId();
|
|
1513
|
+
if (cliId) {
|
|
1514
|
+
cachedId = cliId;
|
|
1515
|
+
if (ls) persist(ls, cliId);
|
|
1516
|
+
return cliId;
|
|
1517
|
+
}
|
|
1518
|
+
if (ls) {
|
|
1519
|
+
let existing = null;
|
|
1520
|
+
try {
|
|
1521
|
+
existing = ls.getItem(DISTINCT_ID_KEY) ?? ls.getItem(LEGACY_STUDIO_ANON_ID_KEY);
|
|
1522
|
+
} catch {
|
|
1523
|
+
}
|
|
1524
|
+
if (existing) {
|
|
1525
|
+
cachedId = existing;
|
|
1526
|
+
persist(ls, existing);
|
|
1527
|
+
return existing;
|
|
1528
|
+
}
|
|
1529
|
+
} else {
|
|
1530
|
+
cachedId = "anonymous";
|
|
1531
|
+
return cachedId;
|
|
1532
|
+
}
|
|
1533
|
+
const id = generateId();
|
|
1534
|
+
cachedId = id;
|
|
1535
|
+
persist(ls, id);
|
|
1536
|
+
return id;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1472
1539
|
// src/utils/studioTelemetry.ts
|
|
1473
1540
|
var POSTHOG_API_KEY = "phc_zjjbX0PnWxERXrMHhkEJWj9A9BhGVLRReICgsfTMmpx";
|
|
1474
1541
|
var POSTHOG_HOST = "https://us.i.posthog.com";
|
|
@@ -1476,23 +1543,8 @@ var FLUSH_INTERVAL_MS = 3e4;
|
|
|
1476
1543
|
var FLUSH_TIMEOUT_MS = 5e3;
|
|
1477
1544
|
var queue = [];
|
|
1478
1545
|
var flushTimer = null;
|
|
1479
|
-
var distinctId = null;
|
|
1480
1546
|
function getDistinctId() {
|
|
1481
|
-
|
|
1482
|
-
try {
|
|
1483
|
-
const stored = localStorage.getItem("hf-studio-anon-id");
|
|
1484
|
-
if (stored) {
|
|
1485
|
-
distinctId = stored;
|
|
1486
|
-
return stored;
|
|
1487
|
-
}
|
|
1488
|
-
} catch {
|
|
1489
|
-
}
|
|
1490
|
-
distinctId = generateId();
|
|
1491
|
-
try {
|
|
1492
|
-
localStorage.setItem("hf-studio-anon-id", distinctId);
|
|
1493
|
-
} catch {
|
|
1494
|
-
}
|
|
1495
|
-
return distinctId;
|
|
1547
|
+
return resolveStudioDistinctId();
|
|
1496
1548
|
}
|
|
1497
1549
|
function isEnabled() {
|
|
1498
1550
|
try {
|
|
@@ -2824,7 +2876,7 @@ function useMusicBeatAnalysis() {
|
|
|
2824
2876
|
void io.writeProjectFile(beatPath, content).catch(() => {
|
|
2825
2877
|
});
|
|
2826
2878
|
};
|
|
2827
|
-
const
|
|
2879
|
+
const persist2 = () => {
|
|
2828
2880
|
const s = usePlayerStore.getState();
|
|
2829
2881
|
const a = s.beatAnalysis;
|
|
2830
2882
|
if (!a) return;
|
|
@@ -2836,7 +2888,7 @@ function useMusicBeatAnalysis() {
|
|
|
2836
2888
|
flush2();
|
|
2837
2889
|
}, PERSIST_DEBOUNCE_MS);
|
|
2838
2890
|
};
|
|
2839
|
-
setBeatPersist(
|
|
2891
|
+
setBeatPersist(persist2);
|
|
2840
2892
|
return () => {
|
|
2841
2893
|
if (timer) clearTimeout(timer);
|
|
2842
2894
|
flush2();
|
|
@@ -5196,11 +5248,6 @@ var STUDIO_RAZOR_TOOL_ENABLED = resolveStudioBooleanEnvFlag(
|
|
|
5196
5248
|
["VITE_STUDIO_ENABLE_RAZOR_TOOL", "VITE_STUDIO_RAZOR_TOOL_ENABLED"],
|
|
5197
5249
|
true
|
|
5198
5250
|
);
|
|
5199
|
-
var STUDIO_STORYBOARD_ENABLED = resolveStudioBooleanEnvFlag(
|
|
5200
|
-
env,
|
|
5201
|
-
["VITE_STUDIO_ENABLE_STORYBOARD", "VITE_STUDIO_STORYBOARD_ENABLED"],
|
|
5202
|
-
false
|
|
5203
|
-
);
|
|
5204
5251
|
var STUDIO_PREVIEW_SELECTION_ENABLED = STUDIO_INSPECTOR_PANELS_ENABLED;
|
|
5205
5252
|
var STUDIO_SDK_CUTOVER_ENABLED = resolveStudioBooleanEnvFlag(
|
|
5206
5253
|
env,
|
|
@@ -9473,30 +9520,10 @@ function useCompositionStack({
|
|
|
9473
9520
|
}
|
|
9474
9521
|
|
|
9475
9522
|
// src/telemetry/config.ts
|
|
9476
|
-
var ANON_ID_KEY = "hyperframes-studio:anonymousId";
|
|
9477
9523
|
var OPT_OUT_KEY = "hyperframes-studio:telemetryDisabled";
|
|
9478
9524
|
var NOTICE_KEY = "hyperframes-studio:telemetryNoticeShown";
|
|
9479
|
-
function safeLocalStorage() {
|
|
9480
|
-
try {
|
|
9481
|
-
return typeof localStorage === "undefined" ? null : localStorage;
|
|
9482
|
-
} catch {
|
|
9483
|
-
return null;
|
|
9484
|
-
}
|
|
9485
|
-
}
|
|
9486
|
-
function newAnonymousId() {
|
|
9487
|
-
return generateId();
|
|
9488
|
-
}
|
|
9489
9525
|
function getAnonymousId() {
|
|
9490
|
-
|
|
9491
|
-
if (!ls) return "anonymous";
|
|
9492
|
-
const existing = ls.getItem(ANON_ID_KEY);
|
|
9493
|
-
if (existing) return existing;
|
|
9494
|
-
const id = newAnonymousId();
|
|
9495
|
-
try {
|
|
9496
|
-
ls.setItem(ANON_ID_KEY, id);
|
|
9497
|
-
} catch {
|
|
9498
|
-
}
|
|
9499
|
-
return id;
|
|
9526
|
+
return resolveStudioDistinctId();
|
|
9500
9527
|
}
|
|
9501
9528
|
function isOptedOut() {
|
|
9502
9529
|
return safeLocalStorage()?.getItem(OPT_OUT_KEY) === "1";
|
|
@@ -9511,13 +9538,6 @@ function markNoticeShown() {
|
|
|
9511
9538
|
}
|
|
9512
9539
|
}
|
|
9513
9540
|
var SESSION_FIRED_KEY = "hyperframes-studio:sessionStartFired";
|
|
9514
|
-
function safeSessionStorage() {
|
|
9515
|
-
try {
|
|
9516
|
-
return typeof sessionStorage === "undefined" ? null : sessionStorage;
|
|
9517
|
-
} catch {
|
|
9518
|
-
return null;
|
|
9519
|
-
}
|
|
9520
|
-
}
|
|
9521
9541
|
function hasFiredSessionStart() {
|
|
9522
9542
|
return safeSessionStorage()?.getItem(SESSION_FIRED_KEY) === "1";
|
|
9523
9543
|
}
|
|
@@ -9612,12 +9632,12 @@ function trackEvent(event, properties = {}) {
|
|
|
9612
9632
|
}
|
|
9613
9633
|
function flush() {
|
|
9614
9634
|
if (eventQueue.length === 0) return;
|
|
9615
|
-
const
|
|
9635
|
+
const distinctId = getAnonymousId();
|
|
9616
9636
|
const batch = eventQueue.map((e) => ({
|
|
9617
9637
|
event: e.event,
|
|
9618
9638
|
// $ip: null tells PostHog to not record the request IP.
|
|
9619
9639
|
properties: { ...e.properties, $ip: null },
|
|
9620
|
-
distinct_id:
|
|
9640
|
+
distinct_id: distinctId,
|
|
9621
9641
|
timestamp: e.timestamp
|
|
9622
9642
|
}));
|
|
9623
9643
|
eventQueue = [];
|
|
@@ -12819,14 +12839,11 @@ function createTransformCommitHandlers({
|
|
|
12819
12839
|
|
|
12820
12840
|
// src/components/editor/PropertyPanel.tsx
|
|
12821
12841
|
import { classifyPropertyGroup } from "@hyperframes/core/gsap-parser";
|
|
12842
|
+
import { resolveEditingSections } from "@hyperframes/core/editing";
|
|
12822
12843
|
|
|
12823
12844
|
// src/components/editor/propertyPanelMediaSection.tsx
|
|
12824
12845
|
import { useState as useState20 } from "react";
|
|
12825
12846
|
import { Fragment as Fragment10, jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
12826
|
-
var MEDIA_TAGS = /* @__PURE__ */ new Set(["video", "audio"]);
|
|
12827
|
-
function isMediaElement(element) {
|
|
12828
|
-
return MEDIA_TAGS.has(element.tagName);
|
|
12829
|
-
}
|
|
12830
12847
|
function MediaSection({
|
|
12831
12848
|
projectDir,
|
|
12832
12849
|
element,
|
|
@@ -13500,9 +13517,6 @@ var DEFAULT_COLOR_GRADING = {
|
|
|
13500
13517
|
colorSpace: HF_COLOR_GRADING_COLOR_SPACE
|
|
13501
13518
|
};
|
|
13502
13519
|
var COLOR_GRADING_DATA_KEY = HF_COLOR_GRADING_ATTR.replace(/^data-/, "");
|
|
13503
|
-
function isColorGradingCapableElement(element) {
|
|
13504
|
-
return element.tagName === "video" || element.tagName === "img";
|
|
13505
|
-
}
|
|
13506
13520
|
function readColorGradingFromElement(element) {
|
|
13507
13521
|
const grading = normalizeHfColorGrading2(element.dataAttributes[COLOR_GRADING_DATA_KEY]) ?? DEFAULT_COLOR_GRADING;
|
|
13508
13522
|
return { ...grading, intensity: 1 };
|
|
@@ -18711,6 +18725,7 @@ var PropertyPanel = memo22(function PropertyPanel2({
|
|
|
18711
18725
|
const manualRotationEditingDisabled = !element.capabilities.canApplyManualRotation;
|
|
18712
18726
|
const sourceLabel = element.id ? `#${element.id}` : element.selector;
|
|
18713
18727
|
const showEditableSections = element.capabilities.canEditStyles;
|
|
18728
|
+
const sections = resolveEditingSections(domEditSelectionToFacts(element, gsapAnimations.length));
|
|
18714
18729
|
const manualOffset = readStudioPathOffset(element.element);
|
|
18715
18730
|
const manualSize = readStudioBoxSize(element.element);
|
|
18716
18731
|
const resolvedWidth = manualSize.width > 0 ? manualSize.width : parsePxMetricValue(styles.width ?? "") ?? element.boundingBox.width;
|
|
@@ -18833,7 +18848,7 @@ var PropertyPanel = memo22(function PropertyPanel2({
|
|
|
18833
18848
|
onRemoveTextField
|
|
18834
18849
|
}
|
|
18835
18850
|
),
|
|
18836
|
-
|
|
18851
|
+
sections.timing && // Render whenever there's an authored clip range OR animations to infer
|
|
18837
18852
|
// one from — a pure-GSAP element with no data-start still gets a Timing
|
|
18838
18853
|
// range (TimingSection derives it from its tweens).
|
|
18839
18854
|
/* @__PURE__ */ jsx54(
|
|
@@ -18844,7 +18859,7 @@ var PropertyPanel = memo22(function PropertyPanel2({
|
|
|
18844
18859
|
onSetAttribute
|
|
18845
18860
|
}
|
|
18846
18861
|
),
|
|
18847
|
-
|
|
18862
|
+
sections.media && /* @__PURE__ */ jsx54(
|
|
18848
18863
|
MediaSection,
|
|
18849
18864
|
{
|
|
18850
18865
|
projectDir,
|
|
@@ -18855,7 +18870,7 @@ var PropertyPanel = memo22(function PropertyPanel2({
|
|
|
18855
18870
|
onSetHtmlAttribute
|
|
18856
18871
|
}
|
|
18857
18872
|
),
|
|
18858
|
-
STUDIO_COLOR_GRADING_ENABLED &&
|
|
18873
|
+
STUDIO_COLOR_GRADING_ENABLED && sections.colorGrading && /* @__PURE__ */ jsx54(
|
|
18859
18874
|
ColorGradingSection,
|
|
18860
18875
|
{
|
|
18861
18876
|
element,
|
|
@@ -22337,6 +22352,9 @@ function normalizeText(v) {
|
|
|
22337
22352
|
const t = v.trim();
|
|
22338
22353
|
return t === "" ? null : t;
|
|
22339
22354
|
}
|
|
22355
|
+
function countHfIdInSource(source, id) {
|
|
22356
|
+
return source.split(`data-hf-id="${id}"`).length - 1 + (source.split(`data-hf-id='${id}'`).length - 1);
|
|
22357
|
+
}
|
|
22340
22358
|
function resolveSnapshot(session, id) {
|
|
22341
22359
|
const els = session.getElements();
|
|
22342
22360
|
const exact = els.find((el) => el.scopedId === id);
|
|
@@ -22379,8 +22397,9 @@ function checkOpValue(op, el, hfId) {
|
|
|
22379
22397
|
if (actual === expected) return null;
|
|
22380
22398
|
return { kind: "value_mismatch", hfId, property, expected, actual };
|
|
22381
22399
|
}
|
|
22382
|
-
function sdkResolverShadowCheck(session, hfId, ops) {
|
|
22400
|
+
function sdkResolverShadowCheck(session, hfId, ops, sourceContent) {
|
|
22383
22401
|
if (!resolveSnapshot(session, hfId)) {
|
|
22402
|
+
if (sourceContent !== void 0 && !sourceContent.includes(hfId)) return [];
|
|
22384
22403
|
return [{ kind: "element_not_found", hfId }];
|
|
22385
22404
|
}
|
|
22386
22405
|
const shadowable = ops.filter(isShadowableOp);
|
|
@@ -22416,28 +22435,58 @@ function redactMismatches(mismatches) {
|
|
|
22416
22435
|
actual: redactValue(m.actual)
|
|
22417
22436
|
}));
|
|
22418
22437
|
}
|
|
22419
|
-
function runResolverShadow(session, hfId, ops) {
|
|
22438
|
+
function runResolverShadow(session, hfId, ops, sourceContent) {
|
|
22420
22439
|
if (!STUDIO_SDK_RESOLVER_SHADOW_ENABLED) return;
|
|
22421
22440
|
if (!hfId) return;
|
|
22422
22441
|
try {
|
|
22423
|
-
const mismatches = sdkResolverShadowCheck(session, hfId, ops);
|
|
22442
|
+
const mismatches = sdkResolverShadowCheck(session, hfId, ops, sourceContent);
|
|
22424
22443
|
if (mismatches.length === 0) return;
|
|
22444
|
+
const isElementNotFound = mismatches.some((m) => m.kind === "element_not_found");
|
|
22425
22445
|
trackStudioEvent("sdk_resolver_shadow", {
|
|
22426
22446
|
hfId,
|
|
22447
|
+
// sessionElementCount > 0 + element_not_found = runtime-only element;
|
|
22448
|
+
// sessionElementCount === 0 = session is empty/broken (actionable).
|
|
22449
|
+
sessionElementCount: session.getElements().length,
|
|
22450
|
+
// Count of data-hf-id="<id>" occurrences in source for an emitted
|
|
22451
|
+
// element_not_found. >1 = duplicate ids → resolver picked the wrong
|
|
22452
|
+
// instance; =1 = single static node the SDK parse dropped (foreign-content
|
|
22453
|
+
// exclusion / sub-comp inlining gap); =0 = the runtime-node filter above
|
|
22454
|
+
// uses a loose substring match (biased toward keeping signal) while this
|
|
22455
|
+
// count uses a strict attribute match — an emitted event with count 0
|
|
22456
|
+
// means hfId appeared in source as plain text (e.g. a class name, comment,
|
|
22457
|
+
// or script string) but never as a data-hf-id attribute. Treat 0 as "not
|
|
22458
|
+
// a genuine attribute occurrence," not as a contradiction.
|
|
22459
|
+
...isElementNotFound && sourceContent !== void 0 ? { sourceHfIdCount: countHfIdInSource(sourceContent, hfId) } : {},
|
|
22427
22460
|
mismatchCount: mismatches.length,
|
|
22428
22461
|
mismatches: JSON.stringify(redactMismatches(mismatches))
|
|
22429
22462
|
});
|
|
22430
22463
|
} catch {
|
|
22431
22464
|
}
|
|
22432
22465
|
}
|
|
22433
|
-
function recordResolverParity(session, hfId, opLabel) {
|
|
22466
|
+
async function recordResolverParity(session, hfId, opLabel, readSource) {
|
|
22434
22467
|
if (!STUDIO_SDK_RESOLVER_SHADOW_ENABLED) return;
|
|
22435
22468
|
if (!session || !hfId) return;
|
|
22436
22469
|
try {
|
|
22437
22470
|
if (resolveSnapshot(session, hfId)) return;
|
|
22471
|
+
const sessionElementCount = session.getElements().length;
|
|
22472
|
+
let source;
|
|
22473
|
+
if (readSource) {
|
|
22474
|
+
try {
|
|
22475
|
+
source = await readSource();
|
|
22476
|
+
} catch {
|
|
22477
|
+
source = void 0;
|
|
22478
|
+
}
|
|
22479
|
+
}
|
|
22480
|
+
if (source !== void 0 && !source.includes(hfId)) return;
|
|
22438
22481
|
trackStudioEvent("sdk_resolver_shadow", {
|
|
22439
22482
|
hfId,
|
|
22440
22483
|
opLabel,
|
|
22484
|
+
sessionElementCount,
|
|
22485
|
+
// sourceHfIdCount: strict data-hf-id="..." attribute count. Can be 0 even
|
|
22486
|
+
// on an emitted (non-suppressed) event — the suppression check above is a
|
|
22487
|
+
// loose substring match (biased toward keeping signal); see the longer
|
|
22488
|
+
// comment on this field in runResolverShadow for the full explanation.
|
|
22489
|
+
...source !== void 0 ? { sourceHfIdCount: countHfIdInSource(source, hfId) } : {},
|
|
22441
22490
|
mismatchCount: 1,
|
|
22442
22491
|
mismatches: JSON.stringify([
|
|
22443
22492
|
{ kind: "element_not_found", hfId }
|
|
@@ -22450,11 +22499,13 @@ function recordAnimationResolverParity(session, animationId, opLabel) {
|
|
|
22450
22499
|
if (!STUDIO_SDK_RESOLVER_SHADOW_ENABLED) return;
|
|
22451
22500
|
if (!session || !animationId) return;
|
|
22452
22501
|
try {
|
|
22453
|
-
const
|
|
22502
|
+
const elements = session.getElements();
|
|
22503
|
+
const resolves = elements.some((el) => el.animationIds.includes(animationId));
|
|
22454
22504
|
if (resolves) return;
|
|
22455
22505
|
trackStudioEvent("sdk_resolver_shadow", {
|
|
22456
22506
|
animationId,
|
|
22457
22507
|
opLabel,
|
|
22508
|
+
sessionElementCount: elements.length,
|
|
22458
22509
|
mismatchCount: 1,
|
|
22459
22510
|
mismatches: JSON.stringify([
|
|
22460
22511
|
{ kind: "animation_not_found", animationId }
|
|
@@ -22551,7 +22602,7 @@ function isSafeAttributeValue(name, value) {
|
|
|
22551
22602
|
return true;
|
|
22552
22603
|
}
|
|
22553
22604
|
|
|
22554
|
-
// src/utils/
|
|
22605
|
+
// src/utils/sdkCutoverEligibility.ts
|
|
22555
22606
|
var CUTOVER_OP_TYPES = /* @__PURE__ */ new Set([
|
|
22556
22607
|
"inline-style",
|
|
22557
22608
|
"text-content",
|
|
@@ -22611,6 +22662,8 @@ function shouldDeclineTextCutoverForTarget(target, ops) {
|
|
|
22611
22662
|
function shouldUseSdkCutover(flagEnabled, hasSession, hfId, ops) {
|
|
22612
22663
|
return flagEnabled && hasSession && !!hfId && ops.length > 0 && ops.every((o) => CUTOVER_OP_TYPES.has(o.type)) && !ops.some(mapsToReservedAttr) && !hasUnsafeHtmlAttributeOp(ops);
|
|
22613
22664
|
}
|
|
22665
|
+
|
|
22666
|
+
// src/utils/sdkCutover.ts
|
|
22614
22667
|
async function captureOnDiskBefore(deps, targetPath, serializedFallback) {
|
|
22615
22668
|
if (!deps.readProjectFile) return serializedFallback;
|
|
22616
22669
|
try {
|
|
@@ -22666,7 +22719,13 @@ async function sdkCutoverPersist(selection, ops, originalContent, targetPath, sd
|
|
|
22666
22719
|
}
|
|
22667
22720
|
}
|
|
22668
22721
|
async function sdkTimingPersist(hfId, targetPath, timingUpdate, sdkSession, deps, options) {
|
|
22669
|
-
|
|
22722
|
+
const timingSrc = deps.readProjectFile;
|
|
22723
|
+
void recordResolverParity(
|
|
22724
|
+
sdkSession,
|
|
22725
|
+
hfId,
|
|
22726
|
+
"setTiming",
|
|
22727
|
+
timingSrc ? () => timingSrc(targetPath) : void 0
|
|
22728
|
+
);
|
|
22670
22729
|
if (!STUDIO_SDK_CUTOVER_ENABLED) return false;
|
|
22671
22730
|
if (!sdkSession || !sdkSession.getElement(hfId)) return false;
|
|
22672
22731
|
if (wrongCompositionFile(deps, targetPath)) return false;
|
|
@@ -22685,8 +22744,15 @@ async function sdkTimingPersist(hfId, targetPath, timingUpdate, sdkSession, deps
|
|
|
22685
22744
|
}
|
|
22686
22745
|
}
|
|
22687
22746
|
function sdkGsapTweenPersist(targetPath, op, sdkSession, deps, options) {
|
|
22688
|
-
if (op.kind === "add")
|
|
22689
|
-
|
|
22747
|
+
if (op.kind === "add") {
|
|
22748
|
+
const gsapSrc = deps.readProjectFile;
|
|
22749
|
+
void recordResolverParity(
|
|
22750
|
+
sdkSession,
|
|
22751
|
+
op.target,
|
|
22752
|
+
"addGsapTween",
|
|
22753
|
+
gsapSrc ? () => gsapSrc(targetPath) : void 0
|
|
22754
|
+
);
|
|
22755
|
+
} else
|
|
22690
22756
|
recordAnimationResolverParity(
|
|
22691
22757
|
sdkSession,
|
|
22692
22758
|
op.animationId,
|
|
@@ -22832,7 +22898,12 @@ function sdkReplaceWithKeyframesPersist(targetPath, animationId, targetSelector,
|
|
|
22832
22898
|
);
|
|
22833
22899
|
}
|
|
22834
22900
|
async function sdkDeletePersist(hfId, originalContent, targetPath, sdkSession, deps) {
|
|
22835
|
-
recordResolverParity(
|
|
22901
|
+
void recordResolverParity(
|
|
22902
|
+
sdkSession,
|
|
22903
|
+
hfId,
|
|
22904
|
+
"removeElement",
|
|
22905
|
+
() => Promise.resolve(originalContent)
|
|
22906
|
+
);
|
|
22836
22907
|
if (!STUDIO_SDK_CUTOVER_ENABLED) return false;
|
|
22837
22908
|
if (!sdkSession || !sdkSession.getElement(hfId)) return false;
|
|
22838
22909
|
if (wrongCompositionFile(deps, targetPath)) return false;
|
|
@@ -29761,7 +29832,7 @@ function useDomEditSession({
|
|
|
29761
29832
|
showToast,
|
|
29762
29833
|
refreshPreviewDocumentVersion,
|
|
29763
29834
|
queueDomEditSave,
|
|
29764
|
-
readProjectFile
|
|
29835
|
+
readProjectFile,
|
|
29765
29836
|
writeProjectFile,
|
|
29766
29837
|
updateEditingFileContent,
|
|
29767
29838
|
domEditSaveTimestampRef,
|
|
@@ -29785,7 +29856,6 @@ function useDomEditSession({
|
|
|
29785
29856
|
forceReloadSdkSession
|
|
29786
29857
|
}) {
|
|
29787
29858
|
void _setRefreshKey;
|
|
29788
|
-
void _readProjectFile;
|
|
29789
29859
|
const {
|
|
29790
29860
|
domEditSelection,
|
|
29791
29861
|
domEditGroupSelections,
|
|
@@ -29916,7 +29986,7 @@ function useDomEditSession({
|
|
|
29916
29986
|
buildDomSelectionFromTarget,
|
|
29917
29987
|
forceReloadSdkSession,
|
|
29918
29988
|
onTrySdkPersist: sdkSession ? (selection, operations, originalContent, targetPath, options) => {
|
|
29919
|
-
runResolverShadow(sdkSession, selection.hfId, operations);
|
|
29989
|
+
runResolverShadow(sdkSession, selection.hfId, operations, originalContent);
|
|
29920
29990
|
return sdkCutoverPersist(
|
|
29921
29991
|
selection,
|
|
29922
29992
|
operations,
|
|
@@ -29944,7 +30014,9 @@ function useDomEditSession({
|
|
|
29944
30014
|
// SDK persist), but the tripwire is decoupled from cutover — record whether
|
|
29945
30015
|
// the SDK resolves each reordered element (the reorderElements op's targets).
|
|
29946
30016
|
onReorderShadow: sdkSession ? (targets) => {
|
|
29947
|
-
|
|
30017
|
+
const reorderSrc = activeCompPath ? () => readProjectFile(activeCompPath) : void 0;
|
|
30018
|
+
for (const target of targets)
|
|
30019
|
+
void recordResolverParity(sdkSession, target, "reorderElements", reorderSrc);
|
|
29948
30020
|
} : void 0
|
|
29949
30021
|
});
|
|
29950
30022
|
const { groupSelection, ungroupSelection } = useGroupCommits({
|
|
@@ -32559,26 +32631,18 @@ function writeViewModeToUrl(mode) {
|
|
|
32559
32631
|
}
|
|
32560
32632
|
window.history.replaceState(window.history.state, "", url);
|
|
32561
32633
|
}
|
|
32562
|
-
function useViewModeState(
|
|
32563
|
-
const [viewMode, setMode] = useState58(
|
|
32564
|
-
() => enabled ? readViewModeFromUrl() : "timeline"
|
|
32565
|
-
);
|
|
32634
|
+
function useViewModeState() {
|
|
32635
|
+
const [viewMode, setMode] = useState58(() => readViewModeFromUrl());
|
|
32566
32636
|
useEffect44(() => {
|
|
32567
|
-
if (!enabled) return;
|
|
32568
32637
|
const onPopState = () => setMode(readViewModeFromUrl());
|
|
32569
32638
|
window.addEventListener("popstate", onPopState);
|
|
32570
32639
|
return () => window.removeEventListener("popstate", onPopState);
|
|
32571
|
-
}, [
|
|
32572
|
-
const setViewMode = useCallback77(
|
|
32573
|
-
(mode)
|
|
32574
|
-
|
|
32575
|
-
|
|
32576
|
-
|
|
32577
|
-
},
|
|
32578
|
-
[enabled]
|
|
32579
|
-
);
|
|
32580
|
-
const effectiveMode = enabled ? viewMode : "timeline";
|
|
32581
|
-
return useMemo27(() => ({ viewMode: effectiveMode, setViewMode }), [effectiveMode, setViewMode]);
|
|
32640
|
+
}, []);
|
|
32641
|
+
const setViewMode = useCallback77((mode) => {
|
|
32642
|
+
setMode(mode);
|
|
32643
|
+
writeViewModeToUrl(mode);
|
|
32644
|
+
}, []);
|
|
32645
|
+
return useMemo27(() => ({ viewMode, setViewMode }), [viewMode, setViewMode]);
|
|
32582
32646
|
}
|
|
32583
32647
|
var ViewModeContext = createContext5(null);
|
|
32584
32648
|
function useViewMode() {
|
|
@@ -32828,7 +32892,7 @@ function StudioHeader({
|
|
|
32828
32892
|
/* @__PURE__ */ jsx67("span", { className: "text-neutral-700 select-none", "aria-hidden": "true", children: "|" }),
|
|
32829
32893
|
/* @__PURE__ */ jsx67("span", { className: "text-[11px] font-medium text-neutral-300", children: projectId })
|
|
32830
32894
|
] }),
|
|
32831
|
-
|
|
32895
|
+
/* @__PURE__ */ jsx67(ViewModeToggle, {}),
|
|
32832
32896
|
/* @__PURE__ */ jsxs56("div", { className: "flex items-center gap-1.5", children: [
|
|
32833
32897
|
/* @__PURE__ */ jsx67(
|
|
32834
32898
|
"button",
|
|
@@ -36957,7 +37021,7 @@ function OffCanvasIndicators({
|
|
|
36957
37021
|
const selectOffCanvas = async () => {
|
|
36958
37022
|
const el = elements.current.get(r.key);
|
|
36959
37023
|
if (!el) return;
|
|
36960
|
-
const { resolveDomEditSelection: resolveDomEditSelection2 } = await import("./domEditingLayers-
|
|
37024
|
+
const { resolveDomEditSelection: resolveDomEditSelection2 } = await import("./domEditingLayers-EK7R7R4G.js");
|
|
36961
37025
|
const acp = activeCompositionPathRef.current ?? "index.html";
|
|
36962
37026
|
const sel = await resolveDomEditSelection2(el, {
|
|
36963
37027
|
activeCompositionPath: acp,
|
|
@@ -42664,9 +42728,9 @@ function makeSlideshowNotesController() {
|
|
|
42664
42728
|
});
|
|
42665
42729
|
};
|
|
42666
42730
|
return {
|
|
42667
|
-
schedule(manifest,
|
|
42731
|
+
schedule(manifest, persist2, delayMs) {
|
|
42668
42732
|
if (timer !== null) clearTimeout(timer);
|
|
42669
|
-
pending = { manifest, persist };
|
|
42733
|
+
pending = { manifest, persist: persist2 };
|
|
42670
42734
|
timer = setTimeout(() => {
|
|
42671
42735
|
timer = null;
|
|
42672
42736
|
drainPending();
|
|
@@ -44757,7 +44821,7 @@ import { jsx as jsx113, jsxs as jsxs96 } from "react/jsx-runtime";
|
|
|
44757
44821
|
function StudioApp() {
|
|
44758
44822
|
const { projectId, resolving, waitingForServer } = useServerConnection();
|
|
44759
44823
|
const initialUrlStateRef = useRef90(readStudioUrlStateFromWindow());
|
|
44760
|
-
const viewModeValue = useViewModeState(
|
|
44824
|
+
const viewModeValue = useViewModeState();
|
|
44761
44825
|
useEffect67(() => {
|
|
44762
44826
|
if (resolving || waitingForServer) return;
|
|
44763
44827
|
if (hasFiredSessionStart()) return;
|