@ni/nimble-components 35.5.2 → 35.5.3

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.
@@ -17712,13 +17712,14 @@
17712
17712
  background-color: transparent;
17713
17713
  cursor: pointer;
17714
17714
  outline: none;
17715
- --ni-private-step-icon-background-full-size: 100% 100%;
17716
- ${'' /* 6px = (2px icon border + 1px inset) * 2 sides */}
17717
- --ni-private-step-icon-background-inset-size: calc(100% - 6px) calc(100% - 6px);
17718
- --ni-private-step-icon-background-none-size: 0% 0%;
17715
+ --ni-private-step-icon-background-full-size: scale(1,1);
17716
+ ${'' /* (32px - 2 * (2px focus border + 1px inset gap)) / 32px = .8125 */}
17717
+ --ni-private-step-icon-background-inset-size: scale(0.8125, 0.8125);
17718
+ --ni-private-step-icon-background-none-size: scale(0,0);
17719
17719
 
17720
17720
  --ni-private-step-icon-color: ${buttonLabelFontColor};
17721
17721
  --ni-private-step-icon-border-color: transparent;
17722
+ --ni-private-step-icon-border-width: 1px;
17722
17723
  --ni-private-step-icon-background-color: rgba(${borderRgbPartialColor}, 0.1);
17723
17724
  --ni-private-step-icon-background-size: var(--ni-private-step-icon-background-full-size);
17724
17725
  --ni-private-step-icon-outline-inset-color: transparent;
@@ -17821,6 +17822,20 @@ Defines an interaction area clip-path that leaves out the severity text so it is
17821
17822
  --ni-private-step-line-color: ${borderHoverColor};
17822
17823
  }
17823
17824
 
17825
+ .icon-background {
17826
+ grid-area: icon;
17827
+ display: inline-block;
17828
+ height: ${controlHeight};
17829
+ width: ${controlHeight};
17830
+ ${userSelectNone};
17831
+ background-color: var(--ni-private-step-icon-background-color);
17832
+ transform: var(--ni-private-step-icon-background-size);
17833
+ border: none;
17834
+ border-radius: 100%;
17835
+ transition:
17836
+ transform ${smallDelay} ease-in-out;
17837
+ }
17838
+
17824
17839
  .icon {
17825
17840
  grid-area: icon;
17826
17841
  display: inline-flex;
@@ -17833,31 +17848,16 @@ Defines an interaction area clip-path that leaves out the severity text so it is
17833
17848
  font: ${buttonLabelFont};
17834
17849
  color: var(--ni-private-step-icon-color);
17835
17850
  ${iconColor.cssCustomProperty}: var(--ni-private-step-icon-color);
17836
- border-style: solid;
17851
+ border: none;
17837
17852
  border-radius: 100%;
17838
- border-color: var(--ni-private-step-icon-border-color);
17839
- border-width: 1px;
17840
- background-image: radial-gradient(
17841
- closest-side,
17842
- ${'' /* Workaround to prevent aliasing on radial-gradient boundaries, see:
17843
- https://frontendmasters.com/blog/obsessing-over-smooth-radial-gradient-disc-edges
17844
- */}
17845
- var(--ni-private-step-icon-background-color) calc(100% - 1px/var(--ni-private-device-pixel-ratio, 1)),
17846
- transparent 100%
17847
- );
17848
- background-origin: border-box;
17849
- background-size: var(--ni-private-step-icon-background-size);
17850
- background-repeat: no-repeat;
17851
- background-position: center center;
17853
+ box-shadow: inset 0px 0px 0px var(--ni-private-step-icon-border-width) var(--ni-private-step-icon-border-color);
17852
17854
  position: relative;
17853
17855
  transition:
17854
- border-color ${smallDelay} ease-in-out,
17855
- border-width ${smallDelay} ease-in-out,
17856
- background-size ${smallDelay} ease-out;
17856
+ box-shadow ${smallDelay} ease-in-out;
17857
17857
  }
17858
17858
 
17859
17859
  :host([selected]) .icon {
17860
- border-width: 2px;
17860
+ --ni-private-step-icon-border-width: 2px;
17861
17861
  }
17862
17862
 
17863
17863
  .icon::before {
@@ -17870,10 +17870,9 @@ Defines an interaction area clip-path that leaves out the severity text so it is
17870
17870
  outline-style: solid;
17871
17871
  outline-width: 0px;
17872
17872
  outline-offset: 0px;
17873
- border: 1px solid transparent;
17873
+ border: none;
17874
17874
  border-radius: 100%;
17875
17875
  color: transparent;
17876
- background-clip: border-box;
17877
17876
  transition:
17878
17877
  outline-color ${smallDelay} ease-in-out,
17879
17878
  outline-width ${smallDelay} ease-in-out,
@@ -18025,7 +18024,7 @@ Defines an interaction area clip-path that leaves out the severity text so it is
18025
18024
  }
