@ni/nimble-components 34.0.0 → 34.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5264,7 +5264,7 @@
5264
5264
  * Returns all displayed elements inside of a root node that match a provided selector
5265
5265
  */
5266
5266
  function getDisplayedNodes(rootNode, selector) {
5267
- if (!rootNode || false || !isHTMLElement(rootNode)) {
5267
+ if (!rootNode || !selector || !isHTMLElement(rootNode)) {
5268
5268
  return;
5269
5269
  }
5270
5270
  const nodes = Array.from(rootNode.querySelectorAll(selector));
@@ -11497,7 +11497,7 @@
11497
11497
  */
11498
11498
  getValidValue(value) {
11499
11499
  var _a, _b;
11500
- let validValue = parseFloat(parseFloat(value).toPrecision(12));
11500
+ let validValue = parseFloat(parseFloat(value).toPrecision(15));
11501
11501
  if (isNaN(validValue)) {
11502
11502
  validValue = "";
11503
11503
  }
@@ -16122,6 +16122,7 @@
16122
16122
  calendarEventBackgroundHoverTransientColor: 'calendar-event-background-hover-transient-color',
16123
16123
  calendarEventOuterBorderHighlightedColor: 'calendar-event-outer-border-highlighted-color',
16124
16124
  calendarRowBackgroundSelectedColor: 'calendar-row-background-selected-color',
16125
+ calendarRowBackgroundConflictColor: 'calendar-row-background-conflict-color',
16125
16126
  calendarEventFillBlockedColor: 'calendar-event-fill-blocked-color',
16126
16127
  calendarGrabHandleBackgroundColor: 'calendar-grab-handle-background-color',
16127
16128
  calendarGridBorderColor: 'calendar-grid-border-color',
@@ -16327,6 +16328,7 @@
16327
16328
  DesignToken.create(styleNameFromTokenName(tokenNames.calendarEventBackgroundHoverTransientColor)).withDefault((element) => getColorForTheme(element, DigitalGreenDark110, DigitalGreenDark105, DigitalGreenDark105));
16328
16329
  DesignToken.create(styleNameFromTokenName(tokenNames.calendarEventOuterBorderHighlightedColor)).withDefault((element) => getColorForTheme(element, Black88, hexToRgbaCssColor(White, 0.85), hexToRgbaCssColor(White, 0.85)));
16329
16330
  DesignToken.create(styleNameFromTokenName(tokenNames.calendarRowBackgroundSelectedColor)).withDefault((element) => getColorForTheme(element, hexToRgbaCssColor(DigitalGreenLight, 0.2), hexToRgbaCssColor(PowerGreen, 0.2), hexToRgbaCssColor(PowerGreen, 0.2)));
16331
+ DesignToken.create(styleNameFromTokenName(tokenNames.calendarRowBackgroundConflictColor)).withDefault((element) => getColorForTheme(element, hexToRgbaCssColor(Fail100LightUi, 0.2), hexToRgbaCssColor(Fail100DarkUi, 0.2), hexToRgbaCssColor(Fail100DarkUi, 0.2)));
16330
16332
  DesignToken.create(styleNameFromTokenName(tokenNames.calendarEventFillBlockedColor)).withDefault((element) => getColorForTheme(element, hexToRgbaCssColor(Black91, 0.07), Black82, Black82));
16331
16333
  DesignToken.create(styleNameFromTokenName(tokenNames.calendarGrabHandleBackgroundColor)).withDefault((element) => getColorForTheme(element, DigitalGreenLight, PowerGreen, PowerGreen));
16332
16334
  DesignToken.create(styleNameFromTokenName(tokenNames.calendarGridBorderColor)).withDefault((element) => getColorForTheme(element, Black22, Black80, Black80));
@@ -27606,7 +27608,7 @@ so this becomes the fallback color for the slot */ ''}
27606
27608
  position in this fragment. The result object will be reused
27607
27609
  (overwritten) the next time the function is called. @internal
27608
27610
  */
27609
- findIndex(pos, round = -1) {
27611
+ findIndex(pos) {
27610
27612
  if (pos == 0)
27611
27613
  return retIndex(0, pos);
27612
27614
  if (pos == this.size)
@@ -27616,7 +27618,7 @@ so this becomes the fallback color for the slot */ ''}
27616
27618
  for (let i = 0, curPos = 0;; i++) {
27617
27619
  let cur = this.child(i), end = curPos + cur.nodeSize;
27618
27620
  if (end >= pos) {
27619
- if (end == pos || round > 0)
27621
+ if (end == pos)
27620
27622
  return retIndex(i + 1, end);
27621
27623
  return retIndex(i, curPos);
27622
27624
  }
@@ -28577,7 +28579,7 @@ so this becomes the fallback color for the slot */ ''}
28577
28579
  `blockSeparator` is given, it will be inserted to separate text
28578
28580
  from different block nodes. If `leafText` is given, it'll be
28579
28581
  inserted for every non-text leaf node encountered, otherwise
28580
- [`leafText`](https://prosemirror.net/docs/ref/#model.NodeSpec^leafText) will be used.
28582
+ [`leafText`](https://prosemirror.net/docs/ref/#model.NodeSpec.leafText) will be used.
28581
28583
  */
28582
28584
  textBetween(from, to, blockSeparator, leafText) {
28583
28585
  return this.content.textBetween(from, to, blockSeparator, leafText);
@@ -29787,8 +29789,8 @@ so this becomes the fallback color for the slot */ ''}
29787
29789
  let type = this.marks[prop], excl = type.spec.excludes;
29788
29790
  type.excluded = excl == null ? [type] : excl == "" ? [] : gatherMarks(this, excl.split(" "));
29789
29791
  }
29790
- this.nodeFromJSON = this.nodeFromJSON.bind(this);
29791
- this.markFromJSON = this.markFromJSON.bind(this);
29792
+ this.nodeFromJSON = json => Node$2.fromJSON(this, json);
29793
+ this.markFromJSON = json => Mark$1.fromJSON(this, json);
29792
29794
  this.topNodeType = this.nodes[this.spec.topNode || "doc"];
29793
29795
  this.cached.wrappings = Object.create(null);
29794
29796
  }
@@ -29824,20 +29826,6 @@ so this becomes the fallback color for the slot */ ''}
29824
29826
  return type.create(attrs);
29825
29827
  }
29826
29828
  /**
29827
- Deserialize a node from its JSON representation. This method is
29828
- bound.
29829
- */
29830
- nodeFromJSON(json) {
29831
- return Node$2.fromJSON(this, json);
29832
- }
29833
- /**
29834
- Deserialize a mark from its JSON representation. This method is
29835
- bound.
29836
- */
29837
- markFromJSON(json) {
29838
- return Mark$1.fromJSON(this, json);
29839
- }
29840
- /**
29841
29829
  @internal
29842
29830
  */
29843
29831
  nodeType(name) {
@@ -30019,7 +30007,7 @@ so this becomes the fallback color for the slot */ ''}
30019
30007
  /**
30020
30008
  Construct a DOM parser using the parsing rules listed in a
30021
30009
  schema's [node specs](https://prosemirror.net/docs/ref/#model.NodeSpec.parseDOM), reordered by
30022
- [priority](https://prosemirror.net/docs/ref/#model.ParseRule.priority).
30010
+ [priority](https://prosemirror.net/docs/ref/#model.GenericParseRule.priority).
30023
30011
  */
30024
30012
  static fromSchema(schema) {
30025
30013
  return schema.cached.domParser ||
@@ -30043,7 +30031,7 @@ so this becomes the fallback color for the slot */ ''}
30043
30031
  if (preserveWhitespace != null)
30044
30032
  return (preserveWhitespace ? OPT_PRESERVE_WS : 0) |
30045
30033
  (preserveWhitespace === "full" ? OPT_PRESERVE_WS_FULL : 0);
30046
- return type && type.whitespace == "pre" ? OPT_PRESERVE_WS | OPT_PRESERVE_WS_FULL : base & -5;
30034
+ return type && type.whitespace == "pre" ? OPT_PRESERVE_WS | OPT_PRESERVE_WS_FULL : base & ~OPT_OPEN_LEFT;
30047
30035
  }
