hyperframes 0.7.22 → 0.7.24
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 +585 -35
- package/dist/commands/contrast-audit.browser.js +40 -0
- package/dist/commands/layout-audit.browser.js +46 -1
- 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/studio/assets/hyperframes-player-BGuumSiM.js +459 -0
- package/dist/studio/assets/{index-B_gDTiNI.js → index-CGW4LOlP.js} +1 -1
- package/dist/studio/assets/{index-B4h4u7eW.js → index-CnZuUYe6.js} +109 -109
- package/dist/studio/assets/{index-gk_X4nXD.js → index-DsVS-Zmd.js} +1 -1
- package/dist/studio/index.html +1 -1
- package/dist/studio/index.js +139 -65
- 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/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
7
7
|
<title>HyperFrames Studio</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-CnZuUYe6.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-DmkOvZns.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/dist/studio/index.js
CHANGED
|
@@ -1470,6 +1470,72 @@ function generateId() {
|
|
|
1470
1470
|
return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
1471
1471
|
}
|
|
1472
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
|
+
|
|
1473
1539
|
// src/utils/studioTelemetry.ts
|
|
1474
1540
|
var POSTHOG_API_KEY = "phc_zjjbX0PnWxERXrMHhkEJWj9A9BhGVLRReICgsfTMmpx";
|
|
1475
1541
|
var POSTHOG_HOST = "https://us.i.posthog.com";
|
|
@@ -1477,23 +1543,8 @@ var FLUSH_INTERVAL_MS = 3e4;
|
|
|
1477
1543
|
var FLUSH_TIMEOUT_MS = 5e3;
|
|
1478
1544
|
var queue = [];
|
|
1479
1545
|
var flushTimer = null;
|
|
1480
|
-
var distinctId = null;
|
|
1481
1546
|
function getDistinctId() {
|
|
1482
|
-
|
|
1483
|
-
try {
|
|
1484
|
-
const stored = localStorage.getItem("hf-studio-anon-id");
|
|
1485
|
-
if (stored) {
|
|
1486
|
-
distinctId = stored;
|
|
1487
|
-
return stored;
|
|
1488
|
-
}
|
|
1489
|
-
} catch {
|
|
1490
|
-
}
|
|
1491
|
-
distinctId = generateId();
|
|
1492
|
-
try {
|
|
1493
|
-
localStorage.setItem("hf-studio-anon-id", distinctId);
|
|
1494
|
-
} catch {
|
|
1495
|
-
}
|
|
1496
|
-
return distinctId;
|
|
1547
|
+
return resolveStudioDistinctId();
|
|
1497
1548
|
}
|
|
1498
1549
|
function isEnabled() {
|
|
1499
1550
|
try {
|
|
@@ -2825,7 +2876,7 @@ function useMusicBeatAnalysis() {
|
|
|
2825
2876
|
void io.writeProjectFile(beatPath, content).catch(() => {
|
|
2826
2877
|
});
|
|
2827
2878
|
};
|
|
2828
|
-
const
|
|
2879
|
+
const persist2 = () => {
|
|
2829
2880
|
const s = usePlayerStore.getState();
|
|
2830
2881
|
const a = s.beatAnalysis;
|
|
2831
2882
|
if (!a) return;
|
|
@@ -2837,7 +2888,7 @@ function useMusicBeatAnalysis() {
|
|
|
2837
2888
|
flush2();
|
|
2838
2889
|
}, PERSIST_DEBOUNCE_MS);
|
|
2839
2890
|
};
|
|
2840
|
-
setBeatPersist(
|
|
2891
|
+
setBeatPersist(persist2);
|
|
2841
2892
|
return () => {
|
|
2842
2893
|
if (timer) clearTimeout(timer);
|
|
2843
2894
|
flush2();
|
|
@@ -9469,30 +9520,10 @@ function useCompositionStack({
|
|
|
9469
9520
|
}
|
|
9470
9521
|
|
|
9471
9522
|
// src/telemetry/config.ts
|
|
9472
|
-
var ANON_ID_KEY = "hyperframes-studio:anonymousId";
|
|
9473
9523
|
var OPT_OUT_KEY = "hyperframes-studio:telemetryDisabled";
|
|
9474
9524
|
var NOTICE_KEY = "hyperframes-studio:telemetryNoticeShown";
|
|
9475
|
-
function safeLocalStorage() {
|
|
9476
|
-
try {
|
|
9477
|
-
return typeof localStorage === "undefined" ? null : localStorage;
|
|
9478
|
-
} catch {
|
|
9479
|
-
return null;
|
|
9480
|
-
}
|
|
9481
|
-
}
|
|
9482
|
-
function newAnonymousId() {
|
|
9483
|
-
return generateId();
|
|
9484
|
-
}
|
|
9485
9525
|
function getAnonymousId() {
|
|
9486
|
-
|
|
9487
|
-
if (!ls) return "anonymous";
|
|
9488
|
-
const existing = ls.getItem(ANON_ID_KEY);
|
|
9489
|
-
if (existing) return existing;
|
|
9490
|
-
const id = newAnonymousId();
|
|
9491
|
-
try {
|
|
9492
|
-
ls.setItem(ANON_ID_KEY, id);
|
|
9493
|
-
} catch {
|
|
9494
|
-
}
|
|
9495
|
-
return id;
|
|
9526
|
+
return resolveStudioDistinctId();
|
|
9496
9527
|
}
|
|
9497
9528
|
function isOptedOut() {
|
|
9498
9529
|
return safeLocalStorage()?.getItem(OPT_OUT_KEY) === "1";
|
|
@@ -9507,13 +9538,6 @@ function markNoticeShown() {
|
|
|
9507
9538
|
}
|
|
9508
9539
|
}
|
|
9509
9540
|
var SESSION_FIRED_KEY = "hyperframes-studio:sessionStartFired";
|
|
9510
|
-
function safeSessionStorage() {
|
|
9511
|
-
try {
|
|
9512
|
-
return typeof sessionStorage === "undefined" ? null : sessionStorage;
|
|
9513
|
-
} catch {
|
|
9514
|
-
return null;
|
|
9515
|
-
}
|
|
9516
|
-
}
|
|
9517
9541
|
function hasFiredSessionStart() {
|
|
9518
9542
|
return safeSessionStorage()?.getItem(SESSION_FIRED_KEY) === "1";
|
|
9519
9543
|
}
|
|
@@ -9608,12 +9632,12 @@ function trackEvent(event, properties = {}) {
|
|
|
9608
9632
|
}
|
|
9609
9633
|
function flush() {
|
|
9610
9634
|
if (eventQueue.length === 0) return;
|
|
9611
|
-
const
|
|
9635
|
+
const distinctId = getAnonymousId();
|
|
9612
9636
|
const batch = eventQueue.map((e) => ({
|
|
9613
9637
|
event: e.event,
|
|
9614
9638
|
// $ip: null tells PostHog to not record the request IP.
|
|
9615
9639
|
properties: { ...e.properties, $ip: null },
|
|
9616
|
-
distinct_id:
|
|
9640
|
+
distinct_id: distinctId,
|
|
9617
9641
|
timestamp: e.timestamp
|
|
9618
9642
|
}));
|
|
9619
9643
|
eventQueue = [];
|
|
@@ -22418,32 +22442,59 @@ function runResolverShadow(session, hfId, ops, sourceContent) {
|
|
|
22418
22442
|
const mismatches = sdkResolverShadowCheck(session, hfId, ops, sourceContent);
|
|
22419
22443
|
if (mismatches.length === 0) return;
|
|
22420
22444
|
const isElementNotFound = mismatches.some((m) => m.kind === "element_not_found");
|
|
22445
|
+
const strictCount = isElementNotFound && sourceContent !== void 0 ? countHfIdInSource(sourceContent, hfId) : void 0;
|
|
22421
22446
|
trackStudioEvent("sdk_resolver_shadow", {
|
|
22422
22447
|
hfId,
|
|
22423
22448
|
// sessionElementCount > 0 + element_not_found = runtime-only element;
|
|
22424
22449
|
// sessionElementCount === 0 = session is empty/broken (actionable).
|
|
22425
22450
|
sessionElementCount: session.getElements().length,
|
|
22426
22451
|
// Count of data-hf-id="<id>" occurrences in source for an emitted
|
|
22427
|
-
// element_not_found
|
|
22428
|
-
//
|
|
22429
|
-
//
|
|
22430
|
-
//
|
|
22431
|
-
|
|
22452
|
+
// element_not_found. >1 = duplicate ids → resolver picked the wrong
|
|
22453
|
+
// instance; =1 = single static node the SDK parse dropped (foreign-content
|
|
22454
|
+
// exclusion / sub-comp inlining gap); =0 = the runtime-node filter above
|
|
22455
|
+
// uses a loose substring match (biased toward keeping signal) while this
|
|
22456
|
+
// count uses a strict attribute match — see sourceLooseMatchOnly below.
|
|
22457
|
+
...strictCount !== void 0 ? { sourceHfIdCount: strictCount } : {},
|
|
22458
|
+
// Loose suppression check matched (kept this event) but the strict
|
|
22459
|
+
// attribute count came back 0 — see the sourceHfIdCount comment above.
|
|
22460
|
+
...strictCount === 0 ? { sourceLooseMatchOnly: true } : {},
|
|
22432
22461
|
mismatchCount: mismatches.length,
|
|
22433
22462
|
mismatches: JSON.stringify(redactMismatches(mismatches))
|
|
22434
22463
|
});
|
|
22435
22464
|
} catch {
|
|
22436
22465
|
}
|
|
22437
22466
|
}
|
|
22438
|
-
function recordResolverParity(session, hfId, opLabel) {
|
|
22467
|
+
async function recordResolverParity(session, hfId, opLabel, readSource) {
|
|
22439
22468
|
if (!STUDIO_SDK_RESOLVER_SHADOW_ENABLED) return;
|
|
22440
22469
|
if (!session || !hfId) return;
|
|
22441
22470
|
try {
|
|
22442
22471
|
if (resolveSnapshot(session, hfId)) return;
|
|
22472
|
+
const sessionElementCount = session.getElements().length;
|
|
22473
|
+
let source;
|
|
22474
|
+
if (readSource) {
|
|
22475
|
+
try {
|
|
22476
|
+
source = await readSource();
|
|
22477
|
+
} catch {
|
|
22478
|
+
source = void 0;
|
|
22479
|
+
}
|
|
22480
|
+
}
|
|
22481
|
+
if (source !== void 0 && !source.includes(hfId)) return;
|
|
22482
|
+
const strictCount = source !== void 0 ? countHfIdInSource(source, hfId) : void 0;
|
|
22443
22483
|
trackStudioEvent("sdk_resolver_shadow", {
|
|
22444
22484
|
hfId,
|
|
22445
22485
|
opLabel,
|
|
22446
|
-
sessionElementCount
|
|
22486
|
+
sessionElementCount,
|
|
22487
|
+
// sourceHfIdCount: strict data-hf-id="..." attribute count. Can be 0 even
|
|
22488
|
+
// on an emitted (non-suppressed) event — the suppression check above is a
|
|
22489
|
+
// loose substring match (biased toward keeping signal); see the longer
|
|
22490
|
+
// comment on this field in runResolverShadow for the full explanation.
|
|
22491
|
+
...strictCount !== void 0 ? { sourceHfIdCount: strictCount } : {},
|
|
22492
|
+
// Loose suppression check matched (kept this event) but the strict
|
|
22493
|
+
// attribute count came back 0 — hfId appeared as plain text (class name,
|
|
22494
|
+
// comment, script string) but never as a data-hf-id="..." attribute.
|
|
22495
|
+
// Lets telemetry consumers filter this cohort without parsing the
|
|
22496
|
+
// sourceHfIdCount comment above.
|
|
22497
|
+
...strictCount === 0 ? { sourceLooseMatchOnly: true } : {},
|
|
22447
22498
|
mismatchCount: 1,
|
|
22448
22499
|
mismatches: JSON.stringify([
|
|
22449
22500
|
{ kind: "element_not_found", hfId }
|
|
@@ -22559,7 +22610,7 @@ function isSafeAttributeValue(name, value) {
|
|
|
22559
22610
|
return true;
|
|
22560
22611
|
}
|
|
22561
22612
|
|
|
22562
|
-
// src/utils/
|
|
22613
|
+
// src/utils/sdkCutoverEligibility.ts
|
|
22563
22614
|
var CUTOVER_OP_TYPES = /* @__PURE__ */ new Set([
|
|
22564
22615
|
"inline-style",
|
|
22565
22616
|
"text-content",
|
|
@@ -22619,6 +22670,8 @@ function shouldDeclineTextCutoverForTarget(target, ops) {
|
|
|
22619
22670
|
function shouldUseSdkCutover(flagEnabled, hasSession, hfId, ops) {
|
|
22620
22671
|
return flagEnabled && hasSession && !!hfId && ops.length > 0 && ops.every((o) => CUTOVER_OP_TYPES.has(o.type)) && !ops.some(mapsToReservedAttr) && !hasUnsafeHtmlAttributeOp(ops);
|
|
22621
22672
|
}
|
|
22673
|
+
|
|
22674
|
+
// src/utils/sdkCutover.ts
|
|
22622
22675
|
async function captureOnDiskBefore(deps, targetPath, serializedFallback) {
|
|
22623
22676
|
if (!deps.readProjectFile) return serializedFallback;
|
|
22624
22677
|
try {
|
|
@@ -22674,7 +22727,13 @@ async function sdkCutoverPersist(selection, ops, originalContent, targetPath, sd
|
|
|
22674
22727
|
}
|
|
22675
22728
|
}
|
|
22676
22729
|
async function sdkTimingPersist(hfId, targetPath, timingUpdate, sdkSession, deps, options) {
|
|
22677
|
-
|
|
22730
|
+
const timingSrc = deps.readProjectFile;
|
|
22731
|
+
void recordResolverParity(
|
|
22732
|
+
sdkSession,
|
|
22733
|
+
hfId,
|
|
22734
|
+
"setTiming",
|
|
22735
|
+
timingSrc ? () => timingSrc(targetPath) : void 0
|
|
22736
|
+
);
|
|
22678
22737
|
if (!STUDIO_SDK_CUTOVER_ENABLED) return false;
|
|
22679
22738
|
if (!sdkSession || !sdkSession.getElement(hfId)) return false;
|
|
22680
22739
|
if (wrongCompositionFile(deps, targetPath)) return false;
|
|
@@ -22693,13 +22752,21 @@ async function sdkTimingPersist(hfId, targetPath, timingUpdate, sdkSession, deps
|
|
|
22693
22752
|
}
|
|
22694
22753
|
}
|
|
22695
22754
|
function sdkGsapTweenPersist(targetPath, op, sdkSession, deps, options) {
|
|
22696
|
-
if (op.kind === "add")
|
|
22697
|
-
|
|
22755
|
+
if (op.kind === "add") {
|
|
22756
|
+
const gsapSrc = deps.readProjectFile;
|
|
22757
|
+
void recordResolverParity(
|
|
22758
|
+
sdkSession,
|
|
22759
|
+
op.target,
|
|
22760
|
+
"addGsapTween",
|
|
22761
|
+
gsapSrc ? () => gsapSrc(targetPath) : void 0
|
|
22762
|
+
);
|
|
22763
|
+
} else {
|
|
22698
22764
|
recordAnimationResolverParity(
|
|
22699
22765
|
sdkSession,
|
|
22700
22766
|
op.animationId,
|
|
22701
22767
|
op.kind === "set" ? "setGsapTween" : "removeGsapTween"
|
|
22702
22768
|
);
|
|
22769
|
+
}
|
|
22703
22770
|
if (!STUDIO_SDK_CUTOVER_ENABLED) return Promise.resolve(false);
|
|
22704
22771
|
if (op.kind === "add" && sdkSession && !sdkSession.getElement(op.target))
|
|
22705
22772
|
return Promise.resolve(false);
|
|
@@ -22840,7 +22907,12 @@ function sdkReplaceWithKeyframesPersist(targetPath, animationId, targetSelector,
|
|
|
22840
22907
|
);
|
|
22841
22908
|
}
|
|
22842
22909
|
async function sdkDeletePersist(hfId, originalContent, targetPath, sdkSession, deps) {
|
|
22843
|
-
recordResolverParity(
|
|
22910
|
+
void recordResolverParity(
|
|
22911
|
+
sdkSession,
|
|
22912
|
+
hfId,
|
|
22913
|
+
"removeElement",
|
|
22914
|
+
() => Promise.resolve(originalContent)
|
|
22915
|
+
);
|
|
22844
22916
|
if (!STUDIO_SDK_CUTOVER_ENABLED) return false;
|
|
22845
22917
|
if (!sdkSession || !sdkSession.getElement(hfId)) return false;
|
|
22846
22918
|
if (wrongCompositionFile(deps, targetPath)) return false;
|
|
@@ -29769,7 +29841,7 @@ function useDomEditSession({
|
|
|
29769
29841
|
showToast,
|
|
29770
29842
|
refreshPreviewDocumentVersion,
|
|
29771
29843
|
queueDomEditSave,
|
|
29772
|
-
readProjectFile
|
|
29844
|
+
readProjectFile,
|
|
29773
29845
|
writeProjectFile,
|
|
29774
29846
|
updateEditingFileContent,
|
|
29775
29847
|
domEditSaveTimestampRef,
|
|
@@ -29793,7 +29865,6 @@ function useDomEditSession({
|
|
|
29793
29865
|
forceReloadSdkSession
|
|
29794
29866
|
}) {
|
|
29795
29867
|
void _setRefreshKey;
|
|
29796
|
-
void _readProjectFile;
|
|
29797
29868
|
const {
|
|
29798
29869
|
domEditSelection,
|
|
29799
29870
|
domEditGroupSelections,
|
|
@@ -29952,7 +30023,10 @@ function useDomEditSession({
|
|
|
29952
30023
|
// SDK persist), but the tripwire is decoupled from cutover — record whether
|
|
29953
30024
|
// the SDK resolves each reordered element (the reorderElements op's targets).
|
|
29954
30025
|
onReorderShadow: sdkSession ? (targets) => {
|
|
29955
|
-
|
|
30026
|
+
let reorderSrcPromise;
|
|
30027
|
+
const reorderSrc = activeCompPath ? () => reorderSrcPromise ??= readProjectFile(activeCompPath) : void 0;
|
|
30028
|
+
for (const target of targets)
|
|
30029
|
+
void recordResolverParity(sdkSession, target, "reorderElements", reorderSrc);
|
|
29956
30030
|
} : void 0
|
|
29957
30031
|
});
|
|
29958
30032
|
const { groupSelection, ungroupSelection } = useGroupCommits({
|
|
@@ -42664,9 +42738,9 @@ function makeSlideshowNotesController() {
|
|
|
42664
42738
|
});
|
|
42665
42739
|
};
|
|
42666
42740
|
return {
|
|
42667
|
-
schedule(manifest,
|
|
42741
|
+
schedule(manifest, persist2, delayMs) {
|
|
42668
42742
|
if (timer !== null) clearTimeout(timer);
|
|
42669
|
-
pending = { manifest, persist };
|
|
42743
|
+
pending = { manifest, persist: persist2 };
|
|
42670
42744
|
timer = setTimeout(() => {
|
|
42671
42745
|
timer = null;
|
|
42672
42746
|
drainPending();
|