18026
18025
 
18027
18026
  .control:hover .icon {
18028
- border-width: 2px;
18027
+ --ni-private-step-icon-border-width: 2px;
18029
18028
  }
18030
18029
 
18031
18030
  .control:hover .line {
@@ -18076,12 +18075,13 @@ Defines an interaction area clip-path that leaves out the severity text so it is
18076
18075
  }
18077
18076
 
18078
18077
  .control${focusVisible} .icon {
18079
- border-width: 2px;
18078
+ --ni-private-step-icon-border-width: 2px;
18080
18079
  }
18081
18080
 
18082
18081
  .control${focusVisible} .icon::before {
18083
18082
  outline-width: ${borderWidth};
18084
- outline-offset: -2px;
18083
+ ${'' /* -1px control to outline edge -2px focus border -1px inset gap */}
18084
+ outline-offset: -4px;
18085
18085
  }
18086
18086
 
18087
18087
  .control${focusVisible} .line {
@@ -18128,7 +18128,7 @@ Defines an interaction area clip-path that leaves out the severity text so it is
18128
18128
  }
18129
18129
 
18130
18130
  .control:active .icon {
18131
- border-width: 2px;
18131
+ --ni-private-step-icon-border-width: 2px;
18132
18132
  }
18133
18133
 
18134
18134
  .control:active .icon::before {
@@ -19462,6 +19462,7 @@ Defines an interaction area clip-path that leaves out the severity text so it is
19462
19462
  aria-roledescription="${x => x.ariaRoledescription}"
19463
19463
  ${ref('control')}
19464
19464
  >
19465
+ <div class="icon-background"></div>
19465
19466
  <div class="icon">
19466
19467
  <span class="current-label">${x => (x.selected ? popupIconCurrentLabel.getValueFor(x) : '')}</span>
19467
19468
  <div class="step-indicator"><slot name="step-indicator"><span aria-hidden="true">${x => x.stepInternals.position}</span></slot></div>
@@ -40791,8 +40792,13 @@ so this becomes the fallback color for the slot */ ''}
40791
40792
  for (let node of added)
40792
40793
  if (node.nodeName == "BR" && node.parentNode) {
40793
40794
  let after = node.nextSibling;
40794
- if (after && after.nodeType == 1 && after.contentEditable == "false")
40795
- node.parentNode.removeChild(node);
40795
+ while (after && after.nodeType == 1) {
40796
+ if (after.contentEditable == "false") {
40797
+ node.parentNode.removeChild(node);
40798
+ break;
40799
+ }
40800
+ after = after.firstChild;
40801
+ }
40796
40802
  }
40797
40803
  }
40798
40804
  else if (gecko && added.length) {
@@ -41630,12 +41636,12 @@ so this becomes the fallback color for the slot */ ''}
41630
41636
  }
41631
41637
  updateDraggedNode(dragging, prev) {
41632
41638
  let sel = dragging.node, found = -1;
41633
- if (this.state.doc.nodeAt(sel.from) == sel.node) {
41639
+ if (sel.from < this.state.doc.content.size && this.state.doc.nodeAt(sel.from) == sel.node) {
41634
41640
  found = sel.from;
41635
41641
  }
41636
41642
  else {
41637
41643
  let movedPos = sel.from + (this.state.doc.content.size - prev.doc.content.size);
41638
- let moved = movedPos > 0 && this.state.doc.nodeAt(movedPos);
41644
+ let moved = movedPos > 0 && movedPos < this.state.doc.content.size && this.state.doc.nodeAt(movedPos);
41639
41645
  if (moved == sel.node)
41640
41646
  found = movedPos;
41641
41647
  }
@@ -43507,6 +43513,67 @@ so this becomes the fallback color for the slot */ ''}
43507
43513
  }
43508
43514
 
43509
43515
  // src/utilities/mergeAttributes.ts
