@oomol-lab/open-flow 0.1.0-beta.81 → 0.1.0-beta.83

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.
Files changed (52) hide show
  1. package/README.md +35 -0
  2. package/dist/browser/{FlowCanvas-CrsiDHK8.js → FlowCanvas-ChbukrDh.js} +879 -535
  3. package/dist/browser/{createResourceDialog-CS3u9ga9.js → createResourceDialog-Bi4fUnbD.js} +5 -4
  4. package/dist/browser/{dialog-CFlvkliO.js → dialog-BzoSxhXQ.js} +1 -1
  5. package/dist/browser/{exportPng-BOPfjeEi.js → exportPng-CrAFfOaD.js} +187 -70
  6. package/dist/browser/{flowChanges-CFj5pL4Y.js → flowChanges-C567g-Pc.js} +2675 -93
  7. package/dist/browser/{flowWorkspace-BeQaeJ3e.js → flowWorkspace-rvcneG4q.js} +980 -2621
  8. package/dist/browser/licenses.md +2 -2
  9. package/dist/browser/{markdownContent-frwDfQQU.js → markdownContent-B-GLj5DU.js} +18 -40
  10. package/dist/browser/{markdownContent-CAG_CQfH.js → markdownContent-D8G_oNOe.js} +18 -41
  11. package/dist/browser/preview.css +125 -80
  12. package/dist/browser/preview.js +1093 -379
  13. package/dist/browser/{tooltip-BDcVTNpu.js → tooltip-DGj5pudg.js} +1 -1
  14. package/dist/browser/ui.css +45 -0
  15. package/dist/browser/{dist-CHwj9BhV.js → videoLink-NAWDmBtf.js} +35 -1
  16. package/dist/browser/workbench-contract.d.ts +6 -0
  17. package/dist/browser/workbench.css +296 -251
  18. package/dist/browser/workbench.d.ts +2 -0
  19. package/dist/browser/workbench.js +294 -141
  20. package/dist/browser/{workbenchSelect-Ci0KCYv9.js → workbenchSelect-BIaEVTx6.js} +2 -2
  21. package/dist/browser/{ContentIcon-CMn0c-kl.js → wrapLayout-C4moMKgb.js} +4400 -4148
  22. package/dist/command/index.js +43 -41
  23. package/dist/common/authoring.d.ts +1 -1
  24. package/dist/common/control-api-conformance.js +306 -2
  25. package/dist/common/control-api.d.ts +20 -0
  26. package/dist/common/control-api.js +306 -4
  27. package/dist/common/control-requests.d.ts +3 -5
  28. package/dist/common/control-requests.js +5 -7
  29. package/dist/common/flow-encoding.d.ts +1 -0
  30. package/dist/common/flow-encoding.js +167 -1
  31. package/dist/common/flow-semantics.js +20 -0
  32. package/dist/common/flow-workflowBundle.d.ts +27 -0
  33. package/dist/common/flow-workflowFile.d.ts +2 -0
  34. package/dist/common/flow-workflowReferences.d.ts +4 -0
  35. package/dist/common/mcp.d.ts +2 -0
  36. package/dist/common/mcp.js +312 -4
  37. package/dist/render/browser/licenses.md +4047 -0
  38. package/dist/render/browser/runtime.css +14914 -0
  39. package/dist/render/browser/runtime.js +267526 -0
  40. package/dist/render/common/png.d.ts +32 -0
  41. package/dist/render/node/index.d.ts +11 -0
  42. package/dist/render/node/index.js +9508 -0
  43. package/dist/render/node/licenses.md +75 -0
  44. package/package.json +12 -2
  45. package/src/control/common/api.ts +50 -0
  46. package/src/control/common/flowDecoders.ts +2 -0
  47. package/src/control/common/mcp.ts +4 -4
  48. package/src/control/common/requests.ts +12 -1
  49. package/src/flow/common/encoding.ts +1 -0
  50. package/src/flow/common/workflowBundle.ts +117 -0
  51. package/src/flow/common/workflowFile.ts +4 -0
  52. package/src/flow/common/workflowReferences.ts +20 -0
@@ -1,11 +1,11 @@
1
1
  import { l as useTranslate } from "./dist-BFmpkX4P.js";
2
- import { xr as Button } from "./tooltip-BDcVTNpu.js";
3
- import { a as DialogFooter, d as Field, f as FieldDescription, h as FieldLabel, i as DialogDescription, in as Input, l as Icon, m as FieldGroup, n as DialogClose, o as DialogHeader, p as FieldError, r as DialogContent, s as DialogTitle, t as Dialog, u as Spinner } from "./dialog-CFlvkliO.js";
4
- import { t as WorkbenchSelect } from "./workbenchSelect-Ci0KCYv9.js";
2
+ import { xr as Button } from "./tooltip-DGj5pudg.js";
3
+ import { a as DialogFooter, d as Field, f as FieldDescription, h as FieldLabel, i as DialogDescription, in as Input, l as Icon, m as FieldGroup, n as DialogClose, o as DialogHeader, p as FieldError, r as DialogContent, s as DialogTitle, t as Dialog, u as Spinner } from "./dialog-BzoSxhXQ.js";
4
+ import { t as WorkbenchSelect } from "./workbenchSelect-BIaEVTx6.js";
5
5
  import { useEffect, useRef, useState } from "react";
6
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
7
  //#region src/workbench/browser/runtime/shell/createResourceDialog.tsx
