@ni/nimble-components 35.5.1 → 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.
@@ -13466,6 +13466,12 @@
13466
13466
  * @internal
13467
13467
  */
13468
13468
  this.direction = Direction.ltr;
13469
+ /**
13470
+ * The collection of focusable toolbar controls.
13471
+ *
13472
+ * @internal
13473
+ */
13474
+ this.focusableElements = [];
13469
13475
  /**
13470
13476
  * The orientation of the toolbar.
13471
13477
  *
@@ -13486,7 +13492,7 @@
13486
13492
  }
13487
13493
  set activeIndex(value) {
13488
13494
  if (this.$fastController.isConnected) {
13489
- this._activeIndex = limit(0, this.focusableElements.length - 1, value);
13495
+ this._activeIndex = limit(0, this.focusableElements.length > 0 ? this.focusableElements.length - 1 : 0, value);
13490
13496
  Observable.notify(this, "activeIndex");
13491
13497
  }
13492
13498
  }
@@ -13501,7 +13507,7 @@
13501
13507
  * @internal
13502
13508
  */
13503
13509
  mouseDownHandler(e) {
13504
- const activeIndex = this.focusableElements?.findIndex(x => x.contains(e.target));
13510
+ const activeIndex = this.focusableElements.findIndex(x => x.contains(e.target));
13505
13511
  if (activeIndex > -1 && this.activeIndex !== activeIndex) {
13506
13512
  this.setFocusedElement(activeIndex);
13507
13513
  }
@@ -13558,7 +13564,7 @@
13558
13564
  return !e.target.closest("[role=radiogroup]");
13559
13565
  }
13560
13566
  const nextIndex = this.activeIndex + incrementer;