43516
+ function splitStyleDeclarations(styles) {
43517
+ const result = [];
43518
+ let current = "";
43519
+ let inSingleQuote = false;
43520
+ let inDoubleQuote = false;
43521
+ let parenDepth = 0;
43522
+ const length = styles.length;
43523
+ for (let i = 0; i < length; i += 1) {
43524
+ const char = styles[i];
43525
+ if (char === "'" && !inDoubleQuote) {
43526
+ inSingleQuote = !inSingleQuote;
43527
+ current += char;
43528
+ continue;
43529
+ }
43530
+ if (char === '"' && !inSingleQuote) {
43531
+ inDoubleQuote = !inDoubleQuote;
43532
+ current += char;
43533
+ continue;
43534
+ }
43535
+ if (!inSingleQuote && !inDoubleQuote) {
43536
+ if (char === "(") {
43537
+ parenDepth += 1;
43538
+ current += char;
43539
+ continue;
43540
+ }
43541
+ if (char === ")" && parenDepth > 0) {
43542
+ parenDepth -= 1;
43543
+ current += char;
43544
+ continue;
43545
+ }
43546
+ if (char === ";" && parenDepth === 0) {
43547
+ result.push(current);
43548
+ current = "";
43549
+ continue;
43550
+ }
43551
+ }
43552
+ current += char;
43553
+ }
43554
+ if (current) {
43555
+ result.push(current);
43556
+ }
43557
+ return result;
43558
+ }
43559
+ function parseStyleEntries(styles) {
43560
+ const pairs = [];
43561
+ const declarations = splitStyleDeclarations(styles || "");
43562
+ const numDeclarations = declarations.length;
43563
+ for (let i = 0; i < numDeclarations; i += 1) {
43564
+ const declaration = declarations[i];
43565
+ const firstColonIndex = declaration.indexOf(":");
43566
+ if (firstColonIndex === -1) {
43567
+ continue;
43568
+ }
43569
+ const property = declaration.slice(0, firstColonIndex).trim();
43570
+ const value = declaration.slice(firstColonIndex + 1).trim();
43571
+ if (property && value) {
43572
+ pairs.push([property, value]);
43573
+ }
43574
+ }
43575
+ return pairs;
43576
+ }
43510
43577
  function mergeAttributes(...objects) {
43511
43578
  return objects.filter((item) => !!item).reduce((items, item) => {
43512
43579
  const mergedAttributes = { ...items };
@@ -43522,17 +43589,7 @@ so this becomes the fallback color for the slot */ ''}
43522
43589
  const insertClasses = valueClasses.filter((valueClass) => !existingClasses.includes(valueClass));
43523
43590
  mergedAttributes[key] = [...existingClasses, ...insertClasses].join(" ");
43524
43591
  } else if (key === "style") {
43525
- const newStyles = value ? value.split(";").map((style2) => style2.trim()).filter(Boolean) : [];
43526
- const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(";").map((style2) => style2.trim()).filter(Boolean) : [];
43527
- const styleMap = /* @__PURE__ */ new Map();
43528
- existingStyles.forEach((style2) => {
43529
- const [property, val] = style2.split(":").map((part) => part.trim());
43530
- styleMap.set(property, val);
43531
- });
43532
- newStyles.forEach((style2) => {
43533
- const [property, val] = style2.split(":").map((part) => part.trim());
43534
- styleMap.set(property, val);
43535
- });
43592
+ const styleMap = new Map([...parseStyleEntries(mergedAttributes[key]), ...parseStyleEntries(value)]);
43536
43593
  mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join("; ");
43537
43594
  } else {
43538
43595
  mergedAttributes[key] = value;
@@ -44119,7 +44176,7 @@ so this becomes the fallback color for the slot */ ''}
44119
44176
  return true;
44120
44177
  }
44121
44178
  if (node.isText) {
44122
- return /^\s*$/m.test((_a = node.text) != null ? _a : "");
44179
+ return !/\S/.test((_a = node.text) != null ? _a : "");
44123
44180
  }
44124
44181
  }
