@volter/editor-game 0.5.65 → 0.5.67

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.
Files changed (281) hide show
  1. package/contributions/audio-unlock.service.ts +2 -2
  2. package/contributions/autoplay.service.ts +1 -1
  3. package/contributions/bridge.command.ts +3 -3
  4. package/contributions/canvas/component-board.service.ts +16 -0
  5. package/contributions/canvas/design-time-mount.service.ts +45 -0
  6. package/contributions/canvas-story-capture.service.ts +12 -0
  7. package/contributions/edit-mode-audio.service.ts +2 -2
  8. package/contributions/edit-mode-networking.service.ts +1 -1
  9. package/contributions/gameplay.command.ts +4 -4
  10. package/contributions/generation.service.ts +3 -3
  11. package/contributions/generations.status.tsx +1 -1
  12. package/contributions/godot.palette.json +99 -0
  13. package/contributions/godot.style.ts +82 -0
  14. package/contributions/godot.view.ts +75 -0
  15. package/contributions/ingest.service.ts +4 -4
  16. package/contributions/instances.command.ts +1 -1
  17. package/contributions/navmesh.menu.ts +1 -1
  18. package/contributions/network-observer.service.ts +14 -0
  19. package/contributions/play.command.ts +11 -5
  20. package/contributions/react/component-board.service.ts +1 -1
  21. package/contributions/react/design-time-mount.service.ts +1 -1
  22. package/contributions/react/react-inspector.service.ts +2 -2
  23. package/contributions/scene-document.service.ts +5 -5
  24. package/contributions/state-watch.menu.ts +1 -1
  25. package/contributions/state-watch.utility.tsx +1 -1
  26. package/contributions/team-playtest.service.ts +4 -4
  27. package/contributions/three/component-board.service.ts +1 -1
  28. package/contributions/three/component-verbs.command.ts +8 -8
  29. package/contributions/three/three-authoring.service.ts +8 -5
  30. package/contributions/three-story-capture.service.ts +12 -0
  31. package/contributions/unity.palette.json +102 -0
  32. package/contributions/unity.style.ts +72 -0
  33. package/contributions/unity.view.ts +82 -0
  34. package/contributions/unreal.palette.json +105 -0
  35. package/contributions/unreal.style.ts +66 -0
  36. package/contributions/unreal.view.ts +93 -0
  37. package/dist-node/serving.mjs +16 -0
  38. package/package.json +33 -16
  39. package/serving/index.ts +27 -0
  40. package/src/asset-budget/AssetBudgetPanel.tsx +1 -1
  41. package/src/asset-budget/asset-budget-model.ts +4 -4
  42. package/src/asset-budget/optimize-apply.ts +7 -7
  43. package/src/audio/AudioDebuggerPanel.tsx +1 -1
  44. package/src/bridge/dispatch.ts +16 -16
  45. package/src/bridge/live-frames.ts +1 -1
  46. package/src/bridge/screenshot.ts +6 -6
  47. package/src/build/BuildProfilesPanel.tsx +3 -3
  48. package/src/canvas/canvas-board/CanvasBoardDocument.tsx +676 -0
  49. package/src/canvas/canvas-board/canvas-board-model.ts +407 -0
  50. package/src/canvas/canvas-board/canvas-component-board.ts +56 -0
  51. package/src/canvas/canvas-design-mount.ts +524 -0
  52. package/src/canvas/design-time-canvas-mount.ts +79 -0
  53. package/src/coverage/live-authoring-surface.ts +6 -6
  54. package/src/coverage/live-project-verbs.ts +2 -2
  55. package/src/coverage/native-system-coverage.ts +6 -6
  56. package/src/coverage/root-coverage.ts +1 -1
  57. package/src/coverage/session-coverage.ts +5 -5
  58. package/src/design-system-stories/ApplicationChrome.stories.tsx +5 -5
  59. package/src/design-system-stories/InspectorNarrowBodies.stories.tsx +13 -53
  60. package/src/edit-mode/edit-mode-audio.ts +4 -4
  61. package/src/edit-mode/edit-mode-networking.ts +2 -2
  62. package/src/game-document/GameCaptureFrameButton.tsx +2 -2
  63. package/src/game-document/GameDocument.tsx +2 -2
  64. package/src/game-document/GamePanel.tsx +8 -8
  65. package/src/game-document/InstanceInspectorPicker.tsx +2 -2
  66. package/src/game-document/crowd-debug.ts +1 -1
  67. package/src/game-document/device-preview.ts +10 -11
  68. package/src/game-document/physics-debug.ts +1 -1
  69. package/src/generation/GenerationActivity.tsx +6 -8
  70. package/src/generation/generation-documents.tsx +8 -8
  71. package/src/generation/generation-jobs.ts +2 -2
  72. package/src/generation/generation-presentation.ts +1 -1
  73. package/src/host/adapter-reach.ts +1 -1
  74. package/src/host/adapter-runtime-bindings.ts +97 -6
  75. package/src/host/api/configurations.ts +2 -2
  76. package/src/host/authoring/babylon-authoring-adapter.ts +8 -8
  77. package/src/host/authoring/contract-hierarchy-authoring.ts +1 -1
  78. package/src/host/authoring/contract-scenes-stories.ts +1 -1
  79. package/src/host/authoring/creation-site-related.ts +2 -2
  80. package/src/host/authoring/ephemeral-persistence.ts +1 -1
  81. package/src/host/authoring/gesture-persist.ts +2 -2
  82. package/src/host/authoring/ingest-data-writer.ts +1 -1
  83. package/src/host/authoring/ingest-source-persistence.ts +8 -8
  84. package/src/host/authoring/mount-isolated-pixi-screen.ts +1 -1
  85. package/src/host/authoring/mounted-authoring.ts +4 -4
  86. package/src/host/authoring/phaser-live-authoring-adapter.ts +4 -4
  87. package/src/host/authoring/pixi-authoring-adapter.ts +42 -17
  88. package/src/host/authoring/pixi-creation-site-write-target.ts +2 -2
  89. package/src/host/authoring/pixi-live-write-target.ts +7 -7
  90. package/src/host/authoring/pixi-source-identity.ts +3 -3
  91. package/src/host/authoring/pixi-source-write-target.ts +1614 -0
  92. package/src/host/authoring/pixi-still-presentation.ts +2 -2
  93. package/src/host/authoring/pixi-structure-history.ts +3 -3
  94. package/src/host/authoring/pixi-transform-channels.ts +16 -14
  95. package/src/host/authoring/source-persistence-backend.ts +6 -6
  96. package/src/host/authoring/struct-write-pipe.ts +3 -3
  97. package/src/host/binding-resolver.ts +8 -9
  98. package/src/host/browser-transpile.ts +2 -2
  99. package/src/host/canvas-entry-runtime.ts +59 -48
  100. package/src/host/canvas-preview-frames.ts +482 -0
  101. package/src/host/components/CameraAuthoringOverlay.tsx +1 -1
  102. package/src/host/components/HeaderTelemetry.tsx +9 -16
  103. package/src/host/components/PixiIsolationSceneContent.tsx +17 -16
  104. package/src/host/components/ThreeIsolationSceneContent.tsx +5 -5
  105. package/src/host/components/frame-debugger-model.ts +2 -2
  106. package/src/host/components/header-telemetry-model.ts +2 -2
  107. package/src/host/components/scene-document.tsx +29 -61
  108. package/src/host/components/utility-view-state.ts +1 -1
  109. package/src/host/components/world-root-stage-binding.tsx +17 -26
  110. package/src/host/components/world-root-stage.ts +130 -63
  111. package/src/host/coverage/capability-coverage.ts +13 -1
  112. package/src/host/coverage/game-contract-seam-evidence.ts +1 -1
  113. package/src/host/coverage/project-verb-coverage.ts +2 -17
  114. package/src/host/coverage/system-adapter-coverage.ts +4 -5
  115. package/src/host/design-system-stories/fixtures/editor-runtime.tsx +14 -8
  116. package/src/host/document-preview-three.ts +2 -2
  117. package/src/host/entry-adjudication.ts +6 -6
  118. package/src/host/game-css-scope-transform.ts +4 -0
  119. package/src/host/game-module-access.ts +1 -1
  120. package/src/host/game-realm-page.ts +16 -8
  121. package/src/host/game-realm-reclaim.ts +1 -1
  122. package/src/host/gameplay-export.ts +25 -14
  123. package/src/host/gameplay-recording.ts +5 -5
  124. package/src/host/gated-globals.ts +6 -6
  125. package/src/host/history/json-history-resource.ts +3 -3
  126. package/src/host/instance-extract-actions.ts +1 -1
  127. package/src/host/instance-fork-actions.ts +1 -1
  128. package/src/host/projection/dom.ts +2 -2
  129. package/src/host/projection/pixi.ts +25 -3
  130. package/src/host/r3f-entry-runtime.ts +65 -34
  131. package/src/host/react-mount-runtime.ts +8 -49
  132. package/src/host/realm-services.ts +2 -2
  133. package/src/host/roots/canvas-root.tsx +361 -0
  134. package/src/host/roots/module-root.ts +1 -1
  135. package/src/host/roots/r3f-root.tsx +473 -0
  136. package/src/host/roots/react-root.ts +9 -43
  137. package/src/host/scene-view-drawability.ts +2 -2
  138. package/src/host/served-bundle-runtime-modules.ts +1 -19
  139. package/src/host/server-log-bridge.ts +3 -3
  140. package/src/host/stories/mounted-story-viewport-source.ts +1 -1
  141. package/src/host/stories/pixi-story-model.ts +30 -0
  142. package/src/host/stories/story-media-captures.ts +46 -0
  143. package/src/host/stories/story-media-presence.ts +3 -3
  144. package/src/host/stories/story-pixi-preview.ts +408 -0
  145. package/src/host/stories/story-three-preview.ts +806 -0
  146. package/src/host/stories/three-story-captures.ts +35 -0
  147. package/src/host/story-three-preview-runtime.ts +56 -0
  148. package/src/host/three-ingest-runtime.ts +1 -1
  149. package/src/host/use-active-performance-source.ts +3 -3
  150. package/src/host/viewport-pose-memory.ts +1 -1
  151. package/src/host/viewport-root-presentation.ts +6 -5
  152. package/src/ingest/active-ingest.ts +2 -2
  153. package/src/ingest/authoring/ingest-dom-surface-authoring.ts +4 -4
  154. package/src/ingest/authoring/ingest-root-adapter.ts +13 -13
  155. package/src/ingest/capture-wait-report.ts +1 -1
  156. package/src/ingest/deferred-ingest-play.ts +11 -10
  157. package/src/ingest/discovery-public-ingest.ts +2 -2
  158. package/src/ingest/ingest-boot-viewport.ts +6 -8
  159. package/src/ingest/ingest-canvas-scene-document.tsx +17 -16
  160. package/src/ingest/ingest-canvas-scene.ts +5 -8
  161. package/src/ingest/ingest-evidence-hook.ts +1 -1
  162. package/src/ingest/ingest-frame-snapshot.ts +1 -1
  163. package/src/ingest/ingest-play-control.ts +4 -4
  164. package/src/ingest/ingest-render-debug.ts +11 -11
  165. package/src/ingest/ingest-siblings.ts +16 -28
  166. package/src/ingest/module-mode.ts +18 -19
  167. package/src/ingest/mount-canvas-ingest-root.ts +27 -27
  168. package/src/ingest/mount-coverage.ts +4 -4
  169. package/src/ingest/mount-dom-ingest-root.ts +16 -16
  170. package/src/ingest/mount-ingest-root.ts +14 -14
  171. package/src/ingest/mount-three-ingest-root.ts +12 -12
  172. package/src/ingest/resolve-canvas.ts +1 -1
  173. package/src/ingest/served-html-boot.ts +1 -1
  174. package/src/ingest/surface-canvas.ts +1 -1
  175. package/src/ingest/unmount-ingest-root.ts +7 -7
  176. package/src/navmesh/navmesh-handler.ts +24 -16
  177. package/src/network/NetworkInspectorPanel.tsx +449 -14
  178. package/src/network/network-inspector-model.ts +14 -2
  179. package/src/play/play-log-events.ts +1 -1
  180. package/src/play/play-mode.ts +99 -142
  181. package/src/play/play-recording.ts +2 -2
  182. package/src/play/react-play-live-authoring.ts +3 -3
  183. package/src/play/run-selection.ts +93 -0
  184. package/src/play-bar/PlayBar.tsx +20 -39
  185. package/src/profiler/FrameDebuggerPanel.tsx +1 -1
  186. package/src/profiler/PerformancePanel.tsx +4 -4
  187. package/src/react/design-time-react-mount.ts +37 -85
  188. package/src/react/dom-authoring-adapter.ts +11 -11
  189. package/src/react/react-inspector-section.tsx +13 -13
  190. package/src/react/react-world-authoring-adapter.ts +31 -143
  191. package/src/react/story-documents/story-documents.tsx +18 -22
  192. package/src/react/ui-board-document.tsx +10 -11
  193. package/src/react/ui-component-board.ts +5 -5
  194. package/src/runtime/adapter/audio-meter.ts +21 -0
  195. package/src/runtime/adapter/first-party-audio-system.ts +230 -0
  196. package/src/runtime/adapter/ingest/contract-debug-adapter.ts +114 -0
  197. package/src/runtime/adapter/ingest/contract-system-adapters.ts +256 -0
  198. package/src/runtime/adapter/ingest/merge-debug-adapters.ts +197 -0
  199. package/src/runtime/adapter/ingest/observation-debug-adapter.ts +162 -0
  200. package/src/runtime/adapter/ingest/upstream-pin.ts +51 -0
  201. package/src/runtime/adapter/native-debug-module.ts +498 -0
  202. package/src/runtime/audio/bus-mixer.ts +161 -0
  203. package/src/runtime/audio/pose-guard.ts +80 -0
  204. package/src/runtime/core/frame-pacing.ts +126 -0
  205. package/src/runtime/core/game-loop.ts +225 -0
  206. package/src/runtime/core/game-scoped-slot.ts +28 -0
  207. package/src/runtime/core/seeded-random.ts +162 -0
  208. package/src/runtime/core/sim-clock.ts +391 -0
  209. package/src/runtime/core/system-runner.ts +269 -0
  210. package/src/runtime/core/types.ts +104 -0
  211. package/src/runtime/create-runtime.ts +1128 -0
  212. package/src/runtime/debug-bridge.ts +570 -0
  213. package/src/runtime/debug-registry.ts +899 -0
  214. package/src/runtime/dev/chrome-trace.ts +153 -0
  215. package/src/runtime/dev/instruments.ts +403 -0
  216. package/src/runtime/dev/logger.ts +119 -0
  217. package/src/runtime/dev/performance-profiler.ts +367 -0
  218. package/src/runtime/dev/register-render-vitals.ts +276 -0
  219. package/src/runtime/dev/render-census.ts +354 -0
  220. package/src/runtime/dev/render-debug-adapter.ts +218 -0
  221. package/src/runtime/dev/render-memory.ts +226 -0
  222. package/src/runtime/dev/render-vitals.ts +338 -0
  223. package/src/runtime/dev/static-batch-advisor.ts +188 -0
  224. package/src/runtime/dev/webgl-frame-capture.ts +366 -0
  225. package/src/runtime/dev/webgl-gpu-timer.ts +53 -0
  226. package/src/runtime/dev-build.ts +47 -0
  227. package/src/runtime/game.ts +1636 -0
  228. package/src/runtime/gameplay-rng-trap.ts +135 -0
  229. package/src/runtime/host-context.ts +64 -0
  230. package/src/runtime/input-router.ts +169 -0
  231. package/src/runtime/mount-manifest.ts +480 -0
  232. package/src/runtime/pixi/authoring.ts +706 -0
  233. package/src/runtime/pixi/ingest.ts +116 -0
  234. package/src/runtime/pixi/physics-registry.ts +49 -0
  235. package/src/runtime/pixi/render-pass-bracket.ts +117 -0
  236. package/src/runtime/pixi/scene-capture.ts +179 -0
  237. package/src/runtime/pixi/system-adapters.ts +69 -0
  238. package/src/runtime/playtest.ts +22 -0
  239. package/src/runtime/presentation.ts +141 -0
  240. package/src/runtime/render-control.ts +642 -0
  241. package/src/runtime/render-seed.ts +77 -0
  242. package/src/runtime/run-ticks-settled.ts +73 -0
  243. package/src/runtime/setup/setup-audio.ts +72 -0
  244. package/src/services/audio-pose-guard.ts +2 -2
  245. package/src/services/game-audio.ts +152 -0
  246. package/src/services/game-network.ts +657 -0
  247. package/src/services/game-physics.ts +334 -0
  248. package/src/state-watch/StateWatchPanel.tsx +1 -1
  249. package/src/three/authoring/camera-runtime-inspector-section.tsx +4 -3
  250. package/src/three/authoring/constraint-inspector-section.tsx +8 -7
  251. package/src/three/authoring/model-asset-inspector-section.tsx +14 -17
  252. package/src/three/authoring/oid-source-persistence.ts +13 -13
  253. package/src/three/authoring/r3f-design-session.ts +79 -61
  254. package/src/three/authoring/r3f-source-authoring-adapter.ts +112 -108
  255. package/src/three/authoring/reflection-probe-inspector-section.tsx +5 -4
  256. package/src/three/authoring/spatial-joint-handles.ts +1 -1
  257. package/src/three/authoring/spatial-lod-handles.ts +1 -1
  258. package/src/three/authoring/spatial-particle-handles.ts +1 -1
  259. package/src/three/authoring/three-authoring-adapter.ts +33 -33
  260. package/src/three/component-verbs/extract-menu.ts +8 -7
  261. package/src/three/component-verbs/fork-menu.ts +8 -7
  262. package/src/three/component-verbs/internals-menu.ts +3 -3
  263. package/src/three/drei-asset-caches.ts +13 -0
  264. package/src/three/story-documents/three-story-documents.tsx +24 -34
  265. package/src/three/three-board/ThreeBoardDocument.tsx +25 -25
  266. package/src/three/three-board/board-scene.ts +7 -7
  267. package/src/three/three-board/three-component-board.ts +5 -5
  268. package/contributions/react/pasteboard.action.ts +0 -41
  269. package/contributions/xstate-behavior.action.ts +0 -42
  270. package/contributions/xstate-behavior.document.tsx +0 -73
  271. package/contributions/xstate-behavior.inspector.tsx +0 -28
  272. package/contributions/xstate-behavior.menu.ts +0 -23
  273. package/src/react/pasteboard-materialize.ts +0 -154
  274. package/src/services/game-audio-unlock.ts +0 -48
  275. package/src/xstate/XStateBehaviorSection.tsx +0 -130
  276. package/src/xstate/XStateMachineInspector.tsx +0 -566
  277. package/src/xstate/character-animation-machine.fixture.ts +0 -74
  278. package/src/xstate/live-behaviors.ts +0 -106
  279. package/src/xstate/use-live-actor-state.ts +0 -44
  280. package/src/xstate/xstate-graph.ts +0 -235
  281. package/src/xstate/xstate-layout.ts +0 -76