13561
- if (this.focusableElements[nextIndex]) {
13567
+ if (this.focusableElements.length > 0 && this.focusableElements[nextIndex]) {
13562
13568
  e.preventDefault();
13563
13569
  }
13564
13570
  this.setFocusedElement(nextIndex);
@@ -13581,7 +13587,7 @@
13581
13587
  * @internal
13582
13588
  */
13583
13589
  reduceFocusableElements() {
13584
- const previousFocusedElement = this.focusableElements?.[this.activeIndex];
13590
+ const previousFocusedElement = this.focusableElements[this.activeIndex];
13585
13591
  this.focusableElements = this.allSlottedItems.reduce(Toolbar.reduceFocusableItems, []);
13586
13592
  // If the previously active item is still focusable, adjust the active index to the
13587
13593
  // index of that item.
@@ -13598,7 +13604,8 @@
13598
13604
  setFocusedElement(activeIndex = this.activeIndex) {
13599
13605
  this.activeIndex = activeIndex;
13600
13606
  this.setFocusableElements();
13601
- if (this.focusableElements[this.activeIndex] &&
13607
+ if (this.focusableElements.length > 0 &&
13608
+ this.focusableElements[this.activeIndex] &&
13602
13609
  // Don't focus the toolbar element if some event handlers moved
13603
13610
  // the focus on another element in the page.
13604
13611
  this.contains(getRootActiveElement(this))) {
@@ -17705,13 +17712,14 @@
17705
17712
  background-color: transparent;
17706
17713
  cursor: pointer;
17707
17714
  outline: none;
17708
- --ni-private-step-icon-background-full-size: 100% 100%;
17709
- ${'' /* 6px = (2px icon border + 1px inset) * 2 sides */}
17710
- --ni-private-step-icon-background-inset-size: calc(100% - 6px) calc(100% - 6px);
17711
- --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);
17712
17719
 
17713
17720
  --ni-private-step-icon-color: ${buttonLabelFontColor};
17714
17721
  --ni-private-step-icon-border-color: transparent;
17722
+ --ni-private-step-icon-border-width: 1px;
17715
17723
  --ni-private-step-icon-background-color: rgba(${borderRgbPartialColor}, 0.1);
17716
17724
  --ni-private-step-icon-background-size: var(--ni-private-step-icon-background-full-size);
17717
17725
  --ni-private-step-icon-outline-inset-color: transparent;
@@ -17814,6 +17822,20 @@ Defines an interaction area clip-path that leaves out the severity text so it is
17814
17822
  --ni-private-step-line-color: ${borderHoverColor};
17815
17823
  }
17816
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
+
17817
17839
  .icon {
17818
17840
  grid-area: icon;
17819
17841
  display: inline-flex;
@@ -17826,31 +17848,16 @@ Defines an interaction area clip-path that leaves out the severity text so it is
17826
17848
  font: ${buttonLabelFont};
17827
17849
  color: var(--ni-private-step-icon-color);
17828
17850
  ${iconColor.cssCustomProperty}: var(--ni-private-step-icon-color);
17829
- border-style: solid;
17851
+ border: none;
17830
17852
  border-radius: 100%;
17831
- border-color: var(--ni-private-step-icon-border-color);
17832
- border-width: 1px;
17833
- background-image: radial-gradient(
17834
- closest-side,
17835
- ${'' /* Workaround to prevent aliasing on radial-gradient boundaries, see:
17836
- https://frontendmasters.com/blog/obsessing-over-smooth-radial-gradient-disc-edges
17837
- */}
17838
- var(--ni-private-step-icon-background-color) calc(100% - 1px/var(--ni-private-device-pixel-ratio, 1)),
17839
- transparent 100%
17840
- );
17841
- background-origin: border-box;
17842
- background-size: var(--ni-private-step-icon-background-size);
17843
- background-repeat: no-repeat;
17844
- 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);
17845
17854
  position: relative;
17846
17855
  transition:
17847
- border-color ${smallDelay} ease-in-out,
17848
- border-width ${smallDelay} ease-in-out,
17849
- background-size ${smallDelay} ease-out;
17856
+ box-shadow ${smallDelay} ease-in-out;
17850
17857
  }
17851
17858
 
17852
17859
  :host([selected]) .icon {
17853
- border-width: 2px;
17860
+ --ni-private-step-icon-border-width: 2px;
17854
17861
  }
17855
17862
 
17856
17863
  .icon::before {
@@ -17863,10 +17870,9 @@ Defines an interaction area clip-path that leaves out the severity text so it is
17863
17870
  outline-style: solid;
17864
17871
  outline-width: 0px;
17865
17872
  outline-offset: 0px;
17866
- border: 1px solid transparent;
17873
+ border: none;
17867
17874
  border-radius: 100%;
17868
17875
  color: transparent;
17869
- background-clip: border-box;
17870
17876
  transition:
17871
17877
  outline-color ${smallDelay} ease-in-out,
17872
17878
  outline-width ${smallDelay} ease-in-out,
@@ -18018,7 +18024,7 @@ Defines an interaction area clip-path that leaves out the severity text so it is
18018
18024
  }
18019
18025
 
18020
18026
  .control:hover .icon {
18021
- border-width: 2px;
18027
+ --ni-private-step-icon-border-width: 2px;
18022
18028
  }
18023
18029
 
18024
18030
  .control:hover .line {
@@ -18069,12 +18075,13 @@ Defines an interaction area clip-path that leaves out the severity text so it is
18069
18075
  }
18070
18076
 
18071
18077
  .control${focusVisible} .icon {
18072
- border-width: 2px;
18078
+ --ni-private-step-icon-border-width: 2px;
18073
18079
  }
18074
18080
 
18075
18081
  .control${focusVisible} .icon::before {
18076
18082
  outline-width: ${borderWidth};
18077
- outline-offset: -2px;
18083
+ ${'' /* -1px control to outline edge -2px focus border -1px inset gap */}
18084
+ outline-offset: -4px;
18078
18085
  }
18079
18086
 
18080
18087
  .control${focusVisible} .line {
@@ -18121,7 +18128,7 @@ Defines an interaction area clip-path that leaves out the severity text so it is
18121
18128
  }
18122
18129
 
18123
18130
  .control:active .icon {
18124
- border-width: 2px;
18131
+ --ni-private-step-icon-border-width: 2px;
18125
18132
  }
18126
18133
 
18127
18134
  .control:active .icon::before {
@@ -19455,6 +19462,7 @@ Defines an interaction area clip-path that leaves out the severity text so it is
19455
19462
  aria-roledescription="${x => x.ariaRoledescription}"
19456
19463
  ${ref('control')}
19457
19464
  >
19465
+ <div class="icon-background"></div>
19458
19466
  <div class="icon">
19459
19467
  <span class="current-label">${x => (x.selected ? popupIconCurrentLabel.getValueFor(x) : '')}</span>
19460
19468
  <div class="step-indicator"><slot name="step-indicator"><span aria-hidden="true">${x => x.stepInternals.position}</span></slot></div>
@@ -40784,8 +40792,13 @@ so this becomes the fallback color for the slot */ ''}
40784
40792
  for (let node of added)
40785
40793
  if (node.nodeName == "BR" && node.parentNode) {
40786
40794
  let after = node.nextSibling;
40787
- if (after && after.nodeType == 1 && after.contentEditable == "false")
40788
- 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
+ }
40789
40802
  }
40790
40803
  }
