@ni/nimble-components 35.3.0 → 35.3.2

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.
@@ -42642,6 +42642,9 @@ so this becomes the fallback color for the slot */ ''}
42642
42642
  keepOnSplit: true,
42643
42643
  isRequired: false
42644
42644
  };
42645
+ const nodeExtensionTypes = nodeExtensions.filter((ext) => ext.name !== "text").map((ext) => ext.name);
42646
+ const markExtensionTypes = markExtensions.map((ext) => ext.name);
42647
+ const allExtensionTypes = [...nodeExtensionTypes, ...markExtensionTypes];
42645
42648
  extensions.forEach((extension) => {
42646
42649
  const context = {
42647
42650
  name: extension.name,
@@ -42659,7 +42662,19 @@ so this becomes the fallback color for the slot */ ''}
42659
42662
  }
42660
42663
  const globalAttributes = addGlobalAttributes();
42661
42664
  globalAttributes.forEach((globalAttribute) => {
42662
- globalAttribute.types.forEach((type) => {
42665
+ let resolvedTypes;
42666
+ if (Array.isArray(globalAttribute.types)) {
42667
+ resolvedTypes = globalAttribute.types;
42668
+ } else if (globalAttribute.types === "*") {
42669
+ resolvedTypes = allExtensionTypes;
42670
+ } else if (globalAttribute.types === "nodes") {
42671
+ resolvedTypes = nodeExtensionTypes;
42672
+ } else if (globalAttribute.types === "marks") {
42673
+ resolvedTypes = markExtensionTypes;
42674
+ } else {
42675
+ resolvedTypes = [];
42676
+ }
42677
+ resolvedTypes.forEach((type) => {
42663
42678
  Object.entries(globalAttribute.attributes).forEach(([name, attribute]) => {
42664
42679
  extensionAttributes.push({
42665
42680
  type,
@@ -43199,6 +43214,9 @@ so this becomes the fallback color for the slot */ ''}
43199
43214
  const from = $from.pos;
43200
43215
  const to = $to.pos;
43201
43216
  state.doc.nodesBetween(from, to, (node, pos) => {
43217
+ if (type && node.inlineContent && !node.type.allowsMarkType(type)) {
43218
+ return false;
43219
+ }
43202
43220
  if (!node.isText && !node.marks.length) {
43203
43221
  return;
43204
43222
  }
@@ -44759,6 +44777,39 @@ so this becomes the fallback color for the slot */ ''}
44759
44777
  };
44760
44778
  }, baseDispatch);
44761
44779
  }
44780
+ /**
44781
+ * Get the composed transformPastedHTML function from all extensions.
44782
+ * @param baseTransform The base transform function (e.g. from the editor props)
44783
+ * @returns A composed transform function that chains all extension transforms
44784
+ */
44785
+ transformPastedHTML(baseTransform) {
44786
+ const { editor } = this;
44787
+ const extensions = sortExtensions([...this.extensions]);
44788
+ return extensions.reduce(
44789
+ (transform, extension) => {
44790
+ const context = {
44791
+ name: extension.name,
44792
+ options: extension.options,
44793
+ storage: this.editor.extensionStorage[extension.name],
44794
+ editor,
44795
+ type: getSchemaTypeByName(extension.name, this.schema)
44796
+ };
44797
+ const extensionTransform = getExtensionField(
44798
+ extension,
44799
+ "transformPastedHTML",
44800
+ context
44801
+ );
44802
+ if (!extensionTransform) {
44803
+ return transform;
44804
+ }
44805
+ return (html, view) => {
44806
+ const transformedHtml = transform(html, view);
44807
+ return extensionTransform.call(context, transformedHtml);
44808
+ };
44809
+ },
44810
+ baseTransform || ((html) => html)
44811
+ );
44812
+ }
44762
44813
  get markViews() {
44763
44814
  const { editor } = this;
44764
44815
  const { markExtensions } = splitExtensions(this.extensions);
@@ -45754,7 +45805,7 @@ img.ProseMirror-separator {
45754
45805
  return this.options.editable && this.view && this.view.editable;
45755
45806
  }
45756
45807
  /**
45757
- * Returns the editor state.
45808
+ * Returns the editor view.
45758
45809
  */
45759
45810
  get view() {
45760
45811
  if (this.editorView) {
@@ -45922,6 +45973,8 @@ img.ProseMirror-separator {
45922
45973
  const { editorProps, enableExtensionDispatchTransaction } = this.options;
45923
45974
  const baseDispatch = editorProps.dispatchTransaction || this.dispatchTransaction.bind(this);
45924
45975
  const dispatch = enableExtensionDispatchTransaction ? this.extensionManager.dispatchTransaction(baseDispatch) : baseDispatch;
45976
+ const baseTransformPastedHTML = editorProps.transformPastedHTML;
45977
+ const transformPastedHTML = this.extensionManager.transformPastedHTML(baseTransformPastedHTML);
45925
45978
  this.editorView = new EditorView(element, {
45926
45979
  ...editorProps,
45927
45980
  attributes: {
@@ -45930,6 +45983,7 @@ img.ProseMirror-separator {
45930
45983
  ...editorProps == null ? void 0 : editorProps.attributes
45931
45984
  },
45932
45985
  dispatchTransaction: dispatch,
45986
+ transformPastedHTML,
45933
45987
  state: this.editorState,
45934
45988
  markViews: this.extensionManager.markViews,
45935
45989
  nodeViews: this.extensionManager.nodeViews
@@ -52693,7 +52747,14 @@ ${renderedContent}
52693
52747
  if (url.length <= proto.length) return false
52694
52748
 
52695
52749
  // disallow '*' at the end of the link (conflicts with emphasis)
52696
- url = url.replace(/\*+$/, '');
52750
+ // do manual backsearch to avoid perf issues with regex /\*+$/ on "****...****a".
52751
+ let urlEnd = url.length;
52752
+ while (urlEnd > 0 && url.charCodeAt(urlEnd - 1) === 0x2A/* * */) {
52753
+ urlEnd--;
52754
+ }
52755
+ if (urlEnd !== url.length) {
52756
+ url = url.slice(0, urlEnd);
52757
+ }
52697
52758
 
52698
52759
  const fullUrl = state.md.normalizeLink(url);
52699
52760
  if (!state.md.validateLink(fullUrl)) return false
@@ -71897,6 +71958,7 @@ focus outline in that case.
71897
71958
  const [offset, align] = offsetInfo;
71898
71959
  this._scrollToOffset(offset, { adjustments: void 0, behavior });
71899
71960
  this.targetWindow.requestAnimationFrame(() => {
71961
+ if (!this.targetWindow) return;
71900
71962
  const verify = () => {
71901
71963
  if (this.currentScrollToIndex !== index) return;
71902
71964
  const currentOffset = this.getScrollOffset();
@@ -73302,25 +73364,32 @@ focus outline in that case.
73302
73364
  this.columnIndex = -1;
73303
73365
  this.focusWithinTable = false;
73304
73366
  this.isCurrentlyFocusingElement = false;
73367
+ this.focusedViaPointer = false;
73305
73368
  this.visibleRowNotifiers = [];
73306
73369
  this.onTableFocusIn = (event) => {
73307
73370
  this.focusWithinTable = true;
73308
- this.updateFocusStateFromActiveElement(false);
73371
+ this.updateFocusStateFromActiveElement();
73309
73372
  // Sets initial focus on the appropriate table content
73310
73373
  const actionMenuOpen = this.table.openActionMenuRecordId !== undefined;
73311
- if ((event.target === this.table
73312
- || this.focusType === TableFocusType.none)
73313
- && !actionMenuOpen) {
73314
- let focusHeader = true;
73315
- if (this.hasRowOrCellFocusType()
73316
- && this.scrollToAndFocusRow(this.rowIndex)) {
73317
- focusHeader = false;
73374
+ if (!actionMenuOpen) {
73375
+ if (this.focusType === TableFocusType.none) {
73376
+ this.focusSomethingOtherThanTheTable();
73318
73377
  }
73319
- if (focusHeader && !this.setFocusOnHeader()) {
73320
- // nothing to focus
73321
- this.table.blur();
73378
+ else if (event.target === this.table) {
73379
+ // restore focus to last focused element
73380
+ if (this.hasRowOrCellFocusType() && this.rowIndexIsValid(this.rowIndex)) {
73381
+ this.scrollToAndFocusRow(this.rowIndex);
73382
+ }
73383
+ else if (this.hasHeaderFocusType()) {
73384
+ this.focusHeaderElement();
73385
+ }
73386
+ else {
73387
+ // should only get here if focusType was row/cell, but rowIndex was invalid
73388
+ this.focusSomethingOtherThanTheTable();
73389
+ }
73322
73390
  }
73323
73391
  }
73392
+ this.focusedViaPointer = false;
73324
73393
  };
73325
73394
  this.onTableFocusOut = () => {
73326
73395
  this.focusWithinTable = false;
@@ -73335,12 +73404,18 @@ focus outline in that case.
73335
73404
  };
73336
73405
  this.onCellViewFocusIn = (event) => {
73337
73406
  event.stopPropagation();
73338
- this.updateFocusStateFromActiveElement(false);
73407
+ this.updateFocusStateFromActiveElement();
73339
73408
  };
73340
73409
  this.onCellFocusIn = (event) => {
73341
73410
  event.stopPropagation();
73342
73411
  const cell = event.detail;
73343
- this.updateFocusStateFromActiveElement(true);
73412
+ const row = this.updateFocusStateFromActiveElement();
73413
+ if (row) {
73414
+ if (this.hasRowOrCellFocusType()
73415
+ && this.rowIndex !== row.resolvedRowIndex) {
73416
+ this.setRowFocusState(row.resolvedRowIndex);
73417
+ }
73418
+ }
73344
73419
  // Currently, clicking a non-interactive cell only updates the focus state to that row, it
73345
73420
  // doesn't focus the cell. If we revisit this, we most likely need to set the cells to tabindex=-1
73346
73421
  // upfront too, so their focusing behavior is consistent whether they've been previously keyboard
@@ -73411,6 +73486,12 @@ focus outline in that case.
73411
73486
  }
73412
73487
  }
73413
73488
  };
73489
+ this.onPointerDown = () => {
73490
+ this.focusedViaPointer = true;
73491
+ };
73492
+ this.onPointerUpOrCancel = () => {
73493
+ this.focusedViaPointer = false;
73494
+ };
73414
73495
  this.onViewportKeyDown = (event) => {
73415
73496
  let handleEvent = !this.inNavigationMode
73416
73497
  && (event.key === keyArrowUp || event.key === keyArrowDown);
@@ -73446,6 +73527,9 @@ focus outline in that case.
73446
73527
  connect() {
73447
73528
  this.table.addEventListener('keydown', this.onCaptureKeyDown, { capture: true });
73448
73529
  this.table.addEventListener('keydown', this.onKeyDown);
73530
+ this.table.addEventListener('pointerdown', this.onPointerDown);
73531
+ this.table.addEventListener('pointerup', this.onPointerUpOrCancel);
73532
+ this.table.addEventListener('pointercancel', this.onPointerUpOrCancel);
73449
73533
  this.table.addEventListener('focusin', this.onTableFocusIn);
73450
73534
  this.table.addEventListener('focusout', this.onTableFocusOut);
73451
73535
  this.table.viewport.addEventListener('keydown', this.onViewportKeyDown);
@@ -73457,6 +73541,9 @@ focus outline in that case.
73457
73541
  disconnect() {
73458
73542
  this.table.removeEventListener('keydown', this.onCaptureKeyDown, { capture: true });
73459
73543
  this.table.removeEventListener('keydown', this.onKeyDown);
73544
+ this.table.removeEventListener('pointerdown', this.onPointerDown);
73545
+ this.table.removeEventListener('pointerup', this.onPointerUpOrCancel);
73546
+ this.table.removeEventListener('pointercancel', this.onPointerUpOrCancel);
73460
73547
  this.table.removeEventListener('focusin', this.onTableFocusIn);
73461
73548
  this.table.removeEventListener('focusout', this.onTableFocusOut);
73462
73549
  this.table.viewport.removeEventListener('keydown', this.onViewportKeyDown);
@@ -73548,6 +73635,13 @@ focus outline in that case.
73548
73635
  this.setCellActionMenuFocusState(row.resolvedRowIndex, columnIndex, false);
73549
73636
  }
73550
73637
  }
73638
+ focusSomethingOtherThanTheTable() {
73639
+ this.setDefaultFocus();
73640
+ if (this.focusType === TableFocusType.none) {
73641
+ // nothing within the table to focus
73642
+ this.table.blur();
73643
+ }
73644
+ }
73551
73645
  onEnterPressed(ctrlKey) {
73552
73646
  let row;
73553
73647
  let rowElements;
@@ -73719,7 +73813,7 @@ focus outline in that case.
73719
73813
  this.headerActionIndex = nextFocusState.headerActionIndex ?? this.headerActionIndex;
73720
73814
  this.cellContentIndex = nextFocusState.cellContentIndex ?? this.cellContentIndex;
73721
73815
  if (this.hasRowOrCellFocusType()) {
73722
- this.focusCurrentRow(false);
73816
+ this.focusCurrentRow(!this.focusedViaPointer);
73723
73817
  }
73724
73818
  else {
73725
73819
  this.focusHeaderElement();
@@ -73891,35 +73985,39 @@ focus outline in that case.
73891
73985
  }
73892
73986
  return false;
73893
73987
  }
73894
- updateFocusStateFromActiveElement(setRowFocus) {
73988
+ updateFocusStateFromActiveElement() {
73895
73989
  // If the user is interacting with the table with non-keyboard methods (like mouse), we need to
73896
73990
  // update our focus state based on the current active/focused element
73897
- const activeElement = this.getActiveElement();
73898
- if (activeElement) {
73899
- const row = this.getContainingRow(activeElement);
73900
- if (row) {
73901
- if (!(row instanceof TableGroupRow)) {
73902
- const cell = this.getContainingCell(activeElement);
73903
- if (cell) {
73904
- const columnIndex = this.table.visibleColumns.indexOf(cell.column);
73905
- if (cell.actionMenuButton === activeElement) {
73906
- this.setCellActionMenuFocusState(row.resolvedRowIndex, columnIndex, false);
73907
- return;
73908
- }
73909
- const contentIndex = cell.cellView.tabbableChildren.indexOf(activeElement);
73910
- if (contentIndex > -1) {
73911
- this.setCellContentFocusState(contentIndex, row.resolvedRowIndex, columnIndex, false);
73912
- return;
73913
- }
73914
- }
73915
- }
73916
- if (setRowFocus
73917
- && this.hasRowOrCellFocusType()
73918
- && this.rowIndex !== row.resolvedRowIndex) {
73919
- this.setRowFocusState(row.resolvedRowIndex);
73920
- }
73991
+ const { activeElement, row, cell } = this.getActiveElementCellAndRow();
73992
+ if (!cell) {
73993
+ return row;
73994
+ }
73995
+ const columnIndex = this.table.visibleColumns.indexOf(cell.column);
73996
+ if (cell.actionMenuButton === activeElement) {
73997
+ this.setCellActionMenuFocusState(row.resolvedRowIndex, columnIndex, false);
73998
+ }
73999
+ else {
74000
+ const contentIndex = cell.cellView.tabbableChildren.indexOf(activeElement);
74001
+ if (contentIndex > -1) {
74002
+ this.setCellContentFocusState(contentIndex, row.resolvedRowIndex, columnIndex, false);
73921
74003
  }
73922
74004
  }
74005
+ return row;
74006
+ }
74007
+ getActiveElementCellAndRow() {
74008
+ const activeElement = this.getActiveElement();
74009
+ if (!activeElement) {
74010
+ return {};
74011
+ }
74012
+ const row = this.getContainingRow(activeElement);
74013
+ if (!row) {
74014
+ return { activeElement };
74015
+ }
74016
+ if (row instanceof TableGroupRow) {
74017
+ return { activeElement, row };
74018
+ }
74019
+ const cell = this.getContainingCell(activeElement);
74020
+ return { activeElement, row, cell };
73923
74021
  }
73924
74022
  focusElement(element, focusOptions) {
73925
74023
  const previousActiveElement = this.getActiveElement();
@@ -73950,13 +74048,6 @@ focus outline in that case.
73950
74048
  menuButton.classList.remove('cell-action-menu-focused');
73951
74049
  }
73952
74050
  }
73953
- setFocusOnHeader() {
73954
- if (this.hasHeaderFocusType()) {
73955
- return this.focusHeaderElement();
73956
- }
73957
- this.setDefaultFocus();
73958
- return this.focusType !== TableFocusType.none;
73959
- }
73960
74051
  setDefaultFocus() {
73961
74052
  const headerElements = this.getTableHeaderFocusableElements();
73962
74053
  if (!this.trySetHeaderActionFocus(headerElements, 0)
@@ -73966,20 +74057,19 @@ focus outline in that case.
73966
74057
  }
73967
74058
  }
73968
74059
  scrollToAndFocusRow(totalRowIndex, scrollOptions) {
73969
- if (totalRowIndex >= 0 && totalRowIndex < this.table.tableData.length) {
73970
- switch (this.focusType) {
73971
- case TableFocusType.none:
73972
- case TableFocusType.headerActions:
73973
- case TableFocusType.columnHeader:
73974
- this.setRowFocusState(totalRowIndex);
73975
- break;
73976
- }
73977
- this.rowIndex = totalRowIndex;
73978
- this.virtualizer.scrollToIndex(totalRowIndex, scrollOptions);
73979
- this.focusCurrentRow(true);
73980
- return true;
74060
+ if (!this.rowIndexIsValid(totalRowIndex)) {
74061
+ return false;
73981
74062
  }
73982
- return false;
74063
+ if (!this.hasRowOrCellFocusType()) {
74064
+ this.setRowFocusState();
74065
+ }
74066
+ this.rowIndex = totalRowIndex;
74067
+ this.virtualizer.scrollToIndex(totalRowIndex, scrollOptions);
74068
+ this.focusCurrentRow(!this.focusedViaPointer);
74069
+ return true;
74070
+ }
74071
+ rowIndexIsValid(rowIndex) {
74072
+ return rowIndex >= 0 && rowIndex < this.table.tableData.length;
73983
74073
  }
73984
74074
  focusCurrentRow(allowScroll) {
73985
74075
  const visibleRowIndex = this.getCurrentRowVisibleIndex();
@@ -74047,7 +74137,7 @@ focus outline in that case.
74047
74137
  break;
74048
74138
  }
74049
74139
  if (focusableElement) {
74050
- this.focusElement(focusableElement);
74140
+ this.focusElement(focusableElement, { preventScroll: this.focusedViaPointer });
74051
74141
  return true;
74052
74142
  }
74053
74143
  return false;
@@ -74168,7 +74258,7 @@ focus outline in that case.
74168
74258
  trySetRowSelectionCheckboxFocus(rowElements) {
74169
74259
  if (rowElements?.selectionCheckbox) {
74170
74260
  this.focusType = TableFocusType.rowSelectionCheckbox;
74171
- this.focusCurrentRow(true);
74261
+ this.focusCurrentRow(!this.focusedViaPointer);
74172
74262
  return true;
74173
74263
  }
74174
74264
  return false;
@@ -74257,7 +74347,7 @@ focus outline in that case.
74257
74347
  this.rowIndex = rowIndex;
74258
74348
  this.columnIndex = columnIndex;
74259
74349
  if (focusElement) {
74260
- this.focusCurrentRow(true);
74350
+ this.focusCurrentRow(!this.focusedViaPointer);
74261
74351
  }
74262
74352
  }
74263
74353
  isResolvedRowType(row) {