@dailies-studio/shot-editor 0.1.0

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 (112) hide show
  1. package/dist/assets/index-B7notge7.css +1 -0
  2. package/dist/assets/index-BBE6Ta9L.js +52 -0
  3. package/dist/index.html +13 -0
  4. package/package.json +45 -0
  5. package/src/api.ts +289 -0
  6. package/src/app/App.tsx +394 -0
  7. package/src/audio/index.tsx +74 -0
  8. package/src/audio/preview.ts +364 -0
  9. package/src/bridge.ts +45 -0
  10. package/src/bridgeTypes.ts +582 -0
  11. package/src/channels.ts +40 -0
  12. package/src/main.tsx +15 -0
  13. package/src/panels/ResizeHandle.tsx +113 -0
  14. package/src/panels/agent/AgentPanel.tsx +478 -0
  15. package/src/panels/agent/agent.css +322 -0
  16. package/src/panels/export/ExportDialog.tsx +284 -0
  17. package/src/panels/files/FilePanel.tsx +564 -0
  18. package/src/panels/files/McpSection.tsx +66 -0
  19. package/src/panels/files/icons.tsx +118 -0
  20. package/src/panels/header/DocSwitcher.tsx +85 -0
  21. package/src/panels/header/Header.tsx +132 -0
  22. package/src/panels/header/HistoryControls.tsx +20 -0
  23. package/src/panels/header/StatusBadges.tsx +49 -0
  24. package/src/panels/header/TransportBar.tsx +86 -0
  25. package/src/panels/header/ZoomControls.tsx +38 -0
  26. package/src/panels/help/HelpSection.tsx +190 -0
  27. package/src/panels/inspector/FramingRows.tsx +69 -0
  28. package/src/panels/inspector/InspectorPanel.tsx +178 -0
  29. package/src/panels/inspector/MarkerSection.tsx +63 -0
  30. package/src/panels/inspector/ParamRow.tsx +71 -0
  31. package/src/panels/inspector/animate/BlockTiming.tsx +341 -0
  32. package/src/panels/inspector/animate/DuringBlocks.tsx +85 -0
  33. package/src/panels/inspector/animate/InOutPresets.tsx +57 -0
  34. package/src/panels/inspector/animate/ResolvedChannels.tsx +150 -0
  35. package/src/panels/inspector/animate/ShotSection.tsx +126 -0
  36. package/src/panels/inspector/animate/useBlocks.ts +43 -0
  37. package/src/panels/inspector/design/AlignRow.tsx +63 -0
  38. package/src/panels/inspector/design/AppearanceSection.tsx +49 -0
  39. package/src/panels/inspector/design/ClonerSection.tsx +142 -0
  40. package/src/panels/inspector/design/ComponentSection.tsx +94 -0
  41. package/src/panels/inspector/design/CornerSection.tsx +52 -0
  42. package/src/panels/inspector/design/FillSection.tsx +89 -0
  43. package/src/panels/inspector/design/HtmlSection.tsx +50 -0
  44. package/src/panels/inspector/design/InstanceSection.tsx +302 -0
  45. package/src/panels/inspector/design/MediaSection.tsx +251 -0
  46. package/src/panels/inspector/design/MeshSection.tsx +172 -0
  47. package/src/panels/inspector/design/ShadowSection.tsx +73 -0
  48. package/src/panels/inspector/design/StrokeSection.tsx +85 -0
  49. package/src/panels/inspector/design/TransformSection.tsx +91 -0
  50. package/src/panels/inspector/design/TypographySection.tsx +170 -0
  51. package/src/panels/inspector/scene/CameraSection.tsx +59 -0
  52. package/src/panels/inspector/scene/EffectsSection.tsx +123 -0
  53. package/src/panels/inspector/scene/SceneSection.tsx +71 -0
  54. package/src/panels/inspector/scene/TransitionSection.tsx +136 -0
  55. package/src/panels/inspector/useDocWrite.ts +268 -0
  56. package/src/panels/material/MaterialPicker.tsx +172 -0
  57. package/src/panels/stage/StageMenu.tsx +38 -0
  58. package/src/panels/stage/StagePanel.tsx +131 -0
  59. package/src/panels/timeline/AudioLane.tsx +340 -0
  60. package/src/panels/timeline/BlockRow.tsx +242 -0
  61. package/src/panels/timeline/ChannelRow.tsx +266 -0
  62. package/src/panels/timeline/LifespanRow.tsx +165 -0
  63. package/src/panels/timeline/MarkerLane.tsx +146 -0
  64. package/src/panels/timeline/SceneStrip.tsx +145 -0
  65. package/src/panels/timeline/TimelineDock.tsx +488 -0
  66. package/src/panels/timeline/model.ts +641 -0
  67. package/src/panels/timeline/snap.ts +191 -0
  68. package/src/panels/toolbar/AddMenu.tsx +230 -0
  69. package/src/panels/toolbar/CameraViewBar.tsx +70 -0
  70. package/src/panels/toolbar/ShadingBar.tsx +42 -0
  71. package/src/panels/toolbar/ToolDockBar.tsx +110 -0
  72. package/src/panels/toolbar/ViewModeBar.tsx +49 -0
  73. package/src/shotTokens.css +131 -0
  74. package/src/stage/FrustumGizmo.tsx +184 -0
  75. package/src/stage/GridPlane.tsx +274 -0
  76. package/src/stage/MoveGizmo.tsx +411 -0
  77. package/src/stage/PerfHud.tsx +206 -0
  78. package/src/stage/SplitRenderer.tsx +511 -0
  79. package/src/stage/StageApp.tsx +3423 -0
  80. package/src/stage/StageTools.tsx +581 -0
  81. package/src/stage/bridgeClient.ts +278 -0
  82. package/src/stage/feed.ts +243 -0
  83. package/src/stage/frustumGeometry.ts +172 -0
  84. package/src/stage/gizmoMath.ts +494 -0
  85. package/src/stage/handles.ts +151 -0
  86. package/src/stage/instanceModules.ts +152 -0
  87. package/src/stage/interactions/move.ts +172 -0
  88. package/src/stage/interactions/panZoom.ts +60 -0
  89. package/src/stage/isolation.ts +155 -0
  90. package/src/stage/main.tsx +110 -0
  91. package/src/stage/modalState.ts +427 -0
  92. package/src/stage/overlays/Overlays.tsx +1046 -0
  93. package/src/stage/panes.ts +121 -0
  94. package/src/stage/penState.ts +112 -0
  95. package/src/stage/project.ts +402 -0
  96. package/src/stage/shading.ts +55 -0
  97. package/src/stage/tokenColor.ts +26 -0
  98. package/src/stage/view.ts +182 -0
  99. package/src/stage/workingView.ts +636 -0
  100. package/src/state/agentActions.ts +203 -0
  101. package/src/state/clientId.ts +25 -0
  102. package/src/state/context.tsx +33 -0
  103. package/src/state/insert.ts +507 -0
  104. package/src/state/keymap.ts +560 -0
  105. package/src/state/menu.ts +141 -0
  106. package/src/state/panelSize.ts +26 -0
  107. package/src/state/renderEvents.ts +100 -0
  108. package/src/state/store.ts +4094 -0
  109. package/src/state/triangles.ts +70 -0
  110. package/src/state/types.ts +384 -0
  111. package/src/styles.css +2948 -0
  112. package/src/tools.ts +181 -0
