@pixerate/editor-react 0.18.1 → 0.19.0
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/README.md +5 -1
- package/dist/canvas/index.cjs +209 -7
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +27 -4
- package/dist/canvas/index.d.ts +27 -4
- package/dist/canvas/index.js +209 -7
- package/dist/canvas/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -51,7 +51,9 @@ export function Document() {
|
|
|
51
51
|
const editor = useEditor({ content: "<p>Hello</p>", richTextOptions: { markdown: true } });
|
|
52
52
|
return (
|
|
53
53
|
<>
|
|
54
|
-
<BubbleMenu editor={editor}>
|
|
54
|
+
<BubbleMenu editor={editor}>
|
|
55
|
+
<button onClick={() => editor?.chain().focus().toggleBold().run()}>Bold</button>
|
|
56
|
+
</BubbleMenu>
|
|
55
57
|
<EditorContent editor={editor} />
|
|
56
58
|
</>
|
|
57
59
|
);
|
|
@@ -100,6 +102,8 @@ useAgentToolProvider(registry, provider);
|
|
|
100
102
|
| `@pixerate/editor-react/generation` | `GenerationSettings` (controls generated from a model's capabilities, reference slots by role, plan adjustments), `useGenerationPlan`, `JobProgress`, `useJobProgress` over `@pixerate/editor/generation` (also re-exported from the root entry) |
|
|
101
103
|
| `@pixerate/editor-react/canvas` | `useCanvasGraph`, `useCanvasLayout`, `useCanvasClipboard`, `useCanvasDocking`, `useCanvasShortcuts`, `useCanvasExplosion`, `useStreamingCanvas`, `AgentPresenceLayer`, plus the pure layout helpers from `@pixerate/editor/canvas` |
|
|
102
104
|
|
|
105
|
+
Spreadsheet persistence: `useSpreadsheetEditor` exposes `document` (and passes it to `onDocumentChange`) with the defined names its formulas use in `document.names`, so saving that document and passing it back as `document` restores workbook, sheet-scoped and LAMBDA names. For several sheets, save `controller.getWorkbook()` instead.
|
|
106
|
+
|
|
103
107
|
## Styling (Tailwind CSS required)
|
|
104
108
|
|
|
105
109
|
The components are styled with [Tailwind CSS](https://tailwindcss.com) utility classes and ship no stylesheet of their own. To style them:
|
package/dist/canvas/index.cjs
CHANGED
|
@@ -53,6 +53,7 @@ __export(canvas_exports, {
|
|
|
53
53
|
TOKEN_MODES_DATA_KEY: () => import_canvas23.TOKEN_MODES_DATA_KEY,
|
|
54
54
|
TokenBindingPicker: () => TokenBindingPicker,
|
|
55
55
|
TokenModeSwitcher: () => TokenModeSwitcher,
|
|
56
|
+
addCanvasVariant: () => import_canvas25.addCanvasVariant,
|
|
56
57
|
addKeyframesAtTime: () => import_canvas24.addKeyframesAtTime,
|
|
57
58
|
alignNodes: () => import_canvas18.alignNodes,
|
|
58
59
|
animateNode: () => import_canvas24.animateNode,
|
|
@@ -158,6 +159,7 @@ __export(canvas_exports, {
|
|
|
158
159
|
getLayoutParent: () => import_canvas22.getLayoutParent,
|
|
159
160
|
getLayoutSizing: () => import_canvas22.getLayoutSizing,
|
|
160
161
|
getLayoutedNodes: () => import_canvas21.getLayoutedNodes,
|
|
162
|
+
getNextVariantValues: () => import_canvas25.getNextVariantValues,
|
|
161
163
|
getNodeAnimation: () => import_canvas24.getNodeAnimation,
|
|
162
164
|
getNodeOverrides: () => import_canvas25.getNodeOverrides,
|
|
163
165
|
getNodeRect: () => import_canvas18.getNodeRect,
|
|
@@ -256,7 +258,10 @@ __export(canvas_exports, {
|
|
|
256
258
|
recordAnimationChanges: () => import_canvas24.recordAnimationChanges,
|
|
257
259
|
relayoutUpdates: () => import_canvas22.relayoutUpdates,
|
|
258
260
|
remapPastedNodes: () => import_canvas21.remapPastedNodes,
|
|
261
|
+
removeCanvasVariant: () => import_canvas25.removeCanvasVariant,
|
|
259
262
|
removeTrack: () => import_canvas24.removeTrack,
|
|
263
|
+
renameCanvasVariantProperty: () => import_canvas25.renameCanvasVariantProperty,
|
|
264
|
+
renameCanvasVariantValue: () => import_canvas25.renameCanvasVariantValue,
|
|
260
265
|
reorderNodes: () => import_canvas18.reorderNodes,
|
|
261
266
|
repositionNodesTo: () => import_canvas21.repositionNodesTo,
|
|
262
267
|
resetCanvasInstanceOverrides: () => import_canvas25.resetCanvasInstanceOverrides,
|
|
@@ -275,6 +280,7 @@ __export(canvas_exports, {
|
|
|
275
280
|
setCanvasComponentProperty: () => import_canvas25.setCanvasComponentProperty,
|
|
276
281
|
setCanvasInstanceProperties: () => import_canvas25.setCanvasInstanceProperties,
|
|
277
282
|
setCanvasTokenMode: () => import_canvas23.setCanvasTokenMode,
|
|
283
|
+
setCanvasVariantProperties: () => import_canvas25.setCanvasVariantProperties,
|
|
278
284
|
setKeyframe: () => import_canvas24.setKeyframe,
|
|
279
285
|
setKeyframeEasing: () => import_canvas24.setKeyframeEasing,
|
|
280
286
|
setMotionPath: () => import_canvas24.setMotionPath,
|
|
@@ -1909,28 +1915,64 @@ function useCanvasComponents(options) {
|
|
|
1909
1915
|
var import_react16 = require("react");
|
|
1910
1916
|
var import_canvas16 = require("@pixerate/editor/canvas");
|
|
1911
1917
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1918
|
+
function InlineField({ value, label, onCommit }) {
|
|
1919
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1920
|
+
"input",
|
|
1921
|
+
{
|
|
1922
|
+
type: "text",
|
|
1923
|
+
"aria-label": label,
|
|
1924
|
+
defaultValue: value,
|
|
1925
|
+
className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
|
|
1926
|
+
onBlur: (e) => {
|
|
1927
|
+
const next = e.currentTarget.value.trim();
|
|
1928
|
+
if (next && next !== value) onCommit(next);
|
|
1929
|
+
else e.currentTarget.value = value;
|
|
1930
|
+
},
|
|
1931
|
+
onKeyDown: (e) => {
|
|
1932
|
+
if (e.key === "Enter") e.currentTarget.blur();
|
|
1933
|
+
if (e.key === "Escape") {
|
|
1934
|
+
e.currentTarget.value = value;
|
|
1935
|
+
e.currentTarget.blur();
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
},
|
|
1939
|
+
value
|
|
1940
|
+
);
|
|
1941
|
+
}
|
|
1912
1942
|
function CanvasComponentsPanel({
|
|
1913
1943
|
nodes,
|
|
1914
1944
|
onInsert,
|
|
1945
|
+
components,
|
|
1946
|
+
onError,
|
|
1915
1947
|
search = true,
|
|
1916
1948
|
className = ""
|
|
1917
1949
|
}) {
|
|
1918
1950
|
const [query, setQuery] = (0, import_react16.useState)("");
|
|
1919
|
-
const
|
|
1951
|
+
const [propsOpen, setPropsOpen] = (0, import_react16.useState)(null);
|
|
1952
|
+
const [menuFor, setMenuFor] = (0, import_react16.useState)(null);
|
|
1953
|
+
const [editing, setEditing] = (0, import_react16.useState)(null);
|
|
1954
|
+
const { components: all, sets } = (0, import_canvas16.listCanvasComponents)(nodes);
|
|
1920
1955
|
const q = query.trim().toLowerCase();
|
|
1921
1956
|
const match = (name) => !q || name.toLowerCase().includes(q);
|
|
1922
|
-
const lone =
|
|
1957
|
+
const lone = all.filter((c) => !c.setId && match(c.name));
|
|
1923
1958
|
const shownSets = sets.filter((s) => match(s.name) || s.variants.some((v) => match(v.name)));
|
|
1924
|
-
const
|
|
1959
|
+
const report = (result) => {
|
|
1960
|
+
if (result && !result.ok && result.reason) onError?.(result.reason);
|
|
1961
|
+
return !!result?.ok;
|
|
1962
|
+
};
|
|
1963
|
+
const small = "shrink-0 rounded px-1 text-[10px] text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-40";
|
|
1964
|
+
const menuItem = "rounded px-2 py-0.5 text-left hover:bg-muted disabled:opacity-40";
|
|
1965
|
+
const item = (id, name, count, extra = {}, onContextMenu) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1925
1966
|
"button",
|
|
1926
1967
|
{
|
|
1927
1968
|
type: "button",
|
|
1928
1969
|
draggable: true,
|
|
1929
1970
|
"data-component-id": id,
|
|
1930
1971
|
...extra,
|
|
1931
|
-
className: "flex w-full items-center justify-between gap-2 rounded px-2 py-1 text-left text-xs hover:bg-muted",
|
|
1972
|
+
className: "flex w-full min-w-0 items-center justify-between gap-2 rounded px-2 py-1 text-left text-xs hover:bg-muted",
|
|
1932
1973
|
title: `Insert an instance of ${name}`,
|
|
1933
1974
|
onClick: () => onInsert(id),
|
|
1975
|
+
onContextMenu,
|
|
1934
1976
|
onDragStart: (e) => {
|
|
1935
1977
|
e.dataTransfer.setData(import_canvas16.CANVAS_COMPONENT_DRAG_TYPE, id);
|
|
1936
1978
|
e.dataTransfer.setData("text/plain", name);
|
|
@@ -1958,11 +2000,165 @@ function CanvasComponentsPanel({
|
|
|
1958
2000
|
}
|
|
1959
2001
|
) : null,
|
|
1960
2002
|
shownSets.map((set) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-component-set": set.id, className: "flex flex-col", children: [
|
|
1961
|
-
|
|
1962
|
-
|
|
2003
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
2004
|
+
item(set.id, set.name, set.variants.reduce((sum, v) => sum + v.instanceCount, 0), { "data-kind": "set" }),
|
|
2005
|
+
components ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2006
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2007
|
+
"button",
|
|
2008
|
+
{
|
|
2009
|
+
type: "button",
|
|
2010
|
+
className: small,
|
|
2011
|
+
"data-action": "add-variant",
|
|
2012
|
+
"aria-label": `Add a variant to ${set.name}`,
|
|
2013
|
+
title: "Add a variant (duplicates the default variant)",
|
|
2014
|
+
onClick: () => report(components.addVariant(set.id)),
|
|
2015
|
+
children: "+\xA0Variant"
|
|
2016
|
+
}
|
|
2017
|
+
),
|
|
2018
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2019
|
+
"button",
|
|
2020
|
+
{
|
|
2021
|
+
type: "button",
|
|
2022
|
+
className: small,
|
|
2023
|
+
"data-action": "variant-properties",
|
|
2024
|
+
"aria-expanded": propsOpen === set.id,
|
|
2025
|
+
"aria-label": `Edit the variant properties of ${set.name}`,
|
|
2026
|
+
title: "Rename variant properties and values",
|
|
2027
|
+
onClick: () => setPropsOpen(propsOpen === set.id ? null : set.id),
|
|
2028
|
+
children: "\u2699"
|
|
2029
|
+
}
|
|
2030
|
+
)
|
|
2031
|
+
] }) : null
|
|
2032
|
+
] }),
|
|
2033
|
+
components && propsOpen === set.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-variant-properties": set.id, className: "ml-3 flex flex-col gap-1 border-l border-border py-1 pl-2", children: set.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-variant-option": option.name, className: "flex flex-col gap-0.5", children: [
|
|
2034
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2035
|
+
InlineField,
|
|
2036
|
+
{
|
|
2037
|
+
value: option.name,
|
|
2038
|
+
label: `Rename property ${option.name}`,
|
|
2039
|
+
onCommit: (next) => report(components.renameVariantProperty(option.name, next, set.id))
|
|
2040
|
+
}
|
|
2041
|
+
),
|
|
2042
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ml-2 flex flex-wrap gap-1", children: option.values.map((value) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2043
|
+
InlineField,
|
|
2044
|
+
{
|
|
2045
|
+
value,
|
|
2046
|
+
label: `Rename ${option.name} value ${value}`,
|
|
2047
|
+
onCommit: (next) => report(components.renameVariantValue(option.name, value, next, set.id))
|
|
2048
|
+
},
|
|
2049
|
+
value
|
|
2050
|
+
)) })
|
|
2051
|
+
] }, option.name)) }) : null,
|
|
2052
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ml-3 flex flex-col border-l border-border pl-1", children: set.variants.map((v) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-variant-row": v.id, className: "flex flex-col", children: [
|
|
2053
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
2054
|
+
item(
|
|
2055
|
+
v.id,
|
|
2056
|
+
v.name,
|
|
2057
|
+
v.instanceCount,
|
|
2058
|
+
{ "data-kind": "variant" },
|
|
2059
|
+
components ? (e) => {
|
|
2060
|
+
e.preventDefault();
|
|
2061
|
+
setMenuFor(v.id);
|
|
2062
|
+
} : void 0
|
|
2063
|
+
),
|
|
2064
|
+
components ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2065
|
+
"button",
|
|
2066
|
+
{
|
|
2067
|
+
type: "button",
|
|
2068
|
+
className: small,
|
|
2069
|
+
"data-action": "variant-menu",
|
|
2070
|
+
"aria-haspopup": "menu",
|
|
2071
|
+
"aria-expanded": menuFor === v.id,
|
|
2072
|
+
"aria-label": `Variant actions for ${v.name}`,
|
|
2073
|
+
onClick: () => setMenuFor(menuFor === v.id ? null : v.id),
|
|
2074
|
+
children: "\u22EF"
|
|
2075
|
+
}
|
|
2076
|
+
) : null
|
|
2077
|
+
] }),
|
|
2078
|
+
components && menuFor === v.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "menu", "data-variant-menu": v.id, className: "ml-2 flex flex-col rounded border border-border bg-background p-1 shadow", children: [
|
|
2079
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2080
|
+
"button",
|
|
2081
|
+
{
|
|
2082
|
+
type: "button",
|
|
2083
|
+
role: "menuitem",
|
|
2084
|
+
className: menuItem,
|
|
2085
|
+
"data-action": "edit-variant",
|
|
2086
|
+
onClick: () => {
|
|
2087
|
+
setEditing(v.id);
|
|
2088
|
+
setMenuFor(null);
|
|
2089
|
+
},
|
|
2090
|
+
children: "Edit values\u2026"
|
|
2091
|
+
}
|
|
2092
|
+
),
|
|
2093
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2094
|
+
"button",
|
|
2095
|
+
{
|
|
2096
|
+
type: "button",
|
|
2097
|
+
role: "menuitem",
|
|
2098
|
+
className: menuItem,
|
|
2099
|
+
"data-action": "duplicate-variant",
|
|
2100
|
+
onClick: () => {
|
|
2101
|
+
setMenuFor(null);
|
|
2102
|
+
report(components.addVariant(set.id, { from: v.id }));
|
|
2103
|
+
},
|
|
2104
|
+
children: "Duplicate"
|
|
2105
|
+
}
|
|
2106
|
+
),
|
|
2107
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2108
|
+
"button",
|
|
2109
|
+
{
|
|
2110
|
+
type: "button",
|
|
2111
|
+
role: "menuitem",
|
|
2112
|
+
className: menuItem,
|
|
2113
|
+
"data-action": "remove-variant",
|
|
2114
|
+
disabled: set.variants.length < 2,
|
|
2115
|
+
title: set.variants.length < 2 ? "A component set needs at least one variant." : "Its instances switch to the closest variant",
|
|
2116
|
+
onClick: () => {
|
|
2117
|
+
setMenuFor(null);
|
|
2118
|
+
report(components.removeVariant(v.id));
|
|
2119
|
+
},
|
|
2120
|
+
children: "Remove variant"
|
|
2121
|
+
}
|
|
2122
|
+
)
|
|
2123
|
+
] }) : null,
|
|
2124
|
+
components && editing === v.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2125
|
+
"form",
|
|
2126
|
+
{
|
|
2127
|
+
"data-variant-editor": v.id,
|
|
2128
|
+
className: "ml-2 flex flex-col gap-1 py-1",
|
|
2129
|
+
onSubmit: (e) => {
|
|
2130
|
+
e.preventDefault();
|
|
2131
|
+
const values = {};
|
|
2132
|
+
for (const input of e.currentTarget.querySelectorAll("input[data-variant-value]")) {
|
|
2133
|
+
values[input.dataset.variantValue] = input.value;
|
|
2134
|
+
}
|
|
2135
|
+
if (report(components.setVariantProperties(values, v.id))) setEditing(null);
|
|
2136
|
+
},
|
|
2137
|
+
children: [
|
|
2138
|
+
set.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-2", children: [
|
|
2139
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16 shrink-0 truncate text-muted-foreground", children: option.name }),
|
|
2140
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2141
|
+
"input",
|
|
2142
|
+
{
|
|
2143
|
+
type: "text",
|
|
2144
|
+
"data-variant-value": option.name,
|
|
2145
|
+
"aria-label": `${option.name} value`,
|
|
2146
|
+
defaultValue: v.variant?.[option.name] ?? "",
|
|
2147
|
+
className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs"
|
|
2148
|
+
}
|
|
2149
|
+
)
|
|
2150
|
+
] }, option.name)),
|
|
2151
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-1", children: [
|
|
2152
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "submit", className: "rounded border border-border px-2 py-0.5 hover:bg-muted", "data-action": "save-variant", children: "Save" }),
|
|
2153
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "rounded px-2 py-0.5 hover:bg-muted", "data-action": "cancel-variant", onClick: () => setEditing(null), children: "Cancel" })
|
|
2154
|
+
] })
|
|
2155
|
+
]
|
|
2156
|
+
}
|
|
2157
|
+
) : null
|
|
2158
|
+
] }, v.id)) })
|
|
1963
2159
|
] }, set.id)),
|
|
1964
2160
|
lone.map((c) => item(c.id, c.name, c.instanceCount, { "data-kind": "component" })),
|
|
1965
|
-
|
|
2161
|
+
all.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-muted-foreground", children: "No components yet. Select a frame and choose Create Component." }) : null
|
|
1966
2162
|
] });
|
|
1967
2163
|
}
|
|
1968
2164
|
function CanvasInstanceInspector({
|
|
@@ -2117,6 +2313,7 @@ var import_canvas25 = require("@pixerate/editor/canvas");
|
|
|
2117
2313
|
TOKEN_MODES_DATA_KEY,
|
|
2118
2314
|
TokenBindingPicker,
|
|
2119
2315
|
TokenModeSwitcher,
|
|
2316
|
+
addCanvasVariant,
|
|
2120
2317
|
addKeyframesAtTime,
|
|
2121
2318
|
alignNodes,
|
|
2122
2319
|
animateNode,
|
|
@@ -2222,6 +2419,7 @@ var import_canvas25 = require("@pixerate/editor/canvas");
|
|
|
2222
2419
|
getLayoutParent,
|
|
2223
2420
|
getLayoutSizing,
|
|
2224
2421
|
getLayoutedNodes,
|
|
2422
|
+
getNextVariantValues,
|
|
2225
2423
|
getNodeAnimation,
|
|
2226
2424
|
getNodeOverrides,
|
|
2227
2425
|
getNodeRect,
|
|
@@ -2320,7 +2518,10 @@ var import_canvas25 = require("@pixerate/editor/canvas");
|
|
|
2320
2518
|
recordAnimationChanges,
|
|
2321
2519
|
relayoutUpdates,
|
|
2322
2520
|
remapPastedNodes,
|
|
2521
|
+
removeCanvasVariant,
|
|
2323
2522
|
removeTrack,
|
|
2523
|
+
renameCanvasVariantProperty,
|
|
2524
|
+
renameCanvasVariantValue,
|
|
2324
2525
|
reorderNodes,
|
|
2325
2526
|
repositionNodesTo,
|
|
2326
2527
|
resetCanvasInstanceOverrides,
|
|
@@ -2339,6 +2540,7 @@ var import_canvas25 = require("@pixerate/editor/canvas");
|
|
|
2339
2540
|
setCanvasComponentProperty,
|
|
2340
2541
|
setCanvasInstanceProperties,
|
|
2341
2542
|
setCanvasTokenMode,
|
|
2543
|
+
setCanvasVariantProperties,
|
|
2342
2544
|
setKeyframe,
|
|
2343
2545
|
setKeyframeEasing,
|
|
2344
2546
|
setMotionPath,
|