@rightkit/video-ui 0.0.0-stage → 0.1.1

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 (148) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/LICENSE-APACHE +201 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +47 -2
  5. package/dist/appName.d.ts +2 -0
  6. package/dist/appName.js +8 -0
  7. package/dist/components/DesktopWorkspace.d.ts +4 -0
  8. package/dist/components/DesktopWorkspace.js +527 -0
  9. package/dist/components/Player.d.ts +49 -0
  10. package/dist/components/Player.js +335 -0
  11. package/dist/components/RangePreview.d.ts +9 -0
  12. package/dist/components/RangePreview.js +22 -0
  13. package/dist/components/Workspace.css +15 -0
  14. package/dist/demo/DemoSettings.d.ts +1 -0
  15. package/dist/demo/DemoSettings.js +43 -0
  16. package/dist/demo/bindings.d.ts +121 -0
  17. package/dist/demo/bindings.js +57 -0
  18. package/dist/demo/demo.css +124 -0
  19. package/dist/demo/useDemo.d.ts +8 -0
  20. package/dist/demo/useDemo.js +37 -0
  21. package/dist/editor/CaptionInspector.d.ts +8 -0
  22. package/dist/editor/CaptionInspector.js +33 -0
  23. package/dist/editor/ChangesPanel.d.ts +13 -0
  24. package/dist/editor/ChangesPanel.js +87 -0
  25. package/dist/editor/ColourInspector.d.ts +5 -0
  26. package/dist/editor/ColourInspector.js +341 -0
  27. package/dist/editor/Inspector.d.ts +15 -0
  28. package/dist/editor/Inspector.js +202 -0
  29. package/dist/editor/Timeline.d.ts +39 -0
  30. package/dist/editor/Timeline.js +506 -0
  31. package/dist/editor/TimelineEditorView.d.ts +9 -0
  32. package/dist/editor/TimelineEditorView.js +237 -0
  33. package/dist/editor/TranscriptPanel.d.ts +20 -0
  34. package/dist/editor/TranscriptPanel.js +180 -0
  35. package/dist/editor/actions.d.ts +63 -0
  36. package/dist/editor/actions.js +124 -0
  37. package/dist/editor/adapter.d.ts +76 -0
  38. package/dist/editor/adapter.js +181 -0
  39. package/dist/editor/capabilities.d.ts +37 -0
  40. package/dist/editor/capabilities.js +33 -0
  41. package/dist/editor/gesture.d.ts +29 -0
  42. package/dist/editor/gesture.js +119 -0
  43. package/dist/editor/index.d.ts +10 -0
  44. package/dist/editor/index.js +7 -0
  45. package/dist/editor/keys.d.ts +15 -0
  46. package/dist/editor/keys.js +42 -0
  47. package/dist/editor/model.d.ts +88 -0
  48. package/dist/editor/model.js +87 -0
  49. package/dist/editor/transcript.d.ts +27 -0
  50. package/dist/editor/transcript.js +59 -0
  51. package/dist/editor/vendor/hyperframes/PlayheadIndicator.d.ts +9 -0
  52. package/dist/editor/vendor/hyperframes/PlayheadIndicator.js +38 -0
  53. package/dist/editor/vendor/hyperframes/audioWaveformPeaks.d.ts +7 -0
  54. package/dist/editor/vendor/hyperframes/audioWaveformPeaks.js +47 -0
  55. package/dist/editor/vendor/hyperframes/rulerGeometry.d.ts +13 -0
  56. package/dist/editor/vendor/hyperframes/rulerGeometry.js +133 -0
  57. package/dist/editor/vendor/hyperframes/useInspectorGestureTransaction.d.ts +33 -0
  58. package/dist/editor/vendor/hyperframes/useInspectorGestureTransaction.js +126 -0
  59. package/dist/env.d.ts +66 -0
  60. package/dist/hooks/useEngine.d.ts +10 -0
  61. package/dist/hooks/useEngine.js +68 -0
  62. package/dist/hooks/useHdrToSdr.d.ts +11 -0
  63. package/dist/hooks/useHdrToSdr.js +19 -0
  64. package/dist/hooks/useProgress.d.ts +10 -0
  65. package/dist/hooks/useProgress.js +32 -0
  66. package/dist/index.d.ts +55 -0
  67. package/dist/index.js +57 -0
  68. package/dist/legal/legalConfig.d.ts +38 -0
  69. package/dist/legal/legalConfig.js +77 -0
  70. package/dist/lib/assemble.d.ts +100 -0
  71. package/dist/lib/assemble.js +72 -0
  72. package/dist/lib/asset.d.ts +2 -0
  73. package/dist/lib/asset.js +3 -0
  74. package/dist/lib/dialog.d.ts +4 -0
  75. package/dist/lib/dialog.js +44 -0
  76. package/dist/lib/engine.d.ts +44 -0
  77. package/dist/lib/engine.js +51 -0
  78. package/dist/lib/genright.d.ts +90 -0
  79. package/dist/lib/genright.js +160 -0
  80. package/dist/lib/media.d.ts +1045 -0
  81. package/dist/lib/media.js +171 -0
  82. package/dist/lib/mediaAdapters.d.ts +18 -0
  83. package/dist/lib/mediaAdapters.js +46 -0
  84. package/dist/lib/mic.d.ts +38 -0
  85. package/dist/lib/mic.js +14 -0
  86. package/dist/lib/models.d.ts +53 -0
  87. package/dist/lib/models.js +72 -0
  88. package/dist/lib/modelsBackend.d.ts +3 -0
  89. package/dist/lib/modelsBackend.js +68 -0
  90. package/dist/lib/progress.d.ts +77 -0
  91. package/dist/lib/progress.js +192 -0
  92. package/dist/lib/project.d.ts +138 -0
  93. package/dist/lib/project.js +48 -0
  94. package/dist/lib/services.d.ts +27 -0
  95. package/dist/lib/services.js +38 -0
  96. package/dist/lib/settingsBackend.d.ts +2 -0
  97. package/dist/lib/settingsBackend.js +57 -0
  98. package/dist/lib/shell.d.ts +172 -0
  99. package/dist/lib/shell.js +32 -0
  100. package/dist/styles.css +24 -0
  101. package/dist/ui/icons.d.ts +7 -0
  102. package/dist/ui/icons.js +62 -0
  103. package/dist/ui/index.d.ts +45 -0
  104. package/dist/ui/index.js +43 -0
  105. package/dist/ui/ui.css +104 -0
  106. package/dist/views/Assets.css +99 -0
  107. package/dist/views/AssetsView.d.ts +6 -0
  108. package/dist/views/AssetsView.js +371 -0
  109. package/dist/views/AutoEditView.d.ts +16 -0
  110. package/dist/views/AutoEditView.js +452 -0
  111. package/dist/views/BatchDelivery.d.ts +3 -0
  112. package/dist/views/BatchDelivery.js +331 -0
  113. package/dist/views/BundleExport.d.ts +3 -0
  114. package/dist/views/BundleExport.js +81 -0
  115. package/dist/views/Exports.css +117 -0
  116. package/dist/views/ExportsView.d.ts +12 -0
  117. package/dist/views/ExportsView.js +354 -0
  118. package/dist/views/FinishedEdit.css +546 -0
  119. package/dist/views/Home.css +97 -0
  120. package/dist/views/Home.d.ts +14 -0
  121. package/dist/views/Home.js +192 -0
  122. package/dist/views/Media.css +65 -0
  123. package/dist/views/OnboardingGate.d.ts +10 -0
  124. package/dist/views/OnboardingGate.js +54 -0
  125. package/dist/views/Phrases.css +45 -0
  126. package/dist/views/PhrasesView.d.ts +4 -0
  127. package/dist/views/PhrasesView.js +104 -0
  128. package/dist/views/ProgressView.d.ts +19 -0
  129. package/dist/views/ProgressView.js +36 -0
  130. package/dist/views/Prompt.css +84 -0
  131. package/dist/views/PromptPanel.d.ts +8 -0
  132. package/dist/views/PromptPanel.js +169 -0
  133. package/dist/views/Recipe.css +84 -0
  134. package/dist/views/RecipeLibrary.d.ts +7 -0
  135. package/dist/views/RecipeLibrary.js +104 -0
  136. package/dist/views/Retention.css +49 -0
  137. package/dist/views/RetentionView.d.ts +7 -0
  138. package/dist/views/RetentionView.js +145 -0
  139. package/dist/views/SettingsView.d.ts +9 -0
  140. package/dist/views/SettingsView.js +235 -0
  141. package/dist/views/Shorts.css +112 -0
  142. package/dist/views/ShortsView.d.ts +4 -0
  143. package/dist/views/ShortsView.js +205 -0
  144. package/dist/views/SourcesView.d.ts +6 -0
  145. package/dist/views/SourcesView.js +417 -0
  146. package/dist/views/TimelineView.d.ts +20 -0
  147. package/dist/views/TimelineView.js +12 -0
  148. package/package.json +68 -3
