@tutti-os/workbench-surface 0.0.215 → 0.0.217

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3718,117 +3718,6 @@ function resolveGenieRowTargetY({
3718
3718
  const verticalEase = easeInQuadratic(verticalProgress);
3719
3719
  return direction === "minimize" ? lerpGenieValue(textureRect.top + sourceY, dockPoint.y, verticalEase) : lerpGenieValue(dockPoint.y, textureRect.top + sourceY, verticalEase);
3720
3720
  }
3721
- function canInlineComputedStyle(element) {
3722
- return element instanceof HTMLElement || typeof SVGElement !== "undefined" && element instanceof SVGElement;
3723
- }
3724
- function isHiddenForGenieTexture(computed) {
3725
- return computed.display === "none" || computed.visibility === "hidden" || computed.visibility === "collapse" || Number.parseFloat(computed.opacity || "1") <= 0;
3726
- }
3727
- function rectsIntersect(a, b) {
3728
- return a.left < b.left + b.width && a.left + a.width > b.left && a.top < b.top + b.height && a.top + a.height > b.top;
3729
- }
3730
- function resolveElementSkipReasonForGenieTexture(element, rootRect, computed) {
3731
- if (isHiddenForGenieTexture(computed)) {
3732
- return "hidden";
3733
- }
3734
- const tagName = element.tagName.toLowerCase();
3735
- if (tagName === "script" || tagName === "style" || tagName === "template") {
3736
- return "unsupported";
3737
- }
3738
- const rect = element.getBoundingClientRect();
3739
- if (rect.width <= 0 || rect.height <= 0) {
3740
- return "zero-size";
3741
- }
3742
- return rectsIntersect(
3743
- {
3744
- height: rect.height,
3745
- left: rect.left,
3746
- top: rect.top,
3747
- width: rect.width
3748
- },
3749
- rootRect
3750
- ) ? null : "offscreen";
3751
- }
3752
- function hasMeaningfulTextNode(node) {
3753
- return node.textContent?.trim() ? true : false;
3754
- }
3755
- function cloneMeaningfulGenieNode(source, rootRect, images, forceInclude = false) {
3756
- if (source.nodeType === Node.TEXT_NODE) {
3757
- if (!hasMeaningfulTextNode(source)) {
3758
- return null;
3759
- }
3760
- return source.cloneNode(false);
3761
- }
3762
- if (source.nodeType !== Node.ELEMENT_NODE) {
3763
- return null;
3764
- }
3765
- const sourceElement = source;
3766
- if (!canInlineComputedStyle(sourceElement)) {
3767
- return null;
3768
- }
3769
- const computed = window.getComputedStyle(sourceElement);
3770
- const skipReason = resolveElementSkipReasonForGenieTexture(
3771
- sourceElement,
3772
- rootRect,
3773
- computed
3774
- );
3775
- const includeSelf = forceInclude || skipReason === null;
3776
- if (!includeSelf && skipReason === "hidden") {
3777
- return null;
3778
- }
3779
- const clone = sourceElement.cloneNode(false);
3780
- copyGenieComputedStyle(sourceElement, clone, computed);
3781
- for (const child of Array.from(source.childNodes)) {
3782
- const childClone = cloneMeaningfulGenieNode(child, rootRect, images);
3783
- if (childClone) {
3784
- clone.appendChild(childClone);
3785
- }
3786
- }
3787
- if (!includeSelf && clone.childNodes.length === 0) {
3788
- return null;
3789
- }
3790
- if (sourceElement instanceof HTMLImageElement) {
3791
- const rect = sourceElement.getBoundingClientRect();
3792
- images.push({
3793
- displayHeight: rect.height,
3794
- displayWidth: rect.width,
3795
- url: sourceElement.currentSrc || sourceElement.src || sourceElement.getAttribute("src") || null
3796
- });
3797
- }
3798
- return clone;
3799
- }
3800
- function copyGenieComputedStyle(source, clone, computed = window.getComputedStyle(source)) {
3801
- if (!canInlineComputedStyle(source) || !canInlineComputedStyle(clone)) {
3802
- return;
3803
- }
3804
- if (computed.cssText) {
3805
- clone.style.cssText = computed.cssText;
3806
- } else {
3807
- for (let index = 0; index < computed.length; index += 1) {
3808
- const propertyName = computed.item(index);
3809
- if (!propertyName) {
3810
- continue;
3811
- }
3812
- clone.style.setProperty(
3813
- propertyName,
3814
- computed.getPropertyValue(propertyName),
3815
- computed.getPropertyPriority(propertyName)
3816
- );
3817
- }
3818
- }
3819
- clone.style.animation = "none";
3820
- clone.style.opacity = "1";
3821
- clone.style.transition = "none";
3822
- clone.style.visibility = "visible";
3823
- }
3824
- function cloneMeaningfulGenieElement(source, rootRect) {
3825
- const images = [];
3826
- const clone = cloneMeaningfulGenieNode(source, rootRect, images, true);
3827
- if (!(clone instanceof HTMLElement)) {
3828
- return null;
3829
- }
3830
- return { clone, images };
3831
- }
3832
3721
  function renderGenieScanlines(context, viewportWidth, viewportHeight, frame) {
3833
3722
  const { direction, dockPoint, texture, textureRect } = frame;
3834
3723
  const progress = clampGenieProgress(frame.progress);
@@ -3930,6 +3819,109 @@ function renderGenieScanlines(context, viewportWidth, viewportHeight, frame) {
3930
3819
  );
3931
3820
  }
3932
3821
 
3822
+ // src/react/genieTextureCapture.ts
3823
+ function collectReadableStylesheetText(document2) {
3824
+ const rules = [];
3825
+ for (const stylesheet of Array.from(document2.styleSheets)) {
3826
+ try {
3827
+ for (const rule of Array.from(stylesheet.cssRules)) {
3828
+ rules.push(rule.cssText);
3829
+ }
3830
+ } catch {
3831
+ }
3832
+ }
3833
+ return rules.join("\n");
3834
+ }
3835
+ function collectImageClones(element) {
3836
+ return Array.from(element.querySelectorAll("img")).map((image) => {
3837
+ const rect = image.getBoundingClientRect();
3838
+ return {
3839
+ displayHeight: rect.height,
3840
+ displayWidth: rect.width,
3841
+ url: image.currentSrc || image.src || image.getAttribute("src") || null
3842
+ };
3843
+ });
3844
+ }
3845
+ function copyResolvedThemeVariables({
3846
+ clone,
3847
+ source,
3848
+ window: window2
3849
+ }) {
3850
+ const sourceStyle = window2.getComputedStyle(source);
3851
+ for (let index = 0; index < sourceStyle.length; index += 1) {
3852
+ const propertyName = sourceStyle.item(index);
3853
+ if (!propertyName.startsWith("--")) {
3854
+ continue;
3855
+ }
3856
+ clone.style.setProperty(
3857
+ propertyName,
3858
+ sourceStyle.getPropertyValue(propertyName),
3859
+ sourceStyle.getPropertyPriority(propertyName)
3860
+ );
3861
+ }
3862
+ }
3863
+ function prepareGenieTextureCapture(element) {
3864
+ const rect = viewportRectFromElement(element);
3865
+ const document2 = element.ownerDocument;
3866
+ const window2 = document2.defaultView;
3867
+ if (!window2 || !isUsableGenieRect(rect)) {
3868
+ return null;
3869
+ }
3870
+ const contentClone = element.cloneNode(true);
3871
+ const documentClone = document2.documentElement.cloneNode(
3872
+ false
3873
+ );
3874
+ const headClone = document2.head.cloneNode(false);
3875
+ const bodyClone = document2.body.cloneNode(false);
3876
+ const stylesheet = document2.createElement("style");
3877
+ stylesheet.dataset.workbenchGenieStylesheet = "true";
3878
+ stylesheet.textContent = `${collectReadableStylesheetText(document2)}
3879
+ *, *::before, *::after {
3880
+ animation: none !important;
3881
+ caret-color: transparent !important;
3882
+ transition: none !important;
3883
+ }`;
3884
+ headClone.append(stylesheet);
3885
+ bodyClone.append(contentClone);
3886
+ documentClone.append(headClone, bodyClone);
3887
+ copyResolvedThemeVariables({
3888
+ clone: documentClone,
3889
+ source: element,
3890
+ window: window2
3891
+ });
3892
+ documentClone.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
3893
+ documentClone.style.position = "relative";
3894
+ documentClone.style.left = "0";
3895
+ documentClone.style.top = "0";
3896
+ documentClone.style.width = `${rect.width}px`;
3897
+ documentClone.style.height = `${rect.height}px`;
3898
+ documentClone.style.transform = "none";
3899
+ documentClone.style.opacity = "1";
3900
+ documentClone.style.visibility = "visible";
3901
+ documentClone.style.pointerEvents = "none";
3902
+ bodyClone.style.position = "relative";
3903
+ bodyClone.style.inset = "0";
3904
+ bodyClone.style.margin = "0";
3905
+ bodyClone.style.width = `${rect.width}px`;
3906
+ bodyClone.style.height = `${rect.height}px`;
3907
+ bodyClone.style.overflow = "hidden";
3908
+ contentClone.style.position = "relative";
3909
+ contentClone.style.left = "0";
3910
+ contentClone.style.top = "0";
3911
+ contentClone.style.width = `${rect.width}px`;
3912
+ contentClone.style.height = `${rect.height}px`;
3913
+ contentClone.style.transform = "none";
3914
+ contentClone.style.opacity = "1";
3915
+ contentClone.style.visibility = "visible";
3916
+ contentClone.style.pointerEvents = "none";
3917
+ contentClone.style.zIndex = "auto";
3918
+ return {
3919
+ clone: documentClone,
3920
+ images: collectImageClones(element),
3921
+ rect
3922
+ };
3923
+ }
3924
+
3933
3925
  // src/react/useWorkbenchGenieAnimation.tsx
3934
3926
  import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
3935
3927
  var genieDurationMs = 400;
@@ -4151,32 +4143,6 @@ async function resizeInlineImageResourceForGenieTexture(imageUrl, imageInfo) {
4151
4143
  return null;
4152
4144
  }
4153
4145
  }
