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