40791
40804
  else if (gecko && added.length) {
@@ -41623,12 +41636,12 @@ so this becomes the fallback color for the slot */ ''}
41623
41636
  }
41624
41637
  updateDraggedNode(dragging, prev) {
41625
41638
  let sel = dragging.node, found = -1;
41626
- 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) {
41627
41640
  found = sel.from;
41628
41641
  }
41629
41642
  else {
41630
41643
  let movedPos = sel.from + (this.state.doc.content.size - prev.doc.content.size);
41631
- 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);
41632
41645
  if (moved == sel.node)
41633
41646
  found = movedPos;
41634
41647
  }
@@ -43500,6 +43513,67 @@ so this becomes the fallback color for the slot */ ''}
43500
43513
  }
43501
43514
 
43502
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
+ }
43503
43577
  function mergeAttributes(...objects) {
43504
43578
  return objects.filter((item) => !!item).reduce((items, item) => {
43505
43579
  const mergedAttributes = { ...items };
@@ -43515,17 +43589,7 @@ so this becomes the fallback color for the slot */ ''}
43515
43589
  const insertClasses = valueClasses.filter((valueClass) => !existingClasses.includes(valueClass));
43516
43590
  mergedAttributes[key] = [...existingClasses, ...insertClasses].join(" ");
43517
43591
  } else if (key === "style") {
43518
- const newStyles = value ? value.split(";").map((style2) => style2.trim()).filter(Boolean) : [];
43519
- const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(";").map((style2) => style2.trim()).filter(Boolean) : [];
43520
- const styleMap = /* @__PURE__ */ new Map();
43521
- existingStyles.forEach((style2) => {
43522
- const [property, val] = style2.split(":").map((part) => part.trim());
43523
- styleMap.set(property, val);
43524
- });
43525
- newStyles.forEach((style2) => {
43526
- const [property, val] = style2.split(":").map((part) => part.trim());
43527
- styleMap.set(property, val);
43528
- });
43592
+ const styleMap = new Map([...parseStyleEntries(mergedAttributes[key]), ...parseStyleEntries(value)]);
43529
43593
  mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join("; ");
43530
43594
  } else {
43531
43595
  mergedAttributes[key] = value;
@@ -44112,7 +44176,7 @@ so this becomes the fallback color for the slot */ ''}
44112
44176
  return true;
44113
44177
  }
44114
44178
  if (node.isText) {
44115
- return /^\s*$/m.test((_a = node.text) != null ? _a : "");
44179
+ return !/\S/.test((_a = node.text) != null ? _a : "");
44116
44180
  }
44117
44181
  }