package/src/tools.ts ADDED
@@ -0,0 +1,181 @@
1
+ // THE TOOL TABLE. One literal, and every list, union and lookup below is
2
+ // DERIVED from it — so adding a tool without answering every question the table
3
+ // asks is a compile error rather than an empty button or a dead key.
4
+ //
5
+ // It lives beside the bridge contract rather than in either half, because both
6
+ // halves read it: the chrome renders the dock from it, and the stage keys its
7
+ // cursor and its gesture routing off the same rows.
8
+ //
9
+ // ── `animate` IS DELIBERATELY NOT A TOOL ────────────────────────────────
10
+ //
11
+ // In Raylight you can be in Animate mode WHILE holding Select: it changes what
12
+ // an edit MEANS, not what a drag DOES. As a member of this union every arm of
13
+ // every switch would have to answer "and what does select do while animate is
14
+ // armed?", which has no answer. It is `animateMode: boolean`, toggled by ⇧A,
15
+ // and it is the one bit that decides whether a gesture writes base or authors a
16
+ // block.
17
+ //
18
+ // ── THE `shift` FIELD, WHICH THE 2D LANE'S TABLE DOES NOT HAVE ──────────
19
+ //
20
+ // Raylight binds `L` to line and `⇧L` to arrow. So the key lane cannot be "a
21
+ // bare letter arms a tool" — it has to be "a letter PLUS whether shift was
22
+ // held", and the shift bit belongs in the table with the letter rather than in
23
+ // a special case beside it.
24
+
25
+ /** Every tool that changes what a canvas press does. */
26
+ export type ShotTool =
27
+ | "select"
28
+ | "move"
29
+ | "text"
30
+ | "image"
31
+ | "rect"
32
+ | "ellipse"
33
+ | "line"
34
+ | "arrow"
35
+ | "path";
36
+
37
+ export interface ToolSpec {
38
+ label: string;
39
+ /**
40
+ * The letter that arms it, lower case, or null for a tool with no binding.
41
+ *
42
+ * ONE PLACE. `toolForKey` is the only reader, and the keymap consults nothing
43
+ * else for a bare letter — so a tool cannot be bound here and to something
44
+ * else somewhere in a switch.
45
+ */
46
+ key: string | null;
47
+ /** Does the binding require SHIFT? `L` is line and `⇧L` is arrow. */
48
+ shift?: true;
49
+ /** "dock" is the toolbar's own row; "flyout" is reached through the shape
50
+ * button. Six buttons in a row is a row; ten is a different object. */
51
+ surface: "dock" | "flyout";
52
+ /** Does a press-drag-release with this tool INSERT a layer? False for select
53
+ * (which picks) and move (which drags). */
54
+ draws: boolean;
55
+ /** The CSS cursor while this tool is armed. A row here rather than a default
56
+ * in the stage means a new tool has to answer "what does the pointer look
57
+ * like" in the same place it answers "what letter arms it". */
58
+ cursor: string;
59
+ }
60
+
61
+ /**
62
+ * The tools, in DOCK ORDER. `Object.keys` on an object literal is insertion
63
+ * order for string keys, and every list below derives its order from this one.
64
+ * The flyout rows sit beside the button they fly out of.
65
+ */
66
+ export const TOOL_SPECS = {
67
+ select: { label: "Select", key: "v", surface: "dock", draws: false, cursor: "default" },
68
+ // The flat-plane move. It is a TOOL and not a modifier because the plane it
69
+ // unprojects onto is the whole difference between it and select — see
70
+ // stage/interactions/move.ts.
71
+ move: { label: "Move", key: "g", surface: "dock", draws: false, cursor: "move" },
72
+ // `draws: true` and a text cursor are not in tension: the box IS drawn, and
73
+ // what the author gets for it is somewhere to type.
74
+ text: { label: "Text", key: "t", surface: "dock", draws: true, cursor: "text" },
75
+ // "Frame" and not "Image": the box the author draws takes an image OR a
76
+ // video, and the server's sniff of the file they pick decides which layer
77
+ // kind it becomes. The tool ID stays `image` because it is a persisted
78
+ // vocabulary — the bridge, the keymap and the insert map all key on it — and
79
+ // renaming a wire word to fix a button's caption is a schema break for a
80
+ // string nobody sees.
81
+ image: { label: "Frame", key: "i", surface: "dock", draws: true, cursor: "crosshair" },
82
+ rect: { label: "Rect", key: "r", surface: "dock", draws: true, cursor: "crosshair" },
83
+ ellipse: { label: "Ellipse", key: "o", surface: "flyout", draws: true, cursor: "crosshair" },
84
+ line: { label: "Line", key: "l", surface: "flyout", draws: true, cursor: "crosshair" },
85
+ arrow: { label: "Arrow", key: "l", shift: true, surface: "flyout", draws: true, cursor: "crosshair" },
86
+ // The pen takes no drag at all and still shows the crosshair: what the cursor
87
+ // announces is "a press here authors geometry", which is true of every press
88
+ // it takes, not "a drag is about to start".
89
+ path: { label: "Pen", key: "p", surface: "dock", draws: false, cursor: "crosshair" },
90
+ // NO `cut` ROW. It armed a crosshair and did nothing at all: the stage's
91
+ // pointer lane has no branch for it, and ⌘B is the real split-at-playhead.
92
+ // Deleting it is compile-checked by the `satisfies` below, and it frees `C`.
93
+ } as const satisfies Record<ShotTool, ToolSpec>;
94
+
95
+ /** Every tool, in dock order. The cast is the one place this file asserts what
96
+ * `satisfies` has already proved: the literal above is the only writer of the
97
+ * object and its key set IS `ShotTool`, which `Object.keys` cannot say because
98
+ * its return type is `string[]` for every object in TypeScript. */
99
+ export const SHOT_TOOLS = Object.keys(TOOL_SPECS) as readonly ShotTool[];
100
+
101
+ /**
102
+ * One row, seen as a `ToolSpec` rather than as its own literal type.
103
+ *
104
+ * `as const satisfies` narrows every row to exactly the keys it wrote, so
105
+ * `TOOL_SPECS.select.shift` is a type ERROR rather than `undefined` — which is
106
+ * excellent for the table and useless for anything iterating it. This is the
107
+ * one widening, and it is in one place.
108
+ */
109
+ export function specOf(tool: ShotTool): ToolSpec {
110
+ return TOOL_SPECS[tool];
111
+ }
112
+
113
+ /** The tools that insert on drag-release, DERIVED so the union and the flag can
114
+ * never disagree. Adding a `draws: true` row widens this union, which is what
115
+ * makes the draw lane's insert map fail to compile until the new tool has an
116
+ * answer there. That is the whole point of the table. */
117
+ export type DrawTool = {
118
+ [K in ShotTool]: (typeof TOOL_SPECS)[K]["draws"] extends true ? K : never;
119
+ }[ShotTool];
120
+
121
+ /**
122
+ * Every tool that ends up CREATING A LAYER, which is the draw tools plus the
123
+ * pen.
124
+ *
125
+ * The pen is not `draws: true` and must not become it: that flag answers "does
126
+ * a press-drag-release insert a layer", the stage's pointer lane forks on it,
127
+ * and the pen's answer is no — it commits across N presses on Enter or a
128
+ * double-click. What the two DO share is the far end of the wire, where an
129
+ * insert map has to answer for each of them, so that map is keyed on this and a
130
+ * new creating tool fails to compile until it has an entry.
131
+ */
132
+ export type InsertTool = DrawTool | "path";
133
+
134
+ /** The tools with a button in the dock's own row. The dock's icon map is keyed
135
+ * on it, so a new dock tool without a glyph is a compile error. */
136
+ export type DockTool = {
137
+ [K in ShotTool]: (typeof TOOL_SPECS)[K]["surface"] extends "dock" ? K : never;
138
+ }[ShotTool];
139
+
140
+ /** The other surface. Derived so the two partition the union by construction. */
141
+ export type FlyoutTool = {
142
+ [K in ShotTool]: (typeof TOOL_SPECS)[K]["surface"] extends "flyout" ? K : never;
143
+ }[ShotTool];
144
+
145
+ /** A type predicate rather than a set-membership test: a `ReadonlySet<string>`
146
+ * narrows nothing, so the draw lane would have to cast its tool back on the
147
+ * far side of a check that could not see it. */
148
+ export function isDrawTool(tool: ShotTool): tool is DrawTool {
149
+ return TOOL_SPECS[tool].draws;
150
+ }
151
+
152
+ const isDockTool = (tool: ShotTool): tool is DockTool => TOOL_SPECS[tool].surface === "dock";
153
+ const isFlyoutTool = (tool: ShotTool): tool is FlyoutTool => TOOL_SPECS[tool].surface === "flyout";
154
+
155
+ export const DOCK_TOOLS: readonly DockTool[] = SHOT_TOOLS.filter(isDockTool);
156
+ export const FLYOUT_TOOLS: readonly FlyoutTool[] = SHOT_TOOLS.filter(isFlyoutTool);
157
+
158
+ /** Keyed on `${letter}${shift ? "+" : ""}` so `l` and `l+` are different
159
+ * entries rather than one entry with a branch beside it. */
160
+ const TOOL_BY_KEY: ReadonlyMap<string, ShotTool> = new Map(
161
+ SHOT_TOOLS.flatMap((tool): Array<[string, ShotTool]> => {
162
+ const spec = specOf(tool);
163
+ return spec.key === null ? [] : [[bindingOf(spec.key, spec.shift === true), tool]];
164
+ }),
165
+ );
166
+
167
+ function bindingOf(key: string, shift: boolean): string {
168
+ return `${key.toLowerCase()}${shift ? "+" : ""}`;
169
+ }
170
+
171
+ /**
172
+ * THE KEYMAP'S WHOLE TOOL LANE: the tool this letter arms, or null when no tool
173
+ * claims it (which is how the transport and zoom keys keep theirs).
174
+ *
175
+ * Case and the shift bit are folded HERE as well as at the call site, so a
176
+ * caller that forgot cannot get a different answer from the one the table
177
+ * gives.
178
+ */
179
+ export function toolForKey(key: string, shift = false): ShotTool | null {
180
+ return TOOL_BY_KEY.get(bindingOf(key, shift)) ?? null;
181
+ }