4154
- function prepareElementTextureCapture(element) {
4155
- const windowRect = viewportRectFromElement(element);
4156
- if (!isUsableGenieRect(windowRect)) {
4157
- return null;
4158
- }
4159
- const clonedElement = cloneMeaningfulGenieElement(element, windowRect);
4160
- if (!clonedElement) {
4161
- return null;
4162
- }
4163
- const { clone, images } = clonedElement;
4164
- clone.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
4165
- clone.style.position = "relative";
4166
- clone.style.left = "0";
4167
- clone.style.top = "0";
4168
- clone.style.width = `${windowRect.width}px`;
4169
- clone.style.height = `${windowRect.height}px`;
4170
- clone.style.transform = "none";
4171
- clone.style.opacity = "1";
4172
- clone.style.visibility = "visible";
4173
- clone.style.pointerEvents = "none";
4174
- return {
4175
- clone,
4176
- images,
4177
- rect: windowRect
4178
- };
4179
- }
4180
4146
  function prepareRenderedGeniePreviewCloneForTexture(clone, textureRect) {
4181
4147
  clone.style.width = `${textureRect.width}px`;
4182
4148
  clone.style.height = `${textureRect.height}px`;
@@ -4220,7 +4186,7 @@ async function renderPreparedElementTexture({
4220
4186
  return { canvas, rect };
4221
4187
  }
4222
4188
  async function captureElementTexture(element) {
4223
- const preparedCapture = prepareElementTextureCapture(element);
4189
+ const preparedCapture = prepareGenieTextureCapture(element);
4224
4190
  return preparedCapture ? renderPreparedElementTexture(preparedCapture) : null;
4225
4191
  }
4226
4192
  function createDockPreviewDataUrl(canvas) {
@@ -4579,7 +4545,7 @@ function useWorkbenchGenieAnimation({
4579
4545
  if (!element) {
4580
4546
  return null;
4581
4547
  }
4582
- const preparedCapture = prepareElementTextureCapture(element);
4548
+ const preparedCapture = prepareGenieTextureCapture(element);
4583
4549
  if (!preparedCapture) {
4584
4550
  return null;
4585
4551
  }
@@ -5234,7 +5200,7 @@ function useWorkbenchGenieAnimation({
5234
5200
  }
5235
5201
  }
5236
5202
  const captureTarget = resolveWorkbenchCaptureElement(nodeElement);
5237
- const preparedTexture = shouldCapturePreview ? prepareElementTextureCapture(captureTarget) : null;
5203
+ const preparedTexture = shouldCapturePreview ? prepareGenieTextureCapture(captureTarget) : null;
5238
5204
  if (!preparedTexture) {
5239
5205
  if (!componentPreviewTexture) {
5240
5206
  logWorkbenchGenieDiagnostic(
@@ -12446,9 +12412,9 @@ function WorkbenchHostDock({
12446
12412
  )
12447
12413
  ) ? popupEntry.entry.dockRetention.pendingLabel : void 0
12448
12414
  } : null,
12449
- capturePreview: popupEntry.entry.capturePopupItemPreview ? async (item) => {
12415
+ capturePreview: popupEntry.entry.capturePopupItemPreview || captureNodePreviewImage ? async (item) => {
12450
12416
  const previewImageUrl = await Promise.resolve(
12451
- popupEntry.entry.capturePopupItemPreview?.(item) ?? null
12417
+ popupEntry.entry.capturePopupItemPreview ? popupEntry.entry.capturePopupItemPreview(item) : captureNodePreviewImage?.(item.node) ?? null
12452
12418
  ).catch(() => null);
12453
12419
  return previewImageUrl ? {
12454
12420
  kind: "image",
@@ -12713,10 +12679,10 @@ function WorkbenchHostDockMinimizedNodePreview({
12713
12679
  }) {
12714
12680
  const [componentPreview, setComponentPreview] = useState8(void 0);
12715
12681
  const [previewImageUrl, setPreviewImageUrl] = useState8(
12716
- () => deferPreview || providePreview ? null : readCachedWorkbenchNodePreviewImage(node.id)
12682
+ () => deferPreview ? null : readCachedWorkbenchNodePreviewImage(node.id)
12717
12683
  );
12718
12684
  useEffect10(() => {
12719
- if (deferPreview || !providePreview || componentPreview !== void 0) {
12685
+ if (deferPreview || !providePreview || componentPreview !== void 0 || previewImageUrl) {
12720
12686
  return void 0;
12721
12687
  }
12722
12688
  let cancelled = false;
@@ -12762,10 +12728,11 @@ function WorkbenchHostDockMinimizedNodePreview({
12762
12728
  node.data.typeId,
12763
12729
  node.id,
12764
12730
  node.minimizedAtUnixMs,
12731
+ previewImageUrl,
12765
12732
  providePreview
12766
12733
  ]);
12767
12734
  useEffect10(() => {
12768
- if (deferPreview || providePreview) {
12735
+ if (deferPreview) {
12769
12736
  return void 0;
12770
12737
  }
12771
12738
  let cancelled = false;
@@ -12822,9 +12789,6 @@ function WorkbenchHostDockMinimizedNodePreview({
12822
12789
  if (deferPreview) {
12823
12790
  return renderMinimizedDockPreviewPlaceholder(className);
12824
12791
  }
12825
- if (componentPreview) {
12826
- return renderMinimizedDockPreviewContent(componentPreview, className);
12827
- }
12828
12792
  if (previewImageUrl) {
12829
12793
  return /* @__PURE__ */ jsx12(
12830
12794
  "span",
@@ -12847,6 +12811,9 @@ function WorkbenchHostDockMinimizedNodePreview({
12847
12811
  }
12848
12812
  );
12849
12813
  }
12814
+ if (componentPreview) {
12815
+ return renderMinimizedDockPreviewContent(componentPreview, className);
12816
+ }
12850
12817
  return renderMinimizedDockPreviewPlaceholder(className);
12851
12818
  }
12852
12819
  function renderMinimizedDockPreviewPlaceholder(className) {
@@ -13984,11 +13951,8 @@ function useWorkbenchHostSurfaceRenderers(input) {
13984
13951
  [input.nodeDefinitionByType]
13985
13952
  );
13986
13953
  const shouldCaptureNodePreviewImage = useCallback13(
13987
- (node) => {
13988
- const minimizedDock = input.nodeDefinitionByType.get(node.data.typeId)?.window?.minimizedDock;
13989
- return minimizedDock?.kind !== "component";
13990
- },
13991
- [input.nodeDefinitionByType]
13954
+ (_node) => true,
13955
+ []
13992
13956
  );
13993
13957
  const renderNodeGeniePreview = useCallback13(
13994
13958
  (node, {