30048
30036
  class NodeContext {
30049
30037
  constructor(type, attrs, marks, solid, match, options) {
@@ -30770,6 +30758,8 @@ so this becomes the fallback color for the slot */ ''}
30770
30758
  let space = name.indexOf(" ");
30771
30759
  if (space > 0)
30772
30760
  dom.setAttributeNS(name.slice(0, space), name.slice(space + 1), attrs[name]);
30761
+ else if (name == "style" && dom.style)
30762
+ dom.style.cssText = attrs[name];
30773
30763
  else
30774
30764
  dom.setAttribute(name, attrs[name]);
30775
30765
  }
@@ -33479,7 +33469,7 @@ so this becomes the fallback color for the slot */ ''}
33479
33469
  throw new RangeError("Selection passed to setSelection must point at the current document");
33480
33470
  this.curSelection = selection;
33481
33471
  this.curSelectionFor = this.steps.length;
33482
- this.updated = (this.updated | UPDATED_SEL) & -3;
33472
+ this.updated = (this.updated | UPDATED_SEL) & ~UPDATED_MARKS;
33483
33473
  this.storedMarks = null;
33484
33474
  return this;
33485
33475
  }
@@ -33530,7 +33520,7 @@ so this becomes the fallback color for the slot */ ''}
33530
33520
  */
33531
33521
  addStep(step, doc) {
33532
33522
  super.addStep(step, doc);
33533
- this.updated = this.updated & -3;
33523
+ this.updated = this.updated & ~UPDATED_MARKS;
33534
33524
  this.storedMarks = null;
33535
33525
  }
33536
33526
  /**
@@ -41876,7 +41866,7 @@ so this becomes the fallback color for the slot */ ''}
41876
41866
  dropEvent = event;