@@ -0,0 +1,124 @@
1
+ /* Agent demo mode. Loaded only by src/demo components, which exist only when __RIGHTKIT_DEMO__. */
2
+
3
+ .cr-demo-facts {
4
+ display: grid;
5
+ grid-template-columns: max-content 1fr;
6
+ gap: 4px 12px;
7
+ margin: 12px 0;
8
+ font-size: 13px;
9
+ }
10
+
11
+ .cr-demo-facts dt {
12
+ color: var(--rk-text-muted, #666);
13
+ }
14
+
15
+ .cr-demo-facts dd {
16
+ margin: 0;
17
+ overflow-wrap: anywhere;
18
+ }
19
+
20
+ .cr-demo-mono {
21
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
22
+ font-size: 12px;
23
+ }
24
+
25
+ .cr-demo-note {
26
+ font-size: 12px;
27
+ color: var(--rk-text-muted, #666);
28
+ }
29
+
30
+ .cr-demo-error {
31
+ color: #b42318;
32
+ font-size: 13px;
33
+ }
34
+
35
+ .cr-demo-btn {
36
+ padding: 6px 12px;
37
+ border: 1px solid var(--rk-border, #c8c8c8);
38
+ border-radius: 8px;
39
+ background: transparent;
40
+ color: inherit;
41
+ font: inherit;
42
+ font-size: 13px;
43
+ cursor: pointer;
44
+ }
45
+
46
+ .cr-demo-btn:disabled {
47
+ opacity: 0.5;
48
+ cursor: default;
49
+ }
50
+
51
+ .cr-demo-btn--danger {
52
+ border-color: #b42318;
53
+ color: #b42318;
54
+ }
55
+
56
+ /* Position only; Notice owns each bar's surface and controls. */
57
+ .cr-demo-position {
58
+ position: fixed;
59
+ left: 50%;
60
+ bottom: 16px;
61
+ z-index: 9999;
62
+ max-width: calc(100vw - 32px);
63
+ transform: translateX(-50%);
64
+ }
65
+
66
+ .cr-demo-dot {
67
+ flex: none;
68
+ width: 10px;
69
+ height: 10px;
70
+ border-radius: 50%;
71
+ background: #b42318;
72
+ }
73
+
74
+ .cr-demo-dot--live {
75
+ animation: cr-demo-pulse 1.4s ease-in-out infinite;
76
+ }
77
+
78
+ @keyframes cr-demo-pulse {
79
+ 50% {
80
+ opacity: 0.35;
81
+ }
82
+ }
83
+
84
+ @media (prefers-reduced-motion: reduce) {
85
+ .cr-demo-dot--live {
86
+ animation: none;
87
+ }
88
+ }
89
+
90
+ .cr-demo-inline {
91
+ display: inline-flex;
92
+ align-items: center;
93
+ gap: 8px;
94
+ }
95
+
96
+ /* The badge window: the whole page is the badge. */
97
+ .cr-demo-badge {
98
+ display: flex;
99
+ align-items: center;
100
+ gap: 10px;
101
+ box-sizing: border-box;
102
+ width: 100vw;
103
+ height: 100vh;
104
+ padding: 6px 10px;
105
+ background: var(--rk-surface, #fff);
106
+ color: var(--rk-text, #111);
107
+ font: 12px/1.3 system-ui, sans-serif;
108
+ border: 2px solid #b42318;
109
+ border-radius: 10px;
110
+ }
111
+
112
+ .cr-demo-badge__text {
113
+ display: flex;
114
+ flex: 1;
115
+ flex-direction: column;
116
+ min-width: 0;
117
+ }
118
+
119
+ .cr-demo-badge__text strong,
120
+ .cr-demo-badge__text span {
121
+ overflow: hidden;
122
+ white-space: nowrap;
123
+ text-overflow: ellipsis;
124
+ }
@@ -0,0 +1,8 @@
1
+ import { type DemoConsent, type DemoState, type DemoStatus } from "./bindings.js";
2
+ /** Live demo state: the saved on/off flag, the session phase and any consent waiting for an answer. */
3
+ export declare function useDemo(): {
4
+ status: DemoStatus | null;
5
+ state: DemoState;
6
+ consent: DemoConsent | null;
7
+ refresh: () => Promise<void>;
8
+ };
@@ -0,0 +1,37 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { demoStatus, onDemoConsent, onDemoState, } from "./bindings.js";
3
+ const IDLE = { phase: "idle", session: null, bundle: null, message: null, hotkey: "" };
4
+ /** Live demo state: the saved on/off flag, the session phase and any consent waiting for an answer. */
5
+ export function useDemo() {
6
+ const [status, setStatus] = useState(null);
7
+ const [state, setState] = useState(IDLE);
8
+ const [consent, setConsent] = useState(null);
9
+ const refresh = useCallback(async () => {
10
+ try {
11
+ const s = await demoStatus();
12
+ setStatus(s);
13
+ setState(s.state);
14
+ setConsent(s.pending_consent);
15
+ }
16
+ catch {
17
+ // A build without the demo feature has no such command: demo mode simply is not there.
18
+ setStatus(null);
19
+ }
20
+ }, []);
21
+ useEffect(() => {
22
+ void refresh();
23
+ const unlisten = Promise.all([
24
+ onDemoState((s) => {
25
+ setState(s);
26
+ setStatus((prev) => (prev ? { ...prev, state: s, hotkey: s.hotkey } : prev));
27
+ if (s.phase !== "awaiting_consent")
28
+ setConsent(null);
29
+ }),
30
+ onDemoConsent((c) => setConsent(c)),
31
+ ]);
32
+ return () => {
33
+ void unlisten.then((fns) => fns.forEach((f) => f()));
34
+ };
35
+ }, [refresh]);
36
+ return { status, state, consent, refresh };
37
+ }
@@ -0,0 +1,8 @@
1
+ import type { EditSession } from "./adapter.js";
2
+ import type { EditorModel } from "./model.js";
3
+ export declare function CaptionInspector({ model, session, onCommitted, onError }: {
4
+ model: EditorModel;
5
+ session: EditSession;
6
+ onCommitted: () => void;
7
+ onError: (s: string) => void;
8
+ }): import("react").JSX.Element;
@@ -0,0 +1,33 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Field, Input } from "@rightkit/react-shell/react";
3
+ import { useState } from "react";
4
+ import { errorText } from "./adapter.js";
5
+ import { editCaption, removeCaption } from "./actions.js";
6
+ export function CaptionInspector({ model, session, onCommitted, onError }) {
7
+ const [id, setId] = useState("");
8
+ const cue = model.captions.find((c) => c.id === id) ?? model.captions[0];
9
+ return _jsxs("div", { className: "fe-inspect", "aria-label": "Caption corrections", children: [_jsx(Field, { label: "Caption", children: (ids) => (_jsx("select", { ...ids, className: "rk-input cr-select", "aria-label": "Caption to correct", value: cue?.id ?? "", onChange: (e) => setId(e.target.value), children: model.captions.map((c) => _jsx("option", { value: c.id, children: c.text }, c.id)) })) }), cue ? _jsx(CaptionFields, { cue: cue, fps: model.fps, onSave: async (next) => {
10
+ try {
11
+ await session.apply(editCaption(cue.id, next), "Caption correction");
12
+ onCommitted();
13
+ }
14
+ catch (e) {
15
+ onError(errorText(e));
16
+ onCommitted();
17
+ }
18
+ }, onRestore: async () => {
19
+ try {
20
+ await session.apply(removeCaption(cue.id), "Restore original caption");
21
+ onCommitted();
22
+ }
23
+ catch (e) {
24
+ onError(errorText(e));
25
+ onCommitted();
26
+ }
27
+ } }, `${cue.id}:${model.revisionCursor}`) : _jsx("p", { className: "cr-muted", children: "Transcribe footage to edit captions." })] });
28
+ }
29
+ function CaptionFields({ cue, fps, onSave, onRestore }) {
30
+ const [draft, setDraft] = useState(cue);
31
+ const number = (label, value, update) => _jsx(Field, { label: label, children: (ids) => (_jsx(Input, { ...ids, type: "number", step: "0.01", "aria-label": label, value: value, onChange: (e) => update(Number(e.target.value)) })) });
32
+ return _jsxs(_Fragment, { children: [_jsx(Field, { label: "Caption text", children: (ids) => (_jsx("textarea", { ...ids, className: "rk-input", "aria-label": "Caption text", maxLength: 160, value: draft.text, onChange: (e) => setDraft({ ...draft, text: e.target.value }) })) }), number("Caption start (s)", draft.start_frame / fps, (v) => setDraft({ ...draft, start_frame: Math.round(v * fps) })), number("Caption duration (s)", draft.frames / fps, (v) => setDraft({ ...draft, frames: Math.round(v * fps) })), number("Caption horizontal position (%)", draft.position.x / 10, (v) => setDraft({ ...draft, position: { ...draft.position, x: Math.round(v * 10) } })), number("Caption vertical position (%)", draft.position.y / 10, (v) => setDraft({ ...draft, position: { ...draft.position, y: Math.round(v * 10) } })), _jsx("button", { type: "button", className: "rk-button", onClick: () => void onSave(draft), children: "Save caption" }), cue.corrected ? _jsx("button", { type: "button", className: "rk-button", onClick: () => void onRestore(), children: "Restore original" }) : null] });
33
+ }
@@ -0,0 +1,13 @@
1
+ import { type StoredPlan } from "../lib/media.js";
2
+ import type { EditSession } from "./adapter.js";
3
+ export declare function ChangesPanel({ dir, plans, loadError, session, onCommitted, onSeek, }: {
4
+ dir: string;
5
+ plans: StoredPlan[];
6
+ /** Why the stored plans could not be read, when they could not. */
7
+ loadError?: string | null;
8
+ session: EditSession;
9
+ /** Re-read `project.show` + cues after a review lands (or fails). */
10
+ onCommitted: () => void;
11
+ /** Seek the timeline playhead to a timeline-mapped second. */
12
+ onSeek: (timeS: number) => void;
13
+ }): import("react").JSX.Element;
@@ -0,0 +1,87 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Changes tab of the Finished edit side panel (docs/design/app-ui.md §3.4).
4
+ * Reads the stored auto-edit plans via `editplan.list` (analysis/editplan-*.json
5
+ * with every item and take mapped through the live timeline by the engine):
6
+ * items grouped by editorial category with counts, each suggestion with its
7
+ * why text, Apply / Dismiss, and "Use other take" for retake groups.
8
+ *
9
+ * Apply/Dismiss/take picks run through `autoedit.apply` reviews
10
+ * ({accept, reject, takes}) — the engine re-resolves the plan under the review
11
+ * and lands it as real revisions, then the host refreshes `project.show`.
12
+ */
13
+ import { Button } from "@rightkit/react-shell/react";
14
+ import { useEffect, useMemo, useState } from "react";
15
+ import { errorMessage } from "../lib/engine.js";
16
+ import { autoeditApply, editplanList, } from "../lib/media.js";
17
+ import { formatSeconds } from "../lib/project.js";
18
+ /** Item kind (snake_case) → the spec's Change groups. */
19
+ function groupOf(item) {
20
+ const k = item.kind ?? "";
21
+ if (k.includes("retake"))
22
+ return "Retakes";
23
+ if (["silence", "long_pause", "breath", "low_energy", "off_mic"].includes(k))
24
+ return "Pacing";
25
+ return "Structure";
26
+ }
27
+ /** Item kind → readable name (title case, no jargon). */
28
+ function kindName(kind) {
29
+ return kind
30
+ .split("_")
31
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
32
+ .join(" ");
33
+ }
34
+ export function ChangesPanel({ dir, plans, loadError, session, onCommitted, onSeek, }) {
35
+ const [local, setLocal] = useState(null);
36
+ const [error, setError] = useState(null);
37
+ const [altFor, setAltFor] = useState(null);
38
+ const data = local ?? plans;
39
+ useEffect(() => setLocal(null), [plans]);
40
+ const review = useMemo(() => async (plan, rv) => {
41
+ setError(null);
42
+ try {
43
+ await autoeditApply(dir, plan.config?.cuts?.preset ?? "natural", {
44
+ source: plan.source ?? plan.source_blake3,
45
+ review: rv,
46
+ });
47
+ const r = await editplanList(dir);
48
+ setLocal(r.plans);
49
+ onCommitted();
50
+ }
51
+ catch (e) {
52
+ setError(errorMessage(e));
53
+ onCommitted();
54
+ }
55
+ }, [dir, onCommitted]);
56
+ const items = data.flatMap((pl) => pl.items ?? []);
57
+ const pending = items.filter((i) => i.tier === "suggest").length;
58
+ if (loadError) {
59
+ return (_jsxs("p", { className: "cr-muted", role: "alert", style: { margin: 0, fontSize: 12 }, children: ["The auto-edit plan could not be read \u2014 ", loadError] }));
60
+ }
61
+ if (items.length === 0 && data.every((pl) => (pl.take_groups ?? []).length === 0)) {
62
+ return (_jsx("p", { className: "cr-muted", style: { margin: 0, fontSize: 12 }, children: "No auto-edit plan on this project yet \u2014 changes will appear here after an auto-edit run." }));
63
+ }
64
+ const groups = ["Retakes", "Pacing", "Structure"]
65
+ .map((label) => ({
66
+ label,
67
+ items: data.flatMap((pl) => (pl.items ?? [])
68
+ .filter((i) => groupOf(i) === label)
69
+ .map((item) => ({ plan: pl, item }))),
70
+ }))
71
+ .filter((g) => g.items.length > 0);
72
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "fe-change-group", children: _jsxs("div", { className: "fe-change-group__head", children: [_jsx("h4", { children: "Auto-edit" }), _jsx("span", { className: "rk-badge", children: items.length }), pending > 0 && _jsxs("span", { className: "rk-badge", children: [pending, " suggested"] })] }) }), error && (_jsx("p", { role: "alert", className: "cr-muted", style: { margin: 0, fontSize: 12 }, children: error })), groups.map((g) => (_jsxs("section", { className: "fe-change-group", children: [_jsxs("div", { className: "fe-change-group__head", children: [_jsx("h4", { children: g.label }), _jsx("span", { className: "rk-badge", children: g.items.length })] }), g.items.map(({ plan, item }) => (_jsx(ChangeRow, { plan: plan, item: item, busy: session.busy, altOpen: altFor === item.id, onToggleAlt: () => setAltFor(altFor === item.id ? null : item.id), onSeek: onSeek, onReview: (rv) => void review(plan, rv) }, item.id)))] }, g.label)))] }));
73
+ }
74
+ function ChangeRow({ plan, item, busy, altOpen, onToggleAlt, onSeek, onReview, }) {
75
+ const suggested = item.tier === "suggest";
76
+ const placed = (item.out?.length ?? 0) > 0;
77
+ const at = item.at_ms ?? item.start_ms;
78
+ const takeGroup = item.take
79
+ ? plan.take_groups?.find((g) => g.id === item.take?.group)
80
+ : undefined;
81
+ const covered = item.covered_by != null;
82
+ const stateChip = suggested ? (_jsx("span", { className: "rk-badge", children: "Suggested" })) : placed ? (_jsx("span", { className: "rk-badge", children: "On timeline" })) : (_jsx("span", { className: "rk-badge", children: "Applied" }));
83
+ return (_jsxs("div", { className: "fe-change", "data-state": suggested ? "suggested" : "applied", children: [_jsxs("div", { className: "fe-change__head", children: [_jsx("button", { type: "button", className: "fe-change__label", title: `${kindName(item.kind)} · ${formatSeconds(at / 1000)} on the timeline`, onClick: () => onSeek(at / 1000), children: item.text ? `\u201C${item.text}\u201D` : kindName(item.kind) }), stateChip] }), item.reason && _jsx("p", { className: "fe-change__reason", children: item.reason }), covered && (_jsx("p", { className: "fe-change__reason", children: "Already covered by a higher-priority change." })), _jsxs("div", { className: "fe-change__actions", children: [suggested && (_jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", disabled: busy, onClick: () => onReview({ accept: [item.id] }), children: "Apply" }), _jsx(Button, { size: "sm", variant: "ghost", disabled: busy, onClick: () => onReview({ reject: [item.id] }), children: "Dismiss" })] })), takeGroup && takeGroup.takes.length > 1 && (_jsx(Button, { size: "sm", variant: "ghost", disabled: busy, onClick: onToggleAlt, children: altOpen ? "Hide takes" : "Use other take" }))] }), altOpen && takeGroup && (_jsx("div", { className: "fe-change__alts", children: takeGroup.takes.map((alt) => {
84
+ const isCurrent = alt.chosen === true || alt.index === takeGroup.chosen;
85
+ return (_jsxs("div", { className: `fe-take${isCurrent ? " fe-take--current" : ""}`, children: [_jsxs("span", { className: "fe-take__label", title: alt.text, children: ["Take ", alt.index + 1, alt.at_ms != null && ` · ${formatSeconds(alt.at_ms / 1000)}`, alt.rank != null && ` · rank ${alt.rank}`] }), isCurrent ? (_jsx("span", { className: "rk-badge", children: "Current" })) : (_jsx(Button, { size: "sm", disabled: busy, onClick: () => onReview({ takes: { [takeGroup.id]: alt.index } }), children: "Use this take" }))] }, alt.index));
86
+ }) }))] }));
87
+ }
@@ -0,0 +1,5 @@
1
+ export declare function ColourInspector({ dir, sourceId, atMs }: {
2
+ dir: string;
3
+ sourceId: string;
4
+ atMs: number;
5
+ }): import("react").JSX.Element;