@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 +6 -0
- package/dist/index.js +193 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +195 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
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: "
|
|
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
|
-
(
|
|
823
|
-
(
|
|
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 = ((
|
|
827
|
-
if ((
|
|
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
|
|
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: ((
|
|
845
|
+
angle: ((_j = element.props) == null ? void 0 : _j.rotation) || 0,
|
|
836
846
|
fontSize: Math.round(
|
|
837
|
-
((
|
|
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: (
|
|
840
|
-
fill:
|
|
841
|
-
fontWeight: (
|
|
842
|
-
stroke: (
|
|
843
|
-
opacity: (
|
|
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: ((
|
|
856
|
+
textAlign: ((_y = element.props) == null ? void 0 : _y.textAlign) ?? "center",
|
|
847
857
|
shadow: new Shadow({
|
|
848
|
-
offsetX: (
|
|
849
|
-
offsetY: (
|
|
850
|
-
blur: (
|
|
851
|
-
color: (
|
|
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: (
|
|
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
|