@@ -6,7 +6,7 @@
6
6
  * entities ARE the `data-oid`-stamped elements of its rendered DOM (the OID
7
7
  * instrumentation from the UI visual-edit program, `../ui-source/oid-transform.ts`,
8
8
  * whose vite-plugin include this slice widens from the `editable-components` fixture
9
- * dir to project scope — see `../../vite-plugin-ui-oid.ts`). This adapter derives
9
+ * dir to project scope — see `@volter/editor-react`'s `serving/ui-oid-plugin.ts`). This adapter derives
10
10
  * its hierarchy from the shared DOM projector (`../projection/dom.ts`) under the
11
11
  * OID identity, over the world's live DOM root (`RootInstance.reactRoot()`);
12
12
  * there is no cached/mirrored state to fall out of sync — every `hierarchy`
@@ -15,7 +15,7 @@
15
15
  * Writes (style/className/delete) reuse the EXISTING T3.2-slice-3 source-write seam
16
16
  * verbatim (`../ui-source/source-write-backend.ts`'s `SourceWriteBackend`, the same
17
17
  * `/__ui-source/write` + `/__ui-source/struct` dev-server endpoints
18
- * `vite-plugin-ui-oid.ts` serves for `UIAuthoringAdapter`/`SourceEditPanel`) — this
18
+ * `@volter/editor-react`'s `serving/ui-oid-plugin.ts` serves for `UIAuthoringAdapter`/`SourceEditPanel`) — this
19
19
  * file does NOT invent a second source-writer. Every edit prepares complete next-file
