made-refine 0.2.4 → 0.2.6

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
@@ -4103,6 +4103,8 @@ var MAX_ZOOM = 5;
4103
4103
  var ZOOM_SENSITIVITY = 0.0145;
4104
4104
  var LINE_HEIGHT_PX = 40;
4105
4105
  var PAGE_HEIGHT_PX = 800;
4106
+ var CANVAS_MEASURE_NODE_BUDGET = 12e3;
4107
+ var CANVAS_PRIORITY_ROOT_SELECTORS = ["#root", "#app", "#__next", "main"];
4106
4108
  function normalizeWheelDelta(e) {
4107
4109
  let { deltaX, deltaY } = e;
4108
4110
  if (e.deltaMode === 1) {
@@ -4114,6 +4116,52 @@ function normalizeWheelDelta(e) {
4114
4116
  }
4115
4117
  return { deltaX, deltaY };
4116
4118
  }
4119
+ function getResolvedOverflowY(style) {
4120
+ return style.overflowY || style.overflow;
4121
+ }
4122
+ function isScrollableOverflowY(value) {
4123
+ return value === "auto" || value === "scroll" || value === "overlay";
4124
+ }
4125
+ function isClippedOverflowY(value) {
4126
+ return value === "hidden" || value === "clip";
4127
+ }
4128
+ function getParentAcrossShadowTree(el) {
4129
+ const parent = el.parentElement;
4130
+ if (parent) return parent;
4131
+ const root = el.getRootNode();
4132
+ if (root instanceof ShadowRoot && root.host instanceof HTMLElement) {
4133
+ return root.host;
4134
+ }
4135
+ return null;
4136
+ }
4137
+ function enqueueChildren(el, queue) {
4138
+ for (const child of el.children) {
4139
+ if (child instanceof HTMLElement) queue.push(child);
4140
+ }
4141
+ const shadowRoot = el.shadowRoot;
4142
+ if (!shadowRoot) return;
4143
+ for (const child of shadowRoot.children) {
4144
+ if (child instanceof HTMLElement) queue.push(child);
4145
+ }
4146
+ }
4147
+ function measureContentBounds(el) {
4148
+ const rect = el.getBoundingClientRect();
4149
+ const pageLeft = rect.left + (window.scrollX || window.pageXOffset || 0);
4150
+ const pageTop = rect.top + (window.scrollY || window.pageYOffset || 0);
4151
+ return {
4152
+ width: Math.max(0, pageLeft) + el.scrollWidth,
4153
+ height: Math.max(0, pageTop) + el.scrollHeight
4154
+ };
4155
+ }
4156
+ function hasClippedAncestor(el) {
4157
+ let ancestor = getParentAcrossShadowTree(el);
4158
+ while (ancestor && ancestor !== document.body) {
4159
+ const ancestorStyle = getComputedStyle(ancestor);
4160
+ if (isClippedOverflowY(getResolvedOverflowY(ancestorStyle))) return true;
4161
+ ancestor = getParentAcrossShadowTree(ancestor);
4162
+ }
4163
+ return false;
4164
+ }
4117
4165
  var PAN_MARGIN = 0.1;
4118
4166
  function clampPan(zoom, panX, panY, bodyW, bodyH) {
4119
4167
  const vw = window.innerWidth;
@@ -4134,8 +4182,9 @@ function useCanvas({ stateRef, setState }) {
4134
4182
  const savedBodyOverflowRef = React7.useRef("");
4135
4183
  const savedHtmlOverflowRef = React7.useRef("");
4136
4184
  const savedHtmlBgColorRef = React7.useRef("");
4185
+ const domStateSavedRef = React7.useRef(false);
4137
4186
  const savedBodyDimensionsRef = React7.useRef({ width: 0, height: 0 });
4138
- const savedScrollContainersRef = React7.useRef([]);
4187
+ const savedExpandedNodesRef = React7.useRef([]);
4139
4188
  const rafIdRef = React7.useRef(null);
4140
4189
  const rafPendingRef = React7.useRef(false);
4141
4190
  const spaceHeldRef = React7.useRef(false);
@@ -4191,108 +4240,162 @@ function useCanvas({ stateRef, setState }) {
4191
4240
  });
4192
4241
  }
4193
4242
  }, [applyTransform, dispatchCanvasChange, setState]);
