@twick/video-editor 0.15.20 → 0.15.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
- import { Track, TrackElement, Size } from '@twick/timeline';
1
+ import { Track, TrackElement, Size, ChapterMarker } from '@twick/timeline';
2
2
  import { ElementColors } from '../../helpers/types';
3
3
  import { DropTarget } from '../../utils/drop-target';
4
4
 
5
- declare function TimelineView({ zoomLevel, selectedItem, duration, tracks, seekTrack, onAddTrack, onReorder, onItemSelect, onEmptyClick, onMarqueeSelect, onElementDrag, onElementDrop, elementColors, selectedIds, playheadPositionPx, isPlayheadActive, onDropOnTimeline, videoResolution, enableDropOnTimeline, }: {
5
+ declare function TimelineView({ zoomLevel, selectedItem, duration, tracks, seekTrack, onAddTrack, onReorder, onItemSelect, onEmptyClick, onMarqueeSelect, onElementDrag, onElementDrop, onSeek, elementColors, selectedIds, playheadPositionPx, isPlayheadActive, onDropOnTimeline, videoResolution, enableDropOnTimeline, chapters, }: {
6
6
  zoomLevel: number;
7
7
  duration: number;
8
8
  tracks: Track[];
@@ -49,5 +49,6 @@ declare function TimelineView({ zoomLevel, selectedItem, duration, tracks, seekT
49
49
  videoResolution?: Size;
50
50
  /** Whether to enable drop-on-timeline */
51
51
  enableDropOnTimeline?: boolean;
52
+ chapters?: ChapterMarker[];
52
53
  }): import("react/jsx-runtime").JSX.Element;
53
54
  export default TimelineView;
@@ -66,6 +66,7 @@ export interface ElementColors {
66
66
  filters: string;
67
67
  transition: string;
68
68
  animation: string;
69
+ effect?: string;
69
70
  }
70
71
  /**
71
72
  * Canvas behavior options for TwickEditor / TwickStudio.
@@ -1,4 +1,4 @@
1
- import { TrackElement, Track } from '@twick/timeline';
1
+ import { TrackElement, Track, ProjectMetadata } from '@twick/timeline';
2
2
  import { DropTarget } from '../utils/drop-target';
3
3
 
4
4
  export interface ElementDropParams {
@@ -14,6 +14,7 @@ interface TimelineManagerReturn {
14
14
  timelineData: {
15
15
  tracks: Track[];
16
16
  version: number;
17
+ metadata?: ProjectMetadata;
17
18
  } | null;
18
19
  onAddTrack: () => void;
19
20
  onElementDrag: (params: {
package/dist/index.js CHANGED
@@ -6902,7 +6902,13 @@ const ELEMENT_TYPES = {
6902
6902
  /** Rectangle element type */
6903
6903
  RECT: "rect",
6904
6904
  /** Circle element type */
6905
- CIRCLE: "circle"
6905
+ CIRCLE: "circle",
6906
+ /** Arrow annotation element type */
6907
+ ARROW: "arrow",
6908
+ /** Line annotation / shape element type */
6909
+ LINE: "line",
6910
+ /** Global / adjustment-layer style effect element */
6911
+ EFFECT: "effect"
6906
6912
  };
6907
6913
  const isBrowser$2 = typeof window !== "undefined";
6908
6914
  const isCanvasSupported = isBrowser$2 && !!window.HTMLCanvasElement;
@@ -7646,7 +7652,7 @@ const addCaptionElement = ({
7646
7652
  canvasMetadata,
7647
7653
  lockAspectRatio = false
7648
7654
  }) => {
7649
- var _a, _b, _c, _d, _e2, _f, _g, _h2, _i2, _j, _k, _l, _m, _n2, _o2, _p, _q, _r2, _s2, _t2, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K;
7655
+ var _a, _b, _c, _d, _e2, _f, _g, _h2, _i2, _j, _k, _l, _m, _n2, _o2, _p, _q, _r2, _s2, _t2, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L;
7650
7656
  const applyToAll = (captionProps == null ? void 0 : captionProps.applyToAll) ?? false;
7651
7657
  const captionTextColor = ((_a = captionProps == null ? void 0 : captionProps.colors) == null ? void 0 : _a.text) ?? ((_b = captionProps == null ? void 0 : captionProps.color) == null ? void 0 : _b.text);
7652
7658
  const { x: x2, y: y2 } = convertToCanvasPosition(
@@ -7671,19 +7677,19 @@ const addCaptionElement = ({
7671
7677
  ),
7672
7678
  fontFamily: (applyToAll ? (_o2 = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _o2.family : ((_q = (_p = element.props) == null ? void 0 : _p.font) == null ? void 0 : _q.family) ?? ((_r2 = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _r2.family)) ?? DEFAULT_CAPTION_PROPS.family,
7673
7679
  fill: resolvedFill,
7674
- fontWeight: (applyToAll ? (_s2 = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _s2.weight : ((_t2 = element.props) == null ? void 0 : _t2.fontWeight) ?? ((_u = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _u.weight)) ?? DEFAULT_CAPTION_PROPS.fontWeight,
7675
- stroke: (applyToAll ? captionProps == null ? void 0 : captionProps.stroke : ((_v = element.props) == null ? void 0 : _v.stroke) ?? (captionProps == null ? void 0 : captionProps.stroke)) ?? DEFAULT_CAPTION_PROPS.stroke,
7676
- opacity: (applyToAll ? captionProps == null ? void 0 : captionProps.opacity : ((_w = element.props) == null ? void 0 : _w.opacity) ?? (captionProps == null ? void 0 : captionProps.opacity)) ?? 1,
7680
+ fontWeight: (applyToAll ? (_s2 = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _s2.weight : ((_u = (_t2 = element.props) == null ? void 0 : _t2.font) == null ? void 0 : _u.weight) ?? ((_v = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _v.weight)) ?? DEFAULT_CAPTION_PROPS.fontWeight,
7681
+ stroke: (applyToAll ? captionProps == null ? void 0 : captionProps.stroke : ((_w = element.props) == null ? void 0 : _w.stroke) ?? (captionProps == null ? void 0 : captionProps.stroke)) ?? DEFAULT_CAPTION_PROPS.stroke,
7682
+ opacity: (applyToAll ? captionProps == null ? void 0 : captionProps.opacity : ((_x = element.props) == null ? void 0 : _x.opacity) ?? (captionProps == null ? void 0 : captionProps.opacity)) ?? 1,
7677
7683
  width,
7678
7684
  splitByGrapheme: false,
7679
- textAlign: ((_x = element.props) == null ? void 0 : _x.textAlign) ?? "center",
7685
+ textAlign: ((_y = element.props) == null ? void 0 : _y.textAlign) ?? "center",
7680
7686
  shadow: new Ds({
7681
- offsetX: (applyToAll ? (_y = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _y[0] : ((_A = (_z = element.props) == null ? void 0 : _z.shadowOffset) == null ? void 0 : _A[0]) ?? ((_B = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _B[0])) ?? ((_C = DEFAULT_CAPTION_PROPS.shadowOffset) == null ? void 0 : _C[0]),
7682
- offsetY: (applyToAll ? (_D = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _D[1] : ((_F = (_E = element.props) == null ? void 0 : _E.shadowOffset) == null ? void 0 : _F[1]) ?? ((_G = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _G[1])) ?? ((_H = DEFAULT_CAPTION_PROPS.shadowOffset) == null ? void 0 : _H[1]),
7683
- blur: (applyToAll ? captionProps == null ? void 0 : captionProps.shadowBlur : ((_I = element.props) == null ? void 0 : _I.shadowBlur) ?? (captionProps == null ? void 0 : captionProps.shadowBlur)) ?? DEFAULT_CAPTION_PROPS.shadowBlur,
7684
- color: (applyToAll ? captionProps == null ? void 0 : captionProps.shadowColor : ((_J = element.props) == null ? void 0 : _J.shadowColor) ?? (captionProps == null ? void 0 : captionProps.shadowColor)) ?? DEFAULT_CAPTION_PROPS.shadowColor
7687
+ offsetX: (applyToAll ? (_z = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _z[0] : ((_B = (_A = element.props) == null ? void 0 : _A.shadowOffset) == null ? void 0 : _B[0]) ?? ((_C = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _C[0])) ?? ((_D = DEFAULT_CAPTION_PROPS.shadowOffset) == null ? void 0 : _D[0]),
7688
+ offsetY: (applyToAll ? (_E = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _E[1] : ((_G = (_F = element.props) == null ? void 0 : _F.shadowOffset) == null ? void 0 : _G[1]) ?? ((_H = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _H[1])) ?? ((_I = DEFAULT_CAPTION_PROPS.shadowOffset) == null ? void 0 : _I[1]),
7689
+ blur: (applyToAll ? captionProps == null ? void 0 : captionProps.shadowBlur : ((_J = element.props) == null ? void 0 : _J.shadowBlur) ?? (captionProps == null ? void 0 : captionProps.shadowBlur)) ?? DEFAULT_CAPTION_PROPS.shadowBlur,
7690
+ color: (applyToAll ? captionProps == null ? void 0 : captionProps.shadowColor : ((_K = element.props) == null ? void 0 : _K.shadowColor) ?? (captionProps == null ? void 0 : captionProps.shadowColor)) ?? DEFAULT_CAPTION_PROPS.shadowColor
7685
7691
  }),
7686
- strokeWidth: (applyToAll ? captionProps == null ? void 0 : captionProps.lineWidth : ((_K = element.props) == null ? void 0 : _K.lineWidth) ?? (captionProps == null ? void 0 : captionProps.lineWidth)) ?? DEFAULT_CAPTION_PROPS.lineWidth
7692
+ strokeWidth: (applyToAll ? captionProps == null ? void 0 : captionProps.lineWidth : ((_L = element.props) == null ? void 0 : _L.lineWidth) ?? (captionProps == null ? void 0 : captionProps.lineWidth)) ?? DEFAULT_CAPTION_PROPS.lineWidth
7687
7693
  });
7688
7694
  caption.set("id", element.id);
7689
7695
  caption.set("zIndex", index);
@@ -8394,6 +8400,148 @@ const WatermarkElement = {
8394
8400
  };
8395
8401
  }
8396
8402
  };
8403
+ const ArrowElement = {
8404
+ name: ELEMENT_TYPES.ARROW,
8405
+ async add(params) {
8406
+ var _a, _b, _c, _d, _e2, _f, _g, _h2, _i2;
8407
+ const { element, index, canvas, canvasMetadata, lockAspectRatio } = params;
8408
+ const baseWidth = ((_a = element.props) == null ? void 0 : _a.width) ?? 220;
8409
+ const baseHeight = ((_b = element.props) == null ? void 0 : _b.height) ?? 14;
8410
+ const { x: x2, y: y2 } = convertToCanvasPosition(
8411
+ ((_c = element.props) == null ? void 0 : _c.x) ?? 0,
8412
+ ((_d = element.props) == null ? void 0 : _d.y) ?? 0,
8413
+ canvasMetadata
8414
+ );
8415
+ const fill = ((_e2 = element.props) == null ? void 0 : _e2.fill) || "#f59e0b";
8416
+ const radius = (((_f = element.props) == null ? void 0 : _f.radius) ?? 4) * canvasMetadata.scaleX;
8417
+ const barWidth = baseWidth * canvasMetadata.scaleX;
8418
+ const barHeight = baseHeight * canvasMetadata.scaleY;
8419
+ const headSize = barHeight * 1.8;
8420
+ const barLength = barWidth - headSize * 0.5;
8421
+ const bar = new jr({
8422
+ left: -barWidth / 2,
8423
+ top: -barHeight / 2,
8424
+ originX: "left",
8425
+ originY: "top",
8426
+ width: barLength,
8427
+ height: barHeight,
8428
+ rx: radius,
8429
+ ry: radius,
8430
+ fill
8431
+ });
8432
+ const arrowHead = new yo({
8433
+ left: barWidth / 2 - headSize * 0.25,
8434
+ top: 0,
8435
+ originX: "center",
8436
+ originY: "center",
8437
+ width: headSize,
8438
+ height: headSize,
8439
+ fill,
8440
+ angle: 90
8441
+ });
8442
+ const opacity = ((_g = element.props) == null ? void 0 : _g.opacity) ?? 1;
8443
+ const group = new Ur([bar, arrowHead], {
8444
+ left: x2,
8445
+ top: y2,
8446
+ originX: "center",
8447
+ originY: "center",
8448
+ angle: ((_h2 = element.props) == null ? void 0 : _h2.rotation) || 0,
8449
+ opacity,
8450
+ selectable: true,
8451
+ hasControls: true
8452
+ });
8453
+ group.set(
8454
+ "lockUniScaling",
8455
+ lockAspectRatio ?? ((_i2 = element.props) == null ? void 0 : _i2.lockAspectRatio) ?? true
8456
+ );
8457
+ group.set("id", element.id);
8458
+ group.set("zIndex", index);
8459
+ canvas.add(group);
8460
+ },
8461
+ updateFromFabricObject(object, element, context) {
8462
+ var _a, _b, _c;
8463
+ const canvasCenter = getObjectCanvasCenter(object);
8464
+ const { x: x2, y: y2 } = convertToVideoPosition(
8465
+ canvasCenter.x,
8466
+ canvasCenter.y,
8467
+ context.canvasMetadata,
8468
+ context.videoSize
8469
+ );
8470
+ const baseWidth = ((_a = element.props) == null ? void 0 : _a.width) ?? 220;
8471
+ const baseHeight = ((_b = element.props) == null ? void 0 : _b.height) ?? 14;
8472
+ const opacity = object.opacity ?? ((_c = element.props) == null ? void 0 : _c.opacity) ?? 1;
8473
+ return {
8474
+ element: {
8475
+ ...element,
8476
+ props: {
8477
+ ...element.props,
8478
+ rotation: getObjectCanvasAngle(object),
8479
+ width: baseWidth * object.scaleX,
8480
+ height: baseHeight * object.scaleY,
8481
+ x: x2,
8482
+ y: y2,
8483
+ opacity
8484
+ }
8485
+ }
8486
+ };
8487
+ }
8488
+ };
8489
+ const LineElement = {
8490
+ name: ELEMENT_TYPES.LINE,
8491
+ async add(params) {
8492
+ var _a;
8493
+ const { element, index, canvas, canvasMetadata, lockAspectRatio } = params;
8494
+ const lineProps = element.props ?? {};
8495
+ const lineElement = {
8496
+ ...element,
8497
+ props: {
8498
+ ...lineProps,
8499
+ // Use fill as stroke color when a stroke is desired; otherwise rely
8500
+ // on fill-only rendering. Avoid the generic "#000000" fallback.
8501
+ stroke: lineProps.stroke ?? lineProps.fill,
8502
+ // If a specific lineWidth is provided, keep it; otherwise default to 0
8503
+ // so the stroke does not override the visual fill color.
8504
+ lineWidth: lineProps.lineWidth ?? 0
8505
+ }
8506
+ };
8507
+ await addRectElement({
8508
+ element: lineElement,
8509
+ index,
8510
+ canvas,
8511
+ canvasMetadata,
8512
+ lockAspectRatio: lockAspectRatio ?? ((_a = lineElement.props) == null ? void 0 : _a.lockAspectRatio)
8513
+ });
8514
+ },
8515
+ updateFromFabricObject(object, element, context) {
8516
+ var _a, _b;
8517
+ const canvasCenter = getObjectCanvasCenter(object);
8518
+ const { x: x2, y: y2 } = convertToVideoPosition(
8519
+ canvasCenter.x,
8520
+ canvasCenter.y,
8521
+ context.canvasMetadata,
8522
+ context.videoSize
8523
+ );
8524
+ return {
8525
+ element: {
8526
+ ...element,
8527
+ props: {
8528
+ ...element.props,
8529
+ rotation: getObjectCanvasAngle(object),
8530
+ width: (((_a = element.props) == null ? void 0 : _a.width) ?? 0) * object.scaleX,
8531
+ height: (((_b = element.props) == null ? void 0 : _b.height) ?? 0) * object.scaleY,
8532
+ x: x2,
8533
+ y: y2
8534
+ }
8535
+ }
8536
+ };
8537
+ }
8538
+ };
8539
+ const EffectElement = {
8540
+ name: ELEMENT_TYPES.EFFECT,
8541
+ async add() {
8542
+ return;
8543
+ }
8544
+ };
8397
8545
  class ElementController {
8398
8546
  constructor() {
8399
8547
  __publicField2(this, "elements", /* @__PURE__ */ new Map());
@@ -8417,6 +8565,9 @@ function registerElements() {
8417
8565
  elementController.register(TextElement);
8418
8566
  elementController.register(CaptionElement);
8419
8567
  elementController.register(WatermarkElement);
8568
+ elementController.register(ArrowElement);
8569
+ elementController.register(LineElement);
8570
+ elementController.register(EffectElement);
8420
8571
  }
8421
8572
  registerElements();
8422
8573
  const useTwickCanvas = ({
@@ -8997,7 +9148,9 @@ const DEFAULT_ELEMENT_COLORS = {
8997
9148
  /** Icon element color - bright orchid */
8998
9149
  icon: "#A76CD4",
8999
9150
  /** Circle element color - deep byzantium */
9000
- circle: "#703D8B"
9151
+ circle: "#703D8B",
9152
+ /** Effect element color - cyan accent for global effects */
9153
+ effect: "#22C3EE"
9001
9154
  };
9002
9155
  const AVAILABLE_TEXT_FONTS = {
9003
9156
  // Google Fonts
@@ -18888,6 +19041,7 @@ const TrackElementView = ({
18888
19041
  onDragStateChange,
18889
19042
  elementColors
18890
19043
  }) => {
19044
+ var _a, _b;
18891
19045
  const ref = React.useRef(null);
18892
19046
  const dragType = React.useRef(null);
18893
19047
  const lastPosRef = React.useRef(null);
@@ -18977,12 +19131,12 @@ const TrackElementView = ({
18977
19131
  lastPosRef.current = position;
18978
19132
  };
18979
19133
  const sendUpdate = (e3) => {
18980
- var _a, _b, _c;
19134
+ var _a2, _b2, _c;
18981
19135
  let dropPointer;
18982
19136
  if (e3) {
18983
19137
  if ("clientX" in e3) {
18984
19138
  dropPointer = { clientX: e3.clientX, clientY: e3.clientY };
18985
- } else if ("changedTouches" in e3 && ((_a = e3.changedTouches) == null ? void 0 : _a[0])) {
19139
+ } else if ("changedTouches" in e3 && ((_a2 = e3.changedTouches) == null ? void 0 : _a2[0])) {
18986
19140
  const t2 = e3.changedTouches[0];
18987
19141
  dropPointer = { clientX: t2.clientX, clientY: t2.clientY };
18988
19142
  }
@@ -18997,15 +19151,16 @@ const TrackElementView = ({
18997
19151
  },
18998
19152
  dragType: dragType.current || ""
18999
19153
  };
19000
- const didChange = ((_b = lastPosRef.current) == null ? void 0 : _b.start) !== position.start || ((_c = lastPosRef.current) == null ? void 0 : _c.end) !== position.end;
19154
+ const didChange = ((_b2 = lastPosRef.current) == null ? void 0 : _b2.start) !== position.start || ((_c = lastPosRef.current) == null ? void 0 : _c.end) !== position.end;
19001
19155
  if (didChange || dropPointer) {
19002
19156
  onDrag(payload, dropPointer);
19003
19157
  }
19004
19158
  };
19005
19159
  const getElementColor = (elementType) => {
19006
19160
  const colors = elementColors || ELEMENT_COLORS;
19007
- if (elementType in colors) {
19008
- return colors[elementType];
19161
+ const key = elementType === timeline.TIMELINE_ELEMENT_TYPE.VIDEO ? "video" : elementType === timeline.TIMELINE_ELEMENT_TYPE.AUDIO ? "audio" : elementType === timeline.TIMELINE_ELEMENT_TYPE.IMAGE ? "image" : elementType === timeline.TIMELINE_ELEMENT_TYPE.TEXT ? "text" : elementType === timeline.TIMELINE_ELEMENT_TYPE.CAPTION ? "caption" : elementType === timeline.TIMELINE_ELEMENT_TYPE.RECT ? "rect" : elementType === timeline.TIMELINE_ELEMENT_TYPE.CIRCLE ? "circle" : elementType === timeline.TIMELINE_ELEMENT_TYPE.ICON ? "icon" : elementType === timeline.TIMELINE_ELEMENT_TYPE.EFFECT ? "effect" : "element";
19162
+ if (key in colors) {
19163
+ return colors[key];
19009
19164
  }
19010
19165
  return ELEMENT_COLORS.element;
19011
19166
  };
@@ -19049,7 +19204,7 @@ const TrackElementView = ({
19049
19204
  className: "twick-track-element-handle twick-track-element-handle-start"
19050
19205
  }
19051
19206
  ) : null,
19052
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twick-track-element-content", children: element.getText ? element.getText() : element.getName() || element.getType() }),
19207
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twick-track-element-content", children: element.getType() === timeline.TIMELINE_ELEMENT_TYPE.EFFECT ? ((_b = (_a = element.getProps) == null ? void 0 : _a.call(element)) == null ? void 0 : _b.effectKey) ?? "Effect" : element.getText ? element.getText() : element.getName() || element.getType() }),
19053
19208
  hasHandles ? /* @__PURE__ */ jsxRuntime.jsx(
19054
19209
  "div",
19055
19210
  {
@@ -19407,13 +19562,15 @@ function TimelineView({
19407
19562
  onMarqueeSelect,
19408
19563
  onElementDrag,
19409
19564
  onElementDrop,
19565
+ onSeek,
19410
19566
  elementColors,
19411
19567
  selectedIds,
19412
19568
  playheadPositionPx = 0,
19413
19569
  isPlayheadActive = false,
19414
19570
  onDropOnTimeline,
19415
19571
  videoResolution,
19416
- enableDropOnTimeline = true
19572
+ enableDropOnTimeline = true,
19573
+ chapters = []
19417
19574
  }) {
19418
19575
  const containerRef = React.useRef(null);
19419
19576
  const seekContainerRef = React.useRef(null);
@@ -19575,9 +19732,36 @@ function TimelineView({
19575
19732
  className: "twick-timeline-scroll-container",
19576
19733
  onScroll: handleScroll,
19577
19734
  children: [
19578
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: timelineWidthPx }, children: seekTrack ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", position: "relative" }, children: [
19735
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: timelineWidthPx }, children: seekTrack ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", position: "relative", minHeight: 34 }, children: [
19579
19736
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twick-seek-track-empty-space", onClick: onAddTrack, children: /* @__PURE__ */ jsxRuntime.jsx(Plus, { color: "white", size: 20 }) }),
19580
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flexGrow: 1 }, children: seekTrack })
19737
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flexGrow: 1 }, children: seekTrack }),
19738
+ chapters.map((chapter) => {
19739
+ const left = LABEL_WIDTH + chapter.time / Math.max(duration, 1e-3) * (timelineWidth - LABEL_WIDTH);
19740
+ return /* @__PURE__ */ jsxRuntime.jsx(
19741
+ "button",
19742
+ {
19743
+ className: "btn-ghost",
19744
+ title: chapter.title,
19745
+ onClick: (e3) => {
19746
+ e3.stopPropagation();
19747
+ onSeek(chapter.time);
19748
+ },
19749
+ style: {
19750
+ position: "absolute",
19751
+ left,
19752
+ top: 0,
19753
+ height: "100%",
19754
+ padding: "0 4px",
19755
+ borderRadius: 0,
19756
+ borderLeft: "1px solid rgba(255,255,255,0.4)",
19757
+ borderRight: "none",
19758
+ minWidth: 0
19759
+ },
19760
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 10, opacity: 0.9 }, children: chapter.title })
19761
+ },
19762
+ chapter.id
19763
+ );
19764
+ })
19581
19765
  ] }) : null }),
19582
19766
  /* @__PURE__ */ jsxRuntime.jsxs(
19583
19767
  "div",
@@ -19892,7 +20076,7 @@ const TimelineManager = ({
19892
20076
  timelineTickConfigs,
19893
20077
  elementColors
19894
20078
  }) => {
19895
- var _a;
20079
+ var _a, _b;
19896
20080
  const { playerState } = livePlayer.useLivePlayerContext();
19897
20081
  const { followPlayheadEnabled, editor, videoResolution, setSelectedItem } = timeline.useTimelineContext();
19898
20082
  const {
@@ -19964,6 +20148,7 @@ const TimelineManager = ({
19964
20148
  elementColors,
19965
20149
  playheadPositionPx: playheadState.positionPx,
19966
20150
  isPlayheadActive,
20151
+ chapters: ((_a = timelineData == null ? void 0 : timelineData.metadata) == null ? void 0 : _a.chapters) ?? [],
19967
20152
  onDropOnTimeline: handleDropOnTimeline,
19968
20153
  videoResolution,
19969
20154
  enableDropOnTimeline: true,
@@ -19973,7 +20158,7 @@ const TimelineManager = ({
19973
20158
  duration: totalDuration,
19974
20159
  zoom: trackZoom,
19975
20160
  onSeek,
19976
- timelineCount: ((_a = timelineData == null ? void 0 : timelineData.tracks) == null ? void 0 : _a.length) ?? 0,
20161
+ timelineCount: ((_b = timelineData == null ? void 0 : timelineData.tracks) == null ? void 0 : _b.length) ?? 0,
19977
20162
  timelineTickConfigs,
19978
20163
  onPlayheadUpdate: handlePlayheadUpdate
19979
20164
  }