20
20
  * text and commits it through one checksum-guarded source history resource. Style,
21
21
  * text, prop, and structural changes therefore share exact-byte undo/redo semantics.
@@ -27,32 +27,32 @@
27
27
  * unavailable via a loud console warning instead of silently no-op'ing).
28
28
  */
29
29
 
30
- import { activeBreakpoint } from '@volter/editor-core/authoring/breakpoint-state';
30
+ import { activeBreakpoint } from '@volter/editor-sdk/kit/breakpoint-state';
31
31
  import {
32
32
  cssTextForStyleValue,
33
33
  numericStyleValue,
34
34
  preserveNumericStyleUnit,
35
- } from '@volter/editor-core/authoring/css-numeric-style';
36
- import { WORLD_SCOPE_NODE_ID } from '@volter/editor-core/authoring/stories-scope';
35
+ } from '@volter/editor-sdk/css-numeric-style';
36
+ import { WORLD_SCOPE_NODE_ID } from '@volter/editor-sdk/kit/stories-scope';
37
37
  import { createStructWritePipe, type StructOpOptions } from '../host/authoring/struct-write-pipe';
38
- import { getRootPan } from '@volter/editor-core/authoring/world-pan-state';
38
+ import { getRootPan } from '@volter/editor-sdk/kit/world-pan-state';
39
39
  import {
40
40
  resolvesLiveOnly,
41
41
  runWritePipe,
42
42
  type WriteAck,
43
43
  type WriteResolution,
44
- } from '@volter/editor-core/authoring/write-pipe';
45
- import { guideClientEdges } from '@volter/editor-core/components/board-guides';
46
- import { editorConsole } from '@volter/editor-core/editor-console';
47
- import type { EditorShellStore } from '@volter/editor-core/editor-shell-store';
48
- import { withProjectSourceHistory } from '@volter/editor-core/history/source-history-backend';
44
+ } from '@volter/editor-sdk/kit/write-pipe';
45
+ import { guideClientEdges } from '@volter/editor-sdk/kit/components/board-guides';
46
+ import { editorConsole } from '@volter/editor-sdk/kit/editor-console';
47
+ import type { ShellStore } from '@volter/editor-sdk/kit/shell-store';
48
+ import { withProjectSourceHistory } from '@volter/editor-sdk/kit/history/source-history-backend';
49
49
  import { DomProjector, oidDomIdentity, projectOidDom } from '../host/projection/dom';
