@ni/ok-components 0.3.3 → 0.3.4

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.
@@ -40793,8 +40793,13 @@ so this becomes the fallback color for the slot */ ''}
40793
40793
  for (let node of added)
40794
40794
  if (node.nodeName == "BR" && node.parentNode) {
40795
40795
  let after = node.nextSibling;
40796
- if (after && after.nodeType == 1 && after.contentEditable == "false")
40797
- node.parentNode.removeChild(node);
40796
+ while (after && after.nodeType == 1) {
40797
+ if (after.contentEditable == "false") {
40798
+ node.parentNode.removeChild(node);
40799
+ break;
40800
+ }
40801
+ after = after.firstChild;
40802
+ }
40798
40803
  }
40799
40804
  }
40800
40805
  else if (gecko && added.length) {
@@ -41632,12 +41637,12 @@ so this becomes the fallback color for the slot */ ''}
41632
41637
  }
41633
41638
  updateDraggedNode(dragging, prev) {
41634
41639
  let sel = dragging.node, found = -1;
41635
- if (this.state.doc.nodeAt(sel.from) == sel.node) {
41640
+ if (sel.from < this.state.doc.content.size && this.state.doc.nodeAt(sel.from) == sel.node) {
41636
41641
  found = sel.from;
41637
41642
  }
41638
41643
  else {
41639
41644
  let movedPos = sel.from + (this.state.doc.content.size - prev.doc.content.size);
41640
- let moved = movedPos > 0 && this.state.doc.nodeAt(movedPos);
41645
+ let moved = movedPos > 0 && movedPos < this.state.doc.content.size && this.state.doc.nodeAt(movedPos);
41641
41646
  if (moved == sel.node)
41642
41647
  found = movedPos;
41643
41648
  }
@@ -43509,6 +43514,67 @@ so this becomes the fallback color for the slot */ ''}
43509
43514
  }
43510
43515
 
43511
43516
  // src/utilities/mergeAttributes.ts
43517
+ function splitStyleDeclarations(styles) {
43518
+ const result = [];
43519
+ let current = "";
43520
+ let inSingleQuote = false;
43521
+ let inDoubleQuote = false;
43522
+ let parenDepth = 0;
43523
+ const length = styles.length;
43524
+ for (let i = 0; i < length; i += 1) {
43525
+ const char = styles[i];
43526
+ if (char === "'" && !inDoubleQuote) {
43527
+ inSingleQuote = !inSingleQuote;
43528
+ current += char;
43529
+ continue;
43530
+ }
43531
+ if (char === '"' && !inSingleQuote) {
43532
+ inDoubleQuote = !inDoubleQuote;
43533
+ current += char;
43534
+ continue;
43535
+ }
43536
+ if (!inSingleQuote && !inDoubleQuote) {
43537
+ if (char === "(") {
43538
+ parenDepth += 1;
43539
+ current += char;
43540
+ continue;
43541
+ }
43542
+ if (char === ")" && parenDepth > 0) {
43543
+ parenDepth -= 1;
43544
+ current += char;
43545
+ continue;
43546
+ }
43547
+ if (char === ";" && parenDepth === 0) {
43548
+ result.push(current);
43549
+ current = "";
43550
+ continue;
43551
+ }
43552
+ }
43553
+ current += char;
43554
+ }
43555
+ if (current) {
43556
+ result.push(current);
43557
+ }
43558
+ return result;
43559
+ }
43560
+ function parseStyleEntries(styles) {
43561
+ const pairs = [];
43562
+ const declarations = splitStyleDeclarations(styles || "");
43563
+ const numDeclarations = declarations.length;
43564
+ for (let i = 0; i < numDeclarations; i += 1) {
43565
+ const declaration = declarations[i];
43566
+ const firstColonIndex = declaration.indexOf(":");
43567
+ if (firstColonIndex === -1) {
43568
+ continue;
43569
+ }
43570
+ const property = declaration.slice(0, firstColonIndex).trim();
43571
+ const value = declaration.slice(firstColonIndex + 1).trim();
43572
+ if (property && value) {
43573
+ pairs.push([property, value]);
43574
+ }
43575
+ }
43576
+ return pairs;
43577
+ }
43512
43578
  function mergeAttributes(...objects) {
43513
43579
  return objects.filter((item) => !!item).reduce((items, item) => {
43514
43580
  const mergedAttributes = { ...items };
@@ -43524,17 +43590,7 @@ so this becomes the fallback color for the slot */ ''}
43524
43590
  const insertClasses = valueClasses.filter((valueClass) => !existingClasses.includes(valueClass));
43525
43591
  mergedAttributes[key] = [...existingClasses, ...insertClasses].join(" ");
43526
43592
  } else if (key === "style") {
43527
- const newStyles = value ? value.split(";").map((style2) => style2.trim()).filter(Boolean) : [];
43528
- const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(";").map((style2) => style2.trim()).filter(Boolean) : [];
43529
- const styleMap = /* @__PURE__ */ new Map();
43530
- existingStyles.forEach((style2) => {
43531
- const [property, val] = style2.split(":").map((part) => part.trim());
43532
- styleMap.set(property, val);
43533
- });
43534
- newStyles.forEach((style2) => {
43535
- const [property, val] = style2.split(":").map((part) => part.trim());
43536
- styleMap.set(property, val);
43537
- });
43593
+ const styleMap = new Map([...parseStyleEntries(mergedAttributes[key]), ...parseStyleEntries(value)]);
43538
43594
  mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join("; ");
43539
43595
  } else {
43540
43596
  mergedAttributes[key] = value;
@@ -44121,7 +44177,7 @@ so this becomes the fallback color for the slot */ ''}
44121
44177
  return true;
44122
44178
  }