4194
- function isScrollableContainer(el) {
4195
- if (el.scrollHeight <= el.clientHeight + 1) return false;
4196
- const style = getComputedStyle(el);
4197
- const overflowY = style.overflowY || style.overflow;
4198
- if (overflowY === "hidden" || overflowY === "clip") return false;
4199
- return overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay";
4200
- }
4201
- function expandScrollContainers() {
4202
- const saved = [];
4203
- const queue = Array.from(document.body.children).filter(
4204
- (el) => el instanceof HTMLElement
4205
- );
4206
- let visited = 0;
4207
- const maxNodes = 5e3;
4208
- while (queue.length > 0 && visited < maxNodes) {
4209
- const nextQueue = [];
4210
- for (const el of queue) {
4211
- if (visited >= maxNodes) break;
4212
- visited++;
4213
- if (isScrollableContainer(el)) {
4214
- const style = el.style;
4215
- saved.push({
4216
- el,
4217
- height: style.height,
4218
- maxHeight: style.maxHeight,
4219
- overflowX: style.overflowX,
4220
- overflowY: style.overflowY
4221
- });
4222
- style.height = "auto";
4223
- style.maxHeight = "none";
4224
- style.overflowX = "visible";
4225
- style.overflowY = "visible";
4226
- }
4227
- for (const child of el.children) {
4228
- if (child instanceof HTMLElement) nextQueue.push(child);
4243
+ function collectTraversalSeeds() {
4244
+ const out = [];
4245
+ const seen = /* @__PURE__ */ new Set();
4246
+ const push = (el) => {
4247
+ if (!(el instanceof HTMLElement)) return;
4248
+ if (!document.body.contains(el)) return;
4249
+ if (seen.has(el)) return;
4250
+ seen.add(el);
4251
+ out.push(el);
4252
+ };
4253
+ for (const selector of CANVAS_PRIORITY_ROOT_SELECTORS) {
4254
+ push(document.querySelector(selector));
4255
+ }
4256
+ for (const child of document.body.children) {
4257
+ push(child);
4258
+ }
4259
+ return out;
4260
+ }
4261
+ function expandScrollableRegionsAndMeasureBody() {
4262
+ const snapshots = /* @__PURE__ */ new Map();
4263
+ const expandedOrder = [];
4264
+ const queue = collectTraversalSeeds();
4265
+ const visited = /* @__PURE__ */ new Set();
4266
+ let visitedCount = 0;
4267
+ let fallbackWidth = 0;
4268
+ let fallbackHeight = 0;
4269
+ const expandNode = (el) => {
4270
+ if (snapshots.has(el)) return;
4271
+ snapshots.set(el, {
4272
+ height: el.style.height,
4273
+ maxHeight: el.style.maxHeight,
4274
+ overflowY: el.style.overflowY
4275
+ });
4276
+ expandedOrder.push(el);
4277
+ el.style.height = "auto";
4278
+ el.style.maxHeight = "none";
4279
+ el.style.overflowY = "visible";
4280
+ };
4281
+ while (queue.length > 0 && visitedCount < CANVAS_MEASURE_NODE_BUDGET) {
4282
+ const el = queue.shift();
4283
+ if (!el || visited.has(el)) continue;
4284
+ visited.add(el);
4285
+ visitedCount++;
4286
+ const hasVerticalOverflow = el.scrollHeight > el.clientHeight + 1;
4287
+ const style = getComputedStyle(el);
4288
+ const overflowY = getResolvedOverflowY(style);
4289
+ const isScrollable = hasVerticalOverflow && isScrollableOverflowY(overflowY);
4290
+ if (isScrollable) {
4291
+ expandNode(el);
4292
+ let ancestor = getParentAcrossShadowTree(el);
4293
+ while (ancestor && ancestor !== document.body) {
4294
+ const ancestorStyle = getComputedStyle(ancestor);
4295
+ if (isClippedOverflowY(getResolvedOverflowY(ancestorStyle))) {
4296
+ expandNode(ancestor);
4297
+ }
4298
+ ancestor = getParentAcrossShadowTree(ancestor);
4229
4299
  }
4230
4300
  }
4231
- queue.length = 0;
4232
- queue.push(...nextQueue);
4301
+ const canContributeFallback = hasVerticalOverflow && (isScrollable || !isClippedOverflowY(overflowY) && !hasClippedAncestor(el));
4302
+ if (canContributeFallback) {
4303
+ const bounds = measureContentBounds(el);
4304
+ fallbackWidth = Math.max(fallbackWidth, bounds.width);
4305
+ fallbackHeight = Math.max(fallbackHeight, bounds.height);
4306
+ }
4307
+ enqueueChildren(el, queue);
4233
4308
  }
4234
- savedScrollContainersRef.current = saved;
4309
+ savedExpandedNodesRef.current = expandedOrder.map((el) => ({ el, ...snapshots.get(el) }));
4310
+ return {
4311
+ width: Math.max(document.body.scrollWidth, document.documentElement.scrollWidth, fallbackWidth, window.innerWidth),
4312
+ height: Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, fallbackHeight, window.innerHeight)
4313
+ };
4235
4314
  }
4236
- function restoreScrollContainers() {
4237
- for (let i = savedScrollContainersRef.current.length - 1; i >= 0; i--) {
4238
- const { el, height, maxHeight, overflowX, overflowY } = savedScrollContainersRef.current[i];
4315
+ function restoreExpandedNodes() {
4316
+ for (let i = savedExpandedNodesRef.current.length - 1; i >= 0; i--) {
4317
+ const { el, height, maxHeight, overflowY } = savedExpandedNodesRef.current[i];
4239
4318
  el.style.height = height;
4240
4319
  el.style.maxHeight = maxHeight;
4241
- el.style.overflowX = overflowX;
4242
4320
  el.style.overflowY = overflowY;
4243
4321
  }
4244
- savedScrollContainersRef.current = [];
4322
+ savedExpandedNodesRef.current = [];
4245
4323
  }
4246
4324
  const enterCanvas = React7.useCallback(() => {
4325
+ if (canvasRef.current.active) return;
4326
+ if (domStateSavedRef.current || savedExpandedNodesRef.current.length > 0) {
4327
+ restoreExpandedNodes();
4328
+ domStateSavedRef.current = false;
4329
+ }
4247
4330
  const scrollX = window.scrollX;
4248
4331
  const scrollY = window.scrollY;
4249
4332
  savedScrollRef.current = { x: scrollX, y: scrollY };
4250
4333
  savedBodyOverflowRef.current = document.body.style.overflow;
4251
4334
  savedHtmlOverflowRef.current = document.documentElement.style.overflow;
4252
4335
  savedHtmlBgColorRef.current = document.documentElement.style.backgroundColor;
4336
+ domStateSavedRef.current = true;
4253
4337
  const existingTransform = document.body.style.transform;
4254
4338
  if (existingTransform && existingTransform !== "none" && existingTransform !== "") {
4255
4339
  console.warn("[made-refine] canvas mode: overriding existing body transform:", existingTransform);
4256
4340
  }
4257
- window.scrollTo(0, 0);
4258
- expandScrollContainers();
4259
- savedBodyDimensionsRef.current = {
4260
- width: document.body.scrollWidth,
4261
- height: document.body.scrollHeight
4262
- };
4263
- updateBodyOffset();
4264
- document.body.style.overflow = "hidden";
4265
- document.documentElement.style.overflow = "hidden";
4266
- document.documentElement.style.backgroundColor = "#F5F5F5";
4267
- const initialPanX = -scrollX;
4268
- const initialPanY = -scrollY;
4269
- applyTransform(1, initialPanX, initialPanY);
4270
- canvasRef.current = { active: true, zoom: 1, panX: initialPanX, panY: initialPanY };
4271
- setCanvasSnapshot(canvasRef.current);
4272
- setState((prev) => ({
4273
- ...prev,
4274
- canvas: { active: true, zoom: 1, panX: initialPanX, panY: initialPanY }
4275
- }));
4276
- dispatchCanvasChange();
4341
+ let entered = false;
4342
+ try {
4343
+ window.scrollTo(0, 0);
4344
+ savedBodyDimensionsRef.current = expandScrollableRegionsAndMeasureBody();
4345
+ updateBodyOffset();
4346
+ document.body.style.overflow = "hidden";
4347
+ document.documentElement.style.overflow = "hidden";
4348
+ document.documentElement.style.backgroundColor = "#F5F5F5";
4349
+ const initialPanX = -scrollX;
4350
+ const initialPanY = -scrollY;
4351
+ applyTransform(1, initialPanX, initialPanY);
4352
+ canvasRef.current = { active: true, zoom: 1, panX: initialPanX, panY: initialPanY };
4353
+ setCanvasSnapshot(canvasRef.current);
4354
+ setState((prev) => ({
4355
+ ...prev,
4356
+ canvas: { active: true, zoom: 1, panX: initialPanX, panY: initialPanY }
4357
+ }));
4358
+ dispatchCanvasChange();
4359
+ entered = true;
4360
+ } finally {
4361
+ if (!entered) {
4362
+ document.body.style.transform = "";
4363
+ document.body.style.transformOrigin = "";
4364
+ restoreExpandedNodes();
4365
+ document.body.style.overflow = savedBodyOverflowRef.current;
4366
+ document.documentElement.style.overflow = savedHtmlOverflowRef.current;
4367
+ document.documentElement.style.backgroundColor = savedHtmlBgColorRef.current;
4368
+ window.scrollTo(scrollX, scrollY);
4369
+ domStateSavedRef.current = false;
4370
+ }
4371
+ }
4277
4372
  }, [applyTransform, dispatchCanvasChange, setState, updateBodyOffset]);
4278
4373
  const exitCanvas = React7.useCallback(() => {
4374
+ const shouldRestoreDom = domStateSavedRef.current || savedExpandedNodesRef.current.length > 0;
4375
+ const wasActive = canvasRef.current.active;
4376
+ if (!wasActive && !shouldRestoreDom) return;
4279
4377
  cancelPendingRaf();
4280
4378
  document.body.style.transform = "";
4281
4379
  document.body.style.transformOrigin = "";
4282
- restoreScrollContainers();
4283
- document.body.style.overflow = savedBodyOverflowRef.current;
4284
- document.documentElement.style.overflow = savedHtmlOverflowRef.current;
4285
- document.documentElement.style.backgroundColor = savedHtmlBgColorRef.current;
4380
+ restoreExpandedNodes();
4381
+ if (shouldRestoreDom) {
4382
+ document.body.style.overflow = savedBodyOverflowRef.current;
4383
+ document.documentElement.style.overflow = savedHtmlOverflowRef.current;
4384
+ document.documentElement.style.backgroundColor = savedHtmlBgColorRef.current;
4385
+ window.scrollTo(savedScrollRef.current.x, savedScrollRef.current.y);
4386
+ }
4286
4387
  document.body.style.cursor = "";
4287
- window.scrollTo(savedScrollRef.current.x, savedScrollRef.current.y);
4388
+ domStateSavedRef.current = false;
4288
4389
  setBodyOffset({ x: 0, y: 0 });
4289
4390
  canvasRef.current = { active: false, zoom: 1, panX: 0, panY: 0 };
4290
4391
  setCanvasSnapshot(canvasRef.current);
4291
- setState((prev) => ({
4292
- ...prev,
4293
- canvas: { active: false, zoom: 1, panX: 0, panY: 0 }
4294
- }));
4295
- dispatchCanvasChange();
4392
+ if (wasActive) {
4393
+ setState((prev) => ({
4394
+ ...prev,
4395
+ canvas: { active: false, zoom: 1, panX: 0, panY: 0 }
4396
+ }));
4397
+ dispatchCanvasChange();
4398
+ }
4296
4399
  }, [cancelPendingRaf, dispatchCanvasChange, setState]);
4297
4400
  const toggleCanvas = React7.useCallback(() => {
4298
4401
  if (canvasRef.current.active) {
@@ -4419,7 +4522,7 @@ function useCanvas({ stateRef, setState }) {
4419
4522
  React7.useEffect(() => {
4420
4523
  return () => {
4421
4524
  cancelPendingRaf();
4422
- if (canvasRef.current.active) {
4525
+ if (canvasRef.current.active || domStateSavedRef.current || savedExpandedNodesRef.current.length > 0) {
4423
4526
  exitCanvas();
4424
4527
  }
4425
4528
  };