@ni/ok-components 0.2.12 → 0.2.14

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.
@@ -73304,25 +73304,32 @@ focus outline in that case.
73304
73304
  this.columnIndex = -1;
73305
73305
  this.focusWithinTable = false;
73306
73306
  this.isCurrentlyFocusingElement = false;
73307
+ this.focusedViaPointer = false;
73307
73308
  this.visibleRowNotifiers = [];
73308
73309
  this.onTableFocusIn = (event) => {
73309
73310
  this.focusWithinTable = true;
73310
- this.updateFocusStateFromActiveElement(false);
73311
+ this.updateFocusStateFromActiveElement();
73311
73312
  // Sets initial focus on the appropriate table content
73312
73313
  const actionMenuOpen = this.table.openActionMenuRecordId !== undefined;
73313
- if ((event.target === this.table
73314
- || this.focusType === TableFocusType.none)
73315
- && !actionMenuOpen) {
73316
- let focusHeader = true;
73317
- if (this.hasRowOrCellFocusType()
73318
- && this.scrollToAndFocusRow(this.rowIndex)) {
73319
- focusHeader = false;
73314
+ if (!actionMenuOpen) {
73315
+ if (this.focusType === TableFocusType.none) {
73316
+ this.focusSomethingOtherThanTheTable();
73320
73317
  }
73321
- if (focusHeader && !this.setFocusOnHeader()) {
73322
- // nothing to focus
73323
- this.table.blur();
73318
+ else if (event.target === this.table) {
73319
+ // restore focus to last focused element
73320
+ if (this.hasRowOrCellFocusType() && this.rowIndexIsValid(this.rowIndex)) {
73321
+ this.scrollToAndFocusRow(this.rowIndex);
73322
+ }
73323
+ else if (this.hasHeaderFocusType()) {
73324
+ this.focusHeaderElement();
73325
+ }
73326
+ else {
73327
+ // should only get here if focusType was row/cell, but rowIndex was invalid
73328
+ this.focusSomethingOtherThanTheTable();
73329
+ }
73324
73330
  }
73325
73331
  }
73332
+ this.focusedViaPointer = false;
73326
73333
  };
73327
73334
  this.onTableFocusOut = () => {
73328
73335
  this.focusWithinTable = false;
@@ -73337,12 +73344,18 @@ focus outline in that case.
73337
73344
  };
73338
73345
  this.onCellViewFocusIn = (event) => {
73339
73346
  event.stopPropagation();
73340
- this.updateFocusStateFromActiveElement(false);
73347
+ this.updateFocusStateFromActiveElement();
73341
73348
  };
73342
73349
  this.onCellFocusIn = (event) => {
73343
73350
  event.stopPropagation();
73344
73351
  const cell = event.detail;
73345
- this.updateFocusStateFromActiveElement(true);
73352
+ const row = this.updateFocusStateFromActiveElement();
73353
+ if (row) {
73354
+ if (this.hasRowOrCellFocusType()
73355
+ && this.rowIndex !== row.resolvedRowIndex) {
73356
+ this.setRowFocusState(row.resolvedRowIndex);
73357
+ }
73358
+ }
73346
73359
  // Currently, clicking a non-interactive cell only updates the focus state to that row, it
73347
73360
  // doesn't focus the cell. If we revisit this, we most likely need to set the cells to tabindex=-1
73348
73361
  // upfront too, so their focusing behavior is consistent whether they've been previously keyboard
@@ -73413,6 +73426,12 @@ focus outline in that case.
73413
73426
  }
73414
73427
  }
73415
73428
  };
73429
+ this.onPointerDown = () => {
73430
+ this.focusedViaPointer = true;
73431
+ };
73432
+ this.onPointerUpOrCancel = () => {
73433
+ this.focusedViaPointer = false;
73434
+ };
73416
73435
  this.onViewportKeyDown = (event) => {
73417
73436
  let handleEvent = !this.inNavigationMode
73418
73437
  && (event.key === keyArrowUp || event.key === keyArrowDown);
@@ -73448,6 +73467,9 @@ focus outline in that case.
73448
73467
  connect() {
73449
73468
  this.table.addEventListener('keydown', this.onCaptureKeyDown, { capture: true });
73450
73469
  this.table.addEventListener('keydown', this.onKeyDown);
73470
+ this.table.addEventListener('pointerdown', this.onPointerDown);
73471
+ this.table.addEventListener('pointerup', this.onPointerUpOrCancel);
73472
+ this.table.addEventListener('pointercancel', this.onPointerUpOrCancel);
73451
73473
  this.table.addEventListener('focusin', this.onTableFocusIn);
73452
73474
  this.table.addEventListener('focusout', this.onTableFocusOut);
73453
73475
  this.table.viewport.addEventListener('keydown', this.onViewportKeyDown);
@@ -73459,6 +73481,9 @@ focus outline in that case.
73459
73481
  disconnect() {
73460
73482
  this.table.removeEventListener('keydown', this.onCaptureKeyDown, { capture: true });
73461
73483
  this.table.removeEventListener('keydown', this.onKeyDown);
73484
+ this.table.removeEventListener('pointerdown', this.onPointerDown);
73485
+ this.table.removeEventListener('pointerup', this.onPointerUpOrCancel);
73486
+ this.table.removeEventListener('pointercancel', this.onPointerUpOrCancel);
73462
73487
  this.table.removeEventListener('focusin', this.onTableFocusIn);
73463
73488
  this.table.removeEventListener('focusout', this.onTableFocusOut);
73464
73489
  this.table.viewport.removeEventListener('keydown', this.onViewportKeyDown);
@@ -73550,6 +73575,13 @@ focus outline in that case.
73550
73575
  this.setCellActionMenuFocusState(row.resolvedRowIndex, columnIndex, false);
73551
73576
  }
73552
73577
  }
73578
+ focusSomethingOtherThanTheTable() {
73579
+ this.setDefaultFocus();
73580
+ if (this.focusType === TableFocusType.none) {
73581
+ // nothing within the table to focus
73582
+ this.table.blur();
73583
+ }
73584
+ }
73553
73585
  onEnterPressed(ctrlKey) {
73554
73586
  let row;
73555
73587
  let rowElements;
@@ -73721,7 +73753,7 @@ focus outline in that case.
73721
73753
  this.headerActionIndex = nextFocusState.headerActionIndex ?? this.headerActionIndex;
73722
73754
  this.cellContentIndex = nextFocusState.cellContentIndex ?? this.cellContentIndex;
73723
73755
  if (this.hasRowOrCellFocusType()) {
73724
- this.focusCurrentRow(false);
73756
+ this.focusCurrentRow(!this.focusedViaPointer);
73725
73757
  }
73726
73758
  else {
73727
73759
  this.focusHeaderElement();
@@ -73893,35 +73925,39 @@ focus outline in that case.
73893
73925
  }
73894
73926
  return false;
73895
73927
  }
73896
- updateFocusStateFromActiveElement(setRowFocus) {
73928
+ updateFocusStateFromActiveElement() {
73897
73929
  // If the user is interacting with the table with non-keyboard methods (like mouse), we need to
73898
73930
  // update our focus state based on the current active/focused element
73899
- const activeElement = this.getActiveElement();
73900
- if (activeElement) {
73901
- const row = this.getContainingRow(activeElement);
73902
- if (row) {
73903
- if (!(row instanceof TableGroupRow)) {
73904
- const cell = this.getContainingCell(activeElement);
73905
- if (cell) {
73906
- const columnIndex = this.table.visibleColumns.indexOf(cell.column);
73907
- if (cell.actionMenuButton === activeElement) {
73908
- this.setCellActionMenuFocusState(row.resolvedRowIndex, columnIndex, false);
73909
- return;
73910
- }
73911
- const contentIndex = cell.cellView.tabbableChildren.indexOf(activeElement);
73912
- if (contentIndex > -1) {
73913
- this.setCellContentFocusState(contentIndex, row.resolvedRowIndex, columnIndex, false);
73914
- return;
73915
- }
73916
- }
73917
- }
73918
- if (setRowFocus
73919
- && this.hasRowOrCellFocusType()
73920
- && this.rowIndex !== row.resolvedRowIndex) {
73921
- this.setRowFocusState(row.resolvedRowIndex);
73922
- }
73931
+ const { activeElement, row, cell } = this.getActiveElementCellAndRow();
73932
+ if (!cell) {
73933
+ return row;
73934
+ }
73935
+ const columnIndex = this.table.visibleColumns.indexOf(cell.column);
73936
+ if (cell.actionMenuButton === activeElement) {
73937
+ this.setCellActionMenuFocusState(row.resolvedRowIndex, columnIndex, false);
73938
+ }
73939
+ else {
73940
+ const contentIndex = cell.cellView.tabbableChildren.indexOf(activeElement);
73941
+ if (contentIndex > -1) {
73942
+ this.setCellContentFocusState(contentIndex, row.resolvedRowIndex, columnIndex, false);
73923
73943
  }
73924
73944
  }
73945
+ return row;
73946
+ }
73947
+ getActiveElementCellAndRow() {
73948
+ const activeElement = this.getActiveElement();
73949
+ if (!activeElement) {
73950
+ return {};
73951
+ }
73952
+ const row = this.getContainingRow(activeElement);
73953
+ if (!row) {
73954
+ return { activeElement };
73955
+ }
73956
+ if (row instanceof TableGroupRow) {
73957
+ return { activeElement, row };
73958
+ }
73959
+ const cell = this.getContainingCell(activeElement);
73960
+ return { activeElement, row, cell };
73925
73961
  }
73926
73962
  focusElement(element, focusOptions) {
73927
73963
  const previousActiveElement = this.getActiveElement();
@@ -73952,13 +73988,6 @@ focus outline in that case.
73952
73988
  menuButton.classList.remove('cell-action-menu-focused');
73953
73989
  }
73954
73990
  }
73955
- setFocusOnHeader() {
73956
- if (this.hasHeaderFocusType()) {
73957
- return this.focusHeaderElement();
73958
- }
73959
- this.setDefaultFocus();
73960
- return this.focusType !== TableFocusType.none;
73961
- }
73962
73991
  setDefaultFocus() {
73963
73992
  const headerElements = this.getTableHeaderFocusableElements();
73964
73993
  if (!this.trySetHeaderActionFocus(headerElements, 0)
@@ -73968,20 +73997,19 @@ focus outline in that case.
73968
73997
  }
73969
73998
  }
73970
73999
  scrollToAndFocusRow(totalRowIndex, scrollOptions) {
73971
- if (totalRowIndex >= 0 && totalRowIndex < this.table.tableData.length) {
73972
- switch (this.focusType) {
73973
- case TableFocusType.none:
73974
- case TableFocusType.headerActions:
73975
- case TableFocusType.columnHeader:
73976
- this.setRowFocusState(totalRowIndex);
73977
- break;
73978
- }
73979
- this.rowIndex = totalRowIndex;
73980
- this.virtualizer.scrollToIndex(totalRowIndex, scrollOptions);
73981
- this.focusCurrentRow(true);
73982
- return true;
74000
+ if (!this.rowIndexIsValid(totalRowIndex)) {
74001
+ return false;
73983
74002
  }
73984
- return false;
74003
+ if (!this.hasRowOrCellFocusType()) {
74004
+ this.setRowFocusState();
74005
+ }
74006
+ this.rowIndex = totalRowIndex;
74007
+ this.virtualizer.scrollToIndex(totalRowIndex, scrollOptions);
74008
+ this.focusCurrentRow(!this.focusedViaPointer);
74009
+ return true;
74010
+ }
74011
+ rowIndexIsValid(rowIndex) {
74012
+ return rowIndex >= 0 && rowIndex < this.table.tableData.length;
73985
74013
  }
73986
74014
  focusCurrentRow(allowScroll) {
73987
74015
  const visibleRowIndex = this.getCurrentRowVisibleIndex();
@@ -74049,7 +74077,7 @@ focus outline in that case.
74049
74077
  break;
74050
74078
  }
74051
74079
  if (focusableElement) {
74052
- this.focusElement(focusableElement);
74080
+ this.focusElement(focusableElement, { preventScroll: this.focusedViaPointer });
74053
74081
  return true;
74054
74082
  }
74055
74083
  return false;
@@ -74170,7 +74198,7 @@ focus outline in that case.
74170
74198
  trySetRowSelectionCheckboxFocus(rowElements) {
74171
74199
  if (rowElements?.selectionCheckbox) {
74172
74200
  this.focusType = TableFocusType.rowSelectionCheckbox;
74173
- this.focusCurrentRow(true);
74201
+ this.focusCurrentRow(!this.focusedViaPointer);
74174
74202
  return true;
74175
74203
  }
74176
74204
  return false;
@@ -74259,7 +74287,7 @@ focus outline in that case.
74259
74287
  this.rowIndex = rowIndex;
74260
74288
  this.columnIndex = columnIndex;
74261
74289
  if (focusElement) {
74262
- this.focusCurrentRow(true);
74290
+ this.focusCurrentRow(!this.focusedViaPointer);
74263
74291
  }
74264
74292
  }
74265
74293
  isResolvedRowType(row) {
@@ -96975,6 +97003,7 @@ focus outline in that case.
96975
97003
 
96976
97004
  const styles$7 = css `
96977
97005
  ${display$1('flex')}
97006
+ ${styles$Y}
96978
97007
 
96979
97008
  :host {
96980
97009
  width: 100%;
@@ -97016,6 +97045,22 @@ focus outline in that case.
97016
97045
  border-bottom-color: ${borderHoverColor};
97017
97046
  }
97018
97047
 
97048
+ :host([error-visible]) .container::after {
97049
+ border-bottom-color: ${failColor};
97050
+ }
97051
+
97052
+ :host([error-visible]) .container {
97053
+ border-bottom-color: ${failColor};
97054
+ }
97055
+
97056
+ :host([error-visible]:hover) .container::after {
97057
+ border-bottom-color: ${failColor};
97058
+ }
97059
+
97060
+ :host([error-visible]:focus-within) .container {
97061
+ border-bottom-color: ${failColor};
97062
+ }
97063
+
97019
97064
  @media (prefers-reduced-motion) {
97020
97065
  .container::after {
97021
97066
  transition-duration: 0s;
@@ -97042,6 +97087,17 @@ focus outline in that case.
97042
97087
  color: ${controlLabelFontColor};
97043
97088
  }
97044
97089
 
97090
+ :host([error-visible]) .error-icon {
97091
+ display: none;
97092
+ }
97093
+
97094
+ :host([error-visible]) .error-icon.scrollbar-width-calculated {
97095
+ display: inline-flex;
97096
+ position: absolute;
97097
+ top: ${mediumPadding};
97098
+ right: var(--ni-private-scrollbar-width);
97099
+ }
97100
+
97045
97101
  .action-button {
97046
97102
  align-self: flex-end;
97047
97103
  width: 80px;
@@ -97073,12 +97129,18 @@ focus outline in that case.
97073
97129
  ${x => (x.processing ? x.stopButtonLabel : x.sendButtonLabel)}
97074
97130
  ${when(x => x.processing, html `<${iconStopSquareTag} slot="start"></${iconStopSquareTag}>`, html `<${iconPaperPlaneTag} slot="start"></${iconPaperPlaneTag}>`)}
97075
97131
  </${buttonTag}>
97132
+ <${iconExclamationMarkTag}
97133
+ severity="error"
97134
+ class="error-icon ${x => (x.scrollbarWidth >= 0 ? 'scrollbar-width-calculated' : '')}"
97135
+ style="--ni-private-scrollbar-width: ${x => x.scrollbarWidth}px;"
97136
+ ></${iconExclamationMarkTag}>
97137
+ ${errorTextTemplate}
97076
97138
  </div>`;
97077
97139
 
97078
97140
  /**
97079
97141
  * A Spright component for composing and sending a chat message
97080
97142
  */
97081
- class ChatInput extends FoundationElement {
97143
+ class ChatInput extends mixinErrorPattern(FoundationElement) {
97082
97144
  constructor() {
97083
97145
  super(...arguments);
97084
97146
  this.value = '';
@@ -97088,6 +97150,12 @@ focus outline in that case.
97088
97150
  * @internal
97089
97151
  */
97090
97152
  this.disableSendButton = true;
97153
+ /**
97154
+ * The width of the vertical scrollbar, if displayed.
97155
+ * @internal
97156
+ */
97157
+ this.scrollbarWidth = -1;
97158
+ this.updateScrollbarWidthQueued = false;
97091
97159
  }
97092
97160
  /**
97093
97161
  * @internal
@@ -97108,6 +97176,19 @@ focus outline in that case.
97108
97176
  textAreaInputHandler() {
97109
97177
  this.value = this.textArea.value;
97110
97178
  this.disableSendButton = this.shouldDisableSendButton();
97179
+ this.queueUpdateScrollbarWidth();
97180
+ }
97181
+ // If a property can affect whether a scrollbar is visible, we need to
97182
+ // call queueUpdateScrollbarWidth() when it changes. The exceptions are
97183
+ // properties that affect size (e.g. height, width, cols, rows), because
97184
+ // we already have a ResizeObserver handling those changes. Also,
97185
+ // a change to errorVisible cannot cause scrollbar visibility to change,
97186
+ // because we always reserve space for the error icon.
97187
+ /**
97188
+ * @internal
97189
+ */
97190
+ placeholderChanged() {
97191
+ this.queueUpdateScrollbarWidth();
97111
97192
  }
97112
97193
  /**
97113
97194
  * @internal
@@ -97116,6 +97197,7 @@ focus outline in that case.
97116
97197
  if (this.textArea) {
97117
97198
  this.textArea.value = this.value;
97118
97199
  this.disableSendButton = this.shouldDisableSendButton();
97200
+ this.queueUpdateScrollbarWidth();
97119
97201
  }
97120
97202
  }
97121
97203
  /**
@@ -97125,6 +97207,15 @@ focus outline in that case.
97125
97207
  super.connectedCallback();
97126
97208
  this.textArea.value = this.value;
97127
97209
  this.disableSendButton = this.shouldDisableSendButton();
97210
+ this.resizeObserver = new ResizeObserver(() => this.onResize());
97211
+ this.resizeObserver.observe(this);
97212
+ }
97213
+ /**
97214
+ * @internal
97215
+ */
97216
+ disconnectedCallback() {
97217
+ super.disconnectedCallback();
97218
+ this.resizeObserver?.disconnect();
97128
97219
  }
97129
97220
  /**
97130
97221
  * @internal
@@ -97160,6 +97251,22 @@ focus outline in that case.
97160
97251
  this.textArea.focus();
97161
97252
  }
97162
97253
  }
97254
+ onResize() {
97255
+ this.scrollbarWidth = this.textArea.offsetWidth - this.textArea.clientWidth;
97256
+ }
97257
+ queueUpdateScrollbarWidth() {
97258
+ if (!this.$fastController.isConnected) {
97259
+ return;
97260
+ }
97261
+ if (!this.updateScrollbarWidthQueued) {
97262
+ this.updateScrollbarWidthQueued = true;
97263
+ DOM.queueUpdate(() => this.updateScrollbarWidth());
97264
+ }
97265
+ }
97266
+ updateScrollbarWidth() {
97267
+ this.updateScrollbarWidthQueued = false;
97268
+ this.scrollbarWidth = this.textArea.offsetWidth - this.textArea.clientWidth;
97269
+ }
97163
97270
  }
97164
97271
  __decorate([
97165
97272
  attr
@@ -97188,6 +97295,9 @@ focus outline in that case.
97188
97295
  __decorate([
97189
97296
  observable
97190
97297
  ], ChatInput.prototype, "disableSendButton", void 0);
97298
+ __decorate([
97299
+ observable
97300
+ ], ChatInput.prototype, "scrollbarWidth", void 0);
97191
97301
  const sprightChatInput = ChatInput.compose({
97192
97302
  baseName: 'chat-input',
97193
97303
  template: template$7,