44123
44179
  if (node.isText) {
44124
- return /^\s*$/m.test((_a = node.text) != null ? _a : "");
44180
+ return !/\S/.test((_a = node.text) != null ? _a : "");
44125
44181
  }
44126
44182
  }
44127
44183
  if (node.isText) {
@@ -47506,17 +47562,21 @@ ${renderedContent}
47506
47562
  const prefix = typeof prefixOrGenerator === "function" ? prefixOrGenerator(ctx) : prefixOrGenerator;
47507
47563
  const [content, ...children] = node.content;
47508
47564
  const mainContent = h2.renderChildren([content]);
47509
- const output = [`${prefix}${mainContent}`];
47565
+ let output = `${prefix}${mainContent}`;
47510
47566
  if (children && children.length > 0) {
47511
- children.forEach((child) => {
47512
- const childContent = h2.renderChildren([child]);
47513
- if (childContent) {
47514
- const indentedChild = childContent.split("\n").map((line) => line ? h2.indent(line) : "").join("\n");
47515
- output.push(indentedChild);
47567
+ children.forEach((child, index) => {
47568
+ var _a, _b;
47569
+ const childContent = (_b = (_a = h2.renderChild) == null ? void 0 : _a.call(h2, child, index + 1)) != null ? _b : h2.renderChildren([child]);
47570
+ if (childContent !== void 0 && childContent !== null) {
47571
+ const indentedChild = childContent.split("\n").map((line) => line ? h2.indent(line) : h2.indent("")).join("\n");
47572
+ output += child.type === "paragraph" ? `
47573
+
47574
+ ${indentedChild}` : `
47575
+ ${indentedChild}`;
47516
47576
  }
47517
47577
  });
47518
47578
  }
47519
- return output.join("\n");
47579
+ return output;
47520
47580
  }
47521
47581
 
47522
47582
  // src/MarkView.ts
@@ -58373,6 +58433,12 @@ ${renderedContent}
58373
58433
  parseMarkdown: (token, helpers) => {
58374
58434
  return helpers.applyMark("bold", helpers.parseInline(token.tokens || []));
58375
58435
  },
58436
+ markdownOptions: {
58437
+ htmlReopen: {
58438
+ open: "<strong>",
58439
+ close: "</strong>"
58440
+ }
58441
+ },
58376
58442
  renderMarkdown: (node, h) => {
58377
58443
  return `**${h.renderChildren(node)}**`;
58378
58444
  },
@@ -58490,6 +58556,12 @@ ${renderedContent}
58490
58556
  parseMarkdown: (token, helpers) => {
58491
58557
  return helpers.applyMark("italic", helpers.parseInline(token.tokens || []));
58492
58558
  },
58559
+ markdownOptions: {
58560
+ htmlReopen: {
58561
+ open: "<em>",
58562
+ close: "</em>"
58563
+ }
58564
+ },
58493
58565
  renderMarkdown: (node, h) => {
58494
58566
  return `*${h.renderChildren(node)}*`;
58495
58567
  },
@@ -60796,14 +60868,16 @@ ${renderedContent}
60796
60868
  },
60797
60869
  markdownTokenName: "list_item",
60798
60870
  parseMarkdown: (token, helpers) => {
60871
+ var _a;
60799
60872
  if (token.type !== "list_item") {
60800
60873
  return [];
60801
60874
  }
60875
+ const parseBlockChildren = (_a = helpers.parseBlockChildren) != null ? _a : helpers.parseChildren;
60802
60876
  let content = [];
60803
60877
  if (token.tokens && token.tokens.length > 0) {
60804
60878
  const hasParagraphTokens = token.tokens.some((t) => t.type === "paragraph");
60805
60879
  if (hasParagraphTokens) {
60806
- content = helpers.parseChildren(token.tokens);
60880
+ content = parseBlockChildren(token.tokens);
60807
60881
  } else {
60808
60882
  const firstToken = token.tokens[0];
60809
60883
  if (firstToken && firstToken.type === "text" && firstToken.tokens && firstToken.tokens.length > 0) {
@@ -60816,11 +60890,11 @@ ${renderedContent}
60816
60890
  ];
60817
60891
  if (token.tokens.length > 1) {
60818
60892
  const remainingTokens = token.tokens.slice(1);
60819
- const additionalContent = helpers.parseChildren(remainingTokens);
60893
+ const additionalContent = parseBlockChildren(remainingTokens);
60820
60894
  content.push(...additionalContent);
60821
60895
  }
60822
60896
  } else {
60823
- content = helpers.parseChildren(token.tokens);
60897
+ content = parseBlockChildren(token.tokens);
60824
60898
  }
60825
60899
  }
60826
60900
  }
@@ -62329,13 +62403,16 @@ ${nextLine.slice(indentLevel + 2)}`;
62329
62403
  }
62330
62404
  return helpers.createNode("paragraph", void 0, content);
62331
62405
  },
62332
- renderMarkdown: (node, h) => {
62406
+ renderMarkdown: (node, h, ctx) => {
62407
+ var _a, _b;
62333
62408
  if (!node) {
62334
62409
  return "";
62335
62410
  }
62336
62411
  const content = Array.isArray(node.content) ? node.content : [];
62337
62412
  if (content.length === 0) {
62338
- return EMPTY_PARAGRAPH_MARKDOWN;
62413
+ const previousContent = Array.isArray((_a = ctx == null ? void 0 : ctx.previousNode) == null ? void 0 : _a.content) ? ctx.previousNode.content : [];
62414
+ const previousNodeIsEmptyParagraph = ((_b = ctx == null ? void 0 : ctx.previousNode) == null ? void 0 : _b.type) === "paragraph" && previousContent.length === 0;
62415
+ return previousNodeIsEmptyParagraph ? EMPTY_PARAGRAPH_MARKDOWN : "";
62339
62416
  }
62340
62417
  return h.renderChildren(content);
62341
62418
  },
@@ -62553,7 +62630,7 @@ ${nextLine.slice(indentLevel + 2)}`;
62553
62630
  */
62554
62631
  static valid($pos) {
62555
62632
  let parent = $pos.parent;
62556
- if (parent.isTextblock || !closedBefore($pos) || !closedAfter($pos))
62633
+ if (parent.inlineContent || !closedBefore($pos) || !closedAfter($pos))
62557
62634
  return false;
62558
62635
  let override = parent.type.spec.allowGapCursor;
62559
62636
  if (override != null)
@@ -63582,6 +63659,9 @@ ${nextLine.slice(indentLevel + 2)}`;
63582
63659
  doc.descendants((node, pos) => {
63583
63660
  const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;
63584
63661
  const isEmpty = !node.isLeaf && isNodeEmpty(node);
63662
+ if (!node.type.isTextblock) {
63663
+ return this.options.includeChildren;
63664
+ }
63585
63665
  if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {
63586
63666
  const classes = [this.options.emptyNodeClass];
63587
63667
  if (isEmptyDoc) {
@@ -72382,7 +72462,7 @@ focus outline in that case.
72382
72462
  this.scrollElement = null;
72383
72463
  this.targetWindow = null;
72384
72464
  this.isScrolling = false;
72385
- this.currentScrollToIndex = null;
72465
+ this.scrollState = null;
72386
72466
  this.measurementsCache = [];
72387
72467
  this.itemSizeCache = /* @__PURE__ */ new Map();
72388
72468
  this.laneAssignments = /* @__PURE__ */ new Map();
@@ -72395,6 +72475,10 @@ focus outline in that case.
72395
72475
  this.scrollDirection = null;
72396
72476
  this.scrollAdjustments = 0;
72397
72477
  this.elementsCache = /* @__PURE__ */ new Map();
72478
+ this.now = () => {
72479
+ var _a, _b, _c;
72480
+ return ((_c = (_b = (_a = this.targetWindow) == null ? void 0 : _a.performance) == null ? void 0 : _b.now) == null ? void 0 : _c.call(_b)) ?? Date.now();
72481
+ };
72398
72482
  this.observer = /* @__PURE__ */ (() => {
72399
72483
  let _ro = null;
72400
72484
  const get = () => {
@@ -72407,7 +72491,18 @@ focus outline in that case.
72407
72491
  return _ro = new this.targetWindow.ResizeObserver((entries) => {
72408
72492
  entries.forEach((entry) => {
72409
72493
  const run = () => {
72410
- this._measureElement(entry.target, entry);
72494
+ const node = entry.target;
72495
+ const index = this.indexFromElement(node);
72496
+ if (!node.isConnected) {
72497
+ this.observer.unobserve(node);
72498
+ return;
72499
+ }
72500
+ if (this.shouldMeasureDuringScroll(index)) {
72501
+ this.resizeItem(
72502
+ index,
72503
+ this.options.measureElement(node, entry, this)
72504
+ );
72505
+ }
72411
72506
  };
72412
72507
  this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
72413
72508
  });
@@ -72492,6 +72587,11 @@ focus outline in that case.
72492
72587
  this.unsubs.filter(Boolean).forEach((d) => d());
72493
72588
  this.unsubs = [];
72494
72589
  this.observer.disconnect();
72590
+ if (this.rafId != null && this.targetWindow) {
72591
+ this.targetWindow.cancelAnimationFrame(this.rafId);
72592
+ this.rafId = null;
72593
+ }
72594
+ this.scrollState = null;
72495
72595
  this.scrollElement = null;
72496
72596
  this.targetWindow = null;
72497
72597
  };
@@ -72530,6 +72630,9 @@ focus outline in that case.
72530
72630
  this.scrollDirection = isScrolling ? this.getScrollOffset() < offset ? "forward" : "backward" : null;
72531
72631
  this.scrollOffset = offset;
72532
72632
  this.isScrolling = isScrolling;
72633
+ if (this.scrollState) {
72634
+ this.scheduleScrollReconcile();
72635
+ }
72533
72636
  this.maybeNotify();
72534
72637
  })
72535
72638
  );
@@ -72539,6 +72642,7 @@ focus outline in that case.
72539
72642
  });
72540
72643
  }
72541
72644
  };
72645
+ this.rafId = null;
72542
72646
  this.getSize = () => {
72543
72647
  if (!this.options.enabled) {
72544
72648
  this.scrollRect = null;
@@ -72757,13 +72861,38 @@ focus outline in that case.
72757
72861
  }
72758
72862
  return parseInt(indexStr, 10);
72759
72863
  };
72760
- this._measureElement = (node, entry) => {
72761
- const index = this.indexFromElement(node);
72762
- const item = this.measurementsCache[index];
72763
- if (!item) {
72864
+ this.shouldMeasureDuringScroll = (index) => {
72865
+ var _a;
72866
+ if (!this.scrollState || this.scrollState.behavior !== "smooth") {
72867
+ return true;
72868
+ }
72869
+ const scrollIndex = this.scrollState.index ?? ((_a = this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)) == null ? void 0 : _a.index);
72870
+ if (scrollIndex !== void 0 && this.range) {
72871
+ const bufferSize = Math.max(
72872
+ this.options.overscan,
72873
+ Math.ceil((this.range.endIndex - this.range.startIndex) / 2)
72874
+ );
72875
+ const minIndex = Math.max(0, scrollIndex - bufferSize);
72876
+ const maxIndex = Math.min(
72877
+ this.options.count - 1,
72878
+ scrollIndex + bufferSize
72879
+ );
72880
+ return index >= minIndex && index <= maxIndex;
72881
+ }
72882
+ return true;
72883
+ };
72884
+ this.measureElement = (node) => {
72885
+ if (!node) {
72886
+ this.elementsCache.forEach((cached, key2) => {
72887
+ if (!cached.isConnected) {
72888
+ this.observer.unobserve(cached);
72889
+ this.elementsCache.delete(key2);
72890
+ }
72891
+ });
72764
72892
  return;
72765
72893
  }
72766
- const key = item.key;
72894
+ const index = this.indexFromElement(node);
72895
+ const key = this.options.getItemKey(index);
72767
72896
  const prevNode = this.elementsCache.get(key);
72768
72897
  if (prevNode !== node) {
72769
72898
  if (prevNode) {
@@ -72772,19 +72901,18 @@ focus outline in that case.
72772
72901
  this.observer.observe(node);
72773
72902
  this.elementsCache.set(key, node);
72774
72903
  }
72775
- if (node.isConnected) {
72776
- this.resizeItem(index, this.options.measureElement(node, entry, this));
72904
+ if ((!this.isScrolling || this.scrollState) && this.shouldMeasureDuringScroll(index)) {
72905
+ this.resizeItem(index, this.options.measureElement(node, void 0, this));
72777
72906
  }
72778
72907
  };
72779
72908
  this.resizeItem = (index, size) => {
72909
+ var _a;
72780
72910
  const item = this.measurementsCache[index];
72781
- if (!item) {
72782
- return;
72783
- }
72911
+ if (!item) return;
72784
72912
  const itemSize = this.itemSizeCache.get(item.key) ?? item.size;
72785
72913
  const delta = size - itemSize;
72786
72914
  if (delta !== 0) {
72787
- if (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this) : item.start < this.getScrollOffset() + this.scrollAdjustments) {
72915
+ 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)) {
72788
72916
  if (this.options.debug) {
72789
72917
  console.info("correction", delta);
72790
72918
  }
@@ -72798,18 +72926,6 @@ focus outline in that case.
72798
72926
  this.notify(false);
72799
72927
  }
72800
72928
  };
72801
- this.measureElement = (node) => {
72802
- if (!node) {
72803
- this.elementsCache.forEach((cached, key) => {
72804
- if (!cached.isConnected) {
72805
- this.observer.unobserve(cached);
72806
- this.elementsCache.delete(key);
72807
- }
72808
- });
72809
- return;
72810
- }
72811
- this._measureElement(node, void 0);
72812
- };
72813
72929
  this.getVirtualItems = memo(
72814
72930
  () => [this.getVirtualIndexes(), this.getMeasurements()],
72815
72931
  (indexes, measurements) => {
@@ -72866,12 +72982,10 @@ focus outline in that case.
72866
72982
  };
72867
72983
  this.getOffsetForIndex = (index, align = "auto") => {
72868
72984
  index = Math.max(0, Math.min(index, this.options.count - 1));
72869
- const item = this.measurementsCache[index];
72870
- if (!item) {
72871
- return void 0;
72872
- }
72873
72985
  const size = this.getSize();
72874
72986
  const scrollOffset = this.getScrollOffset();
72987
+ const item = this.measurementsCache[index];
72988
+ if (!item) return;
72875
72989
  if (align === "auto") {
72876
72990
  if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {
72877
72991
  align = "end";
@@ -72890,85 +73004,55 @@ focus outline in that case.
72890
73004
  align
72891
73005
  ];
72892
73006
  };
72893
- this.isDynamicMode = () => this.elementsCache.size > 0;
72894
- this.scrollToOffset = (toOffset, { align = "start", behavior } = {}) => {
72895
- if (behavior === "smooth" && this.isDynamicMode()) {
72896
- console.warn(
72897
- "The `smooth` scroll behavior is not fully supported with dynamic size."
72898
- );
72899
- }
72900
- this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {
72901
- adjustments: void 0,
72902
- behavior
72903
- });
73007
+ this.scrollToOffset = (toOffset, { align = "start", behavior = "auto" } = {}) => {
73008
+ const offset = this.getOffsetForAlignment(toOffset, align);
73009
+ const now = this.now();
73010
+ this.scrollState = {
73011
+ index: null,
73012
+ align,
73013
+ behavior,
73014
+ startedAt: now,
73015
+ lastTargetOffset: offset,
73016
+ stableFrames: 0
73017
+ };
73018
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
73019
+ this.scheduleScrollReconcile();
72904
73020
  };
72905
- this.scrollToIndex = (index, { align: initialAlign = "auto", behavior } = {}) => {
72906
- if (behavior === "smooth" && this.isDynamicMode()) {
72907
- console.warn(
72908
- "The `smooth` scroll behavior is not fully supported with dynamic size."
72909
- );
72910
- }
73021
+ this.scrollToIndex = (index, {
73022
+ align: initialAlign = "auto",
73023
+ behavior = "auto"
73024
+ } = {}) => {
72911
73025
  index = Math.max(0, Math.min(index, this.options.count - 1));
72912
- this.currentScrollToIndex = index;
72913
- let attempts = 0;
72914
- const maxAttempts = 10;
72915
- const tryScroll = (currentAlign) => {
72916
- if (!this.targetWindow) return;
72917
- const offsetInfo = this.getOffsetForIndex(index, currentAlign);
72918
- if (!offsetInfo) {
72919
- console.warn("Failed to get offset for index:", index);
72920
- return;
72921
- }
72922
- const [offset, align] = offsetInfo;
72923
- this._scrollToOffset(offset, { adjustments: void 0, behavior });
72924
- this.targetWindow.requestAnimationFrame(() => {
72925
- if (!this.targetWindow) return;
72926
- const verify = () => {
72927
- if (this.currentScrollToIndex !== index) return;
72928
- const currentOffset = this.getScrollOffset();
72929
- const afterInfo = this.getOffsetForIndex(index, align);
72930
- if (!afterInfo) {
72931
- console.warn("Failed to get offset for index:", index);
72932
- return;
72933
- }
72934
- if (!approxEqual(afterInfo[0], currentOffset)) {
72935
- scheduleRetry(align);
72936
- }
72937
- };
72938
- if (this.isDynamicMode()) {
72939
- this.targetWindow.requestAnimationFrame(verify);
72940
- } else {
72941
- verify();
72942
- }
72943
- });
72944
- };
72945
- const scheduleRetry = (align) => {
72946
- if (!this.targetWindow) return;
72947
- if (this.currentScrollToIndex !== index) return;
72948
- attempts++;
72949
- if (attempts < maxAttempts) {
72950
- if (this.options.debug) {
72951
- console.info("Schedule retry", attempts, maxAttempts);
72952
- }
72953
- this.targetWindow.requestAnimationFrame(() => tryScroll(align));
72954
- } else {
72955
- console.warn(
72956
- `Failed to scroll to index ${index} after ${maxAttempts} attempts.`
72957
- );
72958
- }
73026
+ const offsetInfo = this.getOffsetForIndex(index, initialAlign);
73027
+ if (!offsetInfo) {
73028
+ return;
73029
+ }
73030
+ const [offset, align] = offsetInfo;
73031
+ const now = this.now();
73032
+ this.scrollState = {
73033
+ index,
73034
+ align,
73035
+ behavior,
73036
+ startedAt: now,
73037
+ lastTargetOffset: offset,
73038
+ stableFrames: 0
72959
73039
  };
72960
- tryScroll(initialAlign);
73040
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
73041
+ this.scheduleScrollReconcile();
72961
73042
  };
72962
- this.scrollBy = (delta, { behavior } = {}) => {
72963
- if (behavior === "smooth" && this.isDynamicMode()) {
72964
- console.warn(
72965
- "The `smooth` scroll behavior is not fully supported with dynamic size."
72966
- );
72967
- }
72968
- this._scrollToOffset(this.getScrollOffset() + delta, {
72969
- adjustments: void 0,
72970
- behavior
72971
- });
73043
+ this.scrollBy = (delta, { behavior = "auto" } = {}) => {
73044
+ const offset = this.getScrollOffset() + delta;
73045
+ const now = this.now();
73046
+ this.scrollState = {
73047
+ index: null,
73048
+ align: "start",
73049
+ behavior,
73050
+ startedAt: now,
73051
+ lastTargetOffset: offset,
73052
+ stableFrames: 0
73053
+ };
73054
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
73055
+ this.scheduleScrollReconcile();
72972
73056
  };
72973
73057
  this.getTotalSize = () => {
72974
73058
  var _a;
@@ -73008,6 +73092,49 @@ focus outline in that case.
73008
73092
  };
73009
73093
  this.setOptions(opts);
73010
73094
  }
73095
+ scheduleScrollReconcile() {
73096
+ if (!this.targetWindow) {
73097
+ this.scrollState = null;
73098
+ return;
73099
+ }
73100
+ if (this.rafId != null) return;
73101
+ this.rafId = this.targetWindow.requestAnimationFrame(() => {
73102
+ this.rafId = null;
73103
+ this.reconcileScroll();
73104
+ });
73105
+ }
73106
+ reconcileScroll() {
73107
+ if (!this.scrollState) return;
73108
+ const el = this.scrollElement;
73109
+ if (!el) return;
73110
+ const MAX_RECONCILE_MS = 5e3;
73111
+ if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {
73112
+ this.scrollState = null;
73113
+ return;
73114
+ }
73115
+ const offsetInfo = this.scrollState.index != null ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align) : void 0;
73116
+ const targetOffset = offsetInfo ? offsetInfo[0] : this.scrollState.lastTargetOffset;
73117
+ const STABLE_FRAMES = 1;
73118
+ const targetChanged = targetOffset !== this.scrollState.lastTargetOffset;
73119
+ if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {
73120
+ this.scrollState.stableFrames++;
73121
+ if (this.scrollState.stableFrames >= STABLE_FRAMES) {
73122
+ this.scrollState = null;
73123
+ return;
73124
+ }
73125
+ } else {
73126
+ this.scrollState.stableFrames = 0;
73127
+ if (targetChanged) {
73128
+ this.scrollState.lastTargetOffset = targetOffset;
73129
+ this.scrollState.behavior = "auto";
73130
+ this._scrollToOffset(targetOffset, {
73131
+ adjustments: void 0,
73132
+ behavior: "auto"
73133
+ });
73134
+ }
73135
+ }
73136
+ this.scheduleScrollReconcile();
73137
+ }
73011
73138
  };
73012
73139
  const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
73013
73140
  while (low <= high) {
@@ -98222,6 +98349,7 @@ focus outline in that case.
98222
98349
  textAreaInputHandler() {
98223
98350
  this.value = this.textArea.value;
98224
98351
  this.isInputEmpty = this.shouldDisableSendButton();
98352
+ this.adjustTextAreaHeight();
98225
98353
  this.queueUpdateScrollbarWidth();
98226
98354
  }
98227
98355
  // If a property can affect whether a scrollbar is visible, we need to
@@ -98243,6 +98371,7 @@ focus outline in that case.
98243
98371
  if (this.textArea) {
98244
98372
  this.textArea.value = this.value;
98245
98373
  this.isInputEmpty = this.shouldDisableSendButton();
98374
+ this.adjustTextAreaHeight();
98246
98375
  this.queueUpdateScrollbarWidth();
98247
98376
  }
98248
98377
  }
@@ -98253,6 +98382,7 @@ focus outline in that case.
98253
98382
  super.connectedCallback();
98254
98383
  this.textArea.value = this.value;
98255
98384
  this.isInputEmpty = this.shouldDisableSendButton();
98385
+ this.adjustTextAreaHeight();
98256
98386
  this.resizeObserver = new ResizeObserver(() => this.onResize());
98257
98387
  this.resizeObserver.observe(this);
98258
98388
  }
@@ -98294,10 +98424,12 @@ focus outline in that case.
98294
98424
  this.isInputEmpty = true;
98295
98425
  if (this.textArea) {
98296
98426
  this.textArea.value = '';
98427
+ this.adjustTextAreaHeight();
98297
98428
  this.textArea.focus();
98298
98429
  }
98299
98430
  }
98300
98431
  onResize() {
98432
+ this.adjustTextAreaHeight();
98301
98433
  this.scrollbarWidth = this.textArea.offsetWidth - this.textArea.clientWidth;
98302
98434
  }
98303
98435
  queueUpdateScrollbarWidth() {
@@ -98309,11 +98441,22 @@ focus outline in that case.
98309
98441
  DOM.queueUpdate(() => this.updateScrollbarWidth());
98310
98442
  }
98311
98443
  }
98444
+ // Workaround for browsers that do not support the CSS property `field-sizing: content`
98445
+ // See https://github.com/ni/nimble/issues/2902
98446
+ adjustTextAreaHeight() {
98447
+ if (ChatInput.fieldSizingSupported || !this.textArea) {
98448
+ return;
98449
+ }
98450
+ const textArea = this.textArea;
98451
+ textArea.style.height = 'auto';
98452
+ textArea.style.height = `${textArea.scrollHeight}px`;
98453
+ }
98312
98454
  updateScrollbarWidth() {
98313
98455
  this.updateScrollbarWidthQueued = false;
98314
98456
  this.scrollbarWidth = this.textArea.offsetWidth - this.textArea.clientWidth;
98315
98457
  }
98316
98458
  }
98459
+ ChatInput.fieldSizingSupported = CSS.supports('field-sizing', 'content');
98317
98460
  __decorate([
98318
98461
  attr
98319
98462
  ], ChatInput.prototype, "placeholder", void 0);