50
50
  import { storyArgPropertyDescriptors } from '../host/stories/story-arg-descriptors';
51
- import { storyDiscoveryUnavailable } from '@volter/editor-core/stories/story-discovery';
52
- import { deriveStoryGroupPath, formatStoryGroupPath } from '@volter/editor-core/stories/story-grouping';
53
- import type { StoryPresentationIndex } from '@volter/editor-core/stories/story-presentation';
54
- import { subscribeProjectStoryModules } from '@volter/editor-core/stories/story-registry';
55
- import { showTransientHint } from '@volter/editor-core/transient-hint';
51
+ import { storyDiscoveryUnavailable } from '@volter/editor-sdk/kit/stories/story-discovery';
52
+ import { deriveStoryGroupPath, formatStoryGroupPath } from '@volter/editor-sdk/kit/stories/story-grouping';
53
+ import type { StoryPresentationIndex } from '@volter/editor-sdk/kit/stories/story-presentation';
54
+ import { subscribeProjectStoryModules } from '@volter/editor-sdk/kit/stories/story-registry';
55
+ import { showTransientHint } from '@volter/editor-sdk/kit/transient-hint';
56
56
  import {
57
57
  browserOrInlineResolver,
58
58
  type ComputedStyleResolver,
@@ -62,26 +62,25 @@ import {
62
62
  findClassRuleSource,
63
63
  findEmptyContainers,
64
64
  firstPartyStylesheetFiles,
65
- getCallSiteOid,
66
65
  getComponentProps,
67
66
  getComputedStyleValue,
68
67
  getDesignTokens,
69
68
  getMatchedCssRules,
70
69
  getReactComponentName,
71
70
  type MatchableElement,
72
- } from '@volter/editor-core/ui-source/inspect';
73
- import type { ComponentPropSpec, OidEntry } from '@volter/editor-core/ui-source/oid-transform';
74
- import { relativeImportSpecifier } from '@volter/editor-core/ui-source/relative-import-specifier';
75
- import type { SourceWriteBackend } from '@volter/editor-core/ui-source/source-write-backend';
76
- import { writeCsfStory, writeNamedStyle } from '@volter/editor-core/ui-source/source-write-backend';
71
+ } from '@volter/editor-sdk/kit/ui-source/inspect';
72
+ import type { ComponentPropSpec, OidEntry } from '@volter/editor-react/source/oid-transform';
73
+ import { relativeImportSpecifier } from '@volter/editor-react/source/relative-import-specifier';
74
+ import type { SourceWriteBackend } from '@volter/editor-sdk/kit/ui-source/source-write-backend';
75
+ import { writeCsfStory, writeNamedStyle } from '@volter/editor-sdk/kit/ui-source/source-write-backend';
77
76
  import {
78
77
  type CssRuleTarget,
79
78
  namedStyleRuleFor,
80
79
  pickCssRuleTarget,
81
80
  tokenReferenceGuardText,
82
- } from '@volter/editor-core/ui-source/writer';
83
- import { UI_COMPONENTS_DOCUMENT_ID } from '@volter/editor-core/workspace-document-ids';
84
- import { activateWorkspaceDocument } from '@volter/editor-core/workspace-document-registry';
81
+ } from '@volter/editor-react/source/writer';
82
+ import { UI_COMPONENTS_DOCUMENT_ID } from '@volter/editor-sdk/kit/workspace-document-ids';
83
+ import { activateWorkspaceDocument } from '@volter/editor-sdk/kit/workspace-document-registry';
85
84
  import type {
86
85
  AssetDropContext,
87
86
  AssetDropProvider,
@@ -255,20 +254,6 @@ export function mapBoxEditPatchKey(key: string, isPositioned: boolean): BoxEditP
255
254
  }
