@pixerate/editor-react 0.17.0 → 0.18.1

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.
@@ -1509,15 +1509,622 @@ import {
1509
1509
  TOKEN_BINDINGS_DATA_KEY,
1510
1510
  TOKEN_MODES_DATA_KEY
1511
1511
  } from "@pixerate/editor/canvas";
1512
+
1513
+ // src/canvas/useCanvasAnimation.ts
1514
+ import { useEffect as useEffect6, useMemo as useMemo5, useRef as useRef10, useSyncExternalStore as useSyncExternalStore3 } from "react";
1515
+ import {
1516
+ createCanvasAnimationController
1517
+ } from "@pixerate/editor/canvas";
1518
+ function useCanvasAnimation(options) {
1519
+ const nodesRef = useRef10(options.nodes);
1520
+ nodesRef.current = options.nodes;
1521
+ const optionsRef = useRef10(options);
1522
+ optionsRef.current = options;
1523
+ const controller = useMemo5(
1524
+ () => createCanvasAnimationController({
1525
+ getNodes: () => nodesRef.current,
1526
+ setNodes: (next) => {
1527
+ nodesRef.current = next;
1528
+ optionsRef.current.setNodes(next);
1529
+ },
1530
+ get history() {
1531
+ return optionsRef.current.history;
1532
+ },
1533
+ get getSelectedIds() {
1534
+ return optionsRef.current.getSelectedIds;
1535
+ },
1536
+ get properties() {
1537
+ return optionsRef.current.properties;
1538
+ },
1539
+ clock: options.clock,
1540
+ duration: options.duration,
1541
+ minDuration: options.minDuration,
1542
+ loop: options.loop,
1543
+ playbackRate: options.playbackRate,
1544
+ fps: options.fps,
1545
+ recording: options.recording,
1546
+ onTime: (time) => optionsRef.current.onTime?.(time)
1547
+ }),
1548
+ []
1549
+ );
1550
+ useEffect6(() => () => controller.destroy(), [controller]);
1551
+ useEffect6(() => {
1552
+ if (options.loop !== void 0) controller.setLoop(options.loop);
1553
+ }, [controller, options.loop]);
1554
+ useEffect6(() => {
1555
+ if (options.playbackRate !== void 0) controller.setPlaybackRate(options.playbackRate);
1556
+ }, [controller, options.playbackRate]);
1557
+ useEffect6(() => {
1558
+ if (options.recording !== void 0) controller.setRecording(options.recording);
1559
+ }, [controller, options.recording]);
1560
+ const state = useSyncExternalStore3(
1561
+ (listener) => controller.subscribe(listener),
1562
+ () => controller.getState(),
1563
+ () => controller.getState()
1564
+ );
1565
+ useEffect6(() => {
1566
+ controller.refresh();
1567
+ }, [controller, options.nodes]);
1568
+ const displayNodes = useMemo5(() => controller.display(options.nodes), [controller, options.nodes, state.time]);
1569
+ return useMemo5(
1570
+ () => ({
1571
+ ...controller,
1572
+ state,
1573
+ time: state.time,
1574
+ playing: state.playing,
1575
+ recording: state.recording,
1576
+ duration: state.duration,
1577
+ selection: state.selection,
1578
+ drag: state.drag,
1579
+ /** The nodes evaluated at the playhead; render these. */
1580
+ displayNodes,
1581
+ get clipboard() {
1582
+ return controller.clipboard;
1583
+ }
1584
+ }),
1585
+ [controller, state, displayNodes]
1586
+ );
1587
+ }
1588
+
1589
+ // src/canvas/AnimationTimeline.tsx
1590
+ import { useEffect as useEffect7, useRef as useRef11 } from "react";
1591
+ import {
1592
+ ANIMATION_EASING_LABELS,
1593
+ ANIMATION_EASING_PRESETS,
1594
+ formatAnimationTime,
1595
+ getTimelineTicks,
1596
+ timeToX,
1597
+ xToTime
1598
+ } from "@pixerate/editor/canvas";
1599
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1600
+ var LOOP_LABELS = { none: "Once", loop: "Loop", "ping-pong": "Ping-pong" };
1601
+ var easingValue = (easing) => typeof easing === "string" ? easing : easing ? "custom" : "linear";
1602
+ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8, labelOf, className = "" }) {
1603
+ const { state } = animation;
1604
+ const duration = state.duration;
1605
+ const rows = animation.timelineRows(nodeIds ?? void 0, labelOf ? { labelOf } : {});
1606
+ const ticks = getTimelineTicks(duration, width);
1607
+ const selectedEasing = (() => {
1608
+ const first = state.selection[0];
1609
+ if (!first) return "";
1610
+ for (const row of rows) for (const k of row.keyframes) if (k.selected && k.ref.property === first.property && k.ref.nodeId === first.nodeId) return easingValue(k.easing);
1611
+ return "";
1612
+ })();
1613
+ const dragRef = useRef11(null);
1614
+ useEffect7(() => {
1615
+ const onKey = (event) => {
1616
+ if (event.key === "Escape" && dragRef.current) {
1617
+ dragRef.current = null;
1618
+ animation.cancelKeyframeDrag();
1619
+ }
1620
+ };
1621
+ window.addEventListener("keydown", onKey);
1622
+ return () => window.removeEventListener("keydown", onKey);
1623
+ }, [animation]);
1624
+ const onRulerDown = (event) => {
1625
+ const lane = event.currentTarget;
1626
+ const left = lane.getBoundingClientRect().left;
1627
+ animation.scrub(xToTime(event.clientX - left, duration, width));
1628
+ const move = (e) => animation.scrub(xToTime(e.clientX - left, duration, width));
1629
+ const up = () => {
1630
+ window.removeEventListener("pointermove", move);
1631
+ window.removeEventListener("pointerup", up);
1632
+ animation.endScrub();
1633
+ };
1634
+ window.addEventListener("pointermove", move);
1635
+ window.addEventListener("pointerup", up);
1636
+ };
1637
+ const onKeyDown = (ref) => (event) => {
1638
+ event.stopPropagation();
1639
+ event.preventDefault();
1640
+ if (event.shiftKey || event.metaKey || event.ctrlKey) {
1641
+ animation.selectKeyframes([ref], "toggle");
1642
+ return;
1643
+ }
1644
+ animation.beginKeyframeDrag([ref]);
1645
+ dragRef.current = { startX: event.clientX };
1646
+ const msPerPx = width > 0 ? duration / width : 0;
1647
+ const move = (e) => {
1648
+ if (!dragRef.current) return;
1649
+ animation.updateKeyframeDrag((e.clientX - dragRef.current.startX) * msPerPx, { snap: !e.altKey, thresholdMs: snapThreshold * msPerPx });
1650
+ };
1651
+ const up = () => {
1652
+ window.removeEventListener("pointermove", move);
1653
+ window.removeEventListener("pointerup", up);
1654
+ if (!dragRef.current) return;
1655
+ dragRef.current = null;
1656
+ animation.endKeyframeDrag();
1657
+ };
1658
+ window.addEventListener("pointermove", move);
1659
+ window.addEventListener("pointerup", up);
1660
+ };
1661
+ const onTimelineKey = (event) => {
1662
+ if ((event.key === "Delete" || event.key === "Backspace") && state.selection.length > 0) {
1663
+ event.preventDefault();
1664
+ animation.deleteKeyframes();
1665
+ }
1666
+ };
1667
+ const btn = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-50";
1668
+ const playheadX = timeToX(state.time, duration, width);
1669
+ const labelWidth = 120;
1670
+ return /* @__PURE__ */ jsxs5("div", { "data-animation-timeline": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, tabIndex: 0, onKeyDown: onTimelineKey, children: [
1671
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap items-center gap-2", role: "toolbar", "aria-label": "Animation", children: [
1672
+ /* @__PURE__ */ jsx5("button", { type: "button", className: btn, "data-action": "toggle-play", "aria-label": state.playing ? "Pause" : "Play", onClick: () => animation.toggle(), children: state.playing ? "\u275A\u275A" : "\u25B6" }),
1673
+ /* @__PURE__ */ jsx5(
1674
+ "button",
1675
+ {
1676
+ type: "button",
1677
+ className: `${btn} ${state.recording ? "text-red-500" : ""}`,
1678
+ "data-action": "record",
1679
+ "aria-pressed": state.recording,
1680
+ "aria-label": "Record keyframes",
1681
+ onClick: () => animation.toggleRecording(),
1682
+ children: "\u25CF Rec"
1683
+ }
1684
+ ),
1685
+ /* @__PURE__ */ jsx5("button", { type: "button", className: btn, "data-action": "add-keyframe", onClick: () => animation.addKeyframe(), children: "\u25C6 Key" }),
1686
+ /* @__PURE__ */ jsxs5("span", { "data-time": "", className: "tabular-nums text-muted-foreground", children: [
1687
+ formatAnimationTime(state.time),
1688
+ " / ",
1689
+ formatAnimationTime(duration)
1690
+ ] }),
1691
+ /* @__PURE__ */ jsxs5(
1692
+ "select",
1693
+ {
1694
+ "aria-label": "Easing",
1695
+ "data-easing-picker": "",
1696
+ className: "rounded border border-border bg-background px-1 py-0.5",
1697
+ value: selectedEasing,
1698
+ disabled: state.selection.length === 0,
1699
+ onChange: (e) => e.target.value && e.target.value !== "custom" && animation.setEasing(e.target.value),
1700
+ children: [
1701
+ /* @__PURE__ */ jsx5("option", { value: "", children: "Easing\u2026" }),
1702
+ ANIMATION_EASING_PRESETS.map((preset) => /* @__PURE__ */ jsx5("option", { value: preset, children: ANIMATION_EASING_LABELS[preset] }, preset)),
1703
+ selectedEasing === "custom" ? /* @__PURE__ */ jsx5("option", { value: "custom", children: "Custom" }) : null
1704
+ ]
1705
+ }
1706
+ ),
1707
+ /* @__PURE__ */ jsx5(
1708
+ "select",
1709
+ {
1710
+ "aria-label": "Loop",
1711
+ "data-loop-picker": "",
1712
+ className: "rounded border border-border bg-background px-1 py-0.5",
1713
+ value: state.loop,
1714
+ onChange: (e) => animation.setLoop(e.target.value),
1715
+ children: Object.keys(LOOP_LABELS).map((mode) => /* @__PURE__ */ jsx5("option", { value: mode, children: LOOP_LABELS[mode] }, mode))
1716
+ }
1717
+ )
1718
+ ] }),
1719
+ /* @__PURE__ */ jsxs5("div", { className: "flex", children: [
1720
+ /* @__PURE__ */ jsx5("div", { style: { width: labelWidth }, className: "shrink-0" }),
1721
+ /* @__PURE__ */ jsxs5(
1722
+ "div",
1723
+ {
1724
+ "data-timeline-ruler": "",
1725
+ className: "relative h-5 cursor-ew-resize border-b border-border",
1726
+ style: { width },
1727
+ onPointerDown: onRulerDown,
1728
+ children: [
1729
+ ticks.map((tick) => /* @__PURE__ */ jsx5("span", { className: "absolute top-0 -translate-x-1/2 text-[10px] text-muted-foreground", style: { left: tick.x }, children: tick.label }, tick.time)),
1730
+ /* @__PURE__ */ jsx5("div", { "data-playhead": "", className: "absolute top-0 h-5 w-px bg-red-500", style: { left: playheadX } })
1731
+ ]
1732
+ }
1733
+ )
1734
+ ] }),
1735
+ rows.length === 0 ? /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground", "data-timeline-empty": "", children: "Select an animated node, or press \u25C6 Key to add a keyframe." }) : rows.map((row) => /* @__PURE__ */ jsxs5("div", { className: "flex items-center", "data-track": row.id, children: [
1736
+ /* @__PURE__ */ jsxs5("label", { className: "flex shrink-0 items-center gap-1 truncate pr-2", style: { width: labelWidth }, title: `${row.nodeLabel} \xB7 ${row.label}`, children: [
1737
+ /* @__PURE__ */ jsx5(
1738
+ "input",
1739
+ {
1740
+ type: "checkbox",
1741
+ "aria-label": `Enable ${row.label}`,
1742
+ checked: row.enabled,
1743
+ onChange: (e) => animation.setTrackEnabled(row.nodeId, row.property, e.target.checked)
1744
+ }
1745
+ ),
1746
+ /* @__PURE__ */ jsxs5("span", { className: "truncate", children: [
1747
+ rows.filter((r) => r.nodeId === row.nodeId).length < rows.length ? `${row.nodeLabel} \xB7 ` : "",
1748
+ row.label
1749
+ ] })
1750
+ ] }),
1751
+ /* @__PURE__ */ jsxs5("div", { "data-lane": "", className: `relative h-5 rounded bg-muted/40 ${row.enabled ? "" : "opacity-50"}`, style: { width }, children: [
1752
+ /* @__PURE__ */ jsx5("div", { className: "pointer-events-none absolute top-0 h-5 w-px bg-red-500/60", style: { left: playheadX } }),
1753
+ state.drag?.target != null ? /* @__PURE__ */ jsx5("div", { "data-snap-target": "", className: "pointer-events-none absolute top-0 h-5 w-px bg-sky-400", style: { left: timeToX(state.drag.target, duration, width) } }) : null,
1754
+ row.keyframes.map((k) => /* @__PURE__ */ jsx5(
1755
+ "button",
1756
+ {
1757
+ type: "button",
1758
+ "data-keyframe": k.ref.time,
1759
+ "aria-pressed": k.selected,
1760
+ "aria-label": `${row.label} keyframe at ${formatAnimationTime(k.ref.time)}`,
1761
+ title: `${formatAnimationTime(k.time)} \xB7 ${String(k.value)}`,
1762
+ className: `absolute top-1/2 h-2.5 w-2.5 -translate-x-1/2 -translate-y-1/2 rotate-45 border ${k.selected ? "border-sky-300 bg-sky-500" : "border-foreground/60 bg-background"} ${k.easing === "hold" ? "rounded-none" : "rounded-[1px]"}`,
1763
+ style: { left: timeToX(k.time, duration, width) },
1764
+ onPointerDown: onKeyDown(k.ref)
1765
+ },
1766
+ k.ref.time
1767
+ ))
1768
+ ] })
1769
+ ] }, row.id))
1770
+ ] });
1771
+ }
1772
+
1773
+ // src/canvas/index.ts
1774
+ import {
1775
+ createCanvasAnimationController as createCanvasAnimationController2,
1776
+ AnimationPlayer,
1777
+ createAnimationPlayer,
1778
+ AnimationEditError,
1779
+ ANIMATION_DATA_KEY,
1780
+ ANIMATION_TIME_EPSILON,
1781
+ ANIMATABLE_PROPERTIES,
1782
+ ANIMATION_EASING_PRESETS as ANIMATION_EASING_PRESETS2,
1783
+ ANIMATION_EASING_LABELS as ANIMATION_EASING_LABELS2,
1784
+ CUBIC_BEZIER_PRESETS,
1785
+ MAX_KEYFRAME_REFS,
1786
+ CSS_ANIMATION_PROPERTIES,
1787
+ evaluateAnimation,
1788
+ evaluateTrack,
1789
+ evaluateEasing,
1790
+ applyAnimation,
1791
+ applyAnimationOverrides,
1792
+ interpolateAnimationValue,
1793
+ getAnimationDuration,
1794
+ wrapAnimationTime,
1795
+ cubicBezierAt,
1796
+ springAt,
1797
+ resolveEasing,
1798
+ parseCssEasing,
1799
+ easingToCss,
1800
+ easingLabel,
1801
+ easingFromInfluence,
1802
+ isAnimationEasing,
1803
+ mixColorsOklab,
1804
+ rgbToOklab,
1805
+ oklabToRgb,
1806
+ parseOklab,
1807
+ formatOklab,
1808
+ getNodeAnimation,
1809
+ getAnimationTrack,
1810
+ getAnimatedProperties,
1811
+ getAnimatableProperty,
1812
+ isNodeAnimated,
1813
+ withNodeAnimation,
1814
+ normalizeKeyframes,
1815
+ isAnimationKeyframe,
1816
+ clampAnimationValue,
1817
+ setKeyframe,
1818
+ addKeyframesAtTime,
1819
+ updateKeyframe,
1820
+ deleteKeyframes,
1821
+ setKeyframeEasing,
1822
+ setTrackEnabled,
1823
+ removeTrack,
1824
+ setMotionPath,
1825
+ moveKeyframes,
1826
+ scaleKeyframes,
1827
+ snapKeyframeDelta,
1828
+ snapTimeToFrame,
1829
+ getKeyframeTimes,
1830
+ copyKeyframes,
1831
+ pasteKeyframes,
1832
+ parseKeyframeClipboard,
1833
+ recordAnimationChanges,
1834
+ animateNode,
1835
+ getAnimatedValue,
1836
+ readAnimatableValue,
1837
+ sampleAnimationFrames,
1838
+ exportCssAnimation,
1839
+ toWebAnimations,
1840
+ playWebAnimations,
1841
+ getCssPropertyAnimations,
1842
+ isCssExportExact,
1843
+ getTimelineRows,
1844
+ getTimelineTicks as getTimelineTicks2,
1845
+ isKeyframeSelected,
1846
+ timeToX as timeToX2,
1847
+ xToTime as xToTime2,
1848
+ formatAnimationTime as formatAnimationTime2
1849
+ } from "@pixerate/editor/canvas";
1850
+
1851
+ // src/canvas/useCanvasComponents.ts
1852
+ import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo6, useRef as useRef12 } from "react";
1853
+ import {
1854
+ createCanvasComponentsController
1855
+ } from "@pixerate/editor/canvas";
1856
+ function useCanvasComponents(options) {
1857
+ const nodesRef = useRef12(options.nodes);
1858
+ nodesRef.current = options.nodes;
1859
+ const optionsRef = useRef12(options);
1860
+ optionsRef.current = options;
1861
+ const controller = useMemo6(
1862
+ () => createCanvasComponentsController({
1863
+ getNodes: () => nodesRef.current,
1864
+ setNodes: (next) => {
1865
+ nodesRef.current = next;
1866
+ optionsRef.current.setNodes(next);
1867
+ },
1868
+ get history() {
1869
+ return optionsRef.current.history;
1870
+ },
1871
+ get getSelectedIds() {
1872
+ return optionsRef.current.getSelectedIds;
1873
+ },
1874
+ onReveal: (node) => optionsRef.current.onReveal?.(node),
1875
+ get idGenerator() {
1876
+ return optionsRef.current.idGenerator;
1877
+ },
1878
+ get textTypes() {
1879
+ return optionsRef.current.textTypes;
1880
+ },
1881
+ get layout() {
1882
+ return optionsRef.current.layout;
1883
+ },
1884
+ get tokens() {
1885
+ return optionsRef.current.tokens;
1886
+ }
1887
+ }),
1888
+ []
1889
+ );
1890
+ useLayoutEffect2(() => {
1891
+ if (optionsRef.current.autoSync !== false) controller.sync();
1892
+ }, [options.nodes, controller]);
1893
+ return controller;
1894
+ }
1895
+
1896
+ // src/canvas/CanvasComponentsPanel.tsx
1897
+ import { useState as useState5 } from "react";
1898
+ import {
1899
+ CANVAS_COMPONENT_DRAG_TYPE,
1900
+ inspectCanvasInstance,
1901
+ listCanvasComponents
1902
+ } from "@pixerate/editor/canvas";
1903
+ import { Fragment, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1904
+ function CanvasComponentsPanel({
1905
+ nodes,
1906
+ onInsert,
1907
+ search = true,
1908
+ className = ""
1909
+ }) {
1910
+ const [query, setQuery] = useState5("");
1911
+ const { components, sets } = listCanvasComponents(nodes);
1912
+ const q = query.trim().toLowerCase();
1913
+ const match = (name) => !q || name.toLowerCase().includes(q);
1914
+ const lone = components.filter((c) => !c.setId && match(c.name));
1915
+ const shownSets = sets.filter((s) => match(s.name) || s.variants.some((v) => match(v.name)));
1916
+ const item = (id, name, count, extra = {}) => /* @__PURE__ */ jsxs6(
1917
+ "button",
1918
+ {
1919
+ type: "button",
1920
+ draggable: true,
1921
+ "data-component-id": id,
1922
+ ...extra,
1923
+ className: "flex w-full items-center justify-between gap-2 rounded px-2 py-1 text-left text-xs hover:bg-muted",
1924
+ title: `Insert an instance of ${name}`,
1925
+ onClick: () => onInsert(id),
1926
+ onDragStart: (e) => {
1927
+ e.dataTransfer.setData(CANVAS_COMPONENT_DRAG_TYPE, id);
1928
+ e.dataTransfer.setData("text/plain", name);
1929
+ e.dataTransfer.effectAllowed = "copy";
1930
+ },
1931
+ children: [
1932
+ /* @__PURE__ */ jsxs6("span", { className: "truncate", children: [
1933
+ /* @__PURE__ */ jsx6("span", { "aria-hidden": true, className: "mr-1 text-muted-foreground", children: "\u25C7" }),
1934
+ name
1935
+ ] }),
1936
+ /* @__PURE__ */ jsx6("span", { className: "text-[10px] text-muted-foreground", "data-instance-count": "", children: count })
1937
+ ]
1938
+ },
1939
+ id
1940
+ );
1941
+ return /* @__PURE__ */ jsxs6("div", { "data-components-panel": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
1942
+ search ? /* @__PURE__ */ jsx6(
1943
+ "input",
1944
+ {
1945
+ type: "search",
1946
+ "aria-label": "Search components",
1947
+ placeholder: "Search components",
1948
+ className: "rounded border border-border bg-background px-2 py-1 text-xs",
1949
+ onInput: (e) => setQuery(e.target.value)
1950
+ }
1951
+ ) : null,
1952
+ shownSets.map((set) => /* @__PURE__ */ jsxs6("div", { "data-component-set": set.id, className: "flex flex-col", children: [
1953
+ item(set.id, set.name, set.variants.reduce((sum, v) => sum + v.instanceCount, 0), { "data-kind": "set" }),
1954
+ /* @__PURE__ */ jsx6("div", { className: "ml-3 flex flex-col border-l border-border pl-1", children: set.variants.map((v) => item(v.id, v.name, v.instanceCount, { "data-kind": "variant" })) })
1955
+ ] }, set.id)),
1956
+ lone.map((c) => item(c.id, c.name, c.instanceCount, { "data-kind": "component" })),
1957
+ components.length === 0 ? /* @__PURE__ */ jsx6("p", { className: "text-muted-foreground", children: "No components yet. Select a frame and choose Create Component." }) : null
1958
+ ] });
1959
+ }
1960
+ function CanvasInstanceInspector({
1961
+ nodes,
1962
+ nodeId,
1963
+ components,
1964
+ onError,
1965
+ className = ""
1966
+ }) {
1967
+ const info = nodeId ? inspectCanvasInstance(nodes, nodeId) : void 0;
1968
+ if (!info) return null;
1969
+ const report = (result) => {
1970
+ if (result && !result.ok && result.reason) onError?.(result.reason);
1971
+ };
1972
+ const setProp = (name, value) => report(components.setInstanceProperties({ [name]: value }, [info.id]));
1973
+ const allComponents = listCanvasComponents(nodes).components;
1974
+ const linked = info.status === "linked";
1975
+ const btn = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-40";
1976
+ return /* @__PURE__ */ jsxs6("div", { "data-instance-inspector": "", "data-instance-id": info.id, className: `flex flex-col gap-2 text-xs text-foreground ${className}`, children: [
1977
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2", children: [
1978
+ /* @__PURE__ */ jsx6("span", { className: "truncate font-medium", "data-instance-main": "", children: linked ? info.componentName : "Main component missing" }),
1979
+ info.nested ? /* @__PURE__ */ jsx6("span", { className: "text-muted-foreground", children: "Nested" }) : null
1980
+ ] }),
1981
+ info.variantOptions.map((option) => /* @__PURE__ */ jsxs6("label", { className: "flex items-center gap-2", "data-variant-property": option.name, children: [
1982
+ /* @__PURE__ */ jsx6("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: option.name }),
1983
+ /* @__PURE__ */ jsx6(
1984
+ "select",
1985
+ {
1986
+ "aria-label": `${option.name} variant`,
1987
+ className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
1988
+ value: info.variant[option.name] ?? "",
1989
+ onChange: (e) => setProp(option.name, e.currentTarget.value),
1990
+ children: option.values.map((v) => /* @__PURE__ */ jsx6("option", { value: v, children: v }, v))
1991
+ }
1992
+ )
1993
+ ] }, option.name)),
1994
+ info.properties.map((p) => /* @__PURE__ */ jsxs6("label", { className: "flex items-center gap-2", "data-component-property": p.name, children: [
1995
+ /* @__PURE__ */ jsx6("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: p.name }),
1996
+ p.type === "boolean" ? /* @__PURE__ */ jsx6("input", { type: "checkbox", "aria-label": p.name, checked: p.value === true, onChange: (e) => setProp(p.name, e.currentTarget.checked) }) : p.type === "text" ? /* @__PURE__ */ jsx6(
1997
+ "input",
1998
+ {
1999
+ type: "text",
2000
+ "aria-label": p.name,
2001
+ defaultValue: String(p.value),
2002
+ className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
2003
+ onBlur: (e) => {
2004
+ if (e.currentTarget.value !== p.value) setProp(p.name, e.currentTarget.value);
2005
+ },
2006
+ onKeyDown: (e) => {
2007
+ if (e.key === "Enter") e.currentTarget.blur();
2008
+ }
2009
+ },
2010
+ String(p.value)
2011
+ ) : /* @__PURE__ */ jsx6(
2012
+ "select",
2013
+ {
2014
+ "aria-label": p.name,
2015
+ className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
2016
+ value: String(p.value),
2017
+ onChange: (e) => setProp(p.name, e.currentTarget.value),
2018
+ children: allComponents.filter((c) => !p.preferred?.length || p.preferred.includes(c.id) || c.id === p.value).map((c) => /* @__PURE__ */ jsx6("option", { value: c.id, children: c.name }, c.id))
2019
+ }
2020
+ )
2021
+ ] }, p.name)),
2022
+ info.overrides.length ? /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-1", "data-instance-overrides": "", children: [
2023
+ /* @__PURE__ */ jsx6("span", { className: "text-muted-foreground", children: "Overrides" }),
2024
+ info.overrides.map((o) => /* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap items-center gap-1", "data-override-layer": o.id, children: [
2025
+ /* @__PURE__ */ jsx6("span", { className: "mr-1 truncate", children: o.name }),
2026
+ o.groups.map((g) => /* @__PURE__ */ jsxs6(
2027
+ "button",
2028
+ {
2029
+ type: "button",
2030
+ className: "rounded bg-muted px-1 text-[10px]",
2031
+ "data-override-group": g,
2032
+ title: `Reset ${g}`,
2033
+ onClick: () => report(components.resetOverrides(o.id, g)),
2034
+ children: [
2035
+ g,
2036
+ " \xD7"
2037
+ ]
2038
+ },
2039
+ g
2040
+ ))
2041
+ ] }, o.id))
2042
+ ] }) : null,
2043
+ /* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap gap-1", children: [
2044
+ linked ? /* @__PURE__ */ jsxs6(Fragment, { children: [
2045
+ /* @__PURE__ */ jsx6("button", { type: "button", className: btn, "data-action": "reset", onClick: () => report(components.resetOverrides(info.id)), children: "Reset all" }),
2046
+ /* @__PURE__ */ jsx6("button", { type: "button", className: btn, "data-action": "go-to-main", onClick: () => components.goToMainComponent(info.id), children: "Go to main" }),
2047
+ /* @__PURE__ */ jsx6(
2048
+ "button",
2049
+ {
2050
+ type: "button",
2051
+ className: btn,
2052
+ "data-action": "push",
2053
+ disabled: info.overrides.length === 0,
2054
+ onClick: () => report(components.pushOverrides(info.rootId)),
2055
+ children: "Push changes"
2056
+ }
2057
+ )
2058
+ ] }) : /* @__PURE__ */ jsx6("button", { type: "button", className: btn, "data-action": "restore", onClick: () => report(components.restoreMainComponent(info.rootId)), children: "Restore main component" }),
2059
+ /* @__PURE__ */ jsx6(
2060
+ "button",
2061
+ {
2062
+ type: "button",
2063
+ className: btn,
2064
+ "data-action": "detach",
2065
+ disabled: info.nested,
2066
+ title: info.nested ? "Detach the outer instance first" : void 0,
2067
+ onClick: () => report(components.detachInstance([info.id])),
2068
+ children: "Detach"
2069
+ }
2070
+ )
2071
+ ] })
2072
+ ] });
2073
+ }
2074
+
2075
+ // src/canvas/index.ts
2076
+ import {
2077
+ createCanvasComponentsController as createCanvasComponentsController2,
2078
+ createCanvasComponent,
2079
+ combineCanvasComponentsAsVariants,
2080
+ createCanvasInstance,
2081
+ detachCanvasInstance,
2082
+ resetCanvasInstanceOverrides,
2083
+ pushCanvasInstanceOverrides,
2084
+ swapCanvasInstance,
2085
+ setCanvasInstanceProperties,
2086
+ setCanvasComponentProperty,
2087
+ bindCanvasComponentProperty,
2088
+ restoreCanvasMainComponent,
2089
+ syncCanvasComponents,
2090
+ syncCanvasInstance,
2091
+ syncAllCanvasInstances,
2092
+ listCanvasComponents as listCanvasComponents2,
2093
+ inspectCanvasInstance as inspectCanvasInstance2,
2094
+ getInstanceStatus,
2095
+ getNodeOverrides,
2096
+ getComponentSourceId,
2097
+ getInstanceData,
2098
+ getCanvasComponentDragId,
2099
+ isCanvasComponent,
2100
+ isCanvasComponentSet,
2101
+ isCanvasInstance,
2102
+ wouldCreateComponentCycle,
2103
+ CANVAS_COMPONENT_DRAG_TYPE as CANVAS_COMPONENT_DRAG_TYPE2
2104
+ } from "@pixerate/editor/canvas";
1512
2105
  export {
2106
+ ANIMATABLE_PROPERTIES,
2107
+ ANIMATION_DATA_KEY,
2108
+ ANIMATION_EASING_LABELS2 as ANIMATION_EASING_LABELS,
2109
+ ANIMATION_EASING_PRESETS2 as ANIMATION_EASING_PRESETS,
2110
+ ANIMATION_TIME_EPSILON,
1513
2111
  AUTO_LAYOUT_DATA_KEY,
1514
2112
  AgentPresenceLayer,
2113
+ AnimationEditError,
2114
+ AnimationPlayer,
2115
+ AnimationTimeline,
2116
+ CANVAS_COMPONENT_DRAG_TYPE2 as CANVAS_COMPONENT_DRAG_TYPE,
1515
2117
  CANVAS_TOKEN_PROPERTIES,
1516
2118
  CHILD_LAYOUT_DATA_KEY,
1517
2119
  CONNECTION_LINE_TYPES,
2120
+ CSS_ANIMATION_PROPERTIES,
2121
+ CUBIC_BEZIER_PRESETS,
2122
+ CanvasComponentsPanel,
1518
2123
  CanvasGuidesLayer,
2124
+ CanvasInstanceInspector,
1519
2125
  CanvasScenesStore2 as CanvasScenesStore,
1520
2126
  DEFAULT_ARRANGE_SHORTCUTS,
2127
+ MAX_KEYFRAME_REFS,
1521
2128
  ManualClock,
1522
2129
  RESIZE_HANDLES,
1523
2130
  SHAPE_DATA_KEY,
@@ -1529,7 +2136,11 @@ export {
1529
2136
  TOKEN_MODES_DATA_KEY,
1530
2137
  TokenBindingPicker,
1531
2138
  TokenModeSwitcher,
2139
+ addKeyframesAtTime,
1532
2140
  alignNodes,
2141
+ animateNode,
2142
+ applyAnimation,
2143
+ applyAnimationOverrides,
1533
2144
  applyConstraints,
1534
2145
  applyNodeUpdates,
1535
2146
  applyShapeCombination,
@@ -1540,6 +2151,7 @@ export {
1540
2151
  bezierPathPointAtLength,
1541
2152
  bezierPathSignedArea,
1542
2153
  bezierPathToSvg,
2154
+ bindCanvasComponentProperty,
1543
2155
  bindCanvasToken3 as bindCanvasToken,
1544
2156
  blendLayout,
1545
2157
  boundsOf,
@@ -1551,31 +2163,49 @@ export {
1551
2163
  canvasHeight,
1552
2164
  centerNodes2 as centerNodes,
1553
2165
  centre,
2166
+ clampAnimationValue,
1554
2167
  clampLayoutSize,
2168
+ combineCanvasComponentsAsVariants,
1555
2169
  combineShapeNodes,
1556
2170
  computeNodesBoundingBox,
1557
2171
  computeSnapGuides,
1558
2172
  connectedOnly,
2173
+ copyKeyframes,
1559
2174
  countPathSegments,
2175
+ createAnimationPlayer,
1560
2176
  createBezierTrajectory,
2177
+ createCanvasAnimationController2 as createCanvasAnimationController,
1561
2178
  createCanvasAutoLayoutController2 as createCanvasAutoLayoutController,
2179
+ createCanvasComponent,
2180
+ createCanvasComponentsController2 as createCanvasComponentsController,
2181
+ createCanvasInstance,
1562
2182
  createCanvasScenesStore,
1563
2183
  createFanOutTrajectory2 as createFanOutTrajectory,
1564
2184
  createGuideIndex,
1565
2185
  createNodeGuideIndex,
2186
+ cubicBezierAt,
1566
2187
  cubicPointAt,
1567
2188
  cubicsToPathData,
1568
2189
  dashContours,
1569
2190
  defaultEasing,
2191
+ deleteKeyframes,
2192
+ detachCanvasInstance,
1570
2193
  detachTokenBindings2 as detachTokenBindings,
1571
2194
  distanceToBezierPath,
1572
2195
  distributeNodes,
1573
2196
  dividePaths,
1574
2197
  dividePolygons,
2198
+ easingFromInfluence,
2199
+ easingLabel,
2200
+ easingToCss,
1575
2201
  ensureLayout2 as ensureLayout,
1576
2202
  estimateCanvasHeight,
1577
2203
  estimateNodeSize,
2204
+ evaluateAnimation,
2205
+ evaluateEasing,
2206
+ evaluateTrack,
1578
2207
  excludePaths,
2208
+ exportCssAnimation,
1579
2209
  findConnectorSnap,
1580
2210
  fitCubicRun,
1581
2211
  fitCubics,
@@ -1585,19 +2215,34 @@ export {
1585
2215
  fitViewportToRect,
1586
2216
  flattenSvgPath,
1587
2217
  flowSide,
2218
+ formatAnimationTime2 as formatAnimationTime,
2219
+ formatOklab,
1588
2220
  getAbsolutePosition,
2221
+ getAnimatableProperty,
2222
+ getAnimatedProperties,
2223
+ getAnimatedValue,
2224
+ getAnimationDuration,
2225
+ getAnimationTrack,
1589
2226
  getAutoLayout,
1590
2227
  getAutoLayoutGrid,
1591
2228
  getAutoLayoutInsertTarget,
1592
2229
  getBindableTokenProperties2 as getBindableTokenProperties,
2230
+ getCanvasComponentDragId,
1593
2231
  getCanvasTokenProperty,
1594
2232
  getCenteredNodePosition2 as getCenteredNodePosition,
1595
2233
  getChildLayout,
2234
+ getComponentSourceId,
2235
+ getCssPropertyAnimations,
1596
2236
  getEffectiveTokenModes3 as getEffectiveTokenModes,
1597
2237
  getFlowChildren,
2238
+ getInstanceData,
2239
+ getInstanceStatus,
2240
+ getKeyframeTimes,
1598
2241
  getLayoutParent,
1599
2242
  getLayoutSizing,
1600
2243
  getLayoutedNodes2 as getLayoutedNodes,
2244
+ getNodeAnimation,
2245
+ getNodeOverrides,
1601
2246
  getNodeRect,
1602
2247
  getNodeShape,
1603
2248
  getNodeSize,
@@ -1606,19 +2251,31 @@ export {
1606
2251
  getResizingNodeRect,
1607
2252
  getShapeRenderData2 as getShapeRenderData,
1608
2253
  getShapeSvg,
2254
+ getTimelineRows,
2255
+ getTimelineTicks2 as getTimelineTicks,
1609
2256
  getTokenPropertyScope,
1610
2257
  getTokensForProperty2 as getTokensForProperty,
1611
2258
  handlePoint,
1612
2259
  hasVisibleStroke,
1613
2260
  inferResizeHandle,
2261
+ inspectCanvasInstance2 as inspectCanvasInstance,
1614
2262
  inspectNodeTokens,
2263
+ interpolateAnimationValue,
1615
2264
  intersectPaths,
1616
2265
  intersectPolygons,
1617
2266
  invertNodeUpdates,
2267
+ isAnimationEasing,
2268
+ isAnimationKeyframe,
1618
2269
  isAutoLayoutFrame,
2270
+ isCanvasComponent,
2271
+ isCanvasComponentSet,
2272
+ isCanvasInstance,
2273
+ isCssExportExact,
1619
2274
  isEventFromTextInput3 as isEventFromTextInput,
2275
+ isKeyframeSelected,
1620
2276
  isLocked,
1621
2277
  isMeasureModifierHeld2 as isMeasureModifierHeld,
2278
+ isNodeAnimated,
1622
2279
  isShapeDescription2 as isShapeDescription,
1623
2280
  isShapeNode,
1624
2281
  isStraightCubic,
@@ -1631,6 +2288,7 @@ export {
1631
2288
  layoutUpMany,
1632
2289
  linearPositionTrajectory2 as linearPositionTrajectory,
1633
2290
  linearTrajectory,
2291
+ listCanvasComponents2 as listCanvasComponents,
1634
2292
  lockNodes,
1635
2293
  makeSizingCoherent,
1636
2294
  matchArrangeShortcut2 as matchArrangeShortcut,
@@ -1640,22 +2298,31 @@ export {
1640
2298
  measureSelection2 as measureSelection,
1641
2299
  measureToLine,
1642
2300
  mergeNodeUpdates,
2301
+ mixColorsOklab,
2302
+ moveKeyframes,
1643
2303
  moveLayoutChild,
1644
2304
  multiPolygonArea,
1645
2305
  multiPolygonBounds,
1646
2306
  nearestHandlePositions,
1647
2307
  normalizeBezierPath,
2308
+ normalizeKeyframes,
1648
2309
  offsetPath,
1649
2310
  offsetShapeNodes,
2311
+ oklabToRgb,
1650
2312
  oppositePosition,
1651
2313
  outlineShapeNodeStrokes,
1652
2314
  outlineStroke,
1653
2315
  overlaps,
1654
2316
  parseCanvasClipboardData2 as parseCanvasClipboardData,
1655
2317
  parseCanvasScenes,
2318
+ parseCssEasing,
2319
+ parseKeyframeClipboard,
2320
+ parseOklab,
1656
2321
  parseSvgPath,
2322
+ pasteKeyframes,
1657
2323
  pathBoolean,
1658
2324
  placeBeside2 as placeBeside,
2325
+ playWebAnimations,
1659
2326
  pointInBezierPath,
1660
2327
  pointInMultiPolygon,
1661
2328
  pointInRings,
@@ -1664,44 +2331,72 @@ export {
1664
2331
  polygonToSvgPath,
1665
2332
  positionToSide,
1666
2333
  pruneCanvasTokenModes,
2334
+ pushCanvasInstanceOverrides,
2335
+ readAnimatableValue,
1667
2336
  readNodeStyleProperty,
1668
2337
  readStyleSize,
1669
2338
  realClock,
2339
+ recordAnimationChanges,
1670
2340
  relayoutUpdates,
1671
2341
  remapPastedNodes2 as remapPastedNodes,
2342
+ removeTrack,
1672
2343
  reorderNodes,
1673
2344
  repositionNodesTo,
2345
+ resetCanvasInstanceOverrides,
1674
2346
  resizeHandleAxes,
1675
2347
  resolveCanvasTokens2 as resolveCanvasTokens,
2348
+ resolveEasing,
1676
2349
  resolvePadding,
2350
+ restoreCanvasMainComponent,
1677
2351
  revertShapeCombination,
2352
+ rgbToOklab,
1678
2353
  ringSignedArea,
1679
2354
  runMultiNodeTransition2 as runMultiNodeTransition,
2355
+ sampleAnimationFrames,
2356
+ scaleKeyframes,
1680
2357
  serializeCanvasNodes2 as serializeCanvasNodes,
2358
+ setCanvasComponentProperty,
2359
+ setCanvasInstanceProperties,
1681
2360
  setCanvasTokenMode3 as setCanvasTokenMode,
2361
+ setKeyframe,
2362
+ setKeyframeEasing,
2363
+ setMotionPath,
2364
+ setTrackEnabled,
1682
2365
  shapeNodeToBezierPath,
1683
2366
  shapeNodeToPolygon,
1684
2367
  shapeToBezierPath,
1685
2368
  shapeToPolygon,
1686
2369
  sideToPosition,
1687
2370
  simplifyRing,
2371
+ snapKeyframeDelta,
1688
2372
  snapNodeDrag,
1689
2373
  snapNodeResize,
1690
2374
  snapResize,
2375
+ snapTimeToFrame,
1691
2376
  snapToGrid,
2377
+ springAt,
1692
2378
  strokeOutlineRings,
1693
2379
  subtractPaths,
1694
2380
  subtractPolygons,
2381
+ swapCanvasInstance,
2382
+ syncAllCanvasInstances,
2383
+ syncCanvasComponents,
2384
+ syncCanvasInstance,
2385
+ timeToX2 as timeToX,
1695
2386
  toBezierPath,
2387
+ toWebAnimations,
1696
2388
  toggleLockNodes,
1697
2389
  transformBezierPath,
1698
2390
  unionPolygons,
1699
2391
  unitePaths,
1700
2392
  unlockNodes,
2393
+ updateKeyframe,
2394
+ useCanvasAnimation,
1701
2395
  useCanvasArrange,
1702
2396
  useCanvasArrangeShortcuts,
1703
2397
  useCanvasAutoLayout,
1704
2398
  useCanvasClipboard,
2399
+ useCanvasComponents,
1705
2400
  useCanvasDocking,
1706
2401
  useCanvasExplosion,
1707
2402
  useCanvasGraph,
@@ -1711,8 +2406,12 @@ export {
1711
2406
  useCanvasShortcuts,
1712
2407
  useCanvasTokens,
1713
2408
  useStreamingCanvas,
2409
+ withNodeAnimation,
1714
2410
  withStyleSize,
2411
+ wouldCreateComponentCycle,
2412
+ wrapAnimationTime,
1715
2413
  writeNodeStyleProperty,
2414
+ xToTime2 as xToTime,
1716
2415
  xorPolygons
1717
2416
  };
1718
2417
  //# sourceMappingURL=index.js.map