hyperframes 0.7.22 → 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.
@@ -1,4 +1,4 @@
1
- import{n as Qi}from"./index-B4h4u7eW.js";/*!
1
+ import{n as Qi}from"./index-B8XMgbWF.js";/*!
2
2
  * Copyright (c) 2026-present, Vanilagy and contributors
3
3
  *
4
4
  * This Source Code Form is subject to the terms of the Mozilla Public
@@ -1 +1 @@
1
- import{g as P}from"./index-B4h4u7eW.js";function j(c,d){for(var s=0;s<d.length;s++){const a=d[s];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in c)){const l=Object.getOwnPropertyDescriptor(a,i);l&&Object.defineProperty(c,i,l.get?l:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}))}var v={},w;function k(){if(w)return v;w=1,Object.defineProperty(v,"__esModule",{value:!0}),v.default=d;var c=window.OfflineAudioContext||window.webkitOfflineAudioContext;function d(e){var r=a(e);return r.start(0),[i,y,O(e.sampleRate),s].reduce(function(t,o){return o(t)},r.buffer.getChannelData(0))}function s(e){return e.sort(function(r,t){return t.count-r.count}).splice(0,5)[0].tempo}function a(e){var r=e.length,t=e.numberOfChannels,o=e.sampleRate,n=new c(t,r,o),u=n.createBufferSource();u.buffer=e;var f=n.createBiquadFilter();return f.type="lowpass",u.connect(f),f.connect(n.destination),u}function i(e){for(var r=[],t=.9,o=.3,n=15;r.length<n&&t>=o;)r=l(e,t),t-=.05;if(r.length<n)throw new Error("Could not find enough samples for a reliable detection.");return r}function l(e,r){for(var t=[],o=0,n=e.length;o<n;o+=1)e[o]>r&&(t.push(o),o+=1e4);return t}function y(e){var r=[];return e.forEach(function(t,o){for(var n=function(x){var g=e[o+x]-t,_=r.some(function(h){if(h.interval===g)return h.count+=1});_||r.push({interval:g,count:1})},u=0;u<10;u+=1)n(u)}),r}function O(e){return function(r){var t=[];return r.forEach(function(o){if(o.interval!==0){for(var n=60/(o.interval/e);n<90;)n*=2;for(;n>180;)n/=2;n=Math.round(n);var u=t.some(function(f){if(f.tempo===n)return f.count+=o.count});u||t.push({tempo:n,count:o.count})}}),t}}return v}var p,b;function q(){return b||(b=1,p=k().default),p}var m=q();const A=P(m),D=j({__proto__:null,default:A},[m]);export{D as i};
1
+ import{g as P}from"./index-B8XMgbWF.js";function j(c,d){for(var s=0;s<d.length;s++){const a=d[s];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in c)){const l=Object.getOwnPropertyDescriptor(a,i);l&&Object.defineProperty(c,i,l.get?l:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}))}var v={},w;function k(){if(w)return v;w=1,Object.defineProperty(v,"__esModule",{value:!0}),v.default=d;var c=window.OfflineAudioContext||window.webkitOfflineAudioContext;function d(e){var r=a(e);return r.start(0),[i,y,O(e.sampleRate),s].reduce(function(t,o){return o(t)},r.buffer.getChannelData(0))}function s(e){return e.sort(function(r,t){return t.count-r.count}).splice(0,5)[0].tempo}function a(e){var r=e.length,t=e.numberOfChannels,o=e.sampleRate,n=new c(t,r,o),u=n.createBufferSource();u.buffer=e;var f=n.createBiquadFilter();return f.type="lowpass",u.connect(f),f.connect(n.destination),u}function i(e){for(var r=[],t=.9,o=.3,n=15;r.length<n&&t>=o;)r=l(e,t),t-=.05;if(r.length<n)throw new Error("Could not find enough samples for a reliable detection.");return r}function l(e,r){for(var t=[],o=0,n=e.length;o<n;o+=1)e[o]>r&&(t.push(o),o+=1e4);return t}function y(e){var r=[];return e.forEach(function(t,o){for(var n=function(x){var g=e[o+x]-t,_=r.some(function(h){if(h.interval===g)return h.count+=1});_||r.push({interval:g,count:1})},u=0;u<10;u+=1)n(u)}),r}function O(e){return function(r){var t=[];return r.forEach(function(o){if(o.interval!==0){for(var n=60/(o.interval/e);n<90;)n*=2;for(;n>180;)n/=2;n=Math.round(n);var u=t.some(function(f){if(f.tempo===n)return f.count+=o.count});u||t.push({tempo:n,count:o.count})}}),t}}return v}var p,b;function q(){return b||(b=1,p=k().default),p}var m=q();const A=P(m),D=j({__proto__:null,default:A},[m]);export{D as i};
@@ -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-B4h4u7eW.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-B8XMgbWF.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-DmkOvZns.css">
10
10
  </head>
11
11
  <body>
@@ -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
- if (distinctId) return distinctId;
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 persist = () => {
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(persist);
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
- const ls = safeLocalStorage();
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 distinctId2 = getAnonymousId();
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: distinctId2,
9640
+ distinct_id: distinctId,
9617
9641
  timestamp: e.timestamp
9618
9642
  }));
9619
9643
  eventQueue = [];
@@ -22424,10 +22448,14 @@ function runResolverShadow(session, hfId, ops, sourceContent) {
22424
22448
  // sessionElementCount === 0 = session is empty/broken (actionable).
22425
22449
  sessionElementCount: session.getElements().length,
22426
22450
  // Count of data-hf-id="<id>" occurrences in source for an emitted
22427
- // element_not_found (the runtime-node filter already dropped absent-from-
22428
- // source ids, so an emitted one is in source ≥1×). >1 = duplicate ids →
22429
- // resolver picked the wrong instance; =1 = single static node the SDK
22430
- // parse dropped (foreign-content exclusion / sub-comp inlining gap).
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.
22431
22459
  ...isElementNotFound && sourceContent !== void 0 ? { sourceHfIdCount: countHfIdInSource(sourceContent, hfId) } : {},
22432
22460
  mismatchCount: mismatches.length,
22433
22461
  mismatches: JSON.stringify(redactMismatches(mismatches))
@@ -22435,15 +22463,30 @@ function runResolverShadow(session, hfId, ops, sourceContent) {
22435
22463
  } catch {
22436
22464
  }
22437
22465
  }
22438
- function recordResolverParity(session, hfId, opLabel) {
22466
+ async function recordResolverParity(session, hfId, opLabel, readSource) {
22439
22467
  if (!STUDIO_SDK_RESOLVER_SHADOW_ENABLED) return;
22440
22468
  if (!session || !hfId) return;
22441
22469
  try {
22442
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;
22443
22481
  trackStudioEvent("sdk_resolver_shadow", {
22444
22482
  hfId,
22445
22483
  opLabel,
22446
- sessionElementCount: session.getElements().length,
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) } : {},
22447
22490
  mismatchCount: 1,
22448
22491
  mismatches: JSON.stringify([
22449
22492
  { kind: "element_not_found", hfId }
@@ -22559,7 +22602,7 @@ function isSafeAttributeValue(name, value) {
22559
22602
  return true;
22560
22603
  }
22561
22604
 
22562
- // src/utils/sdkCutover.ts
22605
+ // src/utils/sdkCutoverEligibility.ts
22563
22606
  var CUTOVER_OP_TYPES = /* @__PURE__ */ new Set([
22564
22607
  "inline-style",
22565
22608
  "text-content",
@@ -22619,6 +22662,8 @@ function shouldDeclineTextCutoverForTarget(target, ops) {
22619
22662
  function shouldUseSdkCutover(flagEnabled, hasSession, hfId, ops) {
22620
22663
  return flagEnabled && hasSession && !!hfId && ops.length > 0 && ops.every((o) => CUTOVER_OP_TYPES.has(o.type)) && !ops.some(mapsToReservedAttr) && !hasUnsafeHtmlAttributeOp(ops);
22621
22664
  }
22665
+
22666
+ // src/utils/sdkCutover.ts
22622
22667
  async function captureOnDiskBefore(deps, targetPath, serializedFallback) {
22623
22668
  if (!deps.readProjectFile) return serializedFallback;
22624
22669
  try {
@@ -22674,7 +22719,13 @@ async function sdkCutoverPersist(selection, ops, originalContent, targetPath, sd
22674
22719
  }
22675
22720
  }
22676
22721
  async function sdkTimingPersist(hfId, targetPath, timingUpdate, sdkSession, deps, options) {
22677
- recordResolverParity(sdkSession, hfId, "setTiming");
22722
+ const timingSrc = deps.readProjectFile;
22723
+ void recordResolverParity(
22724
+ sdkSession,
22725
+ hfId,
22726
+ "setTiming",
22727
+ timingSrc ? () => timingSrc(targetPath) : void 0
22728
+ );
22678
22729
  if (!STUDIO_SDK_CUTOVER_ENABLED) return false;
22679
22730
  if (!sdkSession || !sdkSession.getElement(hfId)) return false;
22680
22731
  if (wrongCompositionFile(deps, targetPath)) return false;
@@ -22693,8 +22744,15 @@ async function sdkTimingPersist(hfId, targetPath, timingUpdate, sdkSession, deps
22693
22744
  }
22694
22745
  }
22695
22746
  function sdkGsapTweenPersist(targetPath, op, sdkSession, deps, options) {
22696
- if (op.kind === "add") recordResolverParity(sdkSession, op.target, "addGsapTween");
22697
- else
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
22698
22756
  recordAnimationResolverParity(
22699
22757
  sdkSession,
22700
22758
  op.animationId,
@@ -22840,7 +22898,12 @@ function sdkReplaceWithKeyframesPersist(targetPath, animationId, targetSelector,
22840
22898
  );
22841
22899
  }
22842
22900
  async function sdkDeletePersist(hfId, originalContent, targetPath, sdkSession, deps) {
22843
- recordResolverParity(sdkSession, hfId, "removeElement");
22901
+ void recordResolverParity(
22902
+ sdkSession,
22903
+ hfId,
22904
+ "removeElement",
22905
+ () => Promise.resolve(originalContent)
22906
+ );
22844
22907
  if (!STUDIO_SDK_CUTOVER_ENABLED) return false;
22845
22908
  if (!sdkSession || !sdkSession.getElement(hfId)) return false;
22846
22909
  if (wrongCompositionFile(deps, targetPath)) return false;
@@ -29769,7 +29832,7 @@ function useDomEditSession({
29769
29832
  showToast,
29770
29833
  refreshPreviewDocumentVersion,
29771
29834
  queueDomEditSave,
29772
- readProjectFile: _readProjectFile,
29835
+ readProjectFile,
29773
29836
  writeProjectFile,
29774
29837
  updateEditingFileContent,
29775
29838
  domEditSaveTimestampRef,
@@ -29793,7 +29856,6 @@ function useDomEditSession({
29793
29856
  forceReloadSdkSession
29794
29857
  }) {
29795
29858
  void _setRefreshKey;
29796
- void _readProjectFile;
29797
29859
  const {
29798
29860
  domEditSelection,
29799
29861
  domEditGroupSelections,
@@ -29952,7 +30014,9 @@ function useDomEditSession({
29952
30014
  // SDK persist), but the tripwire is decoupled from cutover — record whether
29953
30015
  // the SDK resolves each reordered element (the reorderElements op's targets).
29954
30016
  onReorderShadow: sdkSession ? (targets) => {
29955
- for (const target of targets) recordResolverParity(sdkSession, target, "reorderElements");
30017
+ const reorderSrc = activeCompPath ? () => readProjectFile(activeCompPath) : void 0;
30018
+ for (const target of targets)
30019
+ void recordResolverParity(sdkSession, target, "reorderElements", reorderSrc);
29956
30020
  } : void 0
29957
30021
  });
29958
30022
  const { groupSelection, ungroupSelection } = useGroupCommits({
@@ -42664,9 +42728,9 @@ function makeSlideshowNotesController() {
42664
42728
  });
42665
42729
  };
42666
42730
  return {
42667
- schedule(manifest, persist, delayMs) {
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();