@twick/canvas 0.15.19 → 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.
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { Canvas, Control, controlsUtils, FabricImage, Rect, Textbox, Shadow, Group, Circle, ActiveSelection } from "fabric";
5
- import { useState, useRef } from "react";
4
+ import { Canvas, Control, controlsUtils, FabricImage, Rect, Textbox, Shadow, Group, Circle, Triangle, ActiveSelection } from "fabric";
5
+ import { useState, useRef, useCallback } from "react";
6
6
  const DEFAULT_TEXT_PROPS = {
7
7
  /** Font family for text elements */
8
8
  family: "Poppins",
@@ -16,8 +16,8 @@ const DEFAULT_TEXT_PROPS = {
16
16
  lineWidth: 0
17
17
  };
18
18
  const DEFAULT_CAPTION_PROPS = {
19
- /** Font family for caption elements */
20
- family: "Poppins",
19
+ /** Font family for caption elements (matches highlight_bg default) */
20
+ family: "Bangers",
21
21
  /** Font size in pixels */
22
22
  size: 48,
23
23
  /** Text fill color */
@@ -72,8 +72,14 @@ const ELEMENT_TYPES = {
72
72
  CIRCLE: "circle",
73
73
  /** Icon element type */
74
74
  ICON: "icon",
75
+ /** Arrow annotation element type */
76
+ ARROW: "arrow",
77
+ /** Line annotation / shape element type */
78
+ LINE: "line",
75
79
  /** Background color element type */
76
- BACKGROUND_COLOR: "backgroundColor"
80
+ BACKGROUND_COLOR: "backgroundColor",
81
+ /** Global / adjustment-layer style effect element */
82
+ EFFECT: "effect"
77
83
  };
78
84
  const isBrowser = typeof window !== "undefined";
79
85
  const isCanvasSupported = isBrowser && !!window.HTMLCanvasElement;
@@ -817,40 +823,44 @@ const addCaptionElement = ({
817
823
  canvasMetadata,
818
824
  lockAspectRatio = false
819
825
  }) => {
820
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J;
826
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L;
827
+ const applyToAll = (captionProps == null ? void 0 : captionProps.applyToAll) ?? false;
828
+ 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);
821
829
  const { x, y } = convertToCanvasPosition(
822
- ((captionProps == null ? void 0 : captionProps.applyToAll) ? captionProps == null ? void 0 : captionProps.x : ((_a = element.props) == null ? void 0 : _a.x) ?? (captionProps == null ? void 0 : captionProps.x)) ?? 0,
823
- ((captionProps == null ? void 0 : captionProps.applyToAll) ? captionProps == null ? void 0 : captionProps.y : ((_b = element.props) == null ? void 0 : _b.y) ?? (captionProps == null ? void 0 : captionProps.y)) ?? 0,
830
+ (applyToAll ? captionProps == null ? void 0 : captionProps.x : ((_c = element.props) == null ? void 0 : _c.x) ?? (captionProps == null ? void 0 : captionProps.x)) ?? 0,
831
+ (applyToAll ? captionProps == null ? void 0 : captionProps.y : ((_d = element.props) == null ? void 0 : _d.y) ?? (captionProps == null ? void 0 : captionProps.y)) ?? 0,
824
832
  canvasMetadata
825
833
  );
826
- let width = ((_c = element.props) == null ? void 0 : _c.width) ? element.props.width * canvasMetadata.scaleX : canvasMetadata.width - 2 * MARGIN;
827
- if ((_d = element.props) == null ? void 0 : _d.maxWidth) {
834
+ let width = ((_e = element.props) == null ? void 0 : _e.width) ? element.props.width * canvasMetadata.scaleX : canvasMetadata.width - 2 * MARGIN;
835
+ if ((_f = element.props) == null ? void 0 : _f.maxWidth) {
828
836
  width = Math.min(width, element.props.maxWidth * canvasMetadata.scaleX);
829
837
  }
830
- const caption = new Textbox(((_e = element.props) == null ? void 0 : _e.text) || element.t || "", {
838
+ const elementColors = (_g = element.props) == null ? void 0 : _g.colors;
839
+ const resolvedFill = (applyToAll ? captionTextColor : ((_h = element.props) == null ? void 0 : _h.fill) ?? (elementColors == null ? void 0 : elementColors.text) ?? captionTextColor) ?? DEFAULT_CAPTION_PROPS.fill;
840
+ const caption = new Textbox(((_i = element.props) == null ? void 0 : _i.text) || element.t || "", {
831
841
  left: x,
832
842
  top: y,
833
843
  originX: "center",
834
844
  originY: "center",
835
- angle: ((_f = element.props) == null ? void 0 : _f.rotation) || 0,
845
+ angle: ((_j = element.props) == null ? void 0 : _j.rotation) || 0,
836
846
  fontSize: Math.round(
837
- (((captionProps == null ? void 0 : captionProps.applyToAll) ? (_g = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _g.size : ((_i = (_h = element.props) == null ? void 0 : _h.font) == null ? void 0 : _i.size) ?? ((_j = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _j.size)) ?? DEFAULT_CAPTION_PROPS.size) * canvasMetadata.scaleX
847
+ ((applyToAll ? (_k = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _k.size : ((_m = (_l = element.props) == null ? void 0 : _l.font) == null ? void 0 : _m.size) ?? ((_n = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _n.size)) ?? DEFAULT_CAPTION_PROPS.size) * canvasMetadata.scaleX
838
848
  ),
839
- fontFamily: ((captionProps == null ? void 0 : captionProps.applyToAll) ? (_k = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _k.family : ((_m = (_l = element.props) == null ? void 0 : _l.font) == null ? void 0 : _m.family) ?? ((_n = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _n.family)) ?? DEFAULT_CAPTION_PROPS.family,
840
- fill: ((captionProps == null ? void 0 : captionProps.applyToAll) ? (_o = captionProps.color) == null ? void 0 : _o.text : ((_p = element.props) == null ? void 0 : _p.fill) ?? ((_q = captionProps.color) == null ? void 0 : _q.text)) ?? DEFAULT_CAPTION_PROPS.fill,
841
- fontWeight: ((captionProps == null ? void 0 : captionProps.applyToAll) ? (_r = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _r.weight : ((_s = element.props) == null ? void 0 : _s.fontWeight) ?? ((_t = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _t.weight)) ?? DEFAULT_CAPTION_PROPS.fontWeight,
842
- stroke: ((captionProps == null ? void 0 : captionProps.applyToAll) ? captionProps == null ? void 0 : captionProps.stroke : ((_u = element.props) == null ? void 0 : _u.stroke) ?? (captionProps == null ? void 0 : captionProps.stroke)) ?? DEFAULT_CAPTION_PROPS.stroke,
843
- opacity: ((captionProps == null ? void 0 : captionProps.applyToAll) ? captionProps == null ? void 0 : captionProps.opacity : ((_v = element.props) == null ? void 0 : _v.opacity) ?? (captionProps == null ? void 0 : captionProps.opacity)) ?? 1,
849
+ fontFamily: (applyToAll ? (_o = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _o.family : ((_q = (_p = element.props) == null ? void 0 : _p.font) == null ? void 0 : _q.family) ?? ((_r = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _r.family)) ?? DEFAULT_CAPTION_PROPS.family,
850
+ fill: resolvedFill,
851
+ fontWeight: (applyToAll ? (_s = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _s.weight : ((_u = (_t = element.props) == null ? void 0 : _t.font) == null ? void 0 : _u.weight) ?? ((_v = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _v.weight)) ?? DEFAULT_CAPTION_PROPS.fontWeight,
852
+ 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,
853
+ opacity: (applyToAll ? captionProps == null ? void 0 : captionProps.opacity : ((_x = element.props) == null ? void 0 : _x.opacity) ?? (captionProps == null ? void 0 : captionProps.opacity)) ?? 1,
844
854
  width,
845
855
  splitByGrapheme: false,
846
- textAlign: ((_w = element.props) == null ? void 0 : _w.textAlign) ?? "center",
856
+ textAlign: ((_y = element.props) == null ? void 0 : _y.textAlign) ?? "center",
847
857
  shadow: new Shadow({
848
- offsetX: ((captionProps == null ? void 0 : captionProps.applyToAll) ? (_x = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _x[0] : ((_z = (_y = element.props) == null ? void 0 : _y.shadowOffset) == null ? void 0 : _z[0]) ?? ((_A = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _A[0])) ?? ((_B = DEFAULT_CAPTION_PROPS.shadowOffset) == null ? void 0 : _B[0]),
849
- offsetY: ((captionProps == null ? void 0 : captionProps.applyToAll) ? (_C = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _C[1] : ((_E = (_D = element.props) == null ? void 0 : _D.shadowOffset) == null ? void 0 : _E[1]) ?? ((_F = captionProps == null ? void 0 : captionProps.shadowOffset) == null ? void 0 : _F[1])) ?? ((_G = DEFAULT_CAPTION_PROPS.shadowOffset) == null ? void 0 : _G[1]),
850
- blur: ((captionProps == null ? void 0 : captionProps.applyToAll) ? captionProps == null ? void 0 : captionProps.shadowBlur : ((_H = element.props) == null ? void 0 : _H.shadowBlur) ?? (captionProps == null ? void 0 : captionProps.shadowBlur)) ?? DEFAULT_CAPTION_PROPS.shadowBlur,
851
- color: ((captionProps == null ? void 0 : captionProps.applyToAll) ? captionProps == null ? void 0 : captionProps.shadowColor : ((_I = element.props) == null ? void 0 : _I.shadowColor) ?? (captionProps == null ? void 0 : captionProps.shadowColor)) ?? DEFAULT_CAPTION_PROPS.shadowColor
858
+ 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]),
859
+ 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]),
860
+ 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,
861
+ 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
852
862
  }),
853
- strokeWidth: ((captionProps == null ? void 0 : captionProps.applyToAll) ? captionProps == null ? void 0 : captionProps.lineWidth : ((_J = element.props) == null ? void 0 : _J.lineWidth) ?? (captionProps == null ? void 0 : captionProps.lineWidth)) ?? DEFAULT_CAPTION_PROPS.lineWidth
863
+ 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
854
864
  });
855
865
  caption.set("id", element.id);
856
866
  caption.set("zIndex", index);
@@ -1561,6 +1571,148 @@ const WatermarkElement = {
1561
1571
  };
1562
1572
  }
1563
1573
  };
1574
+ const ArrowElement = {
1575
+ name: ELEMENT_TYPES.ARROW,
1576
+ async add(params) {
1577
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1578
+ const { element, index, canvas, canvasMetadata, lockAspectRatio } = params;
1579
+ const baseWidth = ((_a = element.props) == null ? void 0 : _a.width) ?? 220;
1580
+ const baseHeight = ((_b = element.props) == null ? void 0 : _b.height) ?? 14;
1581
+ const { x, y } = convertToCanvasPosition(
1582
+ ((_c = element.props) == null ? void 0 : _c.x) ?? 0,
1583
+ ((_d = element.props) == null ? void 0 : _d.y) ?? 0,
1584
+ canvasMetadata
1585
+ );
1586
+ const fill = ((_e = element.props) == null ? void 0 : _e.fill) || "#f59e0b";
1587
+ const radius = (((_f = element.props) == null ? void 0 : _f.radius) ?? 4) * canvasMetadata.scaleX;
1588
+ const barWidth = baseWidth * canvasMetadata.scaleX;
1589
+ const barHeight = baseHeight * canvasMetadata.scaleY;
1590
+ const headSize = barHeight * 1.8;
1591
+ const barLength = barWidth - headSize * 0.5;
1592
+ const bar = new Rect({
1593
+ left: -barWidth / 2,
1594
+ top: -barHeight / 2,
1595
+ originX: "left",
1596
+ originY: "top",
1597
+ width: barLength,
1598
+ height: barHeight,
1599
+ rx: radius,
1600
+ ry: radius,
1601
+ fill
1602
+ });
1603
+ const arrowHead = new Triangle({
1604
+ left: barWidth / 2 - headSize * 0.25,
1605
+ top: 0,
1606
+ originX: "center",
1607
+ originY: "center",
1608
+ width: headSize,
1609
+ height: headSize,
1610
+ fill,
1611
+ angle: 90
1612
+ });
1613
+ const opacity = ((_g = element.props) == null ? void 0 : _g.opacity) ?? 1;
1614
+ const group = new Group([bar, arrowHead], {
1615
+ left: x,
1616
+ top: y,
1617
+ originX: "center",
1618
+ originY: "center",
1619
+ angle: ((_h = element.props) == null ? void 0 : _h.rotation) || 0,
1620
+ opacity,
1621
+ selectable: true,
1622
+ hasControls: true
1623
+ });
1624
+ group.set(
1625
+ "lockUniScaling",
1626
+ lockAspectRatio ?? ((_i = element.props) == null ? void 0 : _i.lockAspectRatio) ?? true
1627
+ );
1628
+ group.set("id", element.id);
1629
+ group.set("zIndex", index);
1630
+ canvas.add(group);
1631
+ },
1632
+ updateFromFabricObject(object, element, context) {
1633
+ var _a, _b, _c;
1634
+ const canvasCenter = getObjectCanvasCenter(object);
1635
+ const { x, y } = convertToVideoPosition(
1636
+ canvasCenter.x,
1637
+ canvasCenter.y,
1638
+ context.canvasMetadata,
1639
+ context.videoSize
1640
+ );
1641
+ const baseWidth = ((_a = element.props) == null ? void 0 : _a.width) ?? 220;
1642
+ const baseHeight = ((_b = element.props) == null ? void 0 : _b.height) ?? 14;
1643
+ const opacity = object.opacity ?? ((_c = element.props) == null ? void 0 : _c.opacity) ?? 1;
1644
+ return {
1645
+ element: {
1646
+ ...element,
1647
+ props: {
1648
+ ...element.props,
1649
+ rotation: getObjectCanvasAngle(object),
1650
+ width: baseWidth * object.scaleX,
1651
+ height: baseHeight * object.scaleY,
1652
+ x,
1653
+ y,
1654
+ opacity
1655
+ }
1656
+ }
1657
+ };
1658
+ }
1659
+ };
1660
+ const LineElement = {
1661
+ name: ELEMENT_TYPES.LINE,
1662
+ async add(params) {
1663
+ var _a;
1664
+ const { element, index, canvas, canvasMetadata, lockAspectRatio } = params;
1665
+ const lineProps = element.props ?? {};
1666
+ const lineElement = {
1667
+ ...element,
1668
+ props: {
1669
+ ...lineProps,
1670
+ // Use fill as stroke color when a stroke is desired; otherwise rely
1671
+ // on fill-only rendering. Avoid the generic "#000000" fallback.
1672
+ stroke: lineProps.stroke ?? lineProps.fill,
1673
+ // If a specific lineWidth is provided, keep it; otherwise default to 0
1674
+ // so the stroke does not override the visual fill color.
1675
+ lineWidth: lineProps.lineWidth ?? 0
1676
+ }
1677
+ };
1678
+ await addRectElement({
1679
+ element: lineElement,
1680
+ index,
1681
+ canvas,
1682
+ canvasMetadata,
1683
+ lockAspectRatio: lockAspectRatio ?? ((_a = lineElement.props) == null ? void 0 : _a.lockAspectRatio)
1684
+ });
1685
+ },
1686
+ updateFromFabricObject(object, element, context) {
1687
+ var _a, _b;
1688
+ const canvasCenter = getObjectCanvasCenter(object);
1689
+ const { x, y } = convertToVideoPosition(
1690
+ canvasCenter.x,
1691
+ canvasCenter.y,
1692
+ context.canvasMetadata,
1693
+ context.videoSize
1694
+ );
1695
+ return {
1696
+ element: {
1697
+ ...element,
1698
+ props: {
1699
+ ...element.props,
1700
+ rotation: getObjectCanvasAngle(object),
1701
+ width: (((_a = element.props) == null ? void 0 : _a.width) ?? 0) * object.scaleX,
1702
+ height: (((_b = element.props) == null ? void 0 : _b.height) ?? 0) * object.scaleY,
1703
+ x,
1704
+ y
1705
+ }
1706
+ }
1707
+ };
1708
+ }
1709
+ };
1710
+ const EffectElement = {
1711
+ name: ELEMENT_TYPES.EFFECT,
1712
+ async add() {
1713
+ return;
1714
+ }
1715
+ };
1564
1716
  class ElementController {
1565
1717
  constructor() {
1566
1718
  __publicField(this, "elements", /* @__PURE__ */ new Map());
@@ -1584,8 +1736,17 @@ function registerElements() {
1584
1736
  elementController.register(TextElement);
1585
1737
  elementController.register(CaptionElement);
1586
1738
  elementController.register(WatermarkElement);
1739
+ elementController.register(ArrowElement);
1740
+ elementController.register(LineElement);
1741
+ elementController.register(EffectElement);
1587
1742
  }
1588
1743
  registerElements();
1744
+ function registerCanvasHandler(handler) {
1745
+ elementController.register(handler);
1746
+ }
1747
+ function getCanvasHandler(name) {
1748
+ return elementController.get(name);
1749
+ }
1589
1750
  const useTwickCanvas = ({
1590
1751
  onCanvasReady,
1591
1752
  onCanvasOperation,
@@ -1941,10 +2102,18 @@ const useTwickCanvas = ({
1941
2102
  const sendToBack = (elementId) => applyZOrder(elementId, "back");
1942
2103
  const bringForward = (elementId) => applyZOrder(elementId, "forward");
1943
2104
  const sendBackward = (elementId) => applyZOrder(elementId, "backward");
2105
+ const setBackgroundColor = useCallback((color) => {
2106
+ const canvas = twickCanvasRef.current;
2107
+ if (canvas) {
2108
+ canvas.backgroundColor = color;
2109
+ canvas.requestRenderAll();
2110
+ }
2111
+ }, []);
1944
2112
  return {
1945
2113
  twickCanvas,
1946
2114
  buildCanvas,
1947
2115
  resizeCanvas,
2116
+ setBackgroundColor,
1948
2117
  onVideoSizeChange,
1949
2118
  addWatermarkToCanvas,
1950
2119
  addElementToCanvas,
@@ -1970,7 +2139,9 @@ export {
1970
2139
  createCanvas,
1971
2140
  disabledControl,
1972
2141
  elementController,
2142
+ getCanvasHandler,
1973
2143
  getCurrentFrameEffect,
2144
+ registerCanvasHandler,
1974
2145
  reorderElementsByZIndex,
1975
2146
  rotateControl,
1976
2147
  useTwickCanvas