41877
41867
  if (!isDroppedFromProseMirror) {
41878
41868
  const dragFromOtherEditor = tiptapDragFromOtherEditor;
41879
- if (dragFromOtherEditor) {
41869
+ if (dragFromOtherEditor === null || dragFromOtherEditor === void 0 ? void 0 : dragFromOtherEditor.isEditable) {
41880
41870
  // setTimeout to avoid the wrong content after drop, timeout arg can't be empty or 0
41881
41871
  setTimeout(() => {
41882
41872
  const selection = dragFromOtherEditor.state.selection;
@@ -42427,7 +42417,7 @@ so this becomes the fallback color for the slot */ ''}
42427
42417
  tr.deleteRange(originRange.from, originRange.to);
42428
42418
  const newPos = tr.mapping.map(targetPos);
42429
42419
  tr.insert(newPos, contentSlice.content);
42430
- tr.setSelection(new TextSelection(tr.doc.resolve(newPos - 1)));
42420
+ tr.setSelection(new TextSelection(tr.doc.resolve(Math.max(newPos - 1, 0))));
42431
42421
  return true;
42432
42422
  };
42433
42423
 
@@ -42859,25 +42849,42 @@ so this becomes the fallback color for the slot */ ''}
42859
42849
  ...options,
42860
42850
  };
42861
42851
  let content;
42862
- try {
42863
- content = createNodeFromContent(value, editor.schema, {
42864
- parseOptions: {
42865
- preserveWhitespace: 'full',
42866
- ...options.parseOptions,
42867
- },
42868
- errorOnInvalidContent: (_a = options.errorOnInvalidContent) !== null && _a !== void 0 ? _a : editor.options.enableContentCheck,
42869
- });
42870
- }
42871
- catch (e) {
42852
+ const emitContentError = (error) => {
42872
42853
  editor.emit('contentError', {
42873
42854
  editor,
42874
- error: e,
42855
+ error,
42875
42856
  disableCollaboration: () => {
42876
42857
  if (editor.storage.collaboration) {
42877
42858
  editor.storage.collaboration.isDisabled = true;
42878
42859
  }
42879
42860
  },
42880
42861
  });
42862
+ };
42863
+ const parseOptions = {
42864
+ preserveWhitespace: 'full',
42865
+ ...options.parseOptions,
42866
+ };
42867
+ // If `emitContentError` is enabled, we want to check the content for errors
42868
+ // but ignore them (do not remove the invalid content from the document)
42869
+ if (!options.errorOnInvalidContent && !editor.options.enableContentCheck && editor.options.emitContentError) {
42870
+ try {
42871
+ createNodeFromContent(value, editor.schema, {
42872
+ parseOptions,
42873
+ errorOnInvalidContent: true,
42874
+ });
42875
+ }
42876
+ catch (e) {
42877
+ emitContentError(e);
42878
+ }
42879
+ }
42880
+ try {
42881
+ content = createNodeFromContent(value, editor.schema, {
42882
+ parseOptions,
42883
+ errorOnInvalidContent: (_a = options.errorOnInvalidContent) !== null && _a !== void 0 ? _a : editor.options.enableContentCheck,
42884
+ });
42885
+ }
42886
+ catch (e) {
42887
+ emitContentError(e);
42881
42888
  return false;
42882
42889
  }
42883
42890
  let { from, to } = typeof position === 'number' ? { from: position, to: position } : { from: position.from, to: position.to };
@@ -44704,6 +44711,10 @@ so this becomes the fallback color for the slot */ ''}
44704
44711
  const isBlock = node.isBlock && !node.isTextblock;
44705
44712
  const isNonTextAtom = node.isAtom && !node.isText;
44706
44713
  const targetPos = this.pos + offset + (isNonTextAtom ? 0 : 1);
44714
+ // Check if targetPos is within valid document range
44715
+ if (targetPos < 0 || targetPos > this.resolvedPos.doc.nodeSize - 2) {
44716
+ return;
44717
+ }
44707
44718
  const $pos = this.resolvedPos.doc.resolve(targetPos);
44708
44719
  if (!isBlock && $pos.depth <= this.depth) {
44709
44720
  return;
@@ -44903,6 +44914,7 @@ img.ProseMirror-separator {
44903
44914
  enablePasteRules: true,
44904
44915
  enableCoreExtensions: true,
44905
44916
  enableContentCheck: false,
44917
+ emitContentError: false,
44906
44918
  onBeforeCreate: () => null,
44907
44919
  onCreate: () => null,
44908
44920
  onUpdate: () => null,
@@ -58922,6 +58934,13 @@ img.ProseMirror-separator {
58922
58934
  return filtered;
58923
58935
  }
58924
58936
 
58937
+ // From DOMPurify
58938
+ // https://github.com/cure53/DOMPurify/blob/main/src/regexp.ts
58939
+ const UNICODE_WHITESPACE_PATTERN = '[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]';
58940
+ const UNICODE_WHITESPACE_REGEX = new RegExp(UNICODE_WHITESPACE_PATTERN);
58941
+ const UNICODE_WHITESPACE_REGEX_END = new RegExp(`${UNICODE_WHITESPACE_PATTERN}$`);
58942
+ const UNICODE_WHITESPACE_REGEX_GLOBAL = new RegExp(UNICODE_WHITESPACE_PATTERN, 'g');
58943
+
58925
58944
  /**
58926
58945
  * Check if the provided tokens form a valid link structure, which can either be a single link token
58927
58946
  * or a link token surrounded by parentheses or square brackets.
@@ -58978,14 +58997,16 @@ img.ProseMirror-separator {
58978
58997
  textBlock = nodesInChangedRanges[0];
58979
58998
  textBeforeWhitespace = newState.doc.textBetween(textBlock.pos, textBlock.pos + textBlock.node.nodeSize, undefined, ' ');
58980
58999
  }
58981
- else if (nodesInChangedRanges.length
58982
- // We want to make sure to include the block seperator argument to treat hard breaks like spaces.
58983
- && newState.doc.textBetween(newRange.from, newRange.to, ' ', ' ').endsWith(' ')) {
59000
+ else if (nodesInChangedRanges.length) {
59001
+ const endText = newState.doc.textBetween(newRange.from, newRange.to, ' ', ' ');
59002
+ if (!UNICODE_WHITESPACE_REGEX_END.test(endText)) {
59003
+ return;
59004
+ }
58984
59005
  textBlock = nodesInChangedRanges[0];
58985
59006
  textBeforeWhitespace = newState.doc.textBetween(textBlock.pos, newRange.to, undefined, ' ');
58986
59007
  }
58987
59008
  if (textBlock && textBeforeWhitespace) {
58988
- const wordsBeforeWhitespace = textBeforeWhitespace.split(' ').filter(s => s !== '');
59009
+ const wordsBeforeWhitespace = textBeforeWhitespace.split(UNICODE_WHITESPACE_REGEX).filter(Boolean);
58989
59010
  if (wordsBeforeWhitespace.length <= 0) {
58990
59011
  return false;
58991
59012
  }
@@ -59097,10 +59118,6 @@ img.ProseMirror-separator {
59097
59118
  },
59098
59119
  });
59099
59120
  }
59100
- // From DOMPurify
59101
- // https://github.com/cure53/DOMPurify/blob/main/src/regexp.js
59102
- // eslint-disable-next-line no-control-regex
59103
- const ATTR_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g;
59104
59121
  function isAllowedUri(uri, protocols) {
59105
59122
  const allowedProtocols = [
59106
59123
  'http',
@@ -59123,9 +59140,7 @@ img.ProseMirror-separator {
59123
59140
  });
59124
59141
  }
59125
59142
  return (!uri
59126
- || uri
59127
- .replace(ATTR_WHITESPACE, '')
59128
- .match(new RegExp(
59143
+ || uri.replace(UNICODE_WHITESPACE_REGEX_GLOBAL, '').match(new RegExp(
59129
59144
  // eslint-disable-next-line no-useless-escape
59130
59145
  `^(?:(?:${allowedProtocols.join('|')}):|[^a-z]|[a-z0-9+.\-]+(?:[^a-z+.\-:]|$))`, 'i')));
59131
59146
  }
@@ -59420,7 +59435,7 @@ img.ProseMirror-separator {
59420
59435
  * This utility allows you to create suggestions.
59421
59436
  * @see https://tiptap.dev/api/utilities/suggestion
59422
59437
  */
59423
- function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allowSpaces = false, allowToIncludeChar = false, allowedPrefixes = [' '], startOfLine = false, decorationTag = 'span', decorationClass = 'suggestion', command = () => null, items = () => [], render = () => ({}), allow = () => true, findSuggestionMatch: findSuggestionMatch$1 = findSuggestionMatch, }) {
59438
+ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allowSpaces = false, allowToIncludeChar = false, allowedPrefixes = [' '], startOfLine = false, decorationTag = 'span', decorationClass = 'suggestion', decorationContent = '', decorationEmptyClass = 'is-empty', command = () => null, items = () => [], render = () => ({}), allow = () => true, findSuggestionMatch: findSuggestionMatch$1 = findSuggestionMatch, }) {
59424
59439
  let props;
59425
59440
  const renderer = render === null || render === void 0 ? void 0 : render();
59426
59441
  const plugin = new Plugin({
@@ -59530,7 +59545,9 @@ img.ProseMirror-separator {
59530
59545
  // * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)
59531
59546
  if (isEditable && (empty || editor.view.composing)) {
59532
59547
  // Reset active state if we just left the previous suggestion range
59533
- if ((from < prev.range.from || from > prev.range.to) && !composing && !prev.composing) {
59548
+ if ((from < prev.range.from || from > prev.range.to)
59549
+ && !composing
59550
+ && !prev.composing) {
59534
59551
  next.active = false;
59535
59552
  }
59536
59553
  // Try to match against where our cursor currently is
@@ -59544,11 +59561,17 @@ img.ProseMirror-separator {
59544
59561
  });
59545
59562
  const decorationId = `id_${Math.floor(Math.random() * 0xffffffff)}`;
59546
59563
  // If we found a match, update the current state to show it
59547
- if (match && allow({
59548
- editor, state, range: match.range, isActive: prev.active,
59549
- })) {
59564
+ if (match
59565
+ && allow({
59566
+ editor,
59567
+ state,
59568
+ range: match.range,
59569
+ isActive: prev.active,
59570
+ })) {
59550
59571
  next.active = true;
59551
- next.decorationId = prev.decorationId ? prev.decorationId : decorationId;
59572
+ next.decorationId = prev.decorationId
59573
+ ? prev.decorationId
59574
+ : decorationId;
59552
59575
  next.range = match.range;
59553
59576
  next.query = match.query;
59554
59577
  next.text = match.text;
@@ -59582,15 +59605,21 @@ img.ProseMirror-separator {
59582
59605
  },
59583
59606
  // Setup decorator on the currently active suggestion.
59584
59607
  decorations(state) {
59585
- const { active, range, decorationId } = plugin.getState(state);
59608
+ const { active, range, decorationId, query, } = plugin.getState(state);
59586
59609
  if (!active) {
59587
59610
  return null;
59588
59611
  }
59612
+ const isEmpty = !(query === null || query === void 0 ? void 0 : query.length);
59613
+ const classNames = [decorationClass];
59614
+ if (isEmpty) {
59615
+ classNames.push(decorationEmptyClass);
59616
+ }
59589
59617
  return DecorationSet.create(state.doc, [
59590
59618
  Decoration.inline(range.from, range.to, {
59591
59619
  nodeName: decorationTag,
59592
- class: decorationClass,
59620
+ class: classNames.join(' '),
59593
59621
  'data-decoration-id': decorationId,
59622
+ 'data-decoration-content': decorationContent,
59594
59623
  }),
59595
59624
  ]);
59596
59625
  },
@@ -59600,10 +59629,91 @@ img.ProseMirror-separator {
59600
59629
  }
59601
59630
 
59602
59631
  /**
59603
- * The plugin key for the mention plugin.
59604
- * @default 'mention'
59632
+ * Returns the suggestion options for a trigger of the Mention extension. These
59633
+ * options are used to create a `Suggestion` ProseMirror plugin. Each plugin lets
59634
+ * you define a different trigger that opens the Mention menu. For example,
59635
+ * you can define a `@` trigger to mention users and a `#` trigger to mention
59636
+ * tags.
59637
+ *
59638
+ * @param param0 The configured options for the suggestion
59639
+ * @returns
59640
+ */
59641
+ function getSuggestionOptions({ editor: tiptapEditor, overrideSuggestionOptions, extensionName, char = '@', }) {
59642
+ const pluginKey = new PluginKey();
59643
+ return {
59644
+ editor: tiptapEditor,
59645
+ char,
59646
+ pluginKey,
59647
+ command: ({ editor, range, props }) => {
59648
+ var _a, _b, _c;
59649
+ // increase range.to by one when the next node is of type "text"
59650
+ // and starts with a space character
59651
+ const nodeAfter = editor.view.state.selection.$to.nodeAfter;
59652
+ const overrideSpace = (_a = nodeAfter === null || nodeAfter === void 0 ? void 0 : nodeAfter.text) === null || _a === void 0 ? void 0 : _a.startsWith(' ');
59653
+ if (overrideSpace) {
59654
+ range.to += 1;
59655
+ }
59656
+ editor
59657
+ .chain()
59658
+ .focus()
59659
+ .insertContentAt(range, [
59660
+ {
59661
+ type: extensionName,
59662
+ attrs: { ...props, mentionSuggestionChar: char },
59663
+ },
59664
+ {
59665
+ type: 'text',
59666
+ text: ' ',
59667
+ },
59668
+ ])
59669
+ .run();
59670
+ // get reference to `window` object from editor element, to support cross-frame JS usage
59671
+ (_c = (_b = editor.view.dom.ownerDocument.defaultView) === null || _b === void 0 ? void 0 : _b.getSelection()) === null || _c === void 0 ? void 0 : _c.collapseToEnd();
59672
+ },
59673
+ allow: ({ state, range }) => {
59674
+ const $from = state.doc.resolve(range.from);
59675
+ const type = state.schema.nodes[extensionName];
59676
+ const allow = !!$from.parent.type.contentMatch.matchType(type);
59677
+ return allow;
59678
+ },
59679
+ ...overrideSuggestionOptions,
59680
+ };
59681
+ }
59682
+
59683
+ /**
59684
+ * Returns the suggestions for the mention extension.
59685
+ *
59686
+ * @param options The extension options
59687
+ * @returns the suggestions
59688
+ */
59689
+ function getSuggestions(options) {
59690
+ return (options.options.suggestions.length ? options.options.suggestions : [options.options.suggestion]).map(suggestion => getSuggestionOptions({
59691
+ // @ts-ignore `editor` can be `undefined` when converting the document to HTML with the HTML utility
59692
+ editor: options.editor,
59693
+ overrideSuggestionOptions: suggestion,
59694
+ extensionName: options.name,
59695
+ char: suggestion.char,
59696
+ }));
59697
+ }
59698
+ /**
59699
+ * Returns the suggestion options of the mention that has a given character trigger. If not
59700
+ * found, it returns the first suggestion.
59701
+ *
59702
+ * @param options The extension options
59703
+ * @param char The character that triggers the mention
59704
+ * @returns The suggestion options
59605
59705
  */
59606
- const MentionPluginKey = new PluginKey('mention');
59706
+ function getSuggestionFromChar(options, char) {
59707
+ const suggestions = getSuggestions(options);
59708
+ const suggestion = suggestions.find(s => s.char === char);
59709
+ if (suggestion) {
59710
+ return suggestion;
59711
+ }
59712
+ if (suggestions.length) {
59713
+ return suggestions[0];
59714
+ }
59715
+ return null;
59716
+ }
59607
59717
  /**
59608
59718
  * This extension allows you to insert mentions into the editor.
59609
59719
  * @see https://www.tiptap.dev/api/extensions/mention
@@ -59614,55 +59724,21 @@ img.ProseMirror-separator {
59614
59724
  addOptions() {
59615
59725
  return {
59616
59726
  HTMLAttributes: {},
59617
- renderText({ options, node }) {
59618
- var _a;
59619
- return `${options.suggestion.char}${(_a = node.attrs.label) !== null && _a !== void 0 ? _a : node.attrs.id}`;
59727
+ renderText({ node, suggestion }) {
59728
+ var _a, _b;
59729
+ return `${(_a = suggestion === null || suggestion === void 0 ? void 0 : suggestion.char) !== null && _a !== void 0 ? _a : '@'}${(_b = node.attrs.label) !== null && _b !== void 0 ? _b : node.attrs.id}`;
59620
59730
  },
59621
59731
  deleteTriggerWithBackspace: false,
59622
- renderHTML({ options, node }) {
59623
- var _a;
59732
+ renderHTML({ options, node, suggestion }) {
59733
+ var _a, _b;
59624
59734
  return [
59625
59735
  'span',
59626
59736
  mergeAttributes(this.HTMLAttributes, options.HTMLAttributes),
59627
- `${options.suggestion.char}${(_a = node.attrs.label) !== null && _a !== void 0 ? _a : node.attrs.id}`,
59737
+ `${(_a = suggestion === null || suggestion === void 0 ? void 0 : suggestion.char) !== null && _a !== void 0 ? _a : '@'}${(_b = node.attrs.label) !== null && _b !== void 0 ? _b : node.attrs.id}`,
59628
59738
  ];
59629
59739
  },
59630
- suggestion: {
59631
- char: '@',
59632
- pluginKey: MentionPluginKey,
59633
- command: ({ editor, range, props }) => {
59634
- var _a, _b, _c;
59635
- // increase range.to by one when the next node is of type "text"
59636
- // and starts with a space character
59637
- const nodeAfter = editor.view.state.selection.$to.nodeAfter;
59638
- const overrideSpace = (_a = nodeAfter === null || nodeAfter === void 0 ? void 0 : nodeAfter.text) === null || _a === void 0 ? void 0 : _a.startsWith(' ');
59639
- if (overrideSpace) {
59640
- range.to += 1;
59641
- }
59642
- editor
59643
- .chain()
59644
- .focus()
59645
- .insertContentAt(range, [
59646
- {
59647
- type: this.name,
59648
- attrs: props,
59649
- },
59650
- {
59651
- type: 'text',
59652
- text: ' ',
59653
- },
59654
- ])
59655
- .run();
59656
- // get reference to `window` object from editor element, to support cross-frame JS usage
59657
- (_c = (_b = editor.view.dom.ownerDocument.defaultView) === null || _b === void 0 ? void 0 : _b.getSelection()) === null || _c === void 0 ? void 0 : _c.collapseToEnd();
59658
- },
59659
- allow: ({ state, range }) => {
59660
- const $from = state.doc.resolve(range.from);
59661
- const type = state.schema.nodes[this.name];
59662
- const allow = !!$from.parent.type.contentMatch.matchType(type);
59663
- return allow;
59664
- },
59665
- },
59740
+ suggestions: [],
59741
+ suggestion: {},
59666
59742
  };
59667
59743
  },
59668
59744
  group: 'inline',
@@ -59695,6 +59771,16 @@ img.ProseMirror-separator {
59695
59771
  };
59696
59772
  },
59697
59773
  },
59774
+ // When there are multiple types of mentions, this attribute helps distinguish them
59775
+ mentionSuggestionChar: {
59776
+ default: '@',
59777
+ parseHTML: element => element.getAttribute('data-mention-suggestion-char'),
59778
+ renderHTML: attributes => {
59779
+ return {
59780
+ 'data-mention-suggestion-char': attributes.mentionSuggestionChar,
59781
+ };
59782
+ },
59783
+ },
59698
59784
  };
59699
59785
  },
59700
59786
  parseHTML() {
@@ -59705,6 +59791,7 @@ img.ProseMirror-separator {
59705
59791
  ];
59706
59792
  },
59707
59793
  renderHTML({ node, HTMLAttributes }) {
59794
+ const suggestion = getSuggestionFromChar(this, node.attrs.mentionSuggestionChar);
59708
59795
  if (this.options.renderLabel !== undefined) {
59709
59796
  console.warn('renderLabel is deprecated use renderText and renderHTML instead');
59710
59797
  return [
@@ -59713,6 +59800,7 @@ img.ProseMirror-separator {
59713
59800
  this.options.renderLabel({
59714
59801
  options: this.options,
59715
59802
  node,
59803
+ suggestion,
59716
59804
  }),
59717
59805
  ];
59718
59806
  }
@@ -59721,6 +59809,7 @@ img.ProseMirror-separator {
59721
59809
  const html = this.options.renderHTML({
59722
59810
  options: mergedOptions,
59723
59811
  node,
59812
+ suggestion,
59724
59813
  });
59725
59814
  if (typeof html === 'string') {
59726
59815
  return [
@@ -59732,17 +59821,16 @@ img.ProseMirror-separator {
59732
59821
  return html;
59733
59822
  },
59734
59823
  renderText({ node }) {
59824
+ const args = {
59825
+ options: this.options,
59826
+ node,
59827
+ suggestion: getSuggestionFromChar(this, node.attrs.mentionSuggestionChar),
59828
+ };
59735
59829
  if (this.options.renderLabel !== undefined) {
59736
59830
  console.warn('renderLabel is deprecated use renderText and renderHTML instead');
59737
- return this.options.renderLabel({
59738
- options: this.options,
59739
- node,
59740
- });
59831
+ return this.options.renderLabel(args);
59741
59832
  }
59742
- return this.options.renderText({
59743
- options: this.options,
59744
- node,
59745
- });
59833
+ return this.options.renderText(args);
59746
59834
  },
59747
59835
  addKeyboardShortcuts() {
59748
59836
  return {
@@ -59760,17 +59848,27 @@ img.ProseMirror-separator {
59760
59848
  return false;
59761
59849
  }
59762
59850
  });
59851
+ // Store node and position for later use
59852
+ let mentionNode = new Node$2();
59853
+ let mentionPos = 0;
59854
+ state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {
59855
+ if (node.type.name === this.name) {
59856
+ isMention = true;
59857
+ mentionNode = node;
59858
+ mentionPos = pos;
59859
+ return false;
59860
+ }
59861
+ });
59862
+ if (isMention) {
59863
+ tr.insertText(this.options.deleteTriggerWithBackspace ? '' : mentionNode.attrs.mentionSuggestionChar, mentionPos, mentionPos + mentionNode.nodeSize);
59864
+ }
59763
59865
  return isMention;
59764
59866
  }),
59765
59867
  };
59766
59868
  },
59767
59869
  addProseMirrorPlugins() {
59768
- return [
59769
- Suggestion({
59770
- editor: this.editor,
59771
- ...this.options.suggestion,
59772
- }),
59773
- ];
59870
+ // Create a plugin for each suggestion configuration
59871
+ return getSuggestions(this).map(Suggestion);
59774
59872
  },
59775
59873
  });
59776
59874
 
@@ -60133,7 +60231,8 @@ img.ProseMirror-separator {
60133
60231
  mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
60134
60232
  this.options.renderText({
60135
60233
  options: this.options,
60136
- node
60234
+ node,
60235
+ suggestion: null
60137
60236
  })
60138
60237
  ];
60139
60238
  }
@@ -68225,7 +68324,7 @@ focus outline in that case.
68225
68324
  return value;
68226
68325
  }
68227
68326
  }
68228
- const approxEqual = (a, b) => Math.abs(a - b) <= 1;
68327
+ const approxEqual = (a, b) => Math.abs(a - b) < 1.01;
68229
68328
  const debounce = (targetWindow, fn, ms) => {
68230
68329
  let timeoutId;
68231
68330
  return function(...args) {
@@ -68356,7 +68455,6 @@ focus outline in that case.
68356
68455
  this.scrollElement = null;
68357
68456
  this.targetWindow = null;
68358
68457
  this.isScrolling = false;
68359
- this.scrollToIndexTimeoutId = null;
68360
68458
  this.measurementsCache = [];
68361
68459
  this.itemSizeCache = /* @__PURE__ */ new Map();
68362
68460
  this.pendingMeasuredCacheIndexes = [];
@@ -68772,7 +68870,7 @@ focus outline in that case.
68772
68870
  } else if (align === "end") {
68773
68871
  toOffset -= size;
68774
68872
  }
68775
- const maxOffset = this.getTotalSize() - size;
68873
+ const maxOffset = this.getTotalSize() + this.options.scrollMargin - size;
68776
68874
  return Math.max(Math.min(maxOffset, toOffset), 0);
68777
68875
  };
68778
68876
  this.getOffsetForIndex = (index, align = "auto") => {
@@ -68799,14 +68897,7 @@ focus outline in that case.
68799
68897
  ];
68800
68898
  };
68801
68899
  this.isDynamicMode = () => this.elementsCache.size > 0;
68802
- this.cancelScrollToIndex = () => {
68803
- if (this.scrollToIndexTimeoutId !== null && this.targetWindow) {
68804
- this.targetWindow.clearTimeout(this.scrollToIndexTimeoutId);
68805
- this.scrollToIndexTimeoutId = null;
68806
- }
68807
- };
68808
68900
  this.scrollToOffset = (toOffset, { align = "start", behavior } = {}) => {
68809
- this.cancelScrollToIndex();
68810
68901
  if (behavior === "smooth" && this.isDynamicMode()) {
68811
68902
  console.warn(
68812
68903
  "The `smooth` scroll behavior is not fully supported with dynamic size."
@@ -68818,39 +68909,52 @@ focus outline in that case.
68818
68909
  });
68819
68910
  };
68820
68911
  this.scrollToIndex = (index, { align: initialAlign = "auto", behavior } = {}) => {
68821
- index = Math.max(0, Math.min(index, this.options.count - 1));
68822
- this.cancelScrollToIndex();
68823
68912
  if (behavior === "smooth" && this.isDynamicMode()) {
68824
68913
  console.warn(
68825
68914
  "The `smooth` scroll behavior is not fully supported with dynamic size."
68826
68915
  );
68827
68916
  }
68828
- const offsetAndAlign = this.getOffsetForIndex(index, initialAlign);
68829
- if (!offsetAndAlign) return;
68830
- const [offset, align] = offsetAndAlign;
68831
- this._scrollToOffset(offset, { adjustments: void 0, behavior });
68832
- if (behavior !== "smooth" && this.isDynamicMode() && this.targetWindow) {
68833
- this.scrollToIndexTimeoutId = this.targetWindow.setTimeout(() => {
68834
- this.scrollToIndexTimeoutId = null;
68835
- const elementInDOM = this.elementsCache.has(
68836
- this.options.getItemKey(index)
68837
- );
68838
- if (elementInDOM) {
68839
- const result = this.getOffsetForIndex(index, align);
68840
- if (!result) return;
68841
- const [latestOffset] = result;
68842
- const currentScrollOffset = this.getScrollOffset();
68843
- if (!approxEqual(latestOffset, currentScrollOffset)) {
68844
- this.scrollToIndex(index, { align, behavior });
68845
- }
68846
- } else {
68847
- this.scrollToIndex(index, { align, behavior });
68917
+ index = Math.max(0, Math.min(index, this.options.count - 1));
68918
+ let attempts = 0;
68919
+ const maxAttempts = 10;
68920
+ const tryScroll = (currentAlign) => {
68921
+ if (!this.targetWindow) return;
68922
+ const offsetInfo = this.getOffsetForIndex(index, currentAlign);
68923
+ if (!offsetInfo) {
68924
+ console.warn("Failed to get offset for index:", index);
68925
+ return;
68926
+ }
68927
+ const [offset, align] = offsetInfo;
68928
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
68929
+ this.targetWindow.requestAnimationFrame(() => {
68930
+ const currentOffset = this.getScrollOffset();
68931
+ const afterInfo = this.getOffsetForIndex(index, align);
68932
+ if (!afterInfo) {
68933
+ console.warn("Failed to get offset for index:", index);
68934
+ return;
68935
+ }
68936
+ if (!approxEqual(afterInfo[0], currentOffset)) {
68937
+ scheduleRetry(align);
68848
68938
  }
68849
68939
  });
68850
- }
68940
+ };
68941
+ const scheduleRetry = (align) => {
68942
+ if (!this.targetWindow) return;
68943
+ attempts++;
68944
+ if (attempts < maxAttempts) {
68945
+ if (this.options.debug) {
68946
+ console.info("Schedule retry", attempts, maxAttempts);
68947
+ }
68948
+ this.targetWindow.requestAnimationFrame(() => tryScroll(align));
68949
+ } else {
68950
+ console.warn(
68951
+ `Failed to scroll to index ${index} after ${maxAttempts} attempts.`
68952
+ );
68953
+ }
68954
+ };
68955
+ tryScroll(initialAlign);
68851
68956
  };
68852
68957
  this.scrollBy = (delta, { behavior } = {}) => {
68853
- this.cancelScrollToIndex();
68854
68958
  if (behavior === "smooth" && this.isDynamicMode()) {
68855
68959
  console.warn(
68856
68960
  "The `smooth` scroll behavior is not fully supported with dynamic size."
@@ -79779,7 +79883,7 @@ focus outline in that case.
79779
79883
  /** @ignore */ const isBoolean = (x) => typeof x === 'boolean';
79780
79884
  /** @ignore */ const isFunction = (x) => typeof x === 'function';
79781
79885
  /** @ignore */
79782
- // eslint-disable-next-line @typescript-eslint/ban-types
79886
+ // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
79783
79887
  const isObject$1 = (x) => x != null && Object(x) === x;
79784
79888
  /** @ignore */
79785
79889
  const isPromise = (x) => {
@@ -79950,6 +80054,7 @@ focus outline in that case.
79950
80054
  const pump$1 = (iterator) => { iterator.next(); return iterator; };
79951
80055
  /** @ignore */
79952
80056
  function* toArrayBufferViewIterator(ArrayCtor, source) {
80057
+ // eslint-disable-next-line unicorn/consistent-function-scoping
79953
80058
  const wrap = function* (x) { yield x; };
79954
80059
  const buffers = (typeof source === 'string') ? wrap(source)
79955
80060
  : (ArrayBuffer.isView(source)) ? wrap(source)
@@ -79972,6 +80077,7 @@ focus outline in that case.
79972
80077
  if (isPromise(source)) {
79973
80078
  return yield __await(yield __await(yield* __asyncDelegator(__asyncValues(toArrayBufferViewAsyncIterator(ArrayCtor, yield __await(source))))));
79974
80079
  }
80080
+ // eslint-disable-next-line unicorn/consistent-function-scoping
79975
80081
  const wrap = function (x) { return __asyncGenerator(this, arguments, function* () { yield yield __await(yield __await(x)); }); };
79976
80082
  const emit = function (source) {
79977
80083
  return __asyncGenerator(this, arguments, function* () {
@@ -80096,7 +80202,8 @@ focus outline in that case.
80096
80202
  } while (!done);
80097
80203
  }
80098
80204
  catch (e) {
80099
- (threw = true) && (typeof it.throw === 'function') && (it.throw(e));
80205
+ threw = true;
80206
+ (typeof it.throw === 'function') && (it.throw(e));
80100
80207
  }
80101
80208
  finally {
80102
80209
  (threw === false) && (typeof it.return === 'function') && (it.return(null));
@@ -80140,7 +80247,8 @@ focus outline in that case.
80140
80247
  } while (!done);
80141
80248
  }
80142
80249
  catch (e) {
80143
- (threw = true) && (typeof it.throw === 'function') && (yield __await(it.throw(e)));
80250
+ threw = true;
80251
+ (typeof it.throw === 'function') && (yield __await(it.throw(e)));
80144
80252
  }
80145
80253
  finally {
80146
80254
  (threw === false) && (typeof it.return === 'function') && (yield __await(it.return(new Uint8Array(0))));
@@ -80188,7 +80296,8 @@ focus outline in that case.
80188
80296
  } while (!done);
80189
80297
  }
80190
80298
  catch (e) {
80191
- (threw = true) && (yield __await(it['cancel'](e)));
80299
+ threw = true;
80300
+ yield __await(it['cancel'](e));
80192
80301
  }
80193
80302
  finally {
80194
80303
  (threw === false) ? (yield __await(it['cancel']()))
@@ -86708,7 +86817,6 @@ focus outline in that case.
86708
86817
  // KIND, either express or implied. See the License for the
86709
86818
  // specific language governing permissions and limitations
86710
86819
  // under the License.
86711
- /* eslint-disable @typescript-eslint/naming-convention */
86712
86820
  var Builder$1 = Builder$2;
86713
86821
  var ByteBuffer$1 = ByteBuffer$2;
86714
86822
  /** @ignore */
@@ -88903,7 +89011,6 @@ focus outline in that case.
88903
89011
  // KIND, either express or implied. See the License for the
88904
89012
  // specific language governing permissions and limitations
88905
89013
  // under the License.
88906
- /* eslint-disable brace-style */
88907
89014
  /** @ignore */
88908
89015
  function schemaFromJSON(_schema, dictionaries = new Map()) {
88909
89016
  return new Schema(schemaFieldsFromJSON(_schema, dictionaries), customMetadataFromJSON(_schema['metadata']), dictionaries);
@@ -89075,7 +89182,6 @@ focus outline in that case.
89075
89182
  // KIND, either express or implied. See the License for the
89076
89183
  // specific language governing permissions and limitations
89077
89184
  // under the License.
89078
- /* eslint-disable brace-style */
89079
89185
  var Builder = Builder$2;
89080
89186
  var ByteBuffer = ByteBuffer$2;
89081
89187
  /**