@twick/canvas 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.
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
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";
4
+ import { Canvas, Control, controlsUtils, FabricImage, Rect, Textbox, Shadow, Group, Circle, Triangle, ActiveSelection } from "fabric";
5
5
  import { useState, useRef, useCallback } from "react";
6
6
  const DEFAULT_TEXT_PROPS = {
7
7
  /** Font family for text elements */
@@ -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,7 +823,7 @@ 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, _K;
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;
821
827
  const applyToAll = (captionProps == null ? void 0 : captionProps.applyToAll) ?? false;
822
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);
823
829
  const { x, y } = convertToCanvasPosition(
@@ -842,19 +848,19 @@ const addCaptionElement = ({
842
848
  ),
843
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,
844
850
  fill: resolvedFill,
845
- fontWeight: (applyToAll ? (_s = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _s.weight : ((_t = element.props) == null ? void 0 : _t.fontWeight) ?? ((_u = captionProps == null ? void 0 : captionProps.font) == null ? void 0 : _u.weight)) ?? DEFAULT_CAPTION_PROPS.fontWeight,
846
- 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,
847
- opacity: (applyToAll ? captionProps == null ? void 0 : captionProps.opacity : ((_w = element.props) == null ? void 0 : _w.opacity) ?? (captionProps == null ? void 0 : captionProps.opacity)) ?? 1,
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,
848
854
  width,
849
855
  splitByGrapheme: false,
850
- textAlign: ((_x = element.props) == null ? void 0 : _x.textAlign) ?? "center",
856
+ textAlign: ((_y = element.props) == null ? void 0 : _y.textAlign) ?? "center",
851
857
  shadow: new Shadow({
852
- 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]),
853
- 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]),
854
- 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,
855
- 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
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
856
862
  }),
857
- 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
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
858
864
  });
859
865
  caption.set("id", element.id);
860
866
  caption.set("zIndex", index);
@@ -1565,6 +1571,148 @@ const WatermarkElement = {
1565
1571
  };
1566
1572
  }
1567
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
+ };
1568
1716
  class ElementController {
1569
1717
  constructor() {
1570
1718
  __publicField(this, "elements", /* @__PURE__ */ new Map());
@@ -1588,8 +1736,17 @@ function registerElements() {
1588
1736
  elementController.register(TextElement);
1589
1737
  elementController.register(CaptionElement);
1590
1738
  elementController.register(WatermarkElement);
1739
+ elementController.register(ArrowElement);
1740
+ elementController.register(LineElement);
1741
+ elementController.register(EffectElement);
1591
1742
  }
1592
1743
  registerElements();
1744
+ function registerCanvasHandler(handler) {
1745
+ elementController.register(handler);
1746
+ }
1747
+ function getCanvasHandler(name) {
1748
+ return elementController.get(name);
1749
+ }
1593
1750
  const useTwickCanvas = ({
1594
1751
  onCanvasReady,
1595
1752
  onCanvasOperation,
@@ -1982,7 +2139,9 @@ export {
1982
2139
  createCanvas,
1983
2140
  disabledControl,
1984
2141
  elementController,
2142
+ getCanvasHandler,
1985
2143
  getCurrentFrameEffect,
2144
+ registerCanvasHandler,
1986
2145
  reorderElementsByZIndex,
1987
2146
  rotateControl,
1988
2147
  useTwickCanvas