44125
44182
  if (node.isText) {
@@ -47504,17 +47561,21 @@ ${renderedContent}
47504
47561
  const prefix = typeof prefixOrGenerator === "function" ? prefixOrGenerator(ctx) : prefixOrGenerator;
47505
47562
  const [content, ...children] = node.content;
47506
47563
  const mainContent = h2.renderChildren([content]);
47507
- const output = [`${prefix}${mainContent}`];
47564
+ let output = `${prefix}${mainContent}`;
47508
47565
  if (children && children.length > 0) {
47509
- children.forEach((child) => {
47510
- const childContent = h2.renderChildren([child]);
47511
- if (childContent) {
47512
- const indentedChild = childContent.split("\n").map((line) => line ? h2.indent(line) : "").join("\n");
47513
- output.push(indentedChild);
47566
+ children.forEach((child, index) => {
47567
+ var _a, _b;
47568
+ const childContent = (_b = (_a = h2.renderChild) == null ? void 0 : _a.call(h2, child, index + 1)) != null ? _b : h2.renderChildren([child]);
47569
+ if (childContent !== void 0 && childContent !== null) {
47570
+ const indentedChild = childContent.split("\n").map((line) => line ? h2.indent(line) : h2.indent("")).join("\n");
47571
+ output += child.type === "paragraph" ? `
47572
+
47573
+ ${indentedChild}` : `
47574
+ ${indentedChild}`;
47514
47575
  }
47515
47576
  });
47516
47577
  }
47517
- return output.join("\n");
47578
+ return output;
47518
47579
  }
47519
47580
 
47520
47581
  // src/MarkView.ts
@@ -58371,6 +58432,12 @@ ${renderedContent}
58371
58432
  parseMarkdown: (token, helpers) => {
58372
58433
  return helpers.applyMark("bold", helpers.parseInline(token.tokens || []));
58373
58434
  },
58435
+ markdownOptions: {
58436
+ htmlReopen: {
58437
+ open: "<strong>",
58438
+ close: "</strong>"
58439
+ }
58440
+ },
58374
58441
  renderMarkdown: (node, h) => {
58375
58442
  return `**${h.renderChildren(node)}**`;
58376
58443
  },
@@ -58488,6 +58555,12 @@ ${renderedContent}
58488
58555
  parseMarkdown: (token, helpers) => {
58489
58556
  return helpers.applyMark("italic", helpers.parseInline(token.tokens || []));
58490
58557
  },
58558
+ markdownOptions: {
58559
+ htmlReopen: {
58560
+ open: "<em>",
58561
+ close: "</em>"
58562
+ }
58563
+ },
58491
58564
  renderMarkdown: (node, h) => {
58492
58565
  return `*${h.renderChildren(node)}*`;
58493
58566
  },
@@ -60794,14 +60867,16 @@ ${renderedContent}
60794
60867
  },
60795
60868
  markdownTokenName: "list_item",
60796
60869
  parseMarkdown: (token, helpers) => {
60870
+ var _a;
60797
60871
  if (token.type !== "list_item") {
60798
60872
  return [];
60799
60873
  }
60874
+ const parseBlockChildren = (_a = helpers.parseBlockChildren) != null ? _a : helpers.parseChildren;
60800
60875
  let content = [];
60801
60876
  if (token.tokens && token.tokens.length > 0) {
60802
60877
  const hasParagraphTokens = token.tokens.some((t) => t.type === "paragraph");
60803
60878
  if (hasParagraphTokens) {
60804
- content = helpers.parseChildren(token.tokens);
60879
+ content = parseBlockChildren(token.tokens);
60805
60880
  } else {
60806
60881
  const firstToken = token.tokens[0];
60807
60882
  if (firstToken && firstToken.type === "text" && firstToken.tokens && firstToken.tokens.length > 0) {
@@ -60814,11 +60889,11 @@ ${renderedContent}
60814
60889
  ];
60815
60890
  if (token.tokens.length > 1) {
60816
60891
  const remainingTokens = token.tokens.slice(1);
60817
- const additionalContent = helpers.parseChildren(remainingTokens);
60892
+ const additionalContent = parseBlockChildren(remainingTokens);
60818
60893
  content.push(...additionalContent);
60819
60894
  }
60820
60895
  } else {
60821
- content = helpers.parseChildren(token.tokens);
60896
+ content = parseBlockChildren(token.tokens);
60822
60897
  }
60823
60898
  }
60824
60899
  }
@@ -62327,13 +62402,16 @@ ${nextLine.slice(indentLevel + 2)}`;
62327
62402
  }
62328
62403
  return helpers.createNode("paragraph", void 0, content);
62329
62404
  },
62330
- renderMarkdown: (node, h) => {
62405
+ renderMarkdown: (node, h, ctx) => {
62406
+ var _a, _b;
62331
62407
  if (!node) {
62332
62408
  return "";
62333
62409
  }
62334
62410
  const content = Array.isArray(node.content) ? node.content : [];
62335
62411
  if (content.length === 0) {
62336
- return EMPTY_PARAGRAPH_MARKDOWN;
62412
+ const previousContent = Array.isArray((_a = ctx == null ? void 0 : ctx.previousNode) == null ? void 0 : _a.content) ? ctx.previousNode.content : [];
62413
+ const previousNodeIsEmptyParagraph = ((_b = ctx == null ? void 0 : ctx.previousNode) == null ? void 0 : _b.type) === "paragraph" && previousContent.length === 0;
62414
+ return previousNodeIsEmptyParagraph ? EMPTY_PARAGRAPH_MARKDOWN : "";
62337
62415
  }
62338
62416
  return h.renderChildren(content);
62339
62417
  },
@@ -62551,7 +62629,7 @@ ${nextLine.slice(indentLevel + 2)}`;
62551
62629
  */
62552
62630
  static valid($pos) {
62553
62631
  let parent = $pos.parent;
62554
- if (parent.isTextblock || !closedBefore($pos) || !closedAfter($pos))
62632
+ if (parent.inlineContent || !closedBefore($pos) || !closedAfter($pos))
62555
62633
  return false;
62556
62634
  let override = parent.type.spec.allowGapCursor;
62557
62635
  if (override != null)
@@ -63580,6 +63658,9 @@ ${nextLine.slice(indentLevel + 2)}`;
63580
63658
  doc.descendants((node, pos) => {
63581
63659
  const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;
63582
63660
  const isEmpty = !node.isLeaf && isNodeEmpty(node);
63661
+ if (!node.type.isTextblock) {
63662
+ return this.options.includeChildren;
63663
+ }
63583
63664
  if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {
63584
63665
  const classes = [this.options.emptyNodeClass];
63585
63666
  if (isEmptyDoc) {
@@ -66371,6 +66452,7 @@ ${nextLine.slice(indentLevel + 2)}`;
66371
66452
  aria-roledescription="${x => x.ariaRoledescription}"
66372
66453
  ${ref('control')}
66373
66454
  >
66455
+ <div class="icon-background"></div>
66374
66456
  <div class="icon">
66375
66457
  <span class="current-label">${x => (x.selected ? popupIconCurrentLabel.getValueFor(x) : '')}</span>
66376
66458
  <div class="step-indicator"><slot name="step-indicator"><span aria-hidden="true">${x => x.stepInternals.position}</span></slot></div>
@@ -66469,28 +66551,7 @@ ${nextLine.slice(indentLevel + 2)}`;
66469
66551
  }
66470
66552
  `;
66471
66553
 
66472
- /**
66473
- * Observable class to subscribe to changes in the page's device pixel ratio
66474
- * Based on: https://frontendmasters.com/blog/obsessing-over-smooth-radial-gradient-disc-edges/#the-less-code-and-more-flexible-js-solution
66475
- */
66476
- class DevicePixelRatio {
66477
- constructor() {
66478
- const update = () => {
66479
- this.current = window.devicePixelRatio;
66480
- window
66481
- .matchMedia(`(resolution: ${this.current}x)`)
66482
- .addEventListener('change', update, { once: true });
66483
- };
66484
- update();
66485
- }
66486
- }
66487
- __decorate([
66488
- observable
66489
- ], DevicePixelRatio.prototype, "current", void 0);
66490
- const devicePixelRatio = new DevicePixelRatio();
66491
-
66492
66554
  const template$n = html `<ol><slot
66493
- style="--ni-private-device-pixel-ratio: ${() => devicePixelRatio.current};"
66494
66555
  name="step"
66495
66556
  ${slotted('steps')}
66496
66557
  ></slot></ol>`;
@@ -72380,7 +72441,7 @@ focus outline in that case.
72380
72441
  this.scrollElement = null;
72381
72442
  this.targetWindow = null;
72382
72443
  this.isScrolling = false;
72383
- this.currentScrollToIndex = null;
72444
+ this.scrollState = null;
72384
72445
  this.measurementsCache = [];
72385
72446
  this.itemSizeCache = /* @__PURE__ */ new Map();
72386
72447
  this.laneAssignments = /* @__PURE__ */ new Map();
@@ -72393,6 +72454,10 @@ focus outline in that case.
72393
72454
  this.scrollDirection = null;
72394
72455
  this.scrollAdjustments = 0;
72395
72456
  this.elementsCache = /* @__PURE__ */ new Map();
72457
+ this.now = () => {
72458
+ var _a, _b, _c;
72459
+ return ((_c = (_b = (_a = this.targetWindow) == null ? void 0 : _a.performance) == null ? void 0 : _b.now) == null ? void 0 : _c.call(_b)) ?? Date.now();
72460
+ };
72396
72461
  this.observer = /* @__PURE__ */ (() => {
72397
72462
  let _ro = null;
72398
72463
  const get = () => {
@@ -72405,7 +72470,18 @@ focus outline in that case.
72405
72470
  return _ro = new this.targetWindow.ResizeObserver((entries) => {
72406
72471
  entries.forEach((entry) => {
72407
72472
  const run = () => {
72408
- this._measureElement(entry.target, entry);
72473
+ const node = entry.target;
72474
+ const index = this.indexFromElement(node);
72475
+ if (!node.isConnected) {
72476
+ this.observer.unobserve(node);
72477
+ return;
72478
+ }
72479
+ if (this.shouldMeasureDuringScroll(index)) {
72480
+ this.resizeItem(
72481
+ index,
72482
+ this.options.measureElement(node, entry, this)
72483
+ );
72484
+ }
72409
72485
  };
72410
72486
  this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
72411
72487
  });
@@ -72490,6 +72566,11 @@ focus outline in that case.
72490
72566
  this.unsubs.filter(Boolean).forEach((d) => d());
72491
72567
  this.unsubs = [];
72492
72568
  this.observer.disconnect();
72569
+ if (this.rafId != null && this.targetWindow) {
72570
+ this.targetWindow.cancelAnimationFrame(this.rafId);
72571
+ this.rafId = null;
72572
+ }
72573
+ this.scrollState = null;
72493
72574
  this.scrollElement = null;
72494
72575
  this.targetWindow = null;
72495
72576
  };
@@ -72528,6 +72609,9 @@ focus outline in that case.
72528
72609
  this.scrollDirection = isScrolling ? this.getScrollOffset() < offset ? "forward" : "backward" : null;
72529
72610
  this.scrollOffset = offset;
72530
72611
  this.isScrolling = isScrolling;
72612
+ if (this.scrollState) {
72613
+ this.scheduleScrollReconcile();
72614
+ }
72531
72615
  this.maybeNotify();
72532
72616
  })
72533
72617
  );
@@ -72537,6 +72621,7 @@ focus outline in that case.
72537
72621
  });
72538
72622
  }
72539
72623
  };
