@rogieking/figui3 4.6.1 → 4.7.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/fig.js CHANGED
@@ -1140,6 +1140,7 @@ class FigDialog extends HTMLDialogElement {
1140
1140
  #boundPointerMove;
1141
1141
  #boundPointerUp;
1142
1142
  #boundClose;
1143
+ #boundIframeMessage;
1143
1144
  #offset = 16; // 1rem in pixels
1144
1145
  #positionInitialized = false;
1145
1146
  #dragThreshold = 3; // pixels before drag starts
@@ -1150,6 +1151,7 @@ class FigDialog extends HTMLDialogElement {
1150
1151
  this.#boundPointerMove = this.#handlePointerMove.bind(this);
1151
1152
  this.#boundPointerUp = this.#handlePointerUp.bind(this);
1152
1153
  this.#boundClose = this.close.bind(this);
1154
+ this.#boundIframeMessage = this.#handleIframeMessage.bind(this);
1153
1155
  }
1154
1156
 
1155
1157
  connectedCallback() {
@@ -1167,6 +1169,8 @@ class FigDialog extends HTMLDialogElement {
1167
1169
  this.#setupDragListeners();
1168
1170
  this.#applyPosition();
1169
1171
  });
1172
+
1173
+ window.addEventListener("message", this.#boundIframeMessage);
1170
1174
  }
1171
1175
 
1172
1176
  disconnectedCallback() {
@@ -1174,6 +1178,51 @@ class FigDialog extends HTMLDialogElement {
1174
1178
  this.querySelectorAll("fig-button[close-dialog]").forEach((button) => {
1175
1179
  button.removeEventListener("click", this.#boundClose);
1176
1180
  });
1181
+ window.removeEventListener("message", this.#boundIframeMessage);
1182
+ }
1183
+
1184
+ #handleIframeMessage(event) {
1185
+ const data = event?.data;
1186
+ if (!data || data.type !== "figui:iframe-resize") return;
1187
+ const source = event.source;
1188
+ if (!source) return;
1189
+ const iframe = Array.from(this.querySelectorAll("iframe")).find(
1190
+ (el) => el.contentWindow === source,
1191
+ );
1192
+ if (!iframe) return;
1193
+ this.#resizeForIframe(iframe, data);
1194
+ }
1195
+
1196
+ #resizeForIframe(iframe, data) {
1197
+ if (typeof data.height !== "number" || !(data.height > 0)) return;
1198
+
1199
+ // Compute the dialog's non-iframe vertical chrome: dialog padding/border
1200
+ // plus the laid-out height of every direct child that isn't the iframe
1201
+ // (header, footer, gaps between flex children, etc.). We avoid using the
1202
+ // iframe's own rect because it may be 0 or stale before/after the resize.
1203
+ const cs = window.getComputedStyle(this);
1204
+ const verticalBoxExtras =
1205
+ parseFloat(cs.paddingTop || "0") +
1206
+ parseFloat(cs.paddingBottom || "0") +
1207
+ parseFloat(cs.borderTopWidth || "0") +
1208
+ parseFloat(cs.borderBottomWidth || "0");
1209
+
1210
+ let siblingsHeight = 0;
1211
+ const gap = parseFloat(cs.rowGap || cs.gap || "0") || 0;
1212
+ let visibleChildren = 0;
1213
+ for (const child of this.children) {
1214
+ const rect = child.getBoundingClientRect();
1215
+ if (rect.height === 0) continue;
1216
+ visibleChildren += 1;
1217
+ if (child === iframe) continue;
1218
+ siblingsHeight += rect.height;
1219
+ }
1220
+ if (gap && visibleChildren > 1) {
1221
+ siblingsHeight += gap * (visibleChildren - 1);
1222
+ }
1223
+
1224
+ const chrome = verticalBoxExtras + siblingsHeight;
1225
+ this.style.height = `${Math.ceil(data.height + chrome)}px`;
1177
1226
  }
1178
1227
 
1179
1228
  #ensureHeader() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "4.6.1",
3
+ "version": "4.7.0",
4
4
  "description": "A lightweight web components library for building Figma plugin and widget UIs with native look and feel",
5
5
  "author": "Rogie King",
6
6
  "license": "MIT",