256
255
  }
257
256
 
258
- /**
259
- * A pasteboard `<At>` mount — detected by the STRUCTURAL marker the pasteboard
260
- * capability's helper renders (`data-vgai-at="true"`), never by filename or
261
- * import path, so a project's freely edited copy of the helper keeps working
262
- * (the LiveModuleDocument precedent: detection is structural). An `x`/`y` drag
263
- * on one of these writes the callsite's `x`/`y` JSX literals instead of inline
264
- * `left`/`top` style — the authored form the pasteboard design ratified
265
- * (docs/PARITY-PROGRAM-HANDOFF.md, queue item 4: "drag = OID literal write to
266
- * x/y").
267
- */
268
- function isPasteboardAtElement(el: OidElementLike): boolean {
269
- return el.getAttribute('data-vgai-at') === 'true';
270
- }
271
-
272
257
  const OID_ATTR = 'data-oid';
273
258
  const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
274
259
  const VOID_HTML_ELEMENTS = new Set([
@@ -1057,7 +1042,7 @@ export class ReactRootAuthoringAdapter implements AuthoringAdapter {
1057
1042
 
1058
1043
  constructor(
1059
1044
  private readonly root: OidElementLike,
1060
- private readonly store: EditorShellStore,
1045
+ private readonly store: ShellStore,
1061
1046
  opts: ReactRootAuthoringOptions = {},
1062
1047
  ) {
1063
1048
  this.assetRoot = opts.assetRoot ?? root;
@@ -1993,38 +1978,10 @@ export class ReactRootAuthoringAdapter implements AuthoringAdapter {
1993
1978
  bestOrder = order;
1994
1979
  }
1995
1980
  }
1996
- return bestId === null ? null : this.resolvePlacementUnit(bestId);
1981
+ return bestId;
1997
1982
  },
1998
1983
  };
1999
1984
 
2000
- /**
2001
- * The pasteboard's PICK RULE: a hit anywhere inside an `<At>` subtree
2002
- * selects the At — the placement unit whose `x`/`y` a drag writes — never
2003
- * the helper's internals. Without this, the deepest-wins rule above picked
2004
- * a Swatch's inner chip div (a STATIC node whose x/y drag drops by design),
2005
- * and the drag gesture that followed re-picked it out from under the
2006
- * selected At on pointerdown, so no pasteboard drag could ever commit
2007
- * (measured on the moodboard acceptance run, 2026-08-30). Deeper selection
2008
- * stays reachable through the hierarchy panel, which projects the full
2009
- * subtree. Structural (`data-vgai-at`), so it costs nothing outside
2010
- * pasteboard content.
2011
- */
2012
- private resolvePlacementUnit(pickedId: string): string {
2013
- const { nodes } = this.snapshot();
2014
- const picked = nodes.get(pickedId);
2015
- const el = picked?.el as unknown as
2016
- | { closest?(selector: string): unknown; getAttribute?(name: string): string | null }
2017
- | undefined;
2018
- if (!el?.closest) return pickedId;
2019
- if (el.getAttribute?.('data-vgai-at') === 'true') return pickedId;
2020
- const at = el.closest('[data-vgai-at="true"]');
2021
- if (!at) return pickedId;
2022
- for (const [id, node] of nodes) {
2023
- if ((node.el as unknown) === at) return id;
2024
- }
2025
- return pickedId;
2026
- }
2027
-
2028
1985
  /** Host rect to subtract for {@link rects}' HOST-RELATIVE geometry — `this.root`
2029
1986
  * IS the world's own mounted DOM layer (`world.mounted.container` / the ingest
2030
1987
  * sibling's `layer`, see the constructor call sites), i.e. exactly the
@@ -2308,30 +2265,13 @@ export class ReactRootAuthoringAdapter implements AuthoringAdapter {
2308
2265
  priorInline: Map<string, string>,
2309
2266
  ): Promise<void> {
2310
2267
  const wasDirty = this.dirty;
2311
- // A pasteboard `<At>` mount routes its position to the CALLSITE's `x`/`y`
2312
- // JSX literals rather than inline `left`/`top` style — the drag's live
2313
- // preview still moved `el.style.left/top` (the helper renders exactly that
2314
- // from `x`/`y`), but the AUTHORED truth is the props, so that is what the
2315
- // commit writes. Resolved from the fiber (the helper's own internal stamp
2316
- // sits on the same element, so the element's `data-oid` alone would name
2317
- // the helper file, not the callsite in the pasteboard file).
2318
- const node = this.snapshot().nodes.get(id);
2319
- const atCallSiteOid = node && isPasteboardAtElement(node.el) ? getCallSiteOid(node.el) : null;
2320
- const atPropForStyle = (prop: string): 'x' | 'y' | null =>
2321
- atCallSiteOid === null ? null : prop === 'left' ? 'x' : prop === 'top' ? 'y' : null;
2322
2268
  // A4 — echo every touched prop BEFORE any write, so the inspector field shows
2323
2269
  // the dragged value at once (same discipline as `inspector.set`). The echo holds
2324
2270
  // the BARE numeric (a `type:'number'` descriptor's `Inspector` field needs an
2325
2271
  // actual number — see `inspector.get`'s `numericStyleValue` note), NOT the
2326
- // px-suffixed source form D1 writes below. An At placement echoes on the
2327
- // PROP path instead (its Props section is where x/y render).
2272
+ // px-suffixed source form D1 writes below.
2328
2273
  for (const [prop, value] of touched) {
2329
- const atProp = atPropForStyle(prop);
2330
- if (atProp && typeof value === 'number') {
2331
- this.setEcho(id, `${PROP_PATH_PREFIX}${atProp}`, String(Math.round(value)));
2332
- } else {
2333
- this.setEcho(id, `${STYLE_PATH_PREFIX}${prop}`, value);
2334
- }
2274
+ this.setEcho(id, `${STYLE_PATH_PREFIX}${prop}`, value);
2335
2275
  }
2336
2276
  // A GESTURE THAT WROTE NOTHING SAYS SO. Every refusal below only warned in
2337
2277
  // the browser console, so a drag whose commit was refused looked done —
@@ -2345,12 +2285,6 @@ export class ReactRootAuthoringAdapter implements AuthoringAdapter {
2345
2285
  this.lastStyleWriteRefusal = null;
2346
2286
  const commit = async (backend: SourceWriteBackend | undefined): Promise<void> => {
2347
2287
  for (const [prop, value] of touched) {
2348
- const atProp = atPropForStyle(prop);
2349
- if (atProp && typeof value === 'number') {
2350
- await this.writeAtPlacement(id, atCallSiteOid as string, atProp, value, backend);
2351
- applied += 1;
2352
- continue;
2353
- }
2354
2288
  // D1 (spec 27 §4 B2/B3 reload-safety) — a numeric length-prop value must
2355
2289
  // persist to JSX SOURCE in a form React honors on REMOUNT. React 19 DROPS a
2356
2290
  // bare UNITLESS numeric STRING (the writer quotes `String(152)` → `width:
@@ -2396,52 +2330,6 @@ export class ReactRootAuthoringAdapter implements AuthoringAdapter {
2396
2330
  }
2397
2331
  }
2398
2332
 
2399
- /**
2400
- * The pasteboard placement write: one `<At>` callsite prop (`x` or `y`) as a
2401
- * JSX NUMBER LITERAL, `addIfMissing` because the helper defaults both to 0
2402
- * and an author legitimately omits them until the first drag. Refusals
2403
- * follow {@link writePropEdit}'s contract: a dynamic expression (`x={GRID *
2404
- * 2}`) is authored truth the drag must not flatten — guarded and warned by
2405
- * name, never overwritten. Runs inside {@link commitBoxEdit}'s gesture, so a
2406
- * corner drag that writes both axes stays one undo entry.
2407
- */
2408
- private async writeAtPlacement(
2409
- id: string,
2410
- callSiteOid: string,
2411
- prop: 'x' | 'y',
2412
- value: number,
2413
- backend: SourceWriteBackend | undefined,
2414
- ): Promise<void> {
2415
- const echoPath = `${PROP_PATH_PREFIX}${prop}`;
2416
- const b = backend ?? this.writeBackend;
2417
- if (!b?.writeProp) {
2418
- this.clearEcho(id, echoPath);
2419
- console.warn(
2420
- `[ReactRootAuthoringAdapter] cannot write At placement "${prop}" on "${id}": no ` +
2421
- 'source-write backend with prop support in this session (hosted/no dev server).',
2422
- );
2423
- return;
2424
- }
2425
- const res = await b.writeProp(callSiteOid, prop, String(Math.round(value)), {
2426
- addIfMissing: true,
2427
- });
2428
- if (!res.changed) {
2429
- this.clearEcho(id, echoPath);
2430
- if (res.dynamic) this.markGuarded(id, echoPath, DYNAMIC_EXPRESSION_GUARD);
2431
- this.store.notifyIngestEdit();
2432
- console.warn(
2433
- `[ReactRootAuthoringAdapter] At placement write refused/no-op for oid ` +
2434
- `"${callSiteOid}" prop "${prop}": ${
2435
- res.dynamic
2436
- ? 'value is a dynamic expression (guarded) — authored truth the drag must not flatten'
2437
- : (res.error ?? 'no change')
2438
- }`,
2439
- );
2440
- return;
2441
- }
2442
- this.dirty = true;
2443
- }
2444
-
2445
2333
  /**
2446
2334
  * T0 (spec 27 §2) — brings the react adapter's existing off-contract `editText`
2447
2335
  * (below) onto the contract. `get` is a best-effort CLIENT-side read: the live
@@ -3044,12 +2932,12 @@ export class ReactRootAuthoringAdapter implements AuthoringAdapter {
3044
2932
  // `removeMany` here as unsound because the OBVIOUS implementation is N
3045
2933
  // separate `structOp`-style calls, each targeting its OID's `{file,
3046
2934
  // line, col}` from the SERVER's `OidStore.index`
3047
- // (`vite-plugin-ui-oid.ts`'s `handleStruct`) — exactly the per-id
2935
+ // (`@volter/editor-react`'s `serving/ui-oid-plugin.ts`'s `handleStruct`) — exactly the per-id
3048
2936
  // `remove` loop's own stale-offset hazard (see the CORRECTNESS INVARIANT
3049
2937
  // comment below), just without the ordering discipline that loop needs
3050
2938
  // to stay sound. This implementation is NOT that: `removeManyElements`
3051
2939
  // posts every id's raw oid in ONE request to `/__ui-source/struct-many`
3052
- // (`handleStructMany`, `vite-plugin-ui-oid.ts`), which resolves every
2940
+ // (`handleStructMany`, `@volter/editor-react`'s `serving/ui-oid-plugin.ts`), which resolves every
3053
2941
  // oid's offset against a SINGLE shared `readFileSync` snapshot (never a
3054
2942
  // per-id re-read, so no write-to-write staleness is even possible) and
3055
2943
  // applies them highest-offset-first in one pass, one write. That is also
@@ -3677,7 +3565,7 @@ export class ReactRootAuthoringAdapter implements AuthoringAdapter {
3677
3565
  * `#n` siblings share ONE raw oid — deleting it once is correct, per
3678
3566
  * `walkOidTree`'s own disambiguation comment), and posts them ALL in ONE
3679
3567
  * `writeStructMany` call — see that method's doc comment on `SourceWriteBackend`
3680
- * (`source-write-backend.ts`) and `handleStructMany`'s (`vite-plugin-ui-oid.ts`)
3568
+ * (`source-write-backend.ts`) and `handleStructMany`'s (`@volter/editor-react`'s `serving/ui-oid-plugin.ts`)
3681
3569
  * for the soundness argument (one shared file snapshot, highest-offset-first,
3682
3570
  * caller-order-independent). Degrades to a loud no-op — never a silent partial
3683
3571
  * delete — when this session's backend hasn't implemented `writeStructMany` (a
@@ -40,44 +40,43 @@ import { Checkbox, TextInput, themeVars } from '@volter/editor-sdk/widgets';
40
40
  // `@editor/active-project` and not `@editor/project-manager`: the same
41
41
  // function, re-exported, without dragging the whole project-open/storage
42
42
  // estate into this package's program.
43
- import { getCurrentProject } from '@volter/editor-core/active-project';
43
+ import { getCurrentProject } from '@volter/editor-sdk/kit/active-project';
44
44
  import { type Resolution, ResolutionPicker } from '../../host/components/ResolutionPicker';
45
- import { SurfaceStateOverlay } from '@volter/editor-core/components/SurfaceStateOverlay';
46
- import { registerDocumentOpener } from '@volter/editor-core/document-open-registry';
47
- import type { ViewportTab } from '@volter/editor-core/editor-shell-store';
48
- import { createHmrRegistrationGroup } from '@volter/editor-core/hmr-registration-group';
45
+ import { SurfaceStateOverlay } from '@volter/editor-sdk/kit/components/SurfaceStateOverlay';
46
+ import { registerDocumentOpener } from '@volter/editor-sdk/kit/document-open-registry';
47
+ import { createHmrRegistrationGroup } from '@volter/editor-sdk/kit/hmr-registration-group';
49
48
  import {
50
49
  CONTRIBUTED_SECTION_ORDER,
51
50
  STORY_ARGS_SECTION_ID,
52
51
  STORY_ARGS_SECTION_TITLE,
53
- } from '@volter/editor-core/inspection/model';
54
- import { registerInspectorSections } from '@volter/editor-core/inspector-section-registry';
55
- import type { ComposedProjectStory } from '@volter/editor-core/stories/compose-project-stories';
56
- import { getProjectStoryRegions } from '@volter/editor-core/stories/project-story-regions';
57
- import { mountIsolatedStory, runStoryPlay } from '@volter/editor-core/stories/StoryPreviewMount';
58
- import { declaredStoryMedium } from '@volter/editor-core/stories/story-declared-medium';
52
+ } from '@volter/editor-sdk/kit/inspection-model';
53
+ import { registerInspectorSections } from '@volter/editor-sdk/kit/inspector-section-registry';
54
+ import type { ComposedProjectStory } from '@volter/editor-sdk/kit/stories/compose-project-stories';
55
+ import { getProjectStoryRegions } from '@volter/editor-sdk/kit/stories/project-story-regions';
56
+ import { mountIsolatedStory, runStoryPlay } from '@volter/editor-sdk/kit/stories/StoryPreviewMount';
57
+ import { declaredStoryMedium } from '@volter/editor-sdk/kit/stories/story-declared-medium';
59
58
  import {
60
59
  ISOLATED_STORY_DOCUMENT_OPENER,
61
60
  STORY_DOCS_DOCUMENT_OPENER,
62
61
  type StoryDocumentOpenRequest,
63
- } from '@volter/editor-core/stories/story-document-openers';
62
+ } from '@volter/editor-sdk/kit/story-document-openers';
64
63
  import {
65
64
  getProjectStoryModules,
66
65
  refreshProjectStories,
67
66
  subscribeProjectStoryModules,
68
67
  whenProjectStoriesReady,
69
- } from '@volter/editor-core/stories/story-registry';
68
+ } from '@volter/editor-sdk/kit/stories/story-registry';
70
69
  import { domHasRenderableContent } from '../../host/surface-content';
71
- import { explainSurface, type SurfaceContentState } from '@volter/editor-core/surface-state';
72
- import { CONTRIBUTED_WORKSPACE_UTILITIES } from '@volter/editor-core/workspace-core-utilities';
70
+ import { explainSurface, type SurfaceContentState } from '@volter/editor-sdk/kit/surface-state';
71
+ import { CONTRIBUTED_WORKSPACE_UTILITIES } from '@volter/editor-sdk/kit/workspace-core-utilities';
73
72
  import {
74
73
  activeWorkspaceDocument,
75
74
  openWorkspaceDocument,
76
75
  type WorkspaceDocumentContentProps,
77
- } from '@volter/editor-core/workspace-document-registry';
78
- import { registerWorkspaceDocumentRestorer } from '@volter/editor-core/workspace-document-restore';
79
- import { registerWorkspaceUtility } from '@volter/editor-core/workspace-utility-registry';
80
- import { fitPresentation } from '@volter/game-runtime/runtime/presentation';
76
+ } from '@volter/editor-sdk/kit/workspace-document-registry';
77
+ import { registerWorkspaceDocumentRestorer } from '@volter/editor-sdk/kit/workspace-document-restore';
78
+ import { registerWorkspaceUtility } from '@volter/editor-sdk/kit/workspace-utility-registry';
79
+ import { fitPresentation } from '../../runtime/presentation';
81
80
  import { Button, fontMono, fontSizeVar, spaceVar } from '@volter/editor-sdk/widgets';
82
81
  import { useEffect, useRef, useState, useSyncExternalStore } from 'react';
83
82
  import { STORY_ARGS_SECTION_ICON } from './story-args-section';
@@ -205,7 +204,6 @@ export function clearStoryActionLog(id: string): void {
205
204
  /** The narrow store surface story documents need (T6.3 gate hand-off —
206
205
  * same contract as `asset-documents.tsx`). */
207
206
  export interface StoryDocumentStore {
208
- setActiveViewportTab(tab: ViewportTab): void;
209
207
  }
210
208
 
211
209
  /**
@@ -254,7 +252,6 @@ export function openStoryDocument(
254
252
  closeable: true,
255
253
  presentation: () => ({ kind: 'story', modulePath, storyName, mode: 'preview' }),
256
254
  persist: () => ({ modulePath, storyName }),
257
- onActivate: () => store.setActiveViewportTab('edit'),
258
255
  onDispose: (documentId) => {
259
256
  if (_states.delete(documentId)) notifyChanged();
260
257
  },
@@ -298,7 +295,6 @@ export function openStoryDocsDocument(
298
295
  closeable: true,
299
296
  presentation: () => ({ kind: 'story', modulePath, storyName, mode: 'docs' }),
300
297
  persist: () => ({ modulePath, storyName, view: 'docs' }),
301
- onActivate: () => store.setActiveViewportTab('edit'),
302
298
  onDispose: (documentId) => {
303
299
  if (_states.delete(documentId)) notifyChanged();
304
300
  },
@@ -1,4 +1,4 @@
1
- import { registerAvailableWorkspaceDocument } from '@volter/editor-core/workspace-available-documents';
1
+ import { registerAvailableWorkspaceDocument } from '@volter/editor-sdk/kit/workspace-available-documents';
2
2
  /**
3
3
  * THE `UI` BOARD's DOCUMENT — what `ui-component-board.ts` installs, kept in
4
4
  * its own module so the registration's eager closure is the verdict and
@@ -29,17 +29,17 @@ import {
29
29
  designTimeRootDescriptors,
30
30
  projectStoryBoardDescriptor,
31
31
  rememberedPortableStory,
32
- } from '@volter/editor-core/authoring/design-time-layers';
33
- import type { ComponentBoardContext } from '@volter/editor-core/component-board-registry';
34
- import { RootDocumentContent } from '@volter/editor-core/components/world-documents';
35
- import type { DocumentPreviewSource } from '@volter/editor-core/document-preview-source';
36
- import { getCurrentProject } from '@volter/editor-core/project-manager';
32
+ } from '@volter/editor-sdk/kit/authoring/design-time-layers';
33
+ import type { ComponentBoardContext } from '@volter/editor-sdk/kit/component-board-registry';
34
+ import { RootDocumentContent } from '@volter/editor-sdk/kit/components/world-documents';
35
+ import type { DocumentPreviewSource } from '@volter/editor-sdk/kit/document-preview-source';
36
+ import { getCurrentProject } from '@volter/editor-sdk/kit/active-project';
37
37
  import {
38
38
  getProjectPreviewStories,
39
39
  subscribeProjectStoryModules,
40
- } from '@volter/editor-core/stories/story-registry';
41
- import { UI_COMPONENTS_DOCUMENT_ID } from '@volter/editor-core/workspace-document-ids';
42
- import type { WorkspaceDocumentContentProps } from '@volter/editor-core/workspace-document-registry';
40
+ } from '@volter/editor-sdk/kit/stories/story-registry';
41
+ import { UI_COMPONENTS_DOCUMENT_ID } from '@volter/editor-sdk/kit/workspace-document-ids';
42
+ import type { WorkspaceDocumentContentProps } from '@volter/editor-sdk/kit/workspace-document-registry';
43
43
 
44
44
  import { UI_COMPONENTS_TITLE } from './ui-board-title';
45
45
 
@@ -48,7 +48,7 @@ const uiCanvasPreview: DocumentPreviewSource = {
48
48
  JSON.stringify(getProjectPreviewStories().map(({ id, modulePath }) => [id, modulePath])),
49
49
  subscribe: subscribeProjectStoryModules,
50
50
  capture: async ({ width, height }) => {
51
- const { captureDomStoryBoardPreview } = await import('@volter/editor-core/stories/story-capture');
51
+ const { captureDomStoryBoardPreview } = await import('@volter/editor-sdk/kit/stories/story-capture');
52
52
  return captureDomStoryBoardPreview(width, height);
53
53
  },
54
54
  };
@@ -85,7 +85,6 @@ export function installUiBoard({ store, composite }: ComponentBoardContext): voi
85
85
  ...(story ? { story } : {}),
86
86
  };
87
87
  },
88
- onActivate: () => store.setActiveViewportTab('edit'),
89
88
  },
90
89
  // A board NEVER steals focus — presence is answered asynchronously, so a
91
90
  // board that arrives late would otherwise yank the author off whatever
@@ -12,15 +12,15 @@
12
12
  * whose verdict is `'present'`.
13
13
  */
14
14
 
15
- import { commandLine } from '@volter/editor-core/product-command';
16
- import type { ComponentBoard, ComponentBoardContext } from '@volter/editor-core/component-board-registry';
17
- import { editorConsole } from '@volter/editor-core/editor-console';
15
+ import { commandLine } from '@volter/editor-sdk/kit/product-command';
16
+ import type { ComponentBoard, ComponentBoardContext } from '@volter/editor-sdk/kit/component-board-registry';
17
+ import { editorConsole } from '@volter/editor-sdk/kit/editor-console';
18
18
  import {
19
19
  getStoryMediaPresence,
20
20
  subscribeStoryMediaPresence,
21
21
  } from '../host/stories/story-media-presence';
22
- import { projectStoriesReady, subscribeProjectStoryModules } from '@volter/editor-core/stories/story-registry';
23
- import { UI_COMPONENTS_DOCUMENT_ID } from '@volter/editor-core/workspace-document-ids';
22
+ import { projectStoriesReady, subscribeProjectStoryModules } from '@volter/editor-sdk/kit/stories/story-registry';
23
+ import { UI_COMPONENTS_DOCUMENT_ID } from '@volter/editor-sdk/kit/workspace-document-ids';
24
24
  import { UI_COMPONENTS_TITLE } from './ui-board-title';
25
25
 
26
26
  export const uiComponentBoard: ComponentBoard = {
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Meter arithmetic over an `AudioAdapter`'s `AudioMeterFrame.level` — the one
3
+ * place a linear RMS level becomes dBFS and a bar fill. Lives beside the
4
+ * adapter because both readers of a level (the editor's header meter and the
5
+ * `@vgai/game` audio debugger) are consumers of the adapter, and neither may
6
+ * import the other.
7
+ */
8
+
9
+ /** Linear RMS level → dBFS. Silence clamps to `floorDb` (log of 0 is -∞). */
10
+ export function levelToDb(level: number, floorDb = -60): number {
11
+ if (!(level > 0)) return floorDb;
12
+ return Math.max(floorDb, 20 * Math.log10(level));
13
+ }
14
+
15
+ /** Meter-bar fill percentage: dB-scaled from a -60 dBFS floor (a linear
16
+ * scale would pin every real-world level into the bottom pixels). 0 for
17
+ * silence, 100 at/above full scale. */
18
+ export function meterPercent(level: number, floorDb = -60): number {
19
+ const db = levelToDb(level, floorDb);
20
+ return Math.round(((db - floorDb) / -floorDb) * 100);
21
+ }