44118
44182
  if (node.isText) {
@@ -47497,17 +47561,21 @@ ${renderedContent}
47497
47561
  const prefix = typeof prefixOrGenerator === "function" ? prefixOrGenerator(ctx) : prefixOrGenerator;
47498
47562
  const [content, ...children] = node.content;
47499
47563
  const mainContent = h2.renderChildren([content]);
47500
- const output = [`${prefix}${mainContent}`];
47564
+ let output = `${prefix}${mainContent}`;
47501
47565
  if (children && children.length > 0) {
47502
- children.forEach((child) => {
47503
- const childContent = h2.renderChildren([child]);
47504
- if (childContent) {
47505
- const indentedChild = childContent.split("\n").map((line) => line ? h2.indent(line) : "").join("\n");
47506
- 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}`;
47507
47575
  }
47508
47576
  });
47509
47577
  }
47510
- return output.join("\n");
47578
+ return output;
47511
47579
  }
47512
47580
 
47513
47581
  // src/MarkView.ts
@@ -58364,6 +58432,12 @@ ${renderedContent}
58364
58432
  parseMarkdown: (token, helpers) => {
58365
58433
  return helpers.applyMark("bold", helpers.parseInline(token.tokens || []));
58366
58434
  },
58435
+ markdownOptions: {
58436
+ htmlReopen: {
58437
+ open: "<strong>",
58438
+ close: "</strong>"
58439
+ }
58440
+ },
58367
58441
  renderMarkdown: (node, h) => {
58368
58442
  return `**${h.renderChildren(node)}**`;
58369
58443
  },
@@ -58481,6 +58555,12 @@ ${renderedContent}
58481
58555
  parseMarkdown: (token, helpers) => {
58482
58556
  return helpers.applyMark("italic", helpers.parseInline(token.tokens || []));
58483
58557
  },
58558
+ markdownOptions: {
58559
+ htmlReopen: {
58560
+ open: "<em>",
58561
+ close: "</em>"
58562
+ }
58563
+ },
58484
58564
  renderMarkdown: (node, h) => {
58485
58565
  return `*${h.renderChildren(node)}*`;
58486
58566
  },
@@ -60787,14 +60867,16 @@ ${renderedContent}
60787
60867
  },
60788
60868
  markdownTokenName: "list_item",
60789
60869
  parseMarkdown: (token, helpers) => {
60870
+ var _a;
60790
60871
  if (token.type !== "list_item") {
60791
60872
  return [];
60792
60873
  }
60874
+ const parseBlockChildren = (_a = helpers.parseBlockChildren) != null ? _a : helpers.parseChildren;
60793
60875
  let content = [];
60794
60876
  if (token.tokens && token.tokens.length > 0) {
60795
60877
  const hasParagraphTokens = token.tokens.some((t) => t.type === "paragraph");
60796
60878
  if (hasParagraphTokens) {
60797
- content = helpers.parseChildren(token.tokens);
60879
+ content = parseBlockChildren(token.tokens);
60798
60880
  } else {
60799
60881
  const firstToken = token.tokens[0];
60800
60882
  if (firstToken && firstToken.type === "text" && firstToken.tokens && firstToken.tokens.length > 0) {
@@ -60807,11 +60889,11 @@ ${renderedContent}
60807
60889
  ];
60808
60890
  if (token.tokens.length > 1) {
60809
60891
  const remainingTokens = token.tokens.slice(1);
60810
- const additionalContent = helpers.parseChildren(remainingTokens);
60892
+ const additionalContent = parseBlockChildren(remainingTokens);
60811
60893
  content.push(...additionalContent);
60812
60894
  }
60813
60895
  } else {
60814
- content = helpers.parseChildren(token.tokens);
60896
+ content = parseBlockChildren(token.tokens);
60815
60897
  }
60816
60898
  }
60817
60899
  }
@@ -62320,13 +62402,16 @@ ${nextLine.slice(indentLevel + 2)}`;
62320
62402
  }
62321
62403
  return helpers.createNode("paragraph", void 0, content);
62322
62404
  },
62323
- renderMarkdown: (node, h) => {
62405
+ renderMarkdown: (node, h, ctx) => {
62406
+ var _a, _b;
62324
62407
  if (!node) {
62325
62408
  return "";
62326
62409
  }
62327
62410
  const content = Array.isArray(node.content) ? node.content : [];
62328
62411
  if (content.length === 0) {
62329
- 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 : "";
62330
62415
  }
62331
62416
  return h.renderChildren(content);
62332
62417
  },
@@ -62544,7 +62629,7 @@ ${nextLine.slice(indentLevel + 2)}`;
62544
62629
  */
62545
62630
  static valid($pos) {
62546
62631
  let parent = $pos.parent;
62547
- if (parent.isTextblock || !closedBefore($pos) || !closedAfter($pos))
62632
+ if (parent.inlineContent || !closedBefore($pos) || !closedAfter($pos))
62548
62633
  return false;
62549
62634
  let override = parent.type.spec.allowGapCursor;
62550
62635
  if (override != null)
@@ -63573,6 +63658,9 @@ ${nextLine.slice(indentLevel + 2)}`;
63573
63658
  doc.descendants((node, pos) => {
63574
63659
  const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;
63575
63660
  const isEmpty = !node.isLeaf && isNodeEmpty(node);
63661
+ if (!node.type.isTextblock) {
63662
+ return this.options.includeChildren;
63663
+ }
63576
63664
  if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {
63577
63665
  const classes = [this.options.emptyNodeClass];
63578
63666
  if (isEmptyDoc) {
@@ -66364,6 +66452,7 @@ ${nextLine.slice(indentLevel + 2)}`;
66364
66452
  aria-roledescription="${x => x.ariaRoledescription}"
66365
66453
  ${ref('control')}
66366
66454
  >
66455
+ <div class="icon-background"></div>
66367
66456
  <div class="icon">
66368
66457
  <span class="current-label">${x => (x.selected ? popupIconCurrentLabel.getValueFor(x) : '')}</span>
66369
66458
  <div class="step-indicator"><slot name="step-indicator"><span aria-hidden="true">${x => x.stepInternals.position}</span></slot></div>
@@ -66462,28 +66551,7 @@ ${nextLine.slice(indentLevel + 2)}`;
66462
66551
  }
66463
66552
  `;
66464
66553
 
66465
- /**
66466
- * Observable class to subscribe to changes in the page's device pixel ratio
66467
- * Based on: https://frontendmasters.com/blog/obsessing-over-smooth-radial-gradient-disc-edges/#the-less-code-and-more-flexible-js-solution
66468
- */
66469
- class DevicePixelRatio {
66470
- constructor() {
66471
- const update = () => {
66472
- this.current = window.devicePixelRatio;
66473
- window
66474
- .matchMedia(`(resolution: ${this.current}x)`)
66475
- .addEventListener('change', update, { once: true });
66476
- };
66477
- update();
66478
- }
66479
- }
66480
- __decorate([
66481
- observable
66482
- ], DevicePixelRatio.prototype, "current", void 0);
66483
- const devicePixelRatio = new DevicePixelRatio();
66484
-
66485
66554
  const template$n = html `<ol><slot
66486
- style="--ni-private-device-pixel-ratio: ${() => devicePixelRatio.current};"
66487
66555
  name="step"
66488
66556
  ${slotted('steps')}
66489
66557
  ></slot></ol>`;
@@ -72373,7 +72441,7 @@ focus outline in that case.
72373
72441
  this.scrollElement = null;
72374
72442
  this.targetWindow = null;
72375
72443
  this.isScrolling = false;
72376
- this.currentScrollToIndex = null;
72444
+ this.scrollState = null;
72377
72445
  this.measurementsCache = [];
72378
72446
  this.itemSizeCache = /* @__PURE__ */ new Map();
72379
72447
  this.laneAssignments = /* @__PURE__ */ new Map();
@@ -72386,6 +72454,10 @@ focus outline in that case.
72386
72454
  this.scrollDirection = null;
72387
72455
  this.scrollAdjustments = 0;
72388
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
+ };
72389
72461
  this.observer = /* @__PURE__ */ (() => {
72390
72462
  let _ro = null;
72391
72463
  const get = () => {
@@ -72398,7 +72470,18 @@ focus outline in that case.
72398
72470
  return _ro = new this.targetWindow.ResizeObserver((entries) => {
72399
72471
  entries.forEach((entry) => {
72400
72472
  const run = () => {
72401
- 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
+ }
72402
72485
  };
72403
72486
  this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
72404
72487
  });
@@ -72483,6 +72566,11 @@ focus outline in that case.
72483
72566
  this.unsubs.filter(Boolean).forEach((d) => d());
72484
72567
  this.unsubs = [];
72485
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;
72486
72574
  this.scrollElement = null;
72487
72575
  this.targetWindow = null;
72488
72576
  };
@@ -72521,6 +72609,9 @@ focus outline in that case.
72521
72609
  this.scrollDirection = isScrolling ? this.getScrollOffset() < offset ? "forward" : "backward" : null;
72522
72610
  this.scrollOffset = offset;
72523
72611
  this.isScrolling = isScrolling;
72612
+ if (this.scrollState) {
72613
+ this.scheduleScrollReconcile();
72614
+ }
72524
72615
  this.maybeNotify();
72525
72616
  })
72526
72617
  );
@@ -72530,6 +72621,7 @@ focus outline in that case.
72530
72621
  });
72531
72622
  }
72532
72623
  };
72624
+ this.rafId = null;
72533
72625
  this.getSize = () => {
72534
72626
  if (!this.options.enabled) {
72535
72627
  this.scrollRect = null;
@@ -72748,13 +72840,38 @@ focus outline in that case.
72748
72840
  }
72749
72841
  return parseInt(indexStr, 10);
72750
72842
  };
72751
- this._measureElement = (node, entry) => {
72752
- const index = this.indexFromElement(node);
72753
- const item = this.measurementsCache[index];
72754
- 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
+ });
72755
72871
  return;
72756
72872
  }
72757
- const key = item.key;
72873
+ const index = this.indexFromElement(node);
72874
+ const key = this.options.getItemKey(index);
72758
72875
  const prevNode = this.elementsCache.get(key);
72759
72876
  if (prevNode !== node) {
72760
72877
  if (prevNode) {
@@ -72763,19 +72880,18 @@ focus outline in that case.
72763
72880
  this.observer.observe(node);
72764
72881
  this.elementsCache.set(key, node);
72765
72882
  }
72766
- if (node.isConnected) {
72767
- 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));
72768
72885
  }
72769
72886
  };
72770
72887
  this.resizeItem = (index, size) => {
72888
+ var _a;
72771
72889
  const item = this.measurementsCache[index];
72772
- if (!item) {
72773
- return;
72774
- }
72890
+ if (!item) return;
72775
72891
  const itemSize = this.itemSizeCache.get(item.key) ?? item.size;
72776
72892
  const delta = size - itemSize;
72777
72893
  if (delta !== 0) {
72778
- 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)) {
72779
72895
  if (this.options.debug) {
72780
72896
  console.info("correction", delta);
72781
72897
  }
@@ -72789,18 +72905,6 @@ focus outline in that case.
72789
72905
  this.notify(false);
72790
72906
  }
72791
72907
  };
72792
- this.measureElement = (node) => {
72793
- if (!node) {
72794
- this.elementsCache.forEach((cached, key) => {
72795
- if (!cached.isConnected) {
72796
- this.observer.unobserve(cached);
72797
- this.elementsCache.delete(key);
72798
- }
72799
- });
72800
- return;
72801
- }
72802
- this._measureElement(node, void 0);
72803
- };
72804
72908
  this.getVirtualItems = memo(
72805
72909
  () => [this.getVirtualIndexes(), this.getMeasurements()],
72806
72910
  (indexes, measurements) => {
@@ -72857,12 +72961,10 @@ focus outline in that case.
72857
72961
  };
72858
72962
  this.getOffsetForIndex = (index, align = "auto") => {
72859
72963
  index = Math.max(0, Math.min(index, this.options.count - 1));
72860
- const item = this.measurementsCache[index];
72861
- if (!item) {
72862
- return void 0;
72863
- }
72864
72964
  const size = this.getSize();
72865
72965
  const scrollOffset = this.getScrollOffset();
72966
+ const item = this.measurementsCache[index];
72967
+ if (!item) return;
72866
72968
  if (align === "auto") {
72867
72969
  if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {
72868
72970
  align = "end";
@@ -72881,85 +72983,55 @@ focus outline in that case.
72881
72983
  align
72882
72984
  ];
72883
72985
  };
72884
- this.isDynamicMode = () => this.elementsCache.size > 0;
72885
- this.scrollToOffset = (toOffset, { align = "start", behavior } = {}) => {
72886
- if (behavior === "smooth" && this.isDynamicMode()) {
72887
- console.warn(
72888
- "The `smooth` scroll behavior is not fully supported with dynamic size."
72889
- );
72890
- }
72891
- this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {
72892
- adjustments: void 0,
72893
- behavior
72894
- });
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();
72895
72999
  };
72896
- this.scrollToIndex = (index, { align: initialAlign = "auto", behavior } = {}) => {
72897
- if (behavior === "smooth" && this.isDynamicMode()) {
72898
- console.warn(
72899
- "The `smooth` scroll behavior is not fully supported with dynamic size."
72900
- );
72901
- }
73000
+ this.scrollToIndex = (index, {
73001
+ align: initialAlign = "auto",
73002
+ behavior = "auto"
73003
+ } = {}) => {
72902
73004
  index = Math.max(0, Math.min(index, this.options.count - 1));
72903
- this.currentScrollToIndex = index;
72904
- let attempts = 0;
72905
- const maxAttempts = 10;
72906
- const tryScroll = (currentAlign) => {
72907
- if (!this.targetWindow) return;
72908
- const offsetInfo = this.getOffsetForIndex(index, currentAlign);
72909
- if (!offsetInfo) {
72910
- console.warn("Failed to get offset for index:", index);
72911
- return;
72912
- }
72913
- const [offset, align] = offsetInfo;
72914
- this._scrollToOffset(offset, { adjustments: void 0, behavior });
72915
- this.targetWindow.requestAnimationFrame(() => {
72916
- if (!this.targetWindow) return;
72917
- const verify = () => {
72918
- if (this.currentScrollToIndex !== index) return;
72919
- const currentOffset = this.getScrollOffset();
72920
- const afterInfo = this.getOffsetForIndex(index, align);
72921
- if (!afterInfo) {
72922
- console.warn("Failed to get offset for index:", index);
72923
- return;
72924
- }
72925
- if (!approxEqual(afterInfo[0], currentOffset)) {
72926
- scheduleRetry(align);
72927
- }
72928
- };
72929
- if (this.isDynamicMode()) {
72930
- this.targetWindow.requestAnimationFrame(verify);
72931
- } else {
72932
- verify();
72933
- }
72934
- });
72935
- };
72936
- const scheduleRetry = (align) => {
72937
- if (!this.targetWindow) return;
72938
- if (this.currentScrollToIndex !== index) return;
72939
- attempts++;
72940
- if (attempts < maxAttempts) {
72941
- if (this.options.debug) {
72942
- console.info("Schedule retry", attempts, maxAttempts);
72943
- }
72944
- this.targetWindow.requestAnimationFrame(() => tryScroll(align));
72945
- } else {
72946
- console.warn(
72947
- `Failed to scroll to index ${index} after ${maxAttempts} attempts.`
72948
- );
72949
- }
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
72950
73018
  };
72951
- tryScroll(initialAlign);
73019
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
73020
+ this.scheduleScrollReconcile();
72952
73021
  };
72953
- this.scrollBy = (delta, { behavior } = {}) => {
72954
- if (behavior === "smooth" && this.isDynamicMode()) {
72955
- console.warn(
72956
- "The `smooth` scroll behavior is not fully supported with dynamic size."
72957
- );
72958
- }
72959
- this._scrollToOffset(this.getScrollOffset() + delta, {
72960
- adjustments: void 0,
72961
- behavior
72962
- });
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();
72963
73035
  };
72964
73036
  this.getTotalSize = () => {
72965
73037
  var _a;
@@ -72999,6 +73071,49 @@ focus outline in that case.
72999
73071
  };
73000
73072
  this.setOptions(opts);
73001
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
+ }
73002
73117
  };
73003
73118
  const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
73004
73119
  while (low <= high) {