@tangle-network/agent-app 0.42.5 → 0.42.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{DesignCanvas-AOIVN3SJ.js → DesignCanvas-GUTCY763.js} +2 -2
- package/dist/{DesignCanvasEditor-QQNAZRJQ.js → DesignCanvasEditor-ZO4V7H6A.js} +4 -4
- package/dist/{TimelineEditor-Z7C6BFP5.js → TimelineEditor-SNOAGBV6.js} +2 -2
- package/dist/brand/index.d.ts +35 -0
- package/dist/brand/index.js +89 -0
- package/dist/brand/index.js.map +1 -0
- package/dist/{chunk-YYYXGLLQ.js → chunk-6JYDS34Y.js} +184 -54
- package/dist/chunk-6JYDS34Y.js.map +1 -0
- package/dist/{chunk-FJUOBNIY.js → chunk-A5Z53E3A.js} +3 -3
- package/dist/{chunk-V5XZKHCL.js → chunk-AFQXKJAE.js} +132 -2
- package/dist/chunk-AFQXKJAE.js.map +1 -0
- package/dist/{chunk-S6WS2B32.js → chunk-EX3LD5G6.js} +322 -122
- package/dist/chunk-EX3LD5G6.js.map +1 -0
- package/dist/{chunk-DTS5TZRN.js → chunk-MFI4ZM7W.js} +2 -2
- package/dist/chunk-MFI4ZM7W.js.map +1 -0
- package/dist/{chunk-YEWTVDDT.js → chunk-OVUQNKLM.js} +379 -323
- package/dist/chunk-OVUQNKLM.js.map +1 -0
- package/dist/chunk-ZN5J47UX.js +1 -0
- package/dist/chunk-ZN5J47UX.js.map +1 -0
- package/dist/{command-stack-CkjelfK_.d.ts → command-stack-CcWi_2bN.d.ts} +15 -0
- package/dist/design-canvas-react/engine.d.ts +2 -2
- package/dist/design-canvas-react/engine.js +5 -6
- package/dist/design-canvas-react/index.d.ts +61 -8
- package/dist/design-canvas-react/index.js +10 -9
- package/dist/design-canvas-react/lazy.d.ts +2 -2
- package/dist/design-canvas-react/lazy.js +1 -1
- package/dist/{lazy-BHHqS8-j.d.ts → lazy-2XBVp1_e.d.ts} +6 -2
- package/dist/sequences-react/index.d.ts +94 -2
- package/dist/sequences-react/index.js +12 -2
- package/dist/sequences-react/index.js.map +1 -1
- package/dist/studio/index.d.ts +1 -1
- package/dist/studio/index.js +1 -1
- package/dist/studio-react/index.js +1 -1
- package/dist/teams/index.js +5 -5
- package/dist/teams/invitations-api.js +1 -1
- package/dist/teams/resend.d.ts +36 -0
- package/dist/teams/resend.js +38 -0
- package/dist/teams/resend.js.map +1 -0
- package/dist/web-react/index.d.ts +57 -6
- package/dist/web-react/index.js +361 -200
- package/dist/web-react/index.js.map +1 -1
- package/package.json +25 -10
- package/dist/chunk-DTS5TZRN.js.map +0 -1
- package/dist/chunk-S6WS2B32.js.map +0 -1
- package/dist/chunk-SQV7NUEM.js +0 -136
- package/dist/chunk-SQV7NUEM.js.map +0 -1
- package/dist/chunk-V5XZKHCL.js.map +0 -1
- package/dist/chunk-YEWTVDDT.js.map +0 -1
- package/dist/chunk-YYYXGLLQ.js.map +0 -1
- /package/dist/{DesignCanvas-AOIVN3SJ.js.map → DesignCanvas-GUTCY763.js.map} +0 -0
- /package/dist/{DesignCanvasEditor-QQNAZRJQ.js.map → DesignCanvasEditor-ZO4V7H6A.js.map} +0 -0
- /package/dist/{TimelineEditor-Z7C6BFP5.js.map → TimelineEditor-SNOAGBV6.js.map} +0 -0
- /package/dist/{chunk-FJUOBNIY.js.map → chunk-A5Z53E3A.js.map} +0 -0
|
@@ -13,6 +13,24 @@ import {
|
|
|
13
13
|
// src/sequences-react/components/TimelineEditor.tsx
|
|
14
14
|
import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef3, useState as useState3, useSyncExternalStore } from "react";
|
|
15
15
|
|
|
16
|
+
// src/sequences-react/contracts.ts
|
|
17
|
+
var DEFAULT_TIMELINE_LABELS = {
|
|
18
|
+
splitClip: "Split here",
|
|
19
|
+
splitClipAriaLabel: "Split clip at playhead",
|
|
20
|
+
addCaption: "Add caption",
|
|
21
|
+
addCaptionAriaLabel: "Add caption at playhead",
|
|
22
|
+
createExport: "Export\u2026",
|
|
23
|
+
emptyTitle: "This sequence has no tracks yet",
|
|
24
|
+
emptyBody: "Start from a template, drop in a clip, or hand it to the agent.",
|
|
25
|
+
emptyTemplateDoor: "Start from a template",
|
|
26
|
+
emptyClipDoor: "Add a clip",
|
|
27
|
+
emptyAgentDoor: "Ask the agent",
|
|
28
|
+
smallScreenTitle: "Best edited on a larger screen",
|
|
29
|
+
smallScreenBody: "The timeline needs room to scrub and trim. Open this cut on a tablet or desktop to edit.",
|
|
30
|
+
ghostVideoLane: "Video",
|
|
31
|
+
ghostCaptionLane: "Captions"
|
|
32
|
+
};
|
|
33
|
+
|
|
16
34
|
// src/sequences-react/engine/command-stack.ts
|
|
17
35
|
var COMMAND_HISTORY_LIMIT = 200;
|
|
18
36
|
function createCommandStack(initial) {
|
|
@@ -1211,7 +1229,7 @@ function TimelineRuler({ fps, durationFrames, zoom, onScrub }) {
|
|
|
1211
1229
|
{
|
|
1212
1230
|
"data-timeline-ruler": true,
|
|
1213
1231
|
className: "relative h-7 cursor-ew-resize select-none border-b border-[var(--border-default)] bg-[var(--bg-input)]",
|
|
1214
|
-
style: { width: `${durationFrames * zoom}px
|
|
1232
|
+
style: { width: `${durationFrames * zoom}px`, touchAction: "none" },
|
|
1215
1233
|
onPointerDown: handlePointerDown,
|
|
1216
1234
|
onPointerMove: handlePointerMove,
|
|
1217
1235
|
children: ticks.map((tick) => /* @__PURE__ */ jsx4(
|
|
@@ -1604,7 +1622,9 @@ function TimelineClipChip(props) {
|
|
|
1604
1622
|
style: {
|
|
1605
1623
|
left: `${geometry.left}px`,
|
|
1606
1624
|
width: `${geometry.width}px`,
|
|
1607
|
-
transform: shown.translateY !== 0 ? `translateY(${shown.translateY}px)` : void 0
|
|
1625
|
+
transform: shown.translateY !== 0 ? `translateY(${shown.translateY}px)` : void 0,
|
|
1626
|
+
// own the touch gesture so move/trim drags don't trigger lane scroll
|
|
1627
|
+
touchAction: "none"
|
|
1608
1628
|
},
|
|
1609
1629
|
onPointerDown: (event) => beginGesture(event, "move"),
|
|
1610
1630
|
onPointerMove: updateGesture,
|
|
@@ -1750,6 +1770,12 @@ var CaptionPlusGlyph = glyph(
|
|
|
1750
1770
|
/* @__PURE__ */ jsx6("path", { d: "M12 9v6M9 12h6" })
|
|
1751
1771
|
] })
|
|
1752
1772
|
);
|
|
1773
|
+
var ExportGlyph = glyph(
|
|
1774
|
+
/* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1775
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
|
|
1776
|
+
/* @__PURE__ */ jsx6("path", { d: "M12 3v12M8 7l4-4 4 4" })
|
|
1777
|
+
] })
|
|
1778
|
+
);
|
|
1753
1779
|
|
|
1754
1780
|
// src/sequences-react/components/TimelineTrackRow.tsx
|
|
1755
1781
|
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
@@ -1791,7 +1817,7 @@ function TimelineTrackRow(props) {
|
|
|
1791
1817
|
"data-lane-kind": track.kind,
|
|
1792
1818
|
"data-lane-locked": track.locked ? "true" : "false",
|
|
1793
1819
|
className: `relative ${laneHeight} ${track.muted ? "opacity-60" : ""}`,
|
|
1794
|
-
style: { width: `${sequenceDurationFrames * zoom}px
|
|
1820
|
+
style: { width: `${sequenceDurationFrames * zoom}px`, touchAction: "none" },
|
|
1795
1821
|
onPointerDown: handleLanePointerDown,
|
|
1796
1822
|
children: clips.map((clip) => /* @__PURE__ */ jsx7(
|
|
1797
1823
|
TimelineClipChip,
|
|
@@ -1822,62 +1848,194 @@ function TimelineTrackRow(props) {
|
|
|
1822
1848
|
] });
|
|
1823
1849
|
}
|
|
1824
1850
|
|
|
1851
|
+
// src/sequences-react/components/BrandMark.tsx
|
|
1852
|
+
import { lazy, Suspense } from "react";
|
|
1853
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1854
|
+
function MarkSpacer({ size }) {
|
|
1855
|
+
return /* @__PURE__ */ jsx8("span", { "aria-hidden": true, style: { display: "inline-block", width: size, height: size } });
|
|
1856
|
+
}
|
|
1857
|
+
var LazyKnot = lazy(async () => {
|
|
1858
|
+
try {
|
|
1859
|
+
const mod = await import("./brand/index.js");
|
|
1860
|
+
return { default: mod.TangleKnot };
|
|
1861
|
+
} catch {
|
|
1862
|
+
return { default: MarkSpacer };
|
|
1863
|
+
}
|
|
1864
|
+
});
|
|
1865
|
+
function BrandMark({ size, className }) {
|
|
1866
|
+
return /* @__PURE__ */ jsx8(Suspense, { fallback: /* @__PURE__ */ jsx8(MarkSpacer, { size }), children: /* @__PURE__ */ jsx8(LazyKnot, { size, className }) });
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
// src/sequences-react/components/TimelineEmptyState.tsx
|
|
1870
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1871
|
+
var DOOR_BUTTON = "flex min-h-[44px] items-center gap-2 rounded-md border border-[var(--border-default)] bg-[var(--bg-input)] px-3.5 py-2 text-xs font-medium text-[var(--text-secondary)] transition hover:border-[var(--brand-primary)] hover:text-[var(--text-primary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
1872
|
+
function TimelineEmptyState(props) {
|
|
1873
|
+
const labels = { ...DEFAULT_TIMELINE_LABELS, ...props.labels };
|
|
1874
|
+
const doors = [];
|
|
1875
|
+
if (props.onStartFromTemplate) {
|
|
1876
|
+
doors.push({ key: "template", label: labels.emptyTemplateDoor, primary: true, icon: FilmGlyph, onClick: props.onStartFromTemplate });
|
|
1877
|
+
}
|
|
1878
|
+
if (props.onAddClip) {
|
|
1879
|
+
doors.push({ key: "clip", label: labels.emptyClipDoor, primary: false, icon: CaptionPlusGlyph, onClick: props.onAddClip });
|
|
1880
|
+
}
|
|
1881
|
+
if (props.onAskAgent) {
|
|
1882
|
+
doors.push({ key: "agent", label: labels.emptyAgentDoor, primary: false, icon: AgentGlyph, onClick: props.onAskAgent });
|
|
1883
|
+
}
|
|
1884
|
+
return /* @__PURE__ */ jsxs6(
|
|
1885
|
+
"div",
|
|
1886
|
+
{
|
|
1887
|
+
"data-timeline-empty": true,
|
|
1888
|
+
className: "sticky left-0 flex min-h-[6rem] flex-col items-center justify-center gap-3 px-6 py-9 text-center",
|
|
1889
|
+
style: { width: "100%" },
|
|
1890
|
+
children: [
|
|
1891
|
+
/* @__PURE__ */ jsx9(BrandMark, { size: 28, className: "shrink-0 opacity-90" }),
|
|
1892
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-1", children: [
|
|
1893
|
+
/* @__PURE__ */ jsx9("p", { className: "text-sm font-semibold text-[var(--text-primary)]", children: labels.emptyTitle }),
|
|
1894
|
+
/* @__PURE__ */ jsx9("p", { className: "max-w-sm text-xs text-[var(--text-muted)]", children: labels.emptyBody })
|
|
1895
|
+
] }),
|
|
1896
|
+
doors.length > 0 ? /* @__PURE__ */ jsx9("div", { className: "flex flex-wrap items-center justify-center gap-2 pt-1", children: doors.map(({ key, label, primary, icon: Icon, onClick }) => /* @__PURE__ */ jsxs6(
|
|
1897
|
+
"button",
|
|
1898
|
+
{
|
|
1899
|
+
type: "button",
|
|
1900
|
+
onClick,
|
|
1901
|
+
className: primary ? "flex min-h-[44px] items-center gap-2 rounded-md bg-[var(--brand-primary)] px-3.5 py-2 text-xs font-semibold text-[hsl(var(--primary-foreground))] transition hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring" : DOOR_BUTTON,
|
|
1902
|
+
children: [
|
|
1903
|
+
/* @__PURE__ */ jsx9(Icon, { className: "h-4 w-4 shrink-0" }),
|
|
1904
|
+
label
|
|
1905
|
+
]
|
|
1906
|
+
},
|
|
1907
|
+
key
|
|
1908
|
+
)) }) : null
|
|
1909
|
+
]
|
|
1910
|
+
}
|
|
1911
|
+
);
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
// src/sequences-react/components/TimelineGhostLanes.tsx
|
|
1915
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1916
|
+
function GhostLane({
|
|
1917
|
+
label,
|
|
1918
|
+
icon: Icon,
|
|
1919
|
+
height,
|
|
1920
|
+
laneWidth
|
|
1921
|
+
}) {
|
|
1922
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex border-b border-[var(--border-default)] last:border-b-0 opacity-60", children: [
|
|
1923
|
+
/* @__PURE__ */ jsxs7(
|
|
1924
|
+
"div",
|
|
1925
|
+
{
|
|
1926
|
+
className: `sticky left-0 z-10 flex w-36 shrink-0 items-center gap-2 border-r border-[var(--border-default)] bg-[var(--bg-input)] px-2.5 ${height}`,
|
|
1927
|
+
children: [
|
|
1928
|
+
/* @__PURE__ */ jsx10(Icon, { className: "h-3.5 w-3.5 shrink-0 text-[var(--text-muted)]" }),
|
|
1929
|
+
/* @__PURE__ */ jsx10("span", { className: "min-w-0 flex-1 truncate text-xs font-medium text-[var(--text-muted)]", children: label })
|
|
1930
|
+
]
|
|
1931
|
+
}
|
|
1932
|
+
),
|
|
1933
|
+
/* @__PURE__ */ jsx10("div", { className: `${height}`, style: { width: `${laneWidth}px` } })
|
|
1934
|
+
] });
|
|
1935
|
+
}
|
|
1936
|
+
function TimelineGhostLanes({ laneWidth, videoLabel, captionLabel }) {
|
|
1937
|
+
return /* @__PURE__ */ jsxs7("div", { "data-timeline-ghost-lanes": true, "aria-hidden": true, className: "pointer-events-none absolute inset-0", children: [
|
|
1938
|
+
/* @__PURE__ */ jsx10(GhostLane, { label: videoLabel, icon: FilmGlyph, height: "h-16", laneWidth }),
|
|
1939
|
+
/* @__PURE__ */ jsx10(GhostLane, { label: captionLabel, icon: CaptionGlyph, height: "h-9", laneWidth })
|
|
1940
|
+
] });
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
// src/sequences-react/components/TimelineSmallScreenGate.tsx
|
|
1944
|
+
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1945
|
+
function TimelineSmallScreenGate({ labels }) {
|
|
1946
|
+
const copy = { ...DEFAULT_TIMELINE_LABELS, ...labels };
|
|
1947
|
+
return /* @__PURE__ */ jsxs8(
|
|
1948
|
+
"div",
|
|
1949
|
+
{
|
|
1950
|
+
"data-timeline-small-screen": true,
|
|
1951
|
+
className: "flex h-full min-h-0 flex-col items-center justify-center gap-3 bg-[var(--bg-input)] px-8 py-12 text-center text-[var(--text-primary)] sm:hidden",
|
|
1952
|
+
children: [
|
|
1953
|
+
/* @__PURE__ */ jsx11(BrandMark, { size: 32, className: "shrink-0 opacity-90" }),
|
|
1954
|
+
/* @__PURE__ */ jsx11("p", { className: "text-base font-semibold", children: copy.smallScreenTitle }),
|
|
1955
|
+
/* @__PURE__ */ jsx11("p", { className: "max-w-xs text-sm text-[var(--text-muted)]", children: copy.smallScreenBody })
|
|
1956
|
+
]
|
|
1957
|
+
}
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1825
1961
|
// src/sequences-react/components/ZoomControl.tsx
|
|
1826
|
-
import { jsx as
|
|
1827
|
-
function
|
|
1962
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1963
|
+
function zoomPercent(zoom, fitZoom) {
|
|
1964
|
+
const base = fitZoom && fitZoom > 0 ? fitZoom : 1;
|
|
1965
|
+
return Math.round(zoom / base * 100);
|
|
1966
|
+
}
|
|
1967
|
+
var ZOOM_STEP_BUTTON = "flex h-7 w-7 items-center justify-center rounded border border-[var(--border-default)] text-sm leading-none text-[var(--text-secondary)] transition hover:text-[var(--text-primary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
1968
|
+
function ZoomControl({ zoomMath, zoom, onZoomChange, fitZoom }) {
|
|
1828
1969
|
const sliderMin = zoomMath.zoomToSlider(zoomMath.minZoom);
|
|
1829
1970
|
const sliderMax = zoomMath.zoomToSlider(zoomMath.maxZoom);
|
|
1830
1971
|
const sliderStep = (sliderMax - sliderMin) / 100;
|
|
1831
1972
|
const slider = zoomMath.zoomToSlider(zoom);
|
|
1973
|
+
const percent = zoomPercent(zoom, fitZoom);
|
|
1832
1974
|
function setSlider(next) {
|
|
1833
1975
|
const clamped = Math.max(sliderMin, Math.min(sliderMax, next));
|
|
1834
1976
|
onZoomChange(zoomMath.sliderToZoom(clamped));
|
|
1835
1977
|
}
|
|
1836
|
-
return /* @__PURE__ */
|
|
1837
|
-
/* @__PURE__ */
|
|
1978
|
+
return /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1.5", children: [
|
|
1979
|
+
/* @__PURE__ */ jsx12(
|
|
1838
1980
|
"button",
|
|
1839
1981
|
{
|
|
1840
1982
|
type: "button",
|
|
1841
1983
|
"aria-label": "Zoom out",
|
|
1842
1984
|
onClick: () => setSlider(slider - sliderStep * 10),
|
|
1843
|
-
className:
|
|
1985
|
+
className: ZOOM_STEP_BUTTON,
|
|
1844
1986
|
children: "\u2212"
|
|
1845
1987
|
}
|
|
1846
1988
|
),
|
|
1847
|
-
/* @__PURE__ */
|
|
1989
|
+
/* @__PURE__ */ jsx12(
|
|
1848
1990
|
"input",
|
|
1849
1991
|
{
|
|
1850
1992
|
type: "range",
|
|
1851
1993
|
"aria-label": "Timeline zoom",
|
|
1994
|
+
"aria-valuetext": `${percent}%`,
|
|
1852
1995
|
min: sliderMin,
|
|
1853
1996
|
max: sliderMax,
|
|
1854
1997
|
step: sliderStep,
|
|
1855
1998
|
value: slider,
|
|
1856
1999
|
onChange: (event) => setSlider(Number(event.target.value)),
|
|
1857
|
-
className: "h-1 w-24 cursor-pointer accent-[var(--brand-primary)]"
|
|
2000
|
+
className: "hidden h-1 w-24 cursor-pointer accent-[var(--brand-primary)] sm:block"
|
|
1858
2001
|
}
|
|
1859
2002
|
),
|
|
1860
|
-
/* @__PURE__ */
|
|
2003
|
+
/* @__PURE__ */ jsx12(
|
|
1861
2004
|
"button",
|
|
1862
2005
|
{
|
|
1863
2006
|
type: "button",
|
|
1864
2007
|
"aria-label": "Zoom in",
|
|
1865
2008
|
onClick: () => setSlider(slider + sliderStep * 10),
|
|
1866
|
-
className:
|
|
2009
|
+
className: ZOOM_STEP_BUTTON,
|
|
1867
2010
|
children: "+"
|
|
1868
2011
|
}
|
|
2012
|
+
),
|
|
2013
|
+
/* @__PURE__ */ jsxs9(
|
|
2014
|
+
"output",
|
|
2015
|
+
{
|
|
2016
|
+
"aria-hidden": true,
|
|
2017
|
+
title: fitZoom ? "Zoom (100% = fits the whole sequence)" : "Zoom",
|
|
2018
|
+
onClick: fitZoom ? () => onZoomChange(fitZoom) : void 0,
|
|
2019
|
+
className: `w-11 select-none text-right font-mono text-[11px] tabular-nums text-[var(--text-muted)] ${fitZoom ? "cursor-pointer hover:text-[var(--text-primary)]" : ""}`,
|
|
2020
|
+
children: [
|
|
2021
|
+
percent,
|
|
2022
|
+
"%"
|
|
2023
|
+
]
|
|
2024
|
+
}
|
|
1869
2025
|
)
|
|
1870
2026
|
] });
|
|
1871
2027
|
}
|
|
1872
2028
|
|
|
1873
2029
|
// src/sequences-react/components/TimelineEditor.tsx
|
|
1874
|
-
import { Fragment as Fragment3, jsx as
|
|
2030
|
+
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1875
2031
|
var SEQUENCE_MEDIA_DRAG_TYPE = "application/x-sequence-media";
|
|
1876
2032
|
var HISTORY_MIRROR_LIMIT = 200;
|
|
1877
2033
|
var MIN_ZOOM = 5e-3;
|
|
1878
2034
|
var MAX_ZOOM = 24;
|
|
1879
2035
|
var TRACK_HEADER_PX = 144;
|
|
1880
|
-
var TRANSPORT_BUTTON = "flex h-7 w-7 items-center justify-center rounded border border-[var(--border-default)] text-[var(--text-secondary)] transition hover:text-[var(--text-primary)] disabled:cursor-default disabled:opacity-40 disabled:hover:text-[var(--text-secondary)]";
|
|
2036
|
+
var TRANSPORT_BUTTON = "flex h-7 w-7 items-center justify-center rounded border border-[var(--border-default)] text-[var(--text-secondary)] transition hover:text-[var(--text-primary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default disabled:opacity-40 disabled:hover:text-[var(--text-secondary)]";
|
|
2037
|
+
var EDIT_TOOL_BUTTON = "flex h-7 items-center gap-1.5 rounded border border-[var(--border-default)] px-2 text-xs font-medium text-[var(--text-secondary)] transition hover:text-[var(--text-primary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default disabled:opacity-40 disabled:hover:text-[var(--text-secondary)]";
|
|
2038
|
+
var CLUSTER_DIVIDER = "mx-1 h-5 w-px shrink-0 bg-[var(--border-default)]";
|
|
1881
2039
|
function mintClipId() {
|
|
1882
2040
|
const uuid = globalThis.crypto && "randomUUID" in globalThis.crypto ? globalThis.crypto.randomUUID() : null;
|
|
1883
2041
|
return `local-${uuid ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}`;
|
|
@@ -1899,6 +2057,7 @@ function TimelineEditor(props) {
|
|
|
1899
2057
|
const { canWrite, onApplyOperations } = props;
|
|
1900
2058
|
const fps = props.timeline.sequence.fps;
|
|
1901
2059
|
const durationFrames = props.timeline.sequence.durationFrames;
|
|
2060
|
+
const labels = useMemo3(() => ({ ...DEFAULT_TIMELINE_LABELS, ...props.labels }), [props.labels]);
|
|
1902
2061
|
const stack = useMemo3(() => createCommandStack(props.timeline), []);
|
|
1903
2062
|
const editorState = useSyncExternalStore(stack.subscribe, stack.getState, stack.getState);
|
|
1904
2063
|
const timeline = editorState.timeline;
|
|
@@ -1951,13 +2110,16 @@ function TimelineEditor(props) {
|
|
|
1951
2110
|
}, [props.frameProvider]);
|
|
1952
2111
|
const zoomMath = useMemo3(() => createZoomMath({ minZoom: MIN_ZOOM, maxZoom: MAX_ZOOM }), []);
|
|
1953
2112
|
const [zoom, setZoom] = useState3(1);
|
|
2113
|
+
const [fitZoom, setFitZoom] = useState3(void 0);
|
|
1954
2114
|
const trackViewportRef = useRef3(null);
|
|
1955
2115
|
useEffect3(() => {
|
|
1956
2116
|
const viewport = trackViewportRef.current;
|
|
1957
2117
|
if (!viewport) return;
|
|
1958
2118
|
const laneWidth = viewport.clientWidth - TRACK_HEADER_PX;
|
|
1959
2119
|
if (laneWidth <= 0) return;
|
|
1960
|
-
|
|
2120
|
+
const fit = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, laneWidth / durationFrames));
|
|
2121
|
+
setFitZoom(fit);
|
|
2122
|
+
setZoom(fit);
|
|
1961
2123
|
}, []);
|
|
1962
2124
|
const [snapEnabled, setSnapEnabled] = useState3(true);
|
|
1963
2125
|
const [activeSnapPoint, setActiveSnapPoint] = useState3(null);
|
|
@@ -2336,120 +2498,154 @@ function TimelineEditor(props) {
|
|
|
2336
2498
|
);
|
|
2337
2499
|
}
|
|
2338
2500
|
const timelineWidth = timeline.sequence.durationFrames * zoom;
|
|
2339
|
-
return /* @__PURE__ */
|
|
2340
|
-
/* @__PURE__ */
|
|
2341
|
-
|
|
2342
|
-
/* @__PURE__ */
|
|
2343
|
-
/* @__PURE__ */
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
/* @__PURE__ */
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2501
|
+
return /* @__PURE__ */ jsxs10("div", { className: `flex h-full min-h-0 flex-col bg-[var(--bg-input)] text-[var(--text-primary)] ${props.className ?? ""}`, children: [
|
|
2502
|
+
/* @__PURE__ */ jsx13(TimelineSmallScreenGate, { labels: props.labels }),
|
|
2503
|
+
/* @__PURE__ */ jsxs10("div", { className: "hidden min-h-0 flex-1 flex-col sm:flex lg:flex-row", children: [
|
|
2504
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [
|
|
2505
|
+
/* @__PURE__ */ jsx13(PreviewCanvas, { timeline, clock, frameProvider }),
|
|
2506
|
+
/* @__PURE__ */ jsxs10("div", { "aria-label": "Timeline controls", className: "flex h-11 shrink-0 items-center gap-1.5 overflow-x-auto border-y border-[var(--border-default)] px-2", children: [
|
|
2507
|
+
/* @__PURE__ */ jsx13(
|
|
2508
|
+
"button",
|
|
2509
|
+
{
|
|
2510
|
+
type: "button",
|
|
2511
|
+
"aria-label": isPlaying ? "Pause" : "Play",
|
|
2512
|
+
onClick: togglePlayback,
|
|
2513
|
+
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-[var(--brand-primary)] text-[hsl(var(--primary-foreground))] transition hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2514
|
+
children: isPlaying ? /* @__PURE__ */ jsx13(PauseGlyph, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx13(PlayGlyph, { className: "h-4 w-4" })
|
|
2515
|
+
}
|
|
2516
|
+
),
|
|
2517
|
+
/* @__PURE__ */ jsxs10("span", { className: "shrink-0 font-mono text-xs tabular-nums text-[var(--text-secondary)]", children: [
|
|
2518
|
+
formatTimecode(playheadFrame, fps),
|
|
2519
|
+
/* @__PURE__ */ jsxs10("span", { className: "text-[var(--text-muted)]", children: [
|
|
2520
|
+
" / ",
|
|
2521
|
+
formatTimecode(timeline.sequence.durationFrames, fps)
|
|
2522
|
+
] })
|
|
2523
|
+
] }),
|
|
2524
|
+
/* @__PURE__ */ jsx13("div", { className: CLUSTER_DIVIDER }),
|
|
2525
|
+
/* @__PURE__ */ jsx13("button", { type: "button", "aria-label": "Undo", disabled: !stack.canUndo() || !canWrite, onClick: undoLast, className: TRANSPORT_BUTTON, children: /* @__PURE__ */ jsx13(UndoGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
2526
|
+
/* @__PURE__ */ jsx13("button", { type: "button", "aria-label": "Redo", disabled: !stack.canRedo() || !canWrite, onClick: redoLast, className: TRANSPORT_BUTTON, children: /* @__PURE__ */ jsx13(RedoGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
2527
|
+
/* @__PURE__ */ jsx13(
|
|
2528
|
+
"button",
|
|
2529
|
+
{
|
|
2530
|
+
type: "button",
|
|
2531
|
+
"aria-label": "Toggle snapping",
|
|
2532
|
+
"aria-pressed": snapEnabled,
|
|
2533
|
+
onClick: () => setSnapEnabled((current) => !current),
|
|
2534
|
+
className: `${TRANSPORT_BUTTON} ${snapEnabled ? "border-[var(--brand-primary)] text-[var(--brand-primary)] hover:text-[var(--brand-primary)]" : ""}`,
|
|
2535
|
+
children: /* @__PURE__ */ jsx13(MagnetGlyph, { className: "h-3.5 w-3.5" })
|
|
2536
|
+
}
|
|
2537
|
+
),
|
|
2538
|
+
canWrite ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
2539
|
+
/* @__PURE__ */ jsx13("div", { className: CLUSTER_DIVIDER }),
|
|
2540
|
+
/* @__PURE__ */ jsxs10("button", { type: "button", "aria-label": labels.splitClipAriaLabel, disabled: !splittableClip, onClick: splitAtPlayhead, className: EDIT_TOOL_BUTTON, children: [
|
|
2541
|
+
/* @__PURE__ */ jsx13(ScissorsGlyph, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
2542
|
+
/* @__PURE__ */ jsx13("span", { className: "hidden md:inline", children: labels.splitClip })
|
|
2543
|
+
] }),
|
|
2544
|
+
/* @__PURE__ */ jsxs10("button", { type: "button", "aria-label": labels.addCaptionAriaLabel, onClick: addCaptionAtPlayhead, className: EDIT_TOOL_BUTTON, children: [
|
|
2545
|
+
/* @__PURE__ */ jsx13(CaptionPlusGlyph, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
2546
|
+
/* @__PURE__ */ jsx13("span", { className: "hidden md:inline", children: labels.addCaption })
|
|
2547
|
+
] })
|
|
2548
|
+
] }) : null,
|
|
2549
|
+
/* @__PURE__ */ jsx13("div", { className: "min-w-2 flex-1" }),
|
|
2550
|
+
/* @__PURE__ */ jsx13(ZoomControl, { zoomMath, zoom, onZoomChange: setZoom, fitZoom }),
|
|
2551
|
+
props.onCreateExport ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
2552
|
+
/* @__PURE__ */ jsx13("div", { className: CLUSTER_DIVIDER }),
|
|
2553
|
+
/* @__PURE__ */ jsxs10(
|
|
2554
|
+
"button",
|
|
2555
|
+
{
|
|
2556
|
+
type: "button",
|
|
2557
|
+
"aria-label": labels.createExport,
|
|
2558
|
+
onClick: props.onCreateExport,
|
|
2559
|
+
className: "flex h-8 shrink-0 items-center gap-1.5 rounded-md border border-[var(--brand-primary)] px-2.5 text-xs font-semibold text-[var(--brand-primary)] transition hover:bg-[hsl(var(--primary)/0.1)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2560
|
+
children: [
|
|
2561
|
+
/* @__PURE__ */ jsx13(ExportGlyph, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
2562
|
+
/* @__PURE__ */ jsx13("span", { className: "hidden md:inline", children: labels.createExport })
|
|
2563
|
+
]
|
|
2564
|
+
}
|
|
2565
|
+
)
|
|
2566
|
+
] }) : null
|
|
2359
2567
|
] }),
|
|
2360
|
-
/* @__PURE__ */
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
/* @__PURE__ */ jsx9(
|
|
2364
|
-
"button",
|
|
2365
|
-
{
|
|
2366
|
-
type: "button",
|
|
2367
|
-
"aria-label": "Toggle snapping",
|
|
2368
|
-
"aria-pressed": snapEnabled,
|
|
2369
|
-
onClick: () => setSnapEnabled((current) => !current),
|
|
2370
|
-
className: `${TRANSPORT_BUTTON} ${snapEnabled ? "border-[var(--brand-primary)] text-[var(--brand-primary)] hover:text-[var(--brand-primary)]" : ""}`,
|
|
2371
|
-
children: /* @__PURE__ */ jsx9(MagnetGlyph, { className: "h-3.5 w-3.5" })
|
|
2372
|
-
}
|
|
2373
|
-
),
|
|
2374
|
-
canWrite ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
2375
|
-
/* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Split clip at playhead", disabled: !splittableClip, onClick: splitAtPlayhead, className: TRANSPORT_BUTTON, children: /* @__PURE__ */ jsx9(ScissorsGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
2376
|
-
/* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Add caption at playhead", onClick: addCaptionAtPlayhead, className: TRANSPORT_BUTTON, children: /* @__PURE__ */ jsx9(CaptionPlusGlyph, { className: "h-3.5 w-3.5" }) })
|
|
2568
|
+
commitError ? /* @__PURE__ */ jsxs10("div", { className: "flex shrink-0 items-center justify-between gap-3 border-b border-[hsl(var(--destructive)/0.3)] bg-[hsl(var(--destructive)/0.1)] px-3 py-1.5 text-xs text-[var(--text-danger)]", role: "alert", children: [
|
|
2569
|
+
/* @__PURE__ */ jsx13("span", { className: "min-w-0 truncate", children: commitError }),
|
|
2570
|
+
/* @__PURE__ */ jsx13("button", { type: "button", onClick: () => setCommitError(null), className: "shrink-0 underline-offset-2 hover:underline", children: "Dismiss" })
|
|
2377
2571
|
] }) : null,
|
|
2378
|
-
/* @__PURE__ */
|
|
2379
|
-
/* @__PURE__ */
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2572
|
+
props.renderAssetShelf ? /* @__PURE__ */ jsx13("div", { className: "shrink-0 border-b border-[var(--border-default)]", children: props.renderAssetShelf() }) : null,
|
|
2573
|
+
/* @__PURE__ */ jsx13(
|
|
2574
|
+
"div",
|
|
2575
|
+
{
|
|
2576
|
+
ref: trackViewportRef,
|
|
2577
|
+
"data-timeline-tracks": true,
|
|
2578
|
+
className: "relative max-h-60 min-h-[6rem] shrink-0 overflow-auto overscroll-x-contain",
|
|
2579
|
+
onDragOver: handleTrackAreaDragOver,
|
|
2580
|
+
onDrop: handleTrackAreaDrop,
|
|
2581
|
+
children: /* @__PURE__ */ jsxs10("div", { className: "relative", style: { width: `${TRACK_HEADER_PX + timelineWidth}px`, minWidth: "100%" }, children: [
|
|
2582
|
+
/* @__PURE__ */ jsxs10("div", { className: "sticky top-0 z-20 flex", children: [
|
|
2583
|
+
/* @__PURE__ */ jsx13("div", { className: "sticky left-0 z-30 w-36 shrink-0 border-b border-r border-[var(--border-default)] bg-[var(--bg-input)]" }),
|
|
2584
|
+
/* @__PURE__ */ jsx13(TimelineRuler, { fps, durationFrames: timeline.sequence.durationFrames, zoom, onScrub: (frame) => clock.seek(frame) })
|
|
2585
|
+
] }),
|
|
2586
|
+
/* @__PURE__ */ jsxs10("div", { className: "relative", children: [
|
|
2587
|
+
sortedTracks.length === 0 ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
2588
|
+
/* @__PURE__ */ jsx13(
|
|
2589
|
+
TimelineGhostLanes,
|
|
2590
|
+
{
|
|
2591
|
+
laneWidth: timelineWidth,
|
|
2592
|
+
videoLabel: labels.ghostVideoLane,
|
|
2593
|
+
captionLabel: labels.ghostCaptionLane
|
|
2594
|
+
}
|
|
2595
|
+
),
|
|
2596
|
+
/* @__PURE__ */ jsx13(
|
|
2597
|
+
TimelineEmptyState,
|
|
2598
|
+
{
|
|
2599
|
+
labels: props.labels,
|
|
2600
|
+
brandedExport: props.brandedExport,
|
|
2601
|
+
...props.onStartFromTemplate ? { onStartFromTemplate: props.onStartFromTemplate } : {},
|
|
2602
|
+
...props.onAddClip ? { onAddClip: props.onAddClip } : {},
|
|
2603
|
+
...props.onAskAgent ? { onAskAgent: props.onAskAgent } : {}
|
|
2604
|
+
}
|
|
2605
|
+
)
|
|
2606
|
+
] }) : null,
|
|
2607
|
+
sortedTracks.map((track) => /* @__PURE__ */ jsx13(
|
|
2608
|
+
TimelineTrackRow,
|
|
2609
|
+
{
|
|
2610
|
+
track,
|
|
2611
|
+
clips: clipsByTrack.get(track.id) ?? [],
|
|
2612
|
+
fps,
|
|
2613
|
+
zoom,
|
|
2614
|
+
sequenceDurationFrames: timeline.sequence.durationFrames,
|
|
2615
|
+
selectedClipIds: new Set(selectedClipIds),
|
|
2616
|
+
tabbableClipId,
|
|
2617
|
+
canWrite,
|
|
2618
|
+
frameProvider,
|
|
2619
|
+
snapMove,
|
|
2620
|
+
snapEdge,
|
|
2621
|
+
onSnapPointChange: setActiveSnapPoint,
|
|
2622
|
+
onSelectClip: selectClip,
|
|
2623
|
+
onRequestDeleteClip: deleteClip,
|
|
2624
|
+
onFocusStepClip: focusStepClip,
|
|
2625
|
+
onCommitMove: handleCommitMove,
|
|
2626
|
+
onCommitTrim: handleCommitTrim,
|
|
2627
|
+
onCommitText: handleCommitText,
|
|
2628
|
+
onLaneSeek: (frame) => clock.seek(frame)
|
|
2629
|
+
},
|
|
2630
|
+
track.id
|
|
2631
|
+
)),
|
|
2632
|
+
/* @__PURE__ */ jsxs10("div", { className: "pointer-events-none absolute inset-y-0", style: { left: `${TRACK_HEADER_PX}px`, width: `${timelineWidth}px` }, children: [
|
|
2633
|
+
/* @__PURE__ */ jsx13(TimelinePlayhead, { frame: playheadFrame, zoom }),
|
|
2634
|
+
/* @__PURE__ */ jsx13(SnapIndicatorLine, { point: activeSnapPoint, zoom })
|
|
2635
|
+
] })
|
|
2441
2636
|
] })
|
|
2442
2637
|
] })
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
)
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
] })
|
|
2638
|
+
}
|
|
2639
|
+
)
|
|
2640
|
+
] }),
|
|
2641
|
+
props.renderSidePanel ? /* @__PURE__ */ jsx13("aside", { className: "flex max-h-72 shrink-0 flex-col overflow-hidden border-t border-[var(--border-default)] lg:max-h-none lg:w-80 lg:border-l lg:border-t-0", children: props.renderSidePanel({ selectedClips, playheadFrame }) }) : null
|
|
2642
|
+
] })
|
|
2643
|
+
] });
|
|
2449
2644
|
}
|
|
2450
2645
|
var TimelineEditor_default = TimelineEditor;
|
|
2451
2646
|
|
|
2452
2647
|
export {
|
|
2648
|
+
DEFAULT_TIMELINE_LABELS,
|
|
2453
2649
|
COMMAND_HISTORY_LIMIT,
|
|
2454
2650
|
createCommandStack,
|
|
2455
2651
|
moveClipCommand,
|
|
@@ -2495,9 +2691,13 @@ export {
|
|
|
2495
2691
|
TimelineRuler,
|
|
2496
2692
|
TimelineClipChip,
|
|
2497
2693
|
TimelineTrackRow,
|
|
2694
|
+
BrandMark,
|
|
2695
|
+
TimelineEmptyState,
|
|
2696
|
+
TimelineGhostLanes,
|
|
2697
|
+
TimelineSmallScreenGate,
|
|
2498
2698
|
ZoomControl,
|
|
2499
2699
|
SEQUENCE_MEDIA_DRAG_TYPE,
|
|
2500
2700
|
TimelineEditor,
|
|
2501
2701
|
TimelineEditor_default
|
|
2502
2702
|
};
|
|
2503
|
-
//# sourceMappingURL=chunk-
|
|
2703
|
+
//# sourceMappingURL=chunk-EX3LD5G6.js.map
|