72624
+ this.rafId = null;
72540
72625
  this.getSize = () => {
72541
72626
  if (!this.options.enabled) {
72542
72627
  this.scrollRect = null;
@@ -72755,13 +72840,38 @@ focus outline in that case.
72755
72840
  }
72756
72841
  return parseInt(indexStr, 10);
72757
72842
  };
72758
- this._measureElement = (node, entry) => {
72759
- const index = this.indexFromElement(node);
72760
- const item = this.measurementsCache[index];
72761
- if (!item) {
72843
+ this.shouldMeasureDuringScroll = (index) => {
72844
+ var _a;
72845
+ if (!this.scrollState || this.scrollState.behavior !== "smooth") {
72846
+ return true;
72847
+ }
72848
+ const scrollIndex = this.scrollState.index ?? ((_a = this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)) == null ? void 0 : _a.index);
72849
+ if (scrollIndex !== void 0 && this.range) {
72850
+ const bufferSize = Math.max(
72851
+ this.options.overscan,
72852
+ Math.ceil((this.range.endIndex - this.range.startIndex) / 2)
72853
+ );
72854
+ const minIndex = Math.max(0, scrollIndex - bufferSize);
72855
+ const maxIndex = Math.min(
72856
+ this.options.count - 1,
72857
+ scrollIndex + bufferSize
72858
+ );
72859
+ return index >= minIndex && index <= maxIndex;
72860
+ }
72861
+ return true;
72862
+ };
72863
+ this.measureElement = (node) => {
72864
+ if (!node) {
72865
+ this.elementsCache.forEach((cached, key2) => {
72866
+ if (!cached.isConnected) {
72867
+ this.observer.unobserve(cached);
72868
+ this.elementsCache.delete(key2);
72869
+ }
72870
+ });
72762
72871
  return;
72763
72872
  }
72764
- const key = item.key;
72873
+ const index = this.indexFromElement(node);
72874
+ const key = this.options.getItemKey(index);
72765
72875
  const prevNode = this.elementsCache.get(key);
72766
72876
  if (prevNode !== node) {
72767
72877
  if (prevNode) {
@@ -72770,19 +72880,18 @@ focus outline in that case.
72770
72880
  this.observer.observe(node);
72771
72881
  this.elementsCache.set(key, node);
72772
72882
  }
72773
- if (node.isConnected) {
72774
- this.resizeItem(index, this.options.measureElement(node, entry, this));
72883
+ if ((!this.isScrolling || this.scrollState) && this.shouldMeasureDuringScroll(index)) {
72884
+ this.resizeItem(index, this.options.measureElement(node, void 0, this));
72775
72885
  }
72776
72886
  };
72777
72887
  this.resizeItem = (index, size) => {
72888
+ var _a;
72778
72889
  const item = this.measurementsCache[index];
72779
- if (!item) {
72780
- return;
72781
- }
72890
+ if (!item) return;
72782
72891
  const itemSize = this.itemSizeCache.get(item.key) ?? item.size;
72783
72892
  const delta = size - itemSize;
72784
72893
  if (delta !== 0) {
72785
- if (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this) : item.start < this.getScrollOffset() + this.scrollAdjustments) {
72894
+ if (((_a = this.scrollState) == null ? void 0 : _a.behavior) !== "smooth" && (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this) : item.start < this.getScrollOffset() + this.scrollAdjustments)) {
72786
72895
  if (this.options.debug) {
72787
72896
  console.info("correction", delta);
72788
72897
  }
@@ -72796,18 +72905,6 @@ focus outline in that case.
72796
72905
  this.notify(false);
72797
72906
  }
72798
72907
  };
72799
- this.measureElement = (node) => {
72800
- if (!node) {
72801
- this.elementsCache.forEach((cached, key) => {
72802
- if (!cached.isConnected) {
72803
- this.observer.unobserve(cached);
72804
- this.elementsCache.delete(key);
72805
- }
72806
- });
72807
- return;
72808
- }
72809
- this._measureElement(node, void 0);
72810
- };
72811
72908
  this.getVirtualItems = memo(
72812
72909
  () => [this.getVirtualIndexes(), this.getMeasurements()],
72813
72910
  (indexes, measurements) => {
@@ -72864,12 +72961,10 @@ focus outline in that case.
72864
72961
  };
72865
72962
  this.getOffsetForIndex = (index, align = "auto") => {
72866
72963
  index = Math.max(0, Math.min(index, this.options.count - 1));
72867
- const item = this.measurementsCache[index];
72868
- if (!item) {
72869
- return void 0;
72870
- }
72871
72964
  const size = this.getSize();
72872
72965
  const scrollOffset = this.getScrollOffset();
72966
+ const item = this.measurementsCache[index];
72967
+ if (!item) return;
72873
72968
  if (align === "auto") {
72874
72969
  if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {
72875
72970
  align = "end";
@@ -72888,85 +72983,55 @@ focus outline in that case.
72888
72983
  align
72889
72984
  ];
72890
72985
  };
72891
- this.isDynamicMode = () => this.elementsCache.size > 0;
72892
- this.scrollToOffset = (toOffset, { align = "start", behavior } = {}) => {
72893
- if (behavior === "smooth" && this.isDynamicMode()) {
72894
- console.warn(
72895
- "The `smooth` scroll behavior is not fully supported with dynamic size."
72896
- );
72897
- }
72898
- this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {
72899
- adjustments: void 0,
72900
- behavior
72901
- });
72986
+ this.scrollToOffset = (toOffset, { align = "start", behavior = "auto" } = {}) => {
72987
+ const offset = this.getOffsetForAlignment(toOffset, align);
72988
+ const now = this.now();
72989
+ this.scrollState = {
72990
+ index: null,
72991
+ align,
72992
+ behavior,
72993
+ startedAt: now,
72994
+ lastTargetOffset: offset,
72995
+ stableFrames: 0
72996
+ };
72997
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
72998
+ this.scheduleScrollReconcile();
72902
72999
  };
72903
- this.scrollToIndex = (index, { align: initialAlign = "auto", behavior } = {}) => {
72904
- if (behavior === "smooth" && this.isDynamicMode()) {
72905
- console.warn(
72906
- "The `smooth` scroll behavior is not fully supported with dynamic size."
72907
- );
72908
- }
73000
+ this.scrollToIndex = (index, {
73001
+ align: initialAlign = "auto",
73002
+ behavior = "auto"
73003
+ } = {}) => {
72909
73004
  index = Math.max(0, Math.min(index, this.options.count - 1));
72910
- this.currentScrollToIndex = index;
72911
- let attempts = 0;
72912
- const maxAttempts = 10;
72913
- const tryScroll = (currentAlign) => {
72914
- if (!this.targetWindow) return;
72915
- const offsetInfo = this.getOffsetForIndex(index, currentAlign);
72916
- if (!offsetInfo) {
72917
- console.warn("Failed to get offset for index:", index);
72918
- return;
72919
- }
72920
- const [offset, align] = offsetInfo;
72921
- this._scrollToOffset(offset, { adjustments: void 0, behavior });
72922
- this.targetWindow.requestAnimationFrame(() => {
72923
- if (!this.targetWindow) return;
72924
- const verify = () => {
72925
- if (this.currentScrollToIndex !== index) return;
72926
- const currentOffset = this.getScrollOffset();
72927
- const afterInfo = this.getOffsetForIndex(index, align);
72928
- if (!afterInfo) {
72929
- console.warn("Failed to get offset for index:", index);
72930
- return;
72931
- }
72932
- if (!approxEqual(afterInfo[0], currentOffset)) {
72933
- scheduleRetry(align);
72934
- }
72935
- };
72936
- if (this.isDynamicMode()) {
72937
- this.targetWindow.requestAnimationFrame(verify);
72938
- } else {
72939
- verify();
72940
- }
72941
- });
72942
- };
72943
- const scheduleRetry = (align) => {
72944
- if (!this.targetWindow) return;
72945
- if (this.currentScrollToIndex !== index) return;
72946
- attempts++;
72947
- if (attempts < maxAttempts) {
72948
- if (this.options.debug) {
72949
- console.info("Schedule retry", attempts, maxAttempts);
72950
- }
72951
- this.targetWindow.requestAnimationFrame(() => tryScroll(align));
72952
- } else {
72953
- console.warn(
72954
- `Failed to scroll to index ${index} after ${maxAttempts} attempts.`
72955
- );
72956
- }
73005
+ const offsetInfo = this.getOffsetForIndex(index, initialAlign);
73006
+ if (!offsetInfo) {
73007
+ return;
73008
+ }
73009
+ const [offset, align] = offsetInfo;
73010
+ const now = this.now();
73011
+ this.scrollState = {
73012
+ index,
73013
+ align,
73014
+ behavior,
73015
+ startedAt: now,
73016
+ lastTargetOffset: offset,
73017
+ stableFrames: 0
72957
73018
  };
72958
- tryScroll(initialAlign);
73019
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
73020
+ this.scheduleScrollReconcile();
72959
73021
  };
72960
- this.scrollBy = (delta, { behavior } = {}) => {
72961
- if (behavior === "smooth" && this.isDynamicMode()) {
72962
- console.warn(
72963
- "The `smooth` scroll behavior is not fully supported with dynamic size."
72964
- );
72965
- }
72966
- this._scrollToOffset(this.getScrollOffset() + delta, {
72967
- adjustments: void 0,
72968
- behavior
72969
- });
73022
+ this.scrollBy = (delta, { behavior = "auto" } = {}) => {
73023
+ const offset = this.getScrollOffset() + delta;
73024
+ const now = this.now();
73025
+ this.scrollState = {
73026
+ index: null,
73027
+ align: "start",
73028
+ behavior,
73029
+ startedAt: now,
73030
+ lastTargetOffset: offset,
73031
+ stableFrames: 0
73032
+ };
73033
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
73034
+ this.scheduleScrollReconcile();
72970
73035
  };
72971
73036
  this.getTotalSize = () => {
72972
73037
  var _a;
@@ -73006,6 +73071,49 @@ focus outline in that case.
73006
73071
  };
73007
73072
  this.setOptions(opts);
73008
73073
  }
73074
+ scheduleScrollReconcile() {
73075
+ if (!this.targetWindow) {
73076
+ this.scrollState = null;
73077
+ return;
73078
+ }
73079
+ if (this.rafId != null) return;
73080
+ this.rafId = this.targetWindow.requestAnimationFrame(() => {
73081
+ this.rafId = null;
73082
+ this.reconcileScroll();
73083
+ });
73084
+ }
73085
+ reconcileScroll() {
73086
+ if (!this.scrollState) return;
73087
+ const el = this.scrollElement;
73088
+ if (!el) return;
73089
+ const MAX_RECONCILE_MS = 5e3;
73090
+ if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {
73091
+ this.scrollState = null;
73092
+ return;
73093
+ }
73094
+ const offsetInfo = this.scrollState.index != null ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align) : void 0;
73095
+ const targetOffset = offsetInfo ? offsetInfo[0] : this.scrollState.lastTargetOffset;
73096
+ const STABLE_FRAMES = 1;
73097
+ const targetChanged = targetOffset !== this.scrollState.lastTargetOffset;
73098
+ if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {
73099
+ this.scrollState.stableFrames++;
73100
+ if (this.scrollState.stableFrames >= STABLE_FRAMES) {
73101
+ this.scrollState = null;
73102
+ return;
73103
+ }
73104
+ } else {
73105
+ this.scrollState.stableFrames = 0;
73106
+ if (targetChanged) {
73107
+ this.scrollState.lastTargetOffset = targetOffset;
73108
+ this.scrollState.behavior = "auto";
73109
+ this._scrollToOffset(targetOffset, {
73110
+ adjustments: void 0,
73111
+ behavior: "auto"
73112
+ });
73113
+ }
73114
+ }
73115
+ this.scheduleScrollReconcile();
73116
+ }
73009
73117
  };
73010
73118
  const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
73011
73119
  while (low <= high) {