8
- function CreateResourceDialog({ disabled, tagField, field, id, issue, label, name, onNameChange, onOpenChange, onSubmit, pending, submitLabel, sourceUrl, title }) {
8
+ function CreateResourceDialog({ disabled, tagField, summary, field, id, issue, label, name, onNameChange, onOpenChange, onSubmit, pending, submitLabel, sourceUrl, title }) {
9
9
  const t = useTranslate();
10
10
  const input = useRef(null);
11
11
  const portal = useRef(null);
@@ -86,6 +86,7 @@ function CreateResourceDialog({ disabled, tagField, field, id, issue, label, nam
86
86
  })
87
87
  ]
88
88
  }),
89
+ summary,
89
90
  tagField?.(root),
90
91
  field != null && /* @__PURE__ */ jsxs(Field, { children: [
91
92
  /* @__PURE__ */ jsx(FieldLabel, {
@@ -1,5 +1,5 @@
1
1
  import { a as toPlainObject, i as isString } from "./dist-BFmpkX4P.js";
2
- import { $ as useToolbarRootContext, A as string, At as useImplicitActiveTrigger, Bn as transitionStatusMapping, Br as useRefWithInit, C as literal, Cn as getFloatingFocusElement, Cr as cn, D as preprocess, Dn as getTarget, Dr as EMPTY_ARRAY, Dt as createInitialPopupStoreState, E as object, En as contains, Er as useRenderElement, Et as useFloatingRootContext, F as IndexGuessBehavior, Fn as createLucideIcon, Fr as formatErrorMessage, Ft as useDismiss, Gt as CLICK_TRIGGER_IDENTIFIER, Hr as getWindow, I as useCompositeListItem, In as useTransitionStatus, Ir as mergeProps, It as useClick, Jn as closePress, Kn as cancelOpen, Kt as DROPDOWN_COLLISION_AVOIDANCE, Ln as useOpenChangeComplete, Lr as useIsoLayoutEffect, Lt as FloatingFocusManager, M as unknown, Mn as ownerDocument, Mr as useButton, Mt as useTriggerDataForwarding, N as _isoDateTime, Nn as useLabelableId, O as record$1, Or as EMPTY_OBJECT, Ot as popupStoreSelectors, P as Separator, Pn as Check, Pt as platform, Qt as useStore, Sr as buttonVariants, T as number, Tn as activeElement, Tt as useSyncedFloatingRootContext, U as COMPOSITE_KEYS, Un as useValueChanged, Vn as useAnimationFrame, Wn as createChangeEventDetails, Wt as FloatingPortal, Xt as ReactStore, Yt as addEventListener, Zn as imperativeAction, Zt as Store, _ as array, _r as fieldValidityMapping, an as useOnFirstRender, at as useAnchorPositioning, br as useControlled, bt as useListNavigation, ct as CompositeList, dr as useFormContext, dt as CommonPopupDataAttributes, et as useAnchoredPopupScrollLock, f as isTimeZone, fr as useRegisterFieldControl, ft as popupStateMapping, g as _enum, gt as serializeValue, h as ZodType, ht as useOpenInteractionType, i as TooltipTrigger, in as useValueAsRef, it as InternalBackdrop, j as union, jn as isWebKit, jr as useMergedRefs, jt as useOpenStateTransitions, k as strictObject, kt as PopupTriggerMap, lr as windowResize, lt as inertValue, m as ZodISODateTime, mr as useBaseUiId, mt as triggerOpenStateMapping, n as TooltipContent, nt as usePositioner, pr as useFieldRootContext, pt as pressableTriggerOpenStateMapping, rn as createSelector, rr as none, rt as getDisabledMountTransitionStyles, sn as useTimeout, st as useDirection, t as Tooltip, tr as itemPress, tt as useScrollLock, ur as useLabelableContext, ut as getPseudoElementBounds, v as boolean, vr as visuallyHidden, vt as useTypeahead, w as never, wr as cva, x as json$1, xn as rectToClientRect, xr as Button, xt as useInteractions, y as discriminatedUnion, yr as visuallyHiddenInput, yt as useRole, zr as useStableCallback } from "./tooltip-BDcVTNpu.js";
2
+ import { $ as useToolbarRootContext, A as string, At as useImplicitActiveTrigger, Bn as transitionStatusMapping, Br as useStableCallback, C as literal, Cn as getFloatingFocusElement, Cr as cn, D as preprocess, Dn as getTarget, Dr as EMPTY_ARRAY, Dt as createInitialPopupStoreState, E as object, En as contains, Er as useRenderElement, Et as useFloatingRootContext, F as IndexGuessBehavior, Fn as createLucideIcon, Fr as formatErrorMessage, Ft as useDismiss, Gt as CLICK_TRIGGER_IDENTIFIER, I as useCompositeListItem, In as useTransitionStatus, Ir as mergeProps, It as useClick, Jn as closePress, Kn as cancelOpen, Kt as DROPDOWN_COLLISION_AVOIDANCE, Ln as useOpenChangeComplete, Lr as useIsoLayoutEffect, Lt as FloatingFocusManager, M as unknown, Mn as ownerDocument, Mr as useButton, Mt as useTriggerDataForwarding, N as _isoDateTime, Nn as useLabelableId, O as record$1, Or as EMPTY_OBJECT, Ot as popupStoreSelectors, P as Separator, Pn as Check, Pt as platform, Qt as useStore, Sr as buttonVariants, T as number, Tn as activeElement, Tt as useSyncedFloatingRootContext, U as COMPOSITE_KEYS, Un as useValueChanged, Ur as getWindow, Vn as useAnimationFrame, Vr as useRefWithInit, Wn as createChangeEventDetails, Wt as FloatingPortal, Xt as ReactStore, Yt as addEventListener, Zn as imperativeAction, Zt as Store, _ as array, _r as fieldValidityMapping, an as useOnFirstRender, at as useAnchorPositioning, br as useControlled, bt as useListNavigation, ct as CompositeList, dr as useFormContext, dt as CommonPopupDataAttributes, et as useAnchoredPopupScrollLock, f as isTimeZone, fr as useRegisterFieldControl, ft as popupStateMapping, g as _enum, gt as serializeValue, h as ZodType, ht as useOpenInteractionType, i as TooltipTrigger, in as useValueAsRef, it as InternalBackdrop, j as union, jn as isWebKit, jr as useMergedRefs, jt as useOpenStateTransitions, k as strictObject, kt as PopupTriggerMap, lr as windowResize, lt as inertValue, m as ZodISODateTime, mr as useBaseUiId, mt as triggerOpenStateMapping, n as TooltipContent, nt as usePositioner, pr as useFieldRootContext, pt as pressableTriggerOpenStateMapping, rn as createSelector, rr as none, rt as getDisabledMountTransitionStyles, sn as useTimeout, st as useDirection, t as Tooltip, tr as itemPress, tt as useScrollLock, ur as useLabelableContext, ut as getPseudoElementBounds, v as boolean, vr as visuallyHidden, vt as useTypeahead, w as never, wr as cva, x as json$1, xn as rectToClientRect, xr as Button, xt as useInteractions, y as discriminatedUnion, yr as visuallyHiddenInput, yt as useRole } from "./tooltip-DGj5pudg.js";
3
3
  import * as React from "react";
4
4
  import { useMemo } from "react";
5
5
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1,9 +1,9 @@
1
- import { n as IconImageCrossOriginContext, o as IconifyProvider } from "./ContentIcon-CMn0c-kl.js";
2
- import { t as FlowCanvas, x as CanvasStore } from "./FlowCanvas-CrsiDHK8.js";
1
+ import { C as IconifyProvider, y as IconImageCrossOriginContext } from "./wrapLayout-C4moMKgb.js";
2
+ import { E as getFlowPngAspectRatio, t as FlowCanvas, y as CanvasStore } from "./FlowCanvas-ChbukrDh.js";
3
3
  import { createElement } from "react";
4
4
  import "react/jsx-runtime";
5
5
  import { createRoot } from "react-dom/client";
6
- //#region ../../node_modules/.bun/html-to-image@1.11.11/node_modules/html-to-image/es/util.js
6
+ //#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/util.js
7
7
  function resolveUrl(url, baseUrl) {
8
8
  if (url.match(/^[a-z]+:\/\//i)) return url;
9
9
  if (url.match(/^\/\//)) return window.location.protocol + url;
@@ -30,6 +30,13 @@ function toArray(arrayLike) {
30
30
  for (let i = 0, l = arrayLike.length; i < l; i++) arr.push(arrayLike[i]);
31
31
  return arr;
32
32
  }
33
+ var styleProps = null;
34
+ function getStyleProperties(options = {}) {
35
+ if (options.includeStyleProperties) return options.includeStyleProperties;
36
+ if (styleProps) return styleProps;
37
+ styleProps = toArray(window.getComputedStyle(document.documentElement));
38
+ return styleProps;
39
+ }
33
40
  function px(node, styleProperty) {
34
41
  const val = (node.ownerDocument.defaultView || window).getComputedStyle(node).getPropertyValue(styleProperty);
35
42
  return val ? parseFloat(val.replace("px", "")) : 0;
@@ -53,8 +60,11 @@ function getImageSize(targetNode, options = {}) {
53
60
  function createImage(url) {
54
61
  return new Promise((resolve, reject) => {
55
62
  const img = new Image();
56
- img.decode = () => resolve(img);
57
- img.onload = () => resolve(img);
63
+ img.onload = () => {
64
+ img.decode().then(() => {
65
+ requestAnimationFrame(() => resolve(img));
66
+ });
67
+ };
58
68
  img.onerror = reject;
59
69
  img.crossOrigin = "anonymous";
60
70
  img.decoding = "async";
@@ -87,22 +97,22 @@ var isInstanceOfElement = (node, instance) => {
87
97
  return nodePrototype.constructor.name === instance.name || isInstanceOfElement(nodePrototype, instance);
88
98
  };
89
99
  //#endregion
90
- //#region ../../node_modules/.bun/html-to-image@1.11.11/node_modules/html-to-image/es/clone-pseudos.js
100
+ //#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/clone-pseudos.js
91
101
  function formatCSSText(style) {
92
102
  const content = style.getPropertyValue("content");
93
103
  return `${style.cssText} content: '${content.replace(/'|"/g, "")}';`;
94
104
  }
95
- function formatCSSProperties(style) {
96
- return toArray(style).map((name) => {
105
+ function formatCSSProperties(style, options) {
106
+ return getStyleProperties(options).map((name) => {
97
107
  return `${name}: ${style.getPropertyValue(name)}${style.getPropertyPriority(name) ? " !important" : ""};`;
98
108
  }).join(" ");
99
109
  }
100
- function getPseudoElementStyle(className, pseudo, style) {
110
+ function getPseudoElementStyle(className, pseudo, style, options) {
101
111
  const selector = `.${className}:${pseudo}`;
102
- const cssText = style.cssText ? formatCSSText(style) : formatCSSProperties(style);
112
+ const cssText = style.cssText ? formatCSSText(style) : formatCSSProperties(style, options);
103
113
  return document.createTextNode(`${selector}{${cssText}}`);
104
114
  }
105
- function clonePseudoElement(nativeNode, clonedNode, pseudo) {
115
+ function clonePseudoElement(nativeNode, clonedNode, pseudo, options) {
106
116
  const style = window.getComputedStyle(nativeNode, pseudo);
107
117
  const content = style.getPropertyValue("content");
108
118
  if (content === "" || content === "none") return;
@@ -113,15 +123,15 @@ function clonePseudoElement(nativeNode, clonedNode, pseudo) {
113
123
  return;
114
124
  }
115
125
  const styleElement = document.createElement("style");
116
- styleElement.appendChild(getPseudoElementStyle(className, pseudo, style));
126
+ styleElement.appendChild(getPseudoElementStyle(className, pseudo, style, options));
117
127
  clonedNode.appendChild(styleElement);
118
128
  }
119
- function clonePseudoElements(nativeNode, clonedNode) {
120
- clonePseudoElement(nativeNode, clonedNode, ":before");
121
- clonePseudoElement(nativeNode, clonedNode, ":after");
129
+ function clonePseudoElements(nativeNode, clonedNode, options) {
130
+ clonePseudoElement(nativeNode, clonedNode, ":before", options);
131
+ clonePseudoElement(nativeNode, clonedNode, ":after", options);
122
132
  }
123
133
  //#endregion
124
- //#region ../../node_modules/.bun/html-to-image@1.11.11/node_modules/html-to-image/es/mimes.js
134
+ //#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/mimes.js
125
135
  var WOFF = "application/font-woff";
126
136
  var JPEG = "image/jpeg";
127
137
  var mimes = {
@@ -145,7 +155,7 @@ function getMimeType(url) {
145
155
  return mimes[getExtension(url).toLowerCase()] || "";
146
156
  }
147
157
  //#endregion
148
- //#region ../../node_modules/.bun/html-to-image@1.11.11/node_modules/html-to-image/es/dataurl.js
158
+ //#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/dataurl.js
149
159
  function getContentFromDataUrl(dataURL) {
150
160
  return dataURL.split(/,/)[1];
151
161
  }
@@ -202,7 +212,7 @@ async function resourceToDataURL(resourceUrl, contentType, options) {
202
212
  return dataURL;
203
213
  }
204
214
  //#endregion
205
- //#region ../../node_modules/.bun/html-to-image@1.11.11/node_modules/html-to-image/es/clone-node.js
215
+ //#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/clone-node.js
206
216
  async function cloneCanvasElement(canvas) {
207
217
  const dataURL = canvas.toDataURL();
208
218
  if (dataURL === "data:,") return canvas.cloneNode(false);
@@ -220,17 +230,17 @@ async function cloneVideoElement(video, options) {
220
230
  const poster = video.poster;
221
231
  return createImage(await resourceToDataURL(poster, getMimeType(poster), options));
222
232
  }
223
- async function cloneIFrameElement(iframe) {
233
+ async function cloneIFrameElement(iframe, options) {
224
234
  var _a;
225
235
  try {
226
- if ((_a = iframe === null || iframe === void 0 ? void 0 : iframe.contentDocument) === null || _a === void 0 ? void 0 : _a.body) return await cloneNode(iframe.contentDocument.body, {}, true);
236
+ if ((_a = iframe === null || iframe === void 0 ? void 0 : iframe.contentDocument) === null || _a === void 0 ? void 0 : _a.body) return await cloneNode(iframe.contentDocument.body, options, true);
227
237
  } catch (_b) {}
228
238
  return iframe.cloneNode(false);
229
239
  }
230
240
  async function cloneSingleNode(node, options) {
231
241
  if (isInstanceOfElement(node, HTMLCanvasElement)) return cloneCanvasElement(node);
232
242
  if (isInstanceOfElement(node, HTMLVideoElement)) return cloneVideoElement(node, options);
233
- if (isInstanceOfElement(node, HTMLIFrameElement)) return cloneIFrameElement(node);
243
+ if (isInstanceOfElement(node, HTMLIFrameElement)) return cloneIFrameElement(node, options);
234
244
  return node.cloneNode(false);
235
245
  }
236
246
  var isSlotElement = (node) => node.tagName != null && node.tagName.toUpperCase() === "SLOT";
@@ -246,14 +256,14 @@ async function cloneChildren(nativeNode, clonedNode, options) {
246
256
  }), Promise.resolve());
247
257
  return clonedNode;
248
258
  }
249
- function cloneCSSStyle(nativeNode, clonedNode) {
259
+ function cloneCSSStyle(nativeNode, clonedNode, options) {
250
260
  const targetStyle = clonedNode.style;
251
261
  if (!targetStyle) return;
252
262
  const sourceStyle = window.getComputedStyle(nativeNode);
253
263
  if (sourceStyle.cssText) {
254
264
  targetStyle.cssText = sourceStyle.cssText;
255
265
  targetStyle.transformOrigin = sourceStyle.transformOrigin;
256
- } else toArray(sourceStyle).forEach((name) => {
266
+ } else getStyleProperties(options).forEach((name) => {
257
267
  let value = sourceStyle.getPropertyValue(name);
258
268
  if (name === "font-size" && value.endsWith("px")) value = `${Math.floor(parseFloat(value.substring(0, value.length - 2))) - .1}px`;
259
269
  if (isInstanceOfElement(nativeNode, HTMLIFrameElement) && name === "display" && value === "inline") value = "block";
@@ -272,10 +282,10 @@ function cloneSelectValue(nativeNode, clonedNode) {
272
282
  if (selectedOption) selectedOption.setAttribute("selected", "");
273
283
  }
274
284
  }
275
- function decorate(nativeNode, clonedNode) {
285
+ function decorate(nativeNode, clonedNode, options) {
276
286
  if (isInstanceOfElement(clonedNode, Element)) {
277
- cloneCSSStyle(nativeNode, clonedNode);
278
- clonePseudoElements(nativeNode, clonedNode);
287
+ cloneCSSStyle(nativeNode, clonedNode, options);
288
+ clonePseudoElements(nativeNode, clonedNode, options);
279
289
  cloneInputValue(nativeNode, clonedNode);
280
290
  cloneSelectValue(nativeNode, clonedNode);
281
291
  }
@@ -312,10 +322,10 @@ async function ensureSVGSymbols(clone, options) {
312
322
  }
313
323
  async function cloneNode(node, options, isRoot) {
314
324
  if (!isRoot && options.filter && !options.filter(node)) return null;
315
- return Promise.resolve(node).then((clonedNode) => cloneSingleNode(clonedNode, options)).then((clonedNode) => cloneChildren(node, clonedNode, options)).then((clonedNode) => decorate(node, clonedNode)).then((clonedNode) => ensureSVGSymbols(clonedNode, options));
325
+ return Promise.resolve(node).then((clonedNode) => cloneSingleNode(clonedNode, options)).then((clonedNode) => cloneChildren(node, clonedNode, options)).then((clonedNode) => decorate(node, clonedNode, options)).then((clonedNode) => ensureSVGSymbols(clonedNode, options));
316
326
  }
317
327
  //#endregion
318
- //#region ../../node_modules/.bun/html-to-image@1.11.11/node_modules/html-to-image/es/embed-resources.js
328
+ //#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/embed-resources.js
319
329
  var URL_REGEX = /url\((['"]?)([^'"]+?)\1\)/g;
320
330
  var URL_WITH_FORMAT_REGEX = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g;
321
331
  var FONT_SRC_REGEX = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;
@@ -360,7 +370,7 @@ async function embedResources(cssText, baseUrl, options) {
360
370
  return parseURLs(filteredCSSText).reduce((deferred, url) => deferred.then((css) => embed(css, url, baseUrl, options)), Promise.resolve(filteredCSSText));
361
371
  }
362
372
  //#endregion
363
- //#region ../../node_modules/.bun/html-to-image@1.11.11/node_modules/html-to-image/es/embed-images.js
373
+ //#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/embed-images.js
364
374
  async function embedProp(propName, node, options) {
365
375
  var _a;
366
376
  const propValue = (_a = node.style) === null || _a === void 0 ? void 0 : _a.getPropertyValue(propName);
@@ -372,8 +382,8 @@ async function embedProp(propName, node, options) {
372
382
  return false;
373
383
  }
374
384
  async function embedBackground(clonedNode, options) {
375
- if (!await embedProp("background", clonedNode, options)) await embedProp("background-image", clonedNode, options);
376
- if (!await embedProp("mask", clonedNode, options)) await embedProp("mask-image", clonedNode, options);
385
+ await embedProp("background", clonedNode, options) || await embedProp("background-image", clonedNode, options);
386
+ await embedProp("mask", clonedNode, options) || await embedProp("-webkit-mask", clonedNode, options) || await embedProp("mask-image", clonedNode, options) || await embedProp("-webkit-mask-image", clonedNode, options);
377
387
  }
378
388
  async function embedImageNode(clonedNode, options) {
379
389
  const isImageElement = isInstanceOfElement(clonedNode, HTMLImageElement);
@@ -382,7 +392,13 @@ async function embedImageNode(clonedNode, options) {
382
392
  const dataURL = await resourceToDataURL(url, getMimeType(url), options);
383
393
  await new Promise((resolve, reject) => {
384
394
  clonedNode.onload = resolve;
385
- clonedNode.onerror = reject;
395
+ clonedNode.onerror = options.onImageErrorHandler ? (...attributes) => {
396
+ try {
397
+ resolve(options.onImageErrorHandler(...attributes));
398
+ } catch (error) {
399
+ reject(error);
400
+ }
401
+ } : reject;
386
402
  const image = clonedNode;
387
403
  if (image.decode) image.decode = resolve;
388
404
  if (image.loading === "lazy") image.loading = "eager";
@@ -404,7 +420,7 @@ async function embedImages(clonedNode, options) {
404
420
  }
405
421
  }
406
422
  //#endregion
407
- //#region ../../node_modules/.bun/html-to-image@1.11.11/node_modules/html-to-image/es/apply-style.js
423
+ //#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/apply-style.js
408
424
  function applyStyle(node, options) {
409
425
  const { style } = node;
410
426
  if (options.backgroundColor) style.backgroundColor = options.backgroundColor;
@@ -417,7 +433,7 @@ function applyStyle(node, options) {
417
433
  return node;
418
434
  }
419
435
  //#endregion
420
- //#region ../../node_modules/.bun/html-to-image@1.11.11/node_modules/html-to-image/es/embed-webfonts.js
436
+ //#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/embed-webfonts.js
421
437
  var cssFetchCache = {};
422
438
  async function fetchCSS(url) {
423
439
  let cache = cssFetchCache[url];
@@ -493,7 +509,7 @@ async function getCSSRules(styleSheets, options) {
493
509
  } catch (e) {
494
510
  const inline = styleSheets.find((a) => a.href == null) || document.styleSheets[0];
495
511
  if (sheet.href != null) deferreds.push(fetchCSS(sheet.href).then((metadata) => embedFonts(metadata, options)).then((cssText) => parseCSS(cssText).forEach((rule) => {
496
- inline.insertRule(rule, sheet.cssRules.length);
512
+ inline.insertRule(rule, inline.cssRules.length);
497
513
  })).catch((err) => {
498
514
  console.error("Error loading remote stylesheet", err);
499
515
  }));
@@ -520,9 +536,26 @@ async function parseWebFontRules(node, options) {
520
536
  if (node.ownerDocument == null) throw new Error("Provided element is not within a Document");
521
537
  return getWebFontRules(await getCSSRules(toArray(node.ownerDocument.styleSheets), options));
522
538
  }
539
+ function normalizeFontFamily(font) {
540
+ return font.trim().replace(/["']/g, "");
541
+ }
542
+ function getUsedFonts(node) {
543
+ const fonts = /* @__PURE__ */ new Set();
544
+ function traverse(node) {
545
+ (node.style.fontFamily || getComputedStyle(node).fontFamily).split(",").forEach((font) => {
546
+ fonts.add(normalizeFontFamily(font));
547
+ });
548
+ Array.from(node.children).forEach((child) => {
549
+ if (child instanceof HTMLElement) traverse(child);
550
+ });
551
+ }
552
+ traverse(node);
553
+ return fonts;
554
+ }
523
555
  async function getWebFontCSS(node, options) {
524
556
  const rules = await parseWebFontRules(node, options);
525
- return (await Promise.all(rules.map((rule) => {
557
+ const usedFonts = getUsedFonts(node);
558
+ return (await Promise.all(rules.filter((rule) => usedFonts.has(normalizeFontFamily(rule.style.fontFamily))).map((rule) => {
526
559
  const baseUrl = rule.parentStyleSheet ? rule.parentStyleSheet.href : null;
527
560
  return embedResources(rule.cssText, baseUrl, options);
528
561
  }))).join("\n");
@@ -538,7 +571,7 @@ async function embedWebFonts(clonedNode, options) {
538
571
  }
539
572
  }
540
573
  //#endregion
541
- //#region ../../node_modules/.bun/html-to-image@1.11.11/node_modules/html-to-image/es/index.js
574
+ //#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/index.js
542
575
  async function toSvg(node, options = {}) {
543
576
  const { width, height } = getImageSize(node, options);
544
577
  const clonedNode = await cloneNode(node, options, true);
@@ -559,6 +592,49 @@ function openFlowLogoSource(theme) {
559
592
  return theme === "dark" ? open_flow_dark_default : open_flow_light_default;
560
593
  }
561
594
  //#endregion
595
+ //#region src/canvas/browser/graph/FlowCanvas/captureStyles.ts
596
+ /** Capture authored properties instead of hundreds of unrelated browser defaults. */
597
+ function captureStyleProperties(root) {
598
+ const complete = () => Array.from(getComputedStyle(root)).filter((name) => !name.startsWith("--"));
599
+ const properties = /* @__PURE__ */ new Set(["width", "height"]);
600
+ const add = (style) => {
601
+ for (const name of Array.from(style)) {
602
+ if (name === "all") return false;
603
+ if (!name.startsWith("--")) properties.add(name);
604
+ }
605
+ return true;
606
+ };
607
+ const collect = (rules) => {
608
+ for (const rule of rules) {
609
+ const style = rule.style;
610
+ if (style) {
611
+ const selector = rule.selectorText?.replace(/::[\w-]+(?:\([^)]*\))?/g, "");
612
+ let matches = true;
613
+ if (selector) try {
614
+ matches = root.closest(selector) != null || root.querySelector(selector) != null;
615
+ } catch {}
616
+ if (matches && !add(style)) return false;
617
+ }
618
+ if ("cssRules" in rule && !collect(rule.cssRules)) return false;
619
+ const imported = rule.styleSheet;
620
+ if (imported && !collect(imported.cssRules)) return false;
621
+ }
622
+ return true;
623
+ };
624
+ try {
625
+ const doc = root.ownerDocument;
626
+ for (const sheet of [...doc.styleSheets, ...doc.adoptedStyleSheets]) if (!collect(sheet.cssRules)) return complete();
627
+ } catch {
628
+ return complete();
629
+ }
630
+ for (let ancestor = root; ancestor; ancestor = ancestor.parentElement) if (!add(ancestor.style)) return complete();
631
+ for (const node of [root, ...root.querySelectorAll("*")]) {
632
+ if (node.style && !add(node.style)) return complete();
633
+ for (const attribute of node.attributes) if (CSS.supports(attribute.name, "initial")) properties.add(attribute.name);
634
+ }
635
+ return [...properties].toSorted();
636
+ }
637
+ //#endregion
562
638
  //#region src/canvas/browser/graph/FlowCanvas/exportPng.ts
563
639
  var padding = 64;
564
640
  var maximumDimension = 16384;
@@ -665,10 +741,22 @@ async function prepareImages(host, deadline) {
665
741
  if (performance.now() > deadline) throw new Error("Timed out preparing workflow images.");
666
742
  }
667
743
  }
668
- async function renderPng(dataUrl, width, height, background, frame) {
744
+ async function renderPng(dataUrl, width, height, background, frame, aspectRatio) {
669
745
  const ratio = Math.min(2, maximumDimension / width, maximumDimension / height, Math.sqrt(maximumPixels / (width * height)));
670
- let outputWidth = Math.max(1, Math.floor(width * ratio));
671
- let outputHeight = Math.max(1, Math.floor(height * ratio));
746
+ const dimensions = (scale) => {
747
+ if (aspectRatio) {
748
+ const units = Math.max(1, Math.floor(Math.min(width * scale / aspectRatio[0], height * scale / aspectRatio[1])));
749
+ return {
750
+ width: units * aspectRatio[0],
751
+ height: units * aspectRatio[1]
752
+ };
753
+ }
754
+ return {
755
+ width: Math.max(1, Math.floor(width * scale)),
756
+ height: Math.max(1, Math.floor(height * scale))
757
+ };
758
+ };
759
+ let output = dimensions(ratio);
672
760
  const image = new Image();
673
761
  const logo = frame ? new Image() : void 0;
674
762
  image.decoding = "async";
@@ -682,28 +770,28 @@ async function renderPng(dataUrl, width, height, background, frame) {
682
770
  for (let attempt = 0; attempt < 3; attempt++) {
683
771
  const canvas = document.createElement("canvas");
684
772
  try {
685
- canvas.width = outputWidth;
686
- canvas.height = outputHeight;
687
- const context = canvas.getContext("2d", { alpha: false });
773
+ canvas.width = output.width;
774
+ canvas.height = output.height;
775
+ const context = canvas.getContext("2d", { alpha: !!frame });
688
776
  if (!context) throw new Error("Unable to allocate the workflow image.");
689
- context.fillStyle = frame?.outerBackground ?? background;
690
- context.fillRect(0, 0, outputWidth, outputHeight);
691
777
  if (frame && logo) {
692
- context.scale(outputWidth / width, outputHeight / height);
778
+ context.scale(output.width / width, output.height / height);
693
779
  drawFrame(context, image, logo, width, height, background, frame);
694
- } else context.drawImage(image, 0, 0, outputWidth, outputHeight);
780
+ } else {
781
+ context.fillStyle = background;
782
+ context.fillRect(0, 0, output.width, output.height);
783
+ context.drawImage(image, 0, 0, output.width, output.height);
784
+ }
695
785
  if (context.isContextLost?.()) throw new Error("The workflow image context was lost.");
696
786
  const blob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
697
787
  if (!blob || context.isContextLost?.()) throw new Error("Unable to encode the workflow image.");
698
788
  return {
699
789
  blob,
700
- width: outputWidth,
701
- height: outputHeight
790
+ ...output
702
791
  };
703
792
  } catch (error) {
704
- if (attempt === 2 || outputWidth === 1 && outputHeight === 1) throw error;
705
- outputWidth = Math.max(1, Math.floor(outputWidth / 2));
706
- outputHeight = Math.max(1, Math.floor(outputHeight / 2));
793
+ if (attempt === 2 || output.width === 1 && output.height === 1) throw error;
794
+ output = dimensions(ratio / 2 ** (attempt + 1));
707
795
  } finally {
708
796
  canvas.width = canvas.height = 0;
709
797
  }
@@ -715,7 +803,7 @@ async function renderPng(dataUrl, width, height, background, frame) {
715
803
  }
716
804
  }
717
805
  /** Render the real canvas at full detail without moving or changing the user's canvas. */
718
- async function captureFlowImage(model, language, options) {
806
+ async function captureFlowImage(model, language, options, aspectRatio) {
719
807
  const contentPadding = options.frame ? padding / 2 : padding;
720
808
  const positions = model.nodes.map((node) => node.position);
721
809
  const minX = Math.min(0, ...positions.map((position) => position.x));
@@ -742,6 +830,7 @@ async function captureFlowImage(model, language, options) {
742
830
  host.setAttribute("aria-hidden", "true");
743
831
  document.body.append(host);
744
832
  const root = createRoot(host);
833
+ let instance;
745
834
  const store = new CanvasStore(snapshot, false, language, {
746
835
  onMoveNodes: () => {},
747
836
  onChangeComment: () => {}
@@ -753,12 +842,34 @@ async function captureFlowImage(model, language, options) {
753
842
  dark: options.dark ?? false,
754
843
  fitView: false,
755
844
  layoutMotion: false,
756
- nodesDraggable: false
845
+ nodesDraggable: false,
846
+ onInit: (value) => {
847
+ instance = value;
848
+ }
757
849
  }))));
758
850
  const deadline = performance.now() + 15e3;
759
851
  await waitFor(() => store.$.initialized.value && store.$.rfNodes.value.every((node) => !!node.measured?.width && !!node.measured.height), deadline);
760
852
  let hasImagePlaceholders = await prepareImages(host, deadline);
761
853
  await waitFor(() => document.fonts.status === "loaded", deadline);
854
+ if (options.layout === "compact" && store.$.direction.value === "vertical") {
855
+ await nextFrame();
856
+ await nextFrame();
857
+ const bounds = store.compactForExport({
858
+ width: contentPadding * 2 + (options.frame ? 40 : 0),
859
+ height: contentPadding * 2 + (options.frame ? 72 : 0)
860
+ }, instance, aspectRatio ? aspectRatio[0] / aspectRatio[1] : 1);
861
+ host.style.width = Math.ceil(bounds.width + contentPadding * 2 + 1e3) + "px";
862
+ host.style.height = Math.ceil(bounds.height + contentPadding * 2 + 1e3) + "px";
863
+ store.$$.viewport.set({
864
+ x: contentPadding - bounds.x,
865
+ y: contentPadding - bounds.y,
866
+ zoom: 1
867
+ });
868
+ await nextFrame();
869
+ await nextFrame();
870
+ hasImagePlaceholders = await prepareImages(host, deadline) || hasImagePlaceholders;
871
+ await waitFor(() => document.fonts.status === "loaded", deadline);
872
+ }
762
873
  const viewport = host.querySelector(".react-flow__viewport");
763
874
  const origin = viewport.getBoundingClientRect();
764
875
  const bounds = [...viewport.querySelectorAll(".react-flow__node, [data-canvas-bounds]")].map((node) => {
@@ -775,8 +886,13 @@ async function captureFlowImage(model, language, options) {
775
886
  const top = bounds.length ? Math.min(...bounds.map((rect) => rect.y)) : 0;
776
887
  const right = bounds.length ? Math.max(...bounds.map((rect) => rect.x + rect.width)) : 320;
777
888
  const bottom = bounds.length ? Math.max(...bounds.map((rect) => rect.y + rect.height)) : 120;
778
- const width = Math.ceil(right - left + contentPadding * 2);
779
- const height = Math.ceil(bottom - top + contentPadding * 2);
889
+ const naturalWidth = Math.ceil(right - left + contentPadding * 2);
890
+ const naturalHeight = Math.ceil(bottom - top + contentPadding * 2);
891
+ const frameWidth = options.frame ? 40 : 0;
892
+ const frameHeight = options.frame ? 72 : 0;
893
+ const units = aspectRatio ? Math.ceil(Math.max((naturalWidth + frameWidth) / aspectRatio[0], (naturalHeight + frameHeight) / aspectRatio[1])) : 0;
894
+ const width = aspectRatio ? units * aspectRatio[0] - frameWidth : naturalWidth;
895
+ const height = aspectRatio ? units * aspectRatio[1] - frameHeight : naturalHeight;
780
896
  const background = getComputedStyle(host.querySelector(".react-flow")).backgroundColor;
781
897
  const dataUrl = await toSvg(viewport, {
782
898
  width,
@@ -784,8 +900,14 @@ async function captureFlowImage(model, language, options) {
784
900
  imagePlaceholder,
785
901
  preferredFontFormat: "woff2",
786
902
  includeQueryParams: true,
903
+ includeStyleProperties: captureStyleProperties(viewport),
904
+ filter: (node) => {
905
+ if (!(node instanceof HTMLElement)) return true;
906
+ const style = getComputedStyle(node);
907
+ return style.display !== "none" && style.opacity !== "0";
908
+ },
787
909
  style: {
788
- transform: `translate(${contentPadding - left}px, ${contentPadding - top}px)`,
910
+ transform: `translate(${contentPadding + (width - naturalWidth) / 2 - left}px, ${contentPadding + (height - naturalHeight) / 2 - top}px)`,
789
911
  transformOrigin: "0 0"
790
912
  }
791
913
  });
@@ -802,13 +924,11 @@ async function captureFlowImage(model, language, options) {
802
924
  });
803
925
  host.append(palette);
804
926
  const style = getComputedStyle(palette);
805
- const outerBackground = style.backgroundColor;
806
927
  if (options.dark) palette.style.backgroundColor = "var(--ui-card)";
807
928
  frame = {
808
929
  title: options.title ?? "",
809
930
  logo: openFlowLogoSource(options.dark ? "dark" : "light"),
810
931
  background: getComputedStyle(palette).backgroundColor,
811
- outerBackground,
812
932
  foreground: style.color,
813
933
  border: style.borderColor,
814
934
  fontFamily: getComputedStyle(viewport).fontFamily || "sans-serif"
@@ -816,8 +936,8 @@ async function captureFlowImage(model, language, options) {
816
936
  }
817
937
  return {
818
938
  dataUrl,
819
- width: width + (frame ? 40 : 0),
820
- height: height + (frame ? 72 : 0),
939
+ width: width + frameWidth,
940
+ height: height + frameHeight,
821
941
  background,
822
942
  frame,
823
943
  hasImagePlaceholders
@@ -829,17 +949,15 @@ async function captureFlowImage(model, language, options) {
829
949
  }
830
950
  }
831
951
  async function flowToPng(model, language = "en", options = {}) {
832
- const { dataUrl, width, height, background, frame, hasImagePlaceholders } = await captureFlowImage(model, language, options);
952
+ const aspectRatio = getFlowPngAspectRatio(options.aspectRatio);
953
+ const { dataUrl, width, height, background, frame, hasImagePlaceholders } = await captureFlowImage(model, language, options, aspectRatio);
833
954
  return {
834
- ...await renderPng(dataUrl, width, height, background, frame),
955
+ ...await renderPng(dataUrl, width, height, background, frame, aspectRatio),
835
956
  hasImagePlaceholders
836
957
  };
837
958
  }
838
- async function downloadFlowPng(model, title, language = "en", options = {}) {
839
- const result = await flowToPng(model, language, {
840
- ...options,
841
- title
842
- });
959
+ /** Download the exact image already rendered for preview. */
960
+ function downloadPng(result, title) {
843
961
  const url = URL.createObjectURL(result.blob);
844
962
  const link = document.createElement("a");
845
963
  try {
@@ -851,7 +969,6 @@ async function downloadFlowPng(model, title, language = "en", options = {}) {
851
969
  link.remove();
852
970
  setTimeout(() => URL.revokeObjectURL(url), 0);
853
971
  }
854
- return result;
855
972
  }
856
973
  //#endregion
857
- export { downloadFlowPng };
974
+ export { downloadPng, flowToPng };