lightning-base-components 1.21.2-alpha → 1.21.4-alpha
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.
- package/metadata/raptor.json +77 -1
- package/package.json +108 -15
- package/scopedImports/@salesforce-label-LightningDatatable.showActions.js +1 -1
- package/scopedImports/@salesforce-label-LightningForm.controllerFieldsMessage.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.dependentFieldsHeader.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.dependentFieldsListHeading.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.generalDependentFieldsMessage.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.learnMore.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.okButton.js +1 -0
- package/scopedImports/@salesforce-label-LightningLookup.modalCancel.js +1 -0
- package/scopedImports/@salesforce-label-LightningLookup.modalSelect.js +1 -0
- package/scopedImports/@salesforce-label-LightningProgressIndicator.currentStage.js +1 -1
- package/scopedImports/@salesforce-label-LightningProgressIndicator.errorStage.js +1 -0
- package/scopedImports/@salesforce-label-LightningProgressIndicator.stageComplete.js +1 -1
- package/scopedImports/@salesforce-label-LightningProgressIndicator.stageNotStarted.js +1 -1
- package/scopedImports/@salesforce-label-LightningRichTextEditor.colorPicker.js +1 -0
- package/src/lightning/accordion/accordion-section.slds.css +3 -3
- package/src/lightning/accordion/accordion.slds.css +1 -2
- package/src/lightning/accordionSection/accordion-section.slds.css +3 -3
- package/src/lightning/accordionSection/accordionSection.js +3 -1
- package/src/lightning/accordionSection/button.slds.css +1 -1
- package/src/lightning/avatar/avatar.html +1 -0
- package/src/lightning/badge/badge.html +3 -3
- package/src/lightning/badge/badge.js +1 -0
- package/src/lightning/badge/badge.js-meta.xml +3 -0
- package/src/lightning/baseCombobox/base-combobox.slds.css +11 -6
- package/src/lightning/baseCombobox/baseCombobox.html +5 -2
- package/src/lightning/baseCombobox/baseCombobox.js +5 -18
- package/src/lightning/baseCombobox/baseCombobox.js-meta.xml +6 -0
- package/src/lightning/baseCombobox/input-text.slds.css +41 -68
- package/src/lightning/baseCombobox/keyboard.js +12 -4
- package/src/lightning/baseCombobox/listbox.slds.css +51 -99
- package/src/lightning/baseCombobox/spinner.slds.css +62 -62
- package/src/lightning/baseComboboxFormattedText/baseComboboxFormattedText.js-meta.xml +6 -0
- package/src/lightning/baseComboboxItem/baseComboboxItem.js +10 -6
- package/src/lightning/baseComboboxItem/baseComboboxItem.js-meta.xml +6 -0
- package/src/lightning/baseComboboxItem/listbox.slds.css +51 -99
- package/src/lightning/baseFormattedText/baseFormattedText.js +2 -2
- package/src/lightning/button/__docs__/button.md +2 -1
- package/src/lightning/button/button.js +5 -5
- package/src/lightning/button/button.slds.css +1 -1
- package/src/lightning/buttonIcon/__docs__/buttonIcon.md +1 -0
- package/src/lightning/buttonIcon/button-icon.slds.css +1 -1
- package/src/lightning/buttonIcon/buttonIcon.html +1 -1
- package/src/lightning/buttonIcon/buttonIcon.js +18 -17
- package/src/lightning/buttonIconStateful/button-icon-stateful.slds.css +4 -2
- package/src/lightning/buttonIconStateful/button-icon.slds.css +1 -1
- package/src/lightning/buttonIconStateful/button.slds.css +1 -1
- package/src/lightning/buttonMenu/button-icon.slds.css +1 -1
- package/src/lightning/buttonMenu/button-menu.slds.css +8 -2
- package/src/lightning/buttonMenu/button.slds.css +1 -1
- package/src/lightning/buttonMenu/buttonMenu.css +5 -0
- package/src/lightning/buttonMenu/buttonMenu.js +2 -0
- package/src/lightning/buttonStateful/button-stateful.slds.css +6 -2
- package/src/lightning/buttonStateful/button.slds.css +1 -1
- package/src/lightning/buttonStateful/buttonStateful.js +4 -1
- package/src/lightning/calendar/calendar.js-meta.xml +6 -0
- package/src/lightning/calendar/calendar.slds.css +9 -2
- package/src/lightning/colorPickerCustom/color-picker-custom.slds.css +22 -23
- package/src/lightning/colorPickerCustom/colorPickerCustom.js +12 -0
- package/src/lightning/colorPickerCustom/input-text.slds.css +41 -68
- package/src/lightning/colorPickerPanel/color-picker-panel.slds.css +9 -10
- package/src/lightning/colorPickerPanel/colorPickerPanel.js +11 -1
- package/src/lightning/colorPickerPanel/popover.slds.css +0 -2
- package/src/lightning/combobox/combobox.html +1 -0
- package/src/lightning/combobox/combobox.slds.css +1 -2
- package/src/lightning/combobox/form-element.slds.css +54 -54
- package/src/lightning/datatable/__examples__disabled/customComponentWrapper/customComponentWrapper.html +11 -0
- package/src/lightning/datatable/__examples__disabled/customComponentWrapper/customComponentWrapper.js +25 -0
- package/src/lightning/datatable/__examples__disabled/customComponentWrapper/generateData.js +15 -0
- package/src/lightning/datatable/__examples__disabled/customDatatableWrapper/customDatatableWrapper.js +89 -0
- package/src/lightning/datatable/__examples__disabled/customDatatypeDeleteRowBtn/customDatatypeDeleteRowBtn.html +6 -0
- package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatypeDeleteRowBtn/customDatatypeDeleteRowBtn.js +1 -16
- package/src/lightning/datatable/__examples__disabled/customDatatypeLink/customDatatypeLink.html +9 -0
- package/src/lightning/datatable/__examples__disabled/customDatatypeRowOrderingBtn/customDatatypeRowOrderingBtn.html +3 -0
- package/src/lightning/datatable/__examples__disabled/customDatatypeRowOrderingBtn/customDatatypeRowOrderingBtn.js +3 -0
- package/src/lightning/datatable/__examples__disabled/customDatatypeTable/customNumber.html +3 -0
- package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatypeTable/customNumberEdit.html +2 -0
- package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatypeTable/deleteRow.html +3 -2
- package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatypeTable/iconPill.html +1 -1
- package/src/lightning/datatable/{__examples__/customDatatypeRowOrderingBtn/customDatatypeRowOrderingBtn.html → __examples__disabled/customNestedComponent/customNestedComponent.html} +2 -2
- package/src/lightning/datatable/__examples__disabled/customNestedComponent/customNestedComponent.js +12 -0
- package/src/lightning/datatable/__examples__disabled/myCustomTypeDatatable/customInput.html +4 -0
- package/src/lightning/datatable/__examples__disabled/myCustomTypeDatatable/myCustomTypeDatatable.js +17 -0
- package/src/lightning/datatable/__examples__disabled/myCustomTypeDatatable/nestedSimpleComponentParent.html +7 -0
- package/src/lightning/datatable/__examples__disabled/simpleComponentNested/simpleComponentNested.html +9 -0
- package/src/lightning/datatable/__examples__disabled/simpleComponentNested/simpleComponentNested.js +6 -0
- package/src/lightning/datatable/autoWidthStrategy.js +145 -217
- package/src/lightning/datatable/columnResizer.js +80 -190
- package/src/lightning/datatable/columnWidthManager.js +128 -243
- package/src/lightning/datatable/columns.js +192 -283
- package/src/lightning/datatable/datagrid.slds.css +187 -0
- package/src/lightning/datatable/datatable.js +647 -614
- package/src/lightning/datatable/errors.js +19 -28
- package/src/lightning/datatable/fixedWidthStrategy.js +27 -49
- package/src/lightning/datatable/headerActions.js +10 -42
- package/src/lightning/datatable/indexes.js +42 -0
- package/src/lightning/datatable/infiniteLoading.js +27 -46
- package/src/lightning/datatable/inlineEdit.js +311 -322
- package/src/lightning/datatable/keyboard.js +490 -510
- package/src/lightning/datatable/renderManager.js +10 -11
- package/src/lightning/datatable/resizeObserver.js +10 -67
- package/src/lightning/datatable/rowLevelActions.js +7 -6
- package/src/lightning/datatable/rowNumber.js +41 -79
- package/src/lightning/datatable/rowSelection.js +236 -291
- package/src/lightning/datatable/rowSelectionShared.js +26 -33
- package/src/lightning/datatable/rows.js +264 -476
- package/src/lightning/datatable/sort.js +27 -82
- package/src/lightning/datatable/templates/div/div.css +2 -57
- package/src/lightning/datatable/templates/div/div.html +25 -10
- package/src/lightning/datatable/templates/div/div.lbc.native.css +3 -0
- package/src/lightning/datatable/templates/div/div.lbc.synthetic.css +80 -0
- package/src/lightning/datatable/templates/table/table.html +16 -5
- package/src/lightning/datatable/tree.js +17 -35
- package/src/lightning/datatable/types.js +10 -31
- package/src/lightning/datatable/utils.js +54 -29
- package/src/lightning/datatable/virtualization.js +2 -5
- package/src/lightning/datatable/widthManagerShared.js +24 -41
- package/src/lightning/datatable/wrapText.js +45 -77
- package/src/lightning/datepicker/datepicker.js +32 -9
- package/src/lightning/datepicker/datepicker.js-meta.xml +6 -0
- package/src/lightning/datepicker/form-element.slds.css +54 -54
- package/src/lightning/datepicker/input-text.slds.css +41 -68
- package/src/lightning/datetimepicker/datetimepicker.js-meta.xml +6 -0
- package/src/lightning/datetimepicker/form-element.slds.css +54 -54
- package/src/lightning/datetimepicker/input-text.slds.css +41 -68
- package/src/lightning/dualListbox/dual-listbox.slds.css +7 -2
- package/src/lightning/dualListbox/dualListbox.js +7 -8
- package/src/lightning/dualListbox/form-element.slds.css +54 -54
- package/src/lightning/dualListbox/listbox.slds.css +51 -99
- package/src/lightning/dynamicIcon/dynamic-icon-strength.slds.css +1 -2
- package/src/lightning/dynamicIcon/dynamic-icon-trend.slds.css +1 -2
- package/src/lightning/formattedDateTime/formattedDateTime.js +7 -62
- package/src/lightning/formattedDateTime/formattedDateTime.js-meta.xml +3 -0
- package/src/lightning/formattedLocation/formattedLocation.html +1 -3
- package/src/lightning/formattedLocation/formattedLocation.js +3 -25
- package/src/lightning/formattedLookup/events.js +2 -4
- package/src/lightning/formattedName/formattedName.js +3 -2
- package/src/lightning/formattedName/formattedName.js-meta.xml +3 -0
- package/src/lightning/formattedNumber/formattedNumber.js +5 -51
- package/src/lightning/formattedNumber/formattedNumber.js-meta.xml +3 -0
- package/src/lightning/formattedRichText/formattedRichText.js +5 -5
- package/src/lightning/formattedRichText/linkTextNodes.js +58 -0
- package/src/lightning/formattedRichText/richTextConfig.js +1 -0
- package/src/lightning/groupedCombobox/form-element.slds.css +54 -54
- package/src/lightning/groupedCombobox/grouped-combobox.slds.css +0 -2
- package/src/lightning/groupedCombobox/groupedCombobox.js-meta.xml +1 -1
- package/src/lightning/groupedCombobox/input-text.slds.css +41 -68
- package/src/lightning/helptext/button-icon.slds.css +1 -1
- package/src/lightning/helptext/form-element.slds.css +54 -54
- package/src/lightning/helptext/helptext.css +7 -0
- package/src/lightning/helptext/helptext.js +3 -4
- package/src/lightning/icon/icon.html +1 -1
- package/src/lightning/icon/icon.slds.css +12 -25
- package/src/lightning/input/form-element.slds.css +54 -54
- package/src/lightning/input/input.html +5 -0
- package/src/lightning/inputAddress/addressFormat.js +31 -4
- package/src/lightning/inputAddress/fieldsLayout.js +6 -0
- package/src/lightning/inputAddress/form-element.slds.css +54 -54
- package/src/lightning/inputAddress/input-address.slds.css +1 -2
- package/src/lightning/inputAddress/input-text.slds.css +41 -68
- package/src/lightning/inputAddress/inputAddress.html +19 -1
- package/src/lightning/inputAddress/inputAddress.js +75 -3
- package/src/lightning/inputAddress/inputAddress.js-meta.xml +3 -0
- package/src/lightning/inputLocation/form-element.slds.css +54 -54
- package/src/lightning/inputLocation/input-location.slds.css +1 -2
- package/src/lightning/inputLocation/input-text.slds.css +41 -68
- package/src/lightning/inputName/form-element.slds.css +54 -54
- package/src/lightning/inputName/input-text.slds.css +41 -68
- package/src/lightning/interactiveDialogBase/interactive-dialog-base.slds.css +0 -3
- package/src/lightning/interactiveDialogBase/interactiveDialogBase.js-meta.xml +6 -0
- package/src/lightning/internationalizationLibrary/address/AddressFormat.js +553 -610
- package/src/lightning/lookupAddress/form-element.slds.css +54 -54
- package/src/lightning/lookupAddress/listbox.slds.css +51 -99
- package/src/lightning/lookupAddress/location.js +2 -0
- package/src/lightning/lookupAddress/lookup-address.slds.css +0 -2
- package/src/lightning/lookupAddress/lookupAddress.html +6 -1
- package/src/lightning/lookupAddress/lookupAddress.js +40 -10
- package/src/lightning/menuDivider/menu-divider.slds.css +0 -2
- package/src/lightning/menuItem/menu-item.slds.css +8 -2
- package/src/lightning/menuSubheader/menu-subheader.slds.css +1 -2
- package/src/lightning/modal/__docs__/modal.md +10 -1
- package/src/lightning/modal/__modalUtils__/modalContainerTestConstants.js +3 -7
- package/src/lightning/modal/__modalUtils__/modalContainerTestMethods.js +39 -133
- package/src/lightning/modal/__modalUtils__/modalContainerTestMockData.js +1 -1
- package/src/lightning/modal/modal.js +1 -1
- package/src/lightning/modalBase/modal-base.slds.css +3 -3
- package/src/lightning/modalBase/modalBase.html +15 -10
- package/src/lightning/modalBase/modalBase.js +131 -154
- package/src/lightning/modalBase/modalBase.js-meta.xml +6 -0
- package/src/lightning/modalBody/modal-body.slds.css +1 -2
- package/src/lightning/modalBody/modalBody.css +6 -0
- package/src/lightning/modalFooter/modal-footer.slds.css +2 -2
- package/src/lightning/modalFooter/modalFooter.js +0 -21
- package/src/lightning/modalHeader/modal-header.slds.css +1 -2
- package/src/lightning/modalHeader/modalHeader.html +16 -4
- package/src/lightning/modalHeader/modalHeader.js +61 -36
- package/src/lightning/overlay/overlay.js-meta.xml +6 -0
- package/src/lightning/pill/link.html +1 -0
- package/src/lightning/pill/pill.slds.css +32 -58
- package/src/lightning/pill/plain.html +1 -0
- package/src/lightning/pill/plainLink.html +1 -0
- package/src/lightning/pillContainer/button.slds.css +1 -1
- package/src/lightning/pillContainer/listbox.slds.css +51 -99
- package/src/lightning/pillContainer/pill-container.slds.css +6 -10
- package/src/lightning/pillContainer/pill.slds.css +32 -58
- package/src/lightning/popup/popover.slds.css +0 -2
- package/src/lightning/primitiveBubble/primitiveBubble.js +42 -0
- package/src/lightning/primitiveBubble/primitiveBubble.js-meta.xml +6 -0
- package/src/lightning/primitiveButton/primitiveButoon.js-meta.xml +6 -0
- package/src/lightning/primitiveCellCheckbox/checkbox.css +2 -0
- package/src/lightning/primitiveColorpickerButton/color-picker-button.slds.css +16 -38
- package/src/lightning/primitiveCustomCell/primitiveCustomCell.js +26 -1
- package/src/lightning/primitiveDatatableCell/primitiveDatatableCell.js +1 -1
- package/src/lightning/primitiveHeaderActions/primitiveHeaderActions.html +1 -1
- package/src/lightning/primitiveHeaderActions/primitiveHeaderActions.js +13 -0
- package/src/lightning/primitiveHeaderFactory/nonsortableHeader.css +1 -0
- package/src/lightning/primitiveHeaderFactory/nonsortableHeader.html +19 -6
- package/src/lightning/primitiveHeaderFactory/selectableHeader.css +2 -0
- package/src/lightning/primitiveHeaderFactory/sortableHeader.html +3 -1
- package/src/lightning/primitiveIcon/icon.slds.css +12 -25
- package/src/lightning/primitiveIcon/primitiveIcon.js-meta.xml +6 -0
- package/src/lightning/primitiveIframe/primitiveIframe.js +3 -1
- package/src/lightning/primitiveInputCheckbox/form-element.slds.css +54 -54
- package/src/lightning/primitiveInputCheckbox/primitiveInputCheckbox.js +5 -2
- package/src/lightning/primitiveInputCheckbox/primitiveInputCheckbox.js-meta.xml +6 -0
- package/src/lightning/primitiveInputCheckboxButton/form-element.slds.css +54 -54
- package/src/lightning/primitiveInputCheckboxButton/input-checkbox-button.slds.css +6 -4
- package/src/lightning/primitiveInputCheckboxButton/primitiveInputCheckboxButton.js +5 -2
- package/src/lightning/primitiveInputCheckboxButton/primitiveInputCheckboxButton.js-meta.xml +6 -0
- package/src/lightning/primitiveInputColor/form-element.slds.css +54 -54
- package/src/lightning/primitiveInputColor/input-color.slds.css +2 -3
- package/src/lightning/primitiveInputColor/input-text.slds.css +41 -68
- package/src/lightning/primitiveInputColor/primitiveInputColor.js +5 -2
- package/src/lightning/primitiveInputColor/primitiveInputColor.js-meta.xml +6 -0
- package/src/lightning/primitiveInputFile/button.slds.css +1 -1
- package/src/lightning/primitiveInputFile/form-element.slds.css +54 -54
- package/src/lightning/primitiveInputFile/input-file.slds.css +1 -4
- package/src/lightning/primitiveInputFile/primitiveInputFile.js +4 -2
- package/src/lightning/primitiveInputFile/primitiveInputFile.js-meta.xml +6 -0
- package/src/lightning/primitiveInputRadio/primitiveInputRadio.js +4 -2
- package/src/lightning/primitiveInputSimple/form-element.slds.css +54 -54
- package/src/lightning/primitiveInputSimple/input-text.slds.css +41 -68
- package/src/lightning/primitiveInputSimple/primitiveInputSimple.js-meta.xml +6 -0
- package/src/lightning/primitiveInputToggle/form-element.slds.css +54 -54
- package/src/lightning/primitiveInputToggle/input-toggle.slds.css +50 -27
- package/src/lightning/primitiveInputToggle/primitiveInputToggle.js +5 -2
- package/src/lightning/primitiveInputToggle/primitiveInputToggle.js-meta.xml +6 -0
- package/src/lightning/primitiveResizeHandler/primitiveResizeHandler.css +11 -0
- package/src/lightning/primitiveResizeHandler/primitiveResizeHandler.html +2 -1
- package/src/lightning/primitiveResizeHandler/primitiveResizeHandler.js +1 -0
- package/src/lightning/progressBar/progress-bar.slds.css +8 -10
- package/src/lightning/progressRing/progress-ring.slds.css +0 -23
- package/src/lightning/progressStep/base.html +5 -6
- package/src/lightning/progressStep/progressStep.js +15 -23
- package/src/lightning/prompt/__docs__/prompt.md +1 -1
- package/src/lightning/radioGroup/form-element.slds.css +54 -54
- package/src/lightning/radioGroup/radioGroup.html +1 -2
- package/src/lightning/radioGroup/radioGroup.js +1 -0
- package/src/lightning/routingService/routingService.js +31 -5
- package/src/lightning/select/form-element.slds.css +54 -54
- package/src/lightning/select/select.slds.css +4 -2
- package/src/lightning/shadowBaseClassPrivate/shadowBaseClassPrivate.js +0 -2
- package/src/lightning/sldsCommon/sldsCommon.css +134 -98
- package/src/lightning/sldsUtilsAlignment/sldsUtilsAlignment.css +1 -1
- package/src/lightning/sldsUtilsBox/sldsUtilsBox.css +14 -13
- package/src/lightning/sldsUtilsGrid/sldsUtilsGrid.css +95 -92
- package/src/lightning/sldsUtilsHyphenation/sldsUtilsHyphenation.css +1 -1
- package/src/lightning/sldsUtilsMargin/sldsUtilsMargin.css +77 -75
- package/src/lightning/sldsUtilsPadding/sldsUtilsPadding.css +73 -73
- package/src/lightning/sldsUtilsSizing/sldsUtilsSizing.css +552 -558
- package/src/lightning/sldsUtilsVisibility/sldsUtilsVisibility.css +5 -1
- package/src/lightning/spinner/spinner.slds.css +62 -62
- package/src/lightning/staticMap/staticMap.js +3 -2
- package/src/lightning/tab/tab.js +10 -5
- package/src/lightning/tab/tab.js-meta.xml +3 -0
- package/src/lightning/tab/tab.slds.css +14 -7
- package/src/lightning/tabBar/tab-bar.slds.css +16 -6
- package/src/lightning/tabBar/tabBar.js +10 -5
- package/src/lightning/tabset/__docs__/tabset.md +24 -1
- package/src/lightning/tabset/tabset.html +2 -0
- package/src/lightning/tabset/tabset.js +25 -38
- package/src/lightning/tabset/tabset.js-meta.xml +3 -0
- package/src/lightning/tabset/tabset.slds.css +0 -2
- package/src/lightning/textarea/form-element.slds.css +54 -54
- package/src/lightning/textarea/textarea.js +11 -2
- package/src/lightning/textarea/textarea.slds.css +22 -9
- package/src/lightning/timepicker/form-element.slds.css +54 -54
- package/src/lightning/timepicker/timepicker.js-meta.xml +6 -0
- package/src/lightning/timepicker/timepicker.slds.css +2 -2
- package/src/lightning/toast/__docs__/toast.md +20 -22
- package/src/lightning/toast/button-icon.slds.css +1 -1
- package/src/lightning/toast/icon.slds.css +12 -25
- package/src/lightning/toast/toast.js +15 -12
- package/src/lightning/toast/toast.slds.css +6 -18
- package/src/lightning/toastContainer/__docs__/toastContainer.md +3 -2
- package/src/lightning/toastContainer/toast.slds.css +6 -18
- package/src/lightning/toastContainer/toastContainer.js +25 -17
- package/src/lightning/tooltipLibrary/tooltipLibrary.js +36 -24
- package/src/lightning/tree/tree.js +2 -0
- package/src/lightning/utils/classSet.js +9 -3
- package/src/lightning/utilsPrivate/formatUtils.js +158 -0
- package/src/lightning/utilsPrivate/textUtils.js +16 -0
- package/src/lightning/utilsPrivate/utilsPrivate.js +56 -15
- package/src/lightning/utilsPrivate/validationUtils.js +59 -0
- package/src/lightning/verticalNavigation/vertical-navigation.slds.css +14 -0
- package/src/lightning/verticalNavigation/verticalNavigation.css +1 -1
- package/src/lightning/verticalNavigation/verticalNavigation.html +1 -1
- package/src/lightning/verticalNavigation/verticalNavigation.js +66 -28
- package/src/lightning/verticalNavigation/verticalNavigation.js-meta.xml +3 -0
- package/src/lightning/verticalNavigationItem/vertical-navigation-item.slds.css +63 -0
- package/src/lightning/verticalNavigationItem/verticalNavigationItem.css +2 -3
- package/src/lightning/verticalNavigationItem/verticalNavigationItem.js +29 -15
- package/src/lightning/verticalNavigationItem/verticalNavigationItem.js-meta.xml +3 -0
- package/src/lightning/verticalNavigationItem/verticalNavigationItem.lbc.native.css +2 -0
- package/src/lightning/verticalNavigationItem/verticalNavigationItem.lbc.synthetic.css +3 -0
- package/src/lightning/verticalNavigationItemBadge/badge.slds.css +76 -0
- package/src/lightning/verticalNavigationItemBadge/vertical-navigation-item.slds.css +63 -0
- package/src/lightning/verticalNavigationItemBadge/verticalNavigationItemBadge.css +2 -3
- package/src/lightning/verticalNavigationItemBadge/verticalNavigationItemBadge.html +1 -1
- package/src/lightning/verticalNavigationItemBadge/verticalNavigationItemBadge.js +28 -15
- package/src/lightning/verticalNavigationItemBadge/verticalNavigationItemBadge.js-meta.xml +3 -0
- package/src/lightning/verticalNavigationItemBadge/verticalNavigationItemBadge.lbc.native.css +5 -0
- package/src/lightning/verticalNavigationItemBadge/verticalNavigationItemBadge.lbc.synthetic.css +3 -0
- package/src/lightning/verticalNavigationItemIcon/vertical-navigation-item.slds.css +63 -0
- package/src/lightning/verticalNavigationItemIcon/verticalNavigationItemIcon.css +2 -3
- package/src/lightning/verticalNavigationItemIcon/verticalNavigationItemIcon.js +29 -15
- package/src/lightning/verticalNavigationItemIcon/verticalNavigationItemIcon.js-meta.xml +3 -0
- package/src/lightning/verticalNavigationItemIcon/verticalNavigationItemIcon.lbc.native.css +3 -0
- package/src/lightning/verticalNavigationItemIcon/verticalNavigationItemIcon.lbc.synthetic.css +3 -0
- package/src/lightning/verticalNavigationOverflow/button.slds.css +503 -0
- package/src/lightning/verticalNavigationOverflow/vertical-navigation-item.slds.css +63 -0
- package/src/lightning/verticalNavigationOverflow/vertical-navigation-section.slds.css +17 -0
- package/src/lightning/verticalNavigationOverflow/verticalNavigationOverflow.css +2 -1
- package/src/lightning/verticalNavigationOverflow/verticalNavigationOverflow.html +2 -0
- package/src/lightning/verticalNavigationOverflow/verticalNavigationOverflow.js +18 -13
- package/src/lightning/verticalNavigationOverflow/verticalNavigationOverflow.js-meta.xml +3 -0
- package/src/lightning/verticalNavigationOverflow/verticalNavigationOverflow.lbc.native.css +5 -0
- package/src/lightning/verticalNavigationSection/vertical-navigation-section.slds.css +13 -15
- package/src/lightning/verticalNavigationSection/verticalNavigationSection.js-meta.xml +3 -0
- package/src/lightning/datatable/__examples__/customDatatableWrapper/customDatatableWrapper.js +0 -158
- package/src/lightning/datatable/__examples__/customDatatypeDeleteRowBtn/customDatatypeDeleteRowBtn.html +0 -6
- package/src/lightning/datatable/__examples__/customDatatypeLink/customDatatypeLink.html +0 -9
- package/src/lightning/datatable/__examples__/customDatatypeRowOrderingBtn/customDatatypeRowOrderingBtn.js +0 -40
- package/src/lightning/datatable/__examples__/customDatatypeTable/customNumber.html +0 -3
- package/src/lightning/datatable/inlineEditShared.js +0 -26
- package/src/lightning/datatable/resizeSensor.js +0 -244
- package/src/lightning/formattedRichText/linkify.js +0 -43
- package/src/lightning/utilsPrivate/smartSetAttribute.js +0 -19
- /package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatableWrapper/customDatatableWrapper.html +0 -0
- /package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatypeLink/customDatatypeLink.js +0 -0
- /package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatypeNumber/customDatatypeNumber.html +0 -0
- /package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatypeNumber/customDatatypeNumber.js +0 -0
- /package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatypeTable/customDatatypeTable.js +0 -0
- /package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatypeTable/customLink.html +0 -0
- /package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatypeTable/customName.html +0 -0
- /package/src/lightning/datatable/{__examples__ → __examples__disabled}/customDatatypeTable/orderingButtons.html +0 -0
|
@@ -1,28 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
generateColKeyValue,
|
|
4
|
-
getStateColumnIndex,
|
|
5
|
-
} from './columns';
|
|
1
|
+
import { getShadowActiveElements, isRTL } from 'lightning/utilsPrivate';
|
|
2
|
+
import { getCellFromIndexes, HEADER_ROW_KEY, getRowByKey } from './indexes';
|
|
6
3
|
import {
|
|
7
4
|
hasTreeDataType,
|
|
8
5
|
getStateTreeColumn,
|
|
9
6
|
fireRowToggleEvent,
|
|
10
7
|
} from './tree';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
8
|
+
import { generateColKeyValue, getStateColumnIndex } from './columns';
|
|
9
|
+
import { isCellEditable } from './rows';
|
|
13
10
|
import { findFirstVisibleIndex } from './virtualization';
|
|
14
|
-
|
|
15
|
-
import { escapeDoubleQuotes } from './utils';
|
|
16
|
-
|
|
17
|
-
// Indicator/flag for a header row
|
|
18
|
-
const HEADER_ROW = 'HEADER';
|
|
11
|
+
import { getColDataSelector, getRowDataSelector, getScrollerY } from './utils';
|
|
19
12
|
|
|
20
13
|
// SLDS Class for Focus
|
|
21
14
|
export const FOCUS_CLASS = 'slds-has-focus';
|
|
22
15
|
|
|
23
16
|
// Keyboard Navigation Modes
|
|
24
|
-
const
|
|
25
|
-
const
|
|
17
|
+
export const KEYBOARD_NAVIGATION_MODE = 'NAVIGATION';
|
|
18
|
+
export const KEYBOARD_ACTION_MODE = 'ACTION';
|
|
26
19
|
|
|
27
20
|
// Pixel Values
|
|
28
21
|
const TOP_MARGIN = 80;
|
|
@@ -40,43 +33,23 @@ const TAB = 9;
|
|
|
40
33
|
const SPACE = 32;
|
|
41
34
|
|
|
42
35
|
// Navigation Direction
|
|
43
|
-
const NAVIGATION_DIR = (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
TAB_FORWARD: 1,
|
|
61
|
-
TAB_BACKWARD: -1,
|
|
62
|
-
};
|
|
63
|
-
})();
|
|
64
|
-
|
|
65
|
-
// Selectors
|
|
66
|
-
const SELECTORS = {
|
|
67
|
-
headerRow: {
|
|
68
|
-
default: `thead > :nth-child(1)`,
|
|
69
|
-
roleBased: `[role="grid"] > [role="rowgroup"]:nth-child(1) > [role="row"]`,
|
|
70
|
-
},
|
|
71
|
-
dataRowRowGroup: {
|
|
72
|
-
default: `tbody`,
|
|
73
|
-
roleBased: `[role="grid"] > [role="rowgroup"]:nth-child(2)`,
|
|
74
|
-
},
|
|
75
|
-
cell: {
|
|
76
|
-
default: ['td', 'th'],
|
|
77
|
-
roleBased: ['rowheader', 'gridcell', 'columnheader'],
|
|
78
|
-
},
|
|
79
|
-
};
|
|
36
|
+
export const NAVIGATION_DIR = isRTL()
|
|
37
|
+
? {
|
|
38
|
+
RIGHT: -1,
|
|
39
|
+
LEFT: 1,
|
|
40
|
+
USE_CURRENT: 0,
|
|
41
|
+
RESET: 2,
|
|
42
|
+
TAB_FORWARD: -1,
|
|
43
|
+
TAB_BACKWARD: 1,
|
|
44
|
+
}
|
|
45
|
+
: {
|
|
46
|
+
RIGHT: 1,
|
|
47
|
+
LEFT: -1,
|
|
48
|
+
USE_CURRENT: 0,
|
|
49
|
+
RESET: 2,
|
|
50
|
+
TAB_FORWARD: 1,
|
|
51
|
+
TAB_BACKWARD: -1,
|
|
52
|
+
};
|
|
80
53
|
|
|
81
54
|
/***************************** KEYDOWN HANDLERS *****************************/
|
|
82
55
|
|
|
@@ -94,7 +67,7 @@ const SELECTORS = {
|
|
|
94
67
|
*/
|
|
95
68
|
export function handleKeydownOnCell(event) {
|
|
96
69
|
event.stopPropagation();
|
|
97
|
-
reactToKeyboardInActionMode(this
|
|
70
|
+
reactToKeyboardInActionMode(this, event);
|
|
98
71
|
}
|
|
99
72
|
|
|
100
73
|
/**
|
|
@@ -115,13 +88,10 @@ export function handleKeydownOnCell(event) {
|
|
|
115
88
|
* @param {Event} event
|
|
116
89
|
*/
|
|
117
90
|
export function handleKeydownOnTable(event) {
|
|
118
|
-
const targetTagName = event.target.tagName.toLowerCase();
|
|
119
|
-
const targetRole = event.target.getAttribute('role');
|
|
120
|
-
|
|
121
91
|
// Checks if the keydown happened on a cell element and not
|
|
122
92
|
// on an actionable element when in Action Mode.
|
|
123
|
-
if (isCellElement(
|
|
124
|
-
reactToKeyboardInNavMode(this
|
|
93
|
+
if (isCellElement(event.target)) {
|
|
94
|
+
reactToKeyboardInNavMode(this, event);
|
|
125
95
|
}
|
|
126
96
|
}
|
|
127
97
|
|
|
@@ -129,280 +99,309 @@ export function handleKeydownOnTable(event) {
|
|
|
129
99
|
* Changes the datatable state based on the keyboard event sent from the cell component.
|
|
130
100
|
* The result of those changes may trigger a re-render on the table
|
|
131
101
|
*
|
|
132
|
-
* @param {
|
|
133
|
-
* @param {Object} state Datatable state
|
|
102
|
+
* @param {Object} dt - The datatable instance
|
|
134
103
|
* @param {Event} event Custom DOM event sent by the cell
|
|
135
104
|
* @returns {Object} Mutated state
|
|
136
105
|
*/
|
|
137
|
-
function reactToKeyboardInActionMode(
|
|
106
|
+
function reactToKeyboardInActionMode(dt, event) {
|
|
107
|
+
const { state, template } = dt;
|
|
138
108
|
switch (event.detail.keyCode) {
|
|
139
109
|
case ARROW_LEFT:
|
|
140
|
-
|
|
110
|
+
reactToArrowLeft(state, template, event);
|
|
111
|
+
break;
|
|
141
112
|
case ARROW_RIGHT:
|
|
142
|
-
|
|
113
|
+
reactToArrowRight(state, template, event);
|
|
114
|
+
break;
|
|
143
115
|
case ARROW_UP:
|
|
144
|
-
|
|
116
|
+
reactToArrowUp(state, template, event);
|
|
117
|
+
break;
|
|
145
118
|
case ARROW_DOWN:
|
|
146
|
-
|
|
119
|
+
reactToArrowDown(state, template, event);
|
|
120
|
+
break;
|
|
147
121
|
case ENTER:
|
|
148
122
|
case SPACE:
|
|
149
|
-
|
|
123
|
+
reactToEnter(state, template, event);
|
|
124
|
+
break;
|
|
150
125
|
case ESCAPE:
|
|
151
|
-
|
|
126
|
+
reactToEscape(state, template, event);
|
|
127
|
+
break;
|
|
152
128
|
case TAB:
|
|
153
|
-
|
|
129
|
+
reactToTab(state, template, event);
|
|
130
|
+
break;
|
|
154
131
|
default:
|
|
155
|
-
|
|
132
|
+
break;
|
|
156
133
|
}
|
|
157
134
|
}
|
|
158
135
|
|
|
159
|
-
function reactToKeyboardInNavMode(
|
|
136
|
+
function reactToKeyboardInNavMode(dt, event) {
|
|
137
|
+
const { state, template } = dt;
|
|
138
|
+
const {
|
|
139
|
+
activeCell: { colKeyValue, rowKeyValue },
|
|
140
|
+
} = state;
|
|
141
|
+
const { keyCode, shiftKey } = event;
|
|
160
142
|
const syntheticEvent = {
|
|
161
143
|
detail: {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
keyCode
|
|
165
|
-
shiftKey
|
|
144
|
+
colKeyValue,
|
|
145
|
+
rowKeyValue,
|
|
146
|
+
keyCode,
|
|
147
|
+
shiftKey,
|
|
166
148
|
},
|
|
167
149
|
preventDefault: () => {},
|
|
168
150
|
stopPropagation: () => {},
|
|
169
151
|
};
|
|
170
|
-
|
|
171
152
|
// We need event.preventDefault so that actions like arrow up or down
|
|
172
153
|
// does not scroll the table but instead sets focus on the right cells
|
|
173
154
|
switch (event.keyCode) {
|
|
174
155
|
case ARROW_LEFT:
|
|
175
156
|
event.preventDefault();
|
|
176
|
-
|
|
157
|
+
reactToArrowLeft(state, template, syntheticEvent);
|
|
158
|
+
break;
|
|
177
159
|
case ARROW_RIGHT:
|
|
178
160
|
event.preventDefault();
|
|
179
|
-
|
|
161
|
+
reactToArrowRight(state, template, syntheticEvent);
|
|
162
|
+
break;
|
|
180
163
|
case ARROW_UP:
|
|
181
164
|
event.preventDefault();
|
|
182
|
-
|
|
165
|
+
reactToArrowUp(state, template, syntheticEvent);
|
|
166
|
+
break;
|
|
183
167
|
case ARROW_DOWN:
|
|
184
168
|
event.preventDefault();
|
|
185
|
-
|
|
169
|
+
reactToArrowDown(state, template, syntheticEvent);
|
|
170
|
+
break;
|
|
186
171
|
case ENTER:
|
|
187
172
|
case SPACE:
|
|
188
173
|
event.preventDefault();
|
|
189
|
-
|
|
174
|
+
reactToEnter(state, template, syntheticEvent);
|
|
175
|
+
break;
|
|
190
176
|
case ESCAPE:
|
|
191
177
|
// td, th or div[role=gridcell/rowheader] is the active element in the
|
|
192
178
|
// action mode if cell doesn't have action elements; hence this can be
|
|
193
179
|
// reached and we should react to escape as exiting from action mode
|
|
194
180
|
syntheticEvent.detail.keyEvent = event;
|
|
195
|
-
|
|
181
|
+
reactToEscape(state, template, syntheticEvent);
|
|
182
|
+
break;
|
|
196
183
|
case TAB:
|
|
197
|
-
|
|
184
|
+
reactToTab(state, template, syntheticEvent);
|
|
185
|
+
break;
|
|
198
186
|
default:
|
|
199
|
-
|
|
187
|
+
break;
|
|
200
188
|
}
|
|
201
189
|
}
|
|
202
190
|
|
|
203
|
-
function
|
|
204
|
-
setBlurActiveCell(element, state);
|
|
205
|
-
setRowNavigationMode(state);
|
|
206
|
-
setFocusActiveRow(element, state);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function reactToArrowLeft(element, state, event) {
|
|
191
|
+
function reactToArrowLeft(state, template, event) {
|
|
210
192
|
const { rowKeyValue, colKeyValue } = event.detail;
|
|
211
193
|
const { colIndex } = getIndexesByKeys(state, rowKeyValue, colKeyValue);
|
|
212
|
-
const { columns } = state;
|
|
213
|
-
|
|
214
194
|
// Move from navigation mode to row mode when user
|
|
215
195
|
// arrows left when in nav mode and on the first column
|
|
216
196
|
if (colIndex === 0 && canBeRowNavigationMode(state)) {
|
|
217
|
-
|
|
197
|
+
// Tracked state change.
|
|
198
|
+
// Move from cell to row.
|
|
199
|
+
setBlurActiveCell(state, template);
|
|
200
|
+
// Untracked state change.
|
|
201
|
+
setRowNavigationMode(state);
|
|
202
|
+
// Tracked state change.
|
|
203
|
+
setFocusActiveRow(state, template);
|
|
218
204
|
} else {
|
|
219
205
|
const nextColIndex = getNextIndexLeft(state, colIndex);
|
|
220
|
-
|
|
221
206
|
if (nextColIndex === undefined) {
|
|
222
207
|
return;
|
|
223
208
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
// update activeCell
|
|
209
|
+
setBlurActiveCell(state, template);
|
|
210
|
+
// Untracked state change.
|
|
211
|
+
// Update activeCell.
|
|
228
212
|
state.activeCell = {
|
|
229
213
|
rowKeyValue,
|
|
230
214
|
colKeyValue: generateColKeyValue(
|
|
231
|
-
columns[nextColIndex],
|
|
215
|
+
state.columns[nextColIndex],
|
|
232
216
|
nextColIndex
|
|
233
217
|
),
|
|
234
218
|
};
|
|
235
|
-
|
|
219
|
+
// Tracked state change.
|
|
220
|
+
setFocusActiveCell(state, template, NAVIGATION_DIR.LEFT);
|
|
236
221
|
}
|
|
237
222
|
}
|
|
238
223
|
|
|
239
|
-
function reactToArrowRight(
|
|
224
|
+
function reactToArrowRight(state, template, event) {
|
|
240
225
|
const { rowKeyValue, colKeyValue } = event.detail;
|
|
241
226
|
const { colIndex } = getIndexesByKeys(state, rowKeyValue, colKeyValue);
|
|
242
227
|
const nextColIndex = getNextIndexRight(state, colIndex);
|
|
243
|
-
const { columns } = state;
|
|
244
|
-
|
|
245
228
|
if (nextColIndex === undefined) {
|
|
246
229
|
return;
|
|
247
230
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
// update activeCell
|
|
231
|
+
setBlurActiveCell(state, template);
|
|
232
|
+
// Untracked state change.
|
|
233
|
+
// Update activeCell.
|
|
252
234
|
state.activeCell = {
|
|
253
235
|
rowKeyValue,
|
|
254
|
-
colKeyValue: generateColKeyValue(
|
|
236
|
+
colKeyValue: generateColKeyValue(
|
|
237
|
+
state.columns[nextColIndex],
|
|
238
|
+
nextColIndex
|
|
239
|
+
),
|
|
255
240
|
};
|
|
256
|
-
setFocusActiveCell(
|
|
241
|
+
setFocusActiveCell(state, template, NAVIGATION_DIR.RIGHT);
|
|
257
242
|
}
|
|
258
243
|
|
|
259
|
-
function reactToArrowUp(
|
|
244
|
+
function reactToArrowUp(state, template, event) {
|
|
260
245
|
const { rowKeyValue, colKeyValue, keyEvent } = event.detail;
|
|
261
246
|
const { rowIndex } = getIndexesByKeys(state, rowKeyValue, colKeyValue);
|
|
262
247
|
const nextRowIndex = getNextIndexUp(state, rowIndex);
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (state.hideTableHeader && nextRowIndex === -1) {
|
|
248
|
+
if (
|
|
249
|
+
nextRowIndex === undefined ||
|
|
250
|
+
(state.hideTableHeader && nextRowIndex === -1)
|
|
251
|
+
) {
|
|
270
252
|
return;
|
|
271
253
|
}
|
|
272
254
|
|
|
273
255
|
if (keyEvent) {
|
|
274
256
|
keyEvent.stopPropagation();
|
|
275
257
|
}
|
|
276
|
-
|
|
277
|
-
setBlurActiveCell(
|
|
278
|
-
|
|
279
|
-
//
|
|
258
|
+
// Tracked state change.
|
|
259
|
+
setBlurActiveCell(state, template);
|
|
260
|
+
// Untracked state change.
|
|
261
|
+
// Update activeCell.
|
|
280
262
|
state.activeCell = {
|
|
281
|
-
rowKeyValue:
|
|
263
|
+
rowKeyValue:
|
|
264
|
+
nextRowIndex === -1 ? HEADER_ROW_KEY : state.rows[nextRowIndex].key,
|
|
282
265
|
colKeyValue,
|
|
283
266
|
};
|
|
284
|
-
|
|
267
|
+
// Tracked state change.
|
|
268
|
+
setFocusActiveCell(state, template, NAVIGATION_DIR.USE_CURRENT);
|
|
285
269
|
}
|
|
286
270
|
|
|
287
|
-
function reactToArrowDown(
|
|
271
|
+
function reactToArrowDown(state, template, event) {
|
|
288
272
|
const { rowKeyValue, colKeyValue, keyEvent } = event.detail;
|
|
289
273
|
const { rowIndex } = getIndexesByKeys(state, rowKeyValue, colKeyValue);
|
|
290
274
|
const nextRowIndex = getNextIndexDown(state, rowIndex);
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (state.hideTableHeader && nextRowIndex === -1) {
|
|
275
|
+
if (
|
|
276
|
+
nextRowIndex === undefined ||
|
|
277
|
+
(state.hideTableHeader && nextRowIndex === -1)
|
|
278
|
+
) {
|
|
298
279
|
return;
|
|
299
280
|
}
|
|
300
281
|
|
|
301
282
|
if (keyEvent) {
|
|
302
283
|
keyEvent.stopPropagation();
|
|
303
284
|
}
|
|
304
|
-
|
|
305
|
-
setBlurActiveCell(
|
|
306
|
-
|
|
307
|
-
//
|
|
285
|
+
// Tracked state change.
|
|
286
|
+
setBlurActiveCell(state, template);
|
|
287
|
+
// Untracked state change.
|
|
288
|
+
// Update activeCell.
|
|
308
289
|
state.activeCell = {
|
|
309
|
-
rowKeyValue:
|
|
290
|
+
rowKeyValue:
|
|
291
|
+
nextRowIndex === -1 ? HEADER_ROW_KEY : state.rows[nextRowIndex].key,
|
|
310
292
|
colKeyValue,
|
|
311
293
|
};
|
|
312
|
-
setFocusActiveCell(
|
|
294
|
+
setFocusActiveCell(state, template, NAVIGATION_DIR.USE_CURRENT);
|
|
313
295
|
}
|
|
314
296
|
|
|
315
|
-
function reactToEnter(
|
|
316
|
-
if (state.keyboardMode ===
|
|
317
|
-
state.
|
|
297
|
+
function reactToEnter(state, template, event) {
|
|
298
|
+
if (state.keyboardMode === KEYBOARD_NAVIGATION_MODE) {
|
|
299
|
+
// Untracked state change.
|
|
300
|
+
state.keyboardMode = KEYBOARD_ACTION_MODE;
|
|
301
|
+
const { keyCode, keyEvent } = event.detail;
|
|
318
302
|
const { rowIndex, colIndex } = getIndexesActiveCell(state);
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
actionsMap[SPACE] = 'space';
|
|
322
|
-
actionsMap[ENTER] = 'enter';
|
|
323
|
-
|
|
324
|
-
if (event.detail.keyEvent) {
|
|
325
|
-
event.detail.keyEvent.preventDefault();
|
|
303
|
+
if (keyEvent) {
|
|
304
|
+
keyEvent.preventDefault();
|
|
326
305
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
306
|
+
const info = { action: undefined };
|
|
307
|
+
if (keyCode === SPACE) {
|
|
308
|
+
info.action = 'space';
|
|
309
|
+
} else if (keyCode === ENTER) {
|
|
310
|
+
info.action = 'enter';
|
|
311
|
+
}
|
|
312
|
+
// Tracked state changes.
|
|
313
|
+
setModeActiveCell(state, template, info);
|
|
314
|
+
updateCellTabIndex(state, rowIndex, colIndex, -1);
|
|
331
315
|
}
|
|
332
316
|
}
|
|
333
317
|
|
|
334
|
-
function reactToEscape(
|
|
335
|
-
if (state.keyboardMode ===
|
|
318
|
+
function reactToEscape(state, template, event) {
|
|
319
|
+
if (state.keyboardMode === KEYBOARD_ACTION_MODE) {
|
|
336
320
|
// When the table is in action mode this event shouldn't bubble
|
|
337
321
|
// because if the table in inside a modal it should prevent the modal closes
|
|
338
322
|
event.detail.keyEvent.stopPropagation();
|
|
339
|
-
state.
|
|
340
|
-
|
|
341
|
-
|
|
323
|
+
// Untracked state change.
|
|
324
|
+
state.keyboardMode = KEYBOARD_NAVIGATION_MODE;
|
|
325
|
+
// Tracked state changes.
|
|
326
|
+
setModeActiveCell(state, template);
|
|
327
|
+
setFocusActiveCell(state, template, NAVIGATION_DIR.RESET);
|
|
342
328
|
}
|
|
343
329
|
}
|
|
344
330
|
|
|
345
|
-
function reactToTab(
|
|
331
|
+
function reactToTab(state, template, event) {
|
|
346
332
|
event.preventDefault();
|
|
347
333
|
event.stopPropagation();
|
|
348
334
|
|
|
349
|
-
const {
|
|
350
|
-
const direction = getTabDirection(shiftKey);
|
|
335
|
+
const { detail } = event;
|
|
336
|
+
const direction = getTabDirection(detail.shiftKey);
|
|
351
337
|
const isExitCell = isActiveCellAnExitCell(state, direction);
|
|
352
338
|
|
|
353
|
-
//
|
|
354
|
-
if (state.keyboardMode ===
|
|
355
|
-
//
|
|
339
|
+
// If in ACTION mode.
|
|
340
|
+
if (state.keyboardMode === KEYBOARD_ACTION_MODE) {
|
|
341
|
+
// If not on last or first cell, tab through each cell of the grid.
|
|
356
342
|
if (isExitCell === false) {
|
|
357
|
-
//
|
|
358
|
-
|
|
359
|
-
|
|
343
|
+
// Prevent default key event in action mode when actually moving within the grid.
|
|
344
|
+
const { keyEvent } = detail;
|
|
345
|
+
if (keyEvent) {
|
|
346
|
+
keyEvent.preventDefault();
|
|
360
347
|
}
|
|
361
|
-
//
|
|
348
|
+
// Tab in proper direction based on shift key press.
|
|
362
349
|
if (direction === 'BACKWARD') {
|
|
363
|
-
reactToTabBackward(
|
|
350
|
+
reactToTabBackward(state, template);
|
|
364
351
|
} else {
|
|
365
|
-
reactToTabForward(
|
|
352
|
+
reactToTabForward(state, template);
|
|
366
353
|
}
|
|
367
354
|
} else {
|
|
368
|
-
//
|
|
369
|
-
|
|
370
|
-
|
|
355
|
+
// Untracked state change.
|
|
356
|
+
// Exit ACTION mode.
|
|
357
|
+
state.keyboardMode = KEYBOARD_NAVIGATION_MODE;
|
|
358
|
+
// Tracked state change.
|
|
359
|
+
setModeActiveCell(state, template);
|
|
360
|
+
// Untracked state change.
|
|
371
361
|
state.isExitingActionMode = true;
|
|
372
362
|
}
|
|
373
363
|
} else {
|
|
364
|
+
// Untracked state change.
|
|
374
365
|
state.isExitingActionMode = true;
|
|
375
366
|
}
|
|
376
367
|
}
|
|
377
368
|
|
|
378
|
-
export function reactToTabForward(
|
|
379
|
-
const {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
// update activeCell
|
|
369
|
+
export function reactToTabForward(state, template) {
|
|
370
|
+
const { nextColIndex, nextRowIndex } = getNextIndexOnTab(state, 'FORWARD');
|
|
371
|
+
// Tracked state change.
|
|
372
|
+
setBlurActiveCell(state, template);
|
|
373
|
+
// Untracked state change.
|
|
374
|
+
// Update activeCell.
|
|
385
375
|
state.activeCell = {
|
|
386
|
-
rowKeyValue:
|
|
387
|
-
|
|
376
|
+
rowKeyValue:
|
|
377
|
+
nextRowIndex === -1 ? HEADER_ROW_KEY : state.rows[nextRowIndex].key,
|
|
378
|
+
colKeyValue: generateColKeyValue(
|
|
379
|
+
state.columns[nextColIndex],
|
|
380
|
+
nextColIndex
|
|
381
|
+
),
|
|
388
382
|
};
|
|
389
|
-
|
|
383
|
+
// Tracked state change.
|
|
384
|
+
setFocusActiveCell(state, template, NAVIGATION_DIR.TAB_FORWARD, {
|
|
390
385
|
action: 'tab',
|
|
391
386
|
});
|
|
392
387
|
}
|
|
393
388
|
|
|
394
|
-
export function reactToTabBackward(
|
|
395
|
-
const {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
// update activeCell
|
|
389
|
+
export function reactToTabBackward(state, template) {
|
|
390
|
+
const { nextColIndex, nextRowIndex } = getNextIndexOnTab(state, 'BACKWARD');
|
|
391
|
+
// Tracked state change.
|
|
392
|
+
setBlurActiveCell(state, template);
|
|
393
|
+
// Untracked state change.
|
|
394
|
+
// Update activeCell.
|
|
401
395
|
state.activeCell = {
|
|
402
|
-
rowKeyValue:
|
|
403
|
-
|
|
396
|
+
rowKeyValue:
|
|
397
|
+
nextRowIndex === -1 ? HEADER_ROW_KEY : state.rows[nextRowIndex].key,
|
|
398
|
+
colKeyValue: generateColKeyValue(
|
|
399
|
+
state.columns[nextColIndex],
|
|
400
|
+
nextColIndex
|
|
401
|
+
),
|
|
404
402
|
};
|
|
405
|
-
|
|
403
|
+
// Tracked state change.
|
|
404
|
+
setFocusActiveCell(state, template, NAVIGATION_DIR.TAB_BACKWARD, {
|
|
406
405
|
action: 'tab',
|
|
407
406
|
});
|
|
408
407
|
}
|
|
@@ -413,20 +412,16 @@ function getTabDirection(shiftKey) {
|
|
|
413
412
|
|
|
414
413
|
/**
|
|
415
414
|
* Retrieve the next index values for row & column when tab is pressed
|
|
416
|
-
* @param {
|
|
417
|
-
* @param {
|
|
418
|
-
* @returns {
|
|
415
|
+
* @param {Object} state - datatable state
|
|
416
|
+
* @param {String} direction - 'FORWARD' or 'BACKWARD'
|
|
417
|
+
* @returns {Object} - nextRowIndex, nextColIndex values, isExitCell boolean
|
|
419
418
|
*/
|
|
420
|
-
function getNextIndexOnTab(state, direction) {
|
|
419
|
+
function getNextIndexOnTab(state, direction = 'FORWARD') {
|
|
421
420
|
const { rowIndex, colIndex } = getIndexesActiveCell(state);
|
|
422
|
-
|
|
423
421
|
// decide which function to use based on the value of direction
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
return nextTabFunc[direction](state, rowIndex, colIndex);
|
|
422
|
+
return direction === 'BACKWARD'
|
|
423
|
+
? getNextIndexOnTabBackward(state, rowIndex, colIndex)
|
|
424
|
+
: getNextIndexOnTabForward(state, rowIndex, colIndex);
|
|
430
425
|
}
|
|
431
426
|
|
|
432
427
|
function getNextIndexOnTabForward(state, rowIndex, colIndex) {
|
|
@@ -471,105 +466,91 @@ function getNextIndexOnTabBackward(state, rowIndex, colIndex) {
|
|
|
471
466
|
* and will remove the user from row mode and place them in navigation mode
|
|
472
467
|
* Arrow Left: If cell is expanded, this will collapse the expanded row
|
|
473
468
|
*
|
|
474
|
-
* @param {
|
|
475
|
-
* @param {
|
|
476
|
-
* @param {*} event - The keydown event
|
|
469
|
+
* @param {Object} dt - The datatable instance
|
|
470
|
+
* @param {Object} event - The keydown event
|
|
477
471
|
* @returns Mutated state
|
|
478
472
|
*/
|
|
479
|
-
export function reactToKeyboardOnRow(
|
|
473
|
+
export function reactToKeyboardOnRow(dt, event) {
|
|
474
|
+
const { state, template } = dt;
|
|
480
475
|
// TODO: Adapt this selector to also work in a role-based table once tree-grid is also migrated
|
|
476
|
+
const { localName } = event.target;
|
|
481
477
|
if (
|
|
482
|
-
|
|
483
|
-
|
|
478
|
+
localName &&
|
|
479
|
+
localName.indexOf('tr') !== -1 &&
|
|
480
|
+
isRowNavigationMode(state)
|
|
484
481
|
) {
|
|
485
|
-
const element = datatable.template;
|
|
486
482
|
switch (event.detail.keyCode) {
|
|
487
483
|
case ARROW_LEFT:
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
element,
|
|
491
|
-
state,
|
|
492
|
-
event
|
|
493
|
-
);
|
|
484
|
+
reactToArrowLeftOnRow(dt, state, template, event);
|
|
485
|
+
break;
|
|
494
486
|
case ARROW_RIGHT:
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
element,
|
|
498
|
-
state,
|
|
499
|
-
event
|
|
500
|
-
);
|
|
487
|
+
reactToArrowRightOnRow(dt, state, template, event);
|
|
488
|
+
break;
|
|
501
489
|
case ARROW_UP:
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
element,
|
|
505
|
-
state,
|
|
506
|
-
event
|
|
507
|
-
);
|
|
490
|
+
reactToArrowUpOnRow(dt, state, template, event);
|
|
491
|
+
break;
|
|
508
492
|
case ARROW_DOWN:
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
element,
|
|
512
|
-
state,
|
|
513
|
-
event
|
|
514
|
-
);
|
|
493
|
+
reactToArrowDownOnRow(dt, state, template, event);
|
|
494
|
+
break;
|
|
515
495
|
default:
|
|
516
|
-
|
|
496
|
+
break;
|
|
517
497
|
}
|
|
518
498
|
}
|
|
519
|
-
return state;
|
|
520
499
|
}
|
|
521
500
|
|
|
522
|
-
function reactToArrowLeftOnRow(
|
|
501
|
+
function reactToArrowLeftOnRow(dt, state, template, event) {
|
|
523
502
|
const { rowKeyValue, rowHasChildren, rowExpanded, rowLevel } = event.detail;
|
|
524
|
-
//
|
|
525
|
-
//
|
|
503
|
+
// Check if row needs to be collapsed.
|
|
504
|
+
// If not, go to parent and focus there.
|
|
526
505
|
if (rowHasChildren && rowExpanded) {
|
|
527
|
-
fireRowToggleEvent
|
|
506
|
+
fireRowToggleEvent(dt, rowKeyValue, rowExpanded);
|
|
528
507
|
} else if (rowLevel > 1) {
|
|
529
508
|
const treeColumn = getStateTreeColumn(state);
|
|
530
509
|
if (treeColumn) {
|
|
531
|
-
const colKeyValue = treeColumn
|
|
510
|
+
const { colKeyValue } = treeColumn;
|
|
532
511
|
const { rowIndex } = getIndexesByKeys(
|
|
533
512
|
state,
|
|
534
513
|
rowKeyValue,
|
|
535
514
|
colKeyValue
|
|
536
515
|
);
|
|
537
|
-
const parentIndex =
|
|
516
|
+
const parentIndex = getRowParentIndex(state, rowLevel, rowIndex);
|
|
538
517
|
if (parentIndex !== -1) {
|
|
539
|
-
|
|
540
|
-
setBlurActiveRow(
|
|
541
|
-
//
|
|
518
|
+
// Tracked state change.
|
|
519
|
+
setBlurActiveRow(state, template);
|
|
520
|
+
// Untracked state change.
|
|
521
|
+
// Update activeCell for the row.
|
|
542
522
|
state.activeCell = {
|
|
543
|
-
rowKeyValue: rows[parentIndex].key,
|
|
523
|
+
rowKeyValue: state.rows[parentIndex].key,
|
|
544
524
|
colKeyValue,
|
|
545
525
|
};
|
|
546
|
-
|
|
526
|
+
// Tracked state change.
|
|
527
|
+
setFocusActiveRow(state, template);
|
|
547
528
|
}
|
|
548
529
|
}
|
|
549
530
|
}
|
|
550
531
|
}
|
|
551
532
|
|
|
552
|
-
function
|
|
553
|
-
setBlurActiveRow(element, state);
|
|
554
|
-
unsetRowNavigationMode(state);
|
|
555
|
-
setFocusActiveCell(element, state, NAVIGATION_DIR.USE_CURRENT);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
function reactToArrowRightOnRow(element, state, event) {
|
|
533
|
+
function reactToArrowRightOnRow(dt, state, template, event) {
|
|
559
534
|
const { rowKeyValue, rowHasChildren, rowExpanded } = event.detail;
|
|
560
|
-
//
|
|
561
|
-
//
|
|
562
|
-
//
|
|
563
|
-
//
|
|
535
|
+
// Check if row needs to be expanded.
|
|
536
|
+
// Expand row if has children and is collapsed.
|
|
537
|
+
// Otherwise, make this.state.rowMode = false.
|
|
538
|
+
// Move tabIndex 0 to first cell in the row and focus there.
|
|
564
539
|
if (rowHasChildren && !rowExpanded) {
|
|
565
|
-
fireRowToggleEvent
|
|
540
|
+
fireRowToggleEvent(dt, rowKeyValue, rowExpanded);
|
|
566
541
|
} else {
|
|
567
|
-
|
|
542
|
+
// Tracked state change.
|
|
543
|
+
// Move from row to cell.
|
|
544
|
+
setBlurActiveRow(state, template);
|
|
545
|
+
// Untracked state change.
|
|
546
|
+
unsetRowNavigationMode(state);
|
|
547
|
+
// Tracked state change.
|
|
548
|
+
setFocusActiveCell(state, template, NAVIGATION_DIR.USE_CURRENT);
|
|
568
549
|
}
|
|
569
550
|
}
|
|
570
551
|
|
|
571
|
-
function reactToArrowUpOnRow(
|
|
572
|
-
//
|
|
552
|
+
function reactToArrowUpOnRow(state, template, event) {
|
|
553
|
+
// Move tabIndex 0 one row down.
|
|
573
554
|
const { rowKeyValue, keyEvent } = event.detail;
|
|
574
555
|
const treeColumn = getStateTreeColumn(state);
|
|
575
556
|
|
|
@@ -577,24 +558,26 @@ function reactToArrowUpOnRow(element, state, event) {
|
|
|
577
558
|
keyEvent.preventDefault();
|
|
578
559
|
|
|
579
560
|
if (treeColumn) {
|
|
580
|
-
const colKeyValue = treeColumn
|
|
561
|
+
const { colKeyValue } = treeColumn;
|
|
581
562
|
const { rowIndex } = getIndexesByKeys(state, rowKeyValue, colKeyValue);
|
|
582
563
|
const prevRowIndex = getNextIndexUpWrapped(state, rowIndex);
|
|
583
|
-
const { rows } = state;
|
|
584
564
|
if (prevRowIndex !== -1) {
|
|
585
|
-
|
|
586
|
-
|
|
565
|
+
// Tracked state change.
|
|
566
|
+
setBlurActiveRow(state, template);
|
|
567
|
+
// Untracked state change.
|
|
568
|
+
// Update activeCell for the row.
|
|
587
569
|
state.activeCell = {
|
|
588
|
-
rowKeyValue: rows[prevRowIndex].key,
|
|
570
|
+
rowKeyValue: state.rows[prevRowIndex].key,
|
|
589
571
|
colKeyValue,
|
|
590
572
|
};
|
|
591
|
-
|
|
573
|
+
// Tracked state change.
|
|
574
|
+
setFocusActiveRow(state, template);
|
|
592
575
|
}
|
|
593
576
|
}
|
|
594
577
|
}
|
|
595
578
|
|
|
596
|
-
function reactToArrowDownOnRow(
|
|
597
|
-
//
|
|
579
|
+
function reactToArrowDownOnRow(state, template, event) {
|
|
580
|
+
// Move tabIndex 0 one row down.
|
|
598
581
|
const { rowKeyValue, keyEvent } = event.detail;
|
|
599
582
|
const treeColumn = getStateTreeColumn(state);
|
|
600
583
|
|
|
@@ -602,18 +585,20 @@ function reactToArrowDownOnRow(element, state, event) {
|
|
|
602
585
|
keyEvent.preventDefault();
|
|
603
586
|
|
|
604
587
|
if (treeColumn) {
|
|
605
|
-
const colKeyValue = treeColumn
|
|
588
|
+
const { colKeyValue } = treeColumn;
|
|
606
589
|
const { rowIndex } = getIndexesByKeys(state, rowKeyValue, colKeyValue);
|
|
607
590
|
const nextRowIndex = getNextIndexDownWrapped(state, rowIndex);
|
|
608
|
-
const { rows } = state;
|
|
609
591
|
if (nextRowIndex !== -1) {
|
|
610
|
-
|
|
611
|
-
|
|
592
|
+
// Tracked state change.
|
|
593
|
+
setBlurActiveRow(state, template);
|
|
594
|
+
// Untracked state change.
|
|
595
|
+
// Update activeCell for the row.
|
|
612
596
|
state.activeCell = {
|
|
613
|
-
rowKeyValue: rows[nextRowIndex].key,
|
|
597
|
+
rowKeyValue: state.rows[nextRowIndex].key,
|
|
614
598
|
colKeyValue,
|
|
615
599
|
};
|
|
616
|
-
|
|
600
|
+
// Tracked state change.
|
|
601
|
+
setFocusActiveRow(state, template);
|
|
617
602
|
}
|
|
618
603
|
}
|
|
619
604
|
}
|
|
@@ -621,20 +606,24 @@ function reactToArrowDownOnRow(element, state, event) {
|
|
|
621
606
|
/***************************** ACTIVE CELL *****************************/
|
|
622
607
|
|
|
623
608
|
function getDefaultActiveCell(state) {
|
|
624
|
-
const { columns
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
609
|
+
const { columns } = state;
|
|
610
|
+
const { length: colCount } = columns;
|
|
611
|
+
if (colCount) {
|
|
612
|
+
let colIndex = 0;
|
|
613
|
+
let existCustomerColumn = false;
|
|
614
|
+
for (let i = 0; i < colCount; i += 1) {
|
|
615
|
+
colIndex = i;
|
|
616
|
+
if (columns[i].internal !== true) {
|
|
617
|
+
existCustomerColumn = true;
|
|
618
|
+
break;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
632
621
|
if (!existCustomerColumn) {
|
|
633
622
|
colIndex = 0;
|
|
634
623
|
}
|
|
635
|
-
|
|
624
|
+
const { rows } = state;
|
|
636
625
|
return {
|
|
637
|
-
rowKeyValue: rows.length > 0 ? rows[0].key :
|
|
626
|
+
rowKeyValue: rows.length > 0 ? rows[0].key : HEADER_ROW_KEY,
|
|
638
627
|
colKeyValue: generateColKeyValue(columns[colIndex], colIndex),
|
|
639
628
|
};
|
|
640
629
|
}
|
|
@@ -650,31 +639,35 @@ function setDefaultActiveCell(state) {
|
|
|
650
639
|
* Given a datatable template and state, returns an LWC component reference that represents
|
|
651
640
|
* the currently active cell in the table.
|
|
652
641
|
*
|
|
653
|
-
* @param {Object} template -
|
|
654
|
-
* @param {Object} state -
|
|
642
|
+
* @param {Object} template - The datatable template
|
|
643
|
+
* @param {Object} state - The datatable state
|
|
655
644
|
*/
|
|
656
645
|
export function getActiveCellElement(template, state) {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
646
|
+
const { activeCell } = state;
|
|
647
|
+
return activeCell
|
|
648
|
+
? getCellElementByKeys(
|
|
649
|
+
template,
|
|
650
|
+
activeCell.rowKeyValue,
|
|
651
|
+
activeCell.colKeyValue
|
|
652
|
+
)
|
|
653
|
+
: null;
|
|
662
654
|
}
|
|
663
655
|
|
|
664
656
|
/**
|
|
665
657
|
* Returns if the pair rowKeyValue, colKeyValue are the current activeCell values
|
|
666
658
|
*
|
|
667
|
-
* @param {
|
|
668
|
-
* @param {
|
|
669
|
-
* @param {
|
|
670
|
-
* @returns {
|
|
659
|
+
* @param {Object} state - datatable state
|
|
660
|
+
* @param {String} rowKeyValue - the unique row key value
|
|
661
|
+
* @param {String} colKeyValue {string} - the unique col key value
|
|
662
|
+
* @returns {Boolean} - true if rowKeyValue, colKeyValue are the current activeCell values.
|
|
671
663
|
*/
|
|
672
664
|
export function isActiveCell(state, rowKeyValue, colKeyValue) {
|
|
673
|
-
|
|
665
|
+
const { activeCell } = state;
|
|
666
|
+
if (activeCell) {
|
|
674
667
|
const {
|
|
675
668
|
rowKeyValue: currentRowKeyValue,
|
|
676
669
|
colKeyValue: currentColKeyValue,
|
|
677
|
-
} =
|
|
670
|
+
} = activeCell;
|
|
678
671
|
return (
|
|
679
672
|
currentRowKeyValue === rowKeyValue &&
|
|
680
673
|
currentColKeyValue === colKeyValue
|
|
@@ -683,41 +676,26 @@ export function isActiveCell(state, rowKeyValue, colKeyValue) {
|
|
|
683
676
|
return false;
|
|
684
677
|
}
|
|
685
678
|
|
|
686
|
-
/**
|
|
687
|
-
* Updates the current activeCell in the state with the new rowKeyValue, colKeyValue
|
|
688
|
-
* @param {object} state - datatable state
|
|
689
|
-
* @param {string} rowKeyValue - the unique row key value
|
|
690
|
-
* @param {string} colKeyValue {string} - the unique col key value
|
|
691
|
-
* @returns {object} state - mutated datatable state
|
|
692
|
-
*/
|
|
693
|
-
export function updateActiveCell(state, rowKeyValue, colKeyValue) {
|
|
694
|
-
state.activeCell = {
|
|
695
|
-
rowKeyValue,
|
|
696
|
-
colKeyValue,
|
|
697
|
-
};
|
|
698
|
-
return state;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
679
|
/**
|
|
702
680
|
* It check if in the current (data, columns) the activeCell still valid.
|
|
703
681
|
* When data changed the activeCell could be removed, then we check if there is cellToFocusNext
|
|
704
682
|
* which is calculated from previously focused cell, if so we sync to that
|
|
705
683
|
* If active cell is still valid we keep it the same
|
|
706
684
|
*
|
|
707
|
-
* @param {
|
|
708
|
-
* @returns {object} state - mutated datatable state
|
|
685
|
+
* @param {Object} state - The datatable state
|
|
709
686
|
*/
|
|
710
687
|
export function syncActiveCell(state) {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
688
|
+
const { activeCell } = state;
|
|
689
|
+
if (!activeCell || !stillValidActiveCell(state)) {
|
|
690
|
+
// Untracked state changes.
|
|
691
|
+
if (activeCell && state.cellToFocusNext) {
|
|
692
|
+
// There is previously focused cell.
|
|
714
693
|
setNextActiveCellFromPrev(state);
|
|
715
694
|
} else {
|
|
716
|
-
//
|
|
695
|
+
// There is no active cell or there is no previously focused cell.
|
|
717
696
|
setDefaultActiveCell(state);
|
|
718
697
|
}
|
|
719
698
|
}
|
|
720
|
-
return state;
|
|
721
699
|
}
|
|
722
700
|
|
|
723
701
|
/**
|
|
@@ -731,37 +709,38 @@ export function syncActiveCell(state) {
|
|
|
731
709
|
*/
|
|
732
710
|
function setNextActiveCellFromPrev(state) {
|
|
733
711
|
const { rowIndex, colIndex } = state.cellToFocusNext;
|
|
712
|
+
const { columns, rows } = state;
|
|
713
|
+
const { length: rowCount } = rows;
|
|
734
714
|
let nextRowIndex = rowIndex;
|
|
735
|
-
|
|
736
|
-
const rowsCount = state.rows ? state.rows.length : 0;
|
|
737
|
-
const colsCount = state.columns.length ? state.columns.length : 0;
|
|
738
|
-
|
|
739
|
-
if (nextRowIndex > rowsCount - 1) {
|
|
715
|
+
if (nextRowIndex > rowCount - 1) {
|
|
740
716
|
// row index not existing after update to new 5 > 5-1, 6 > 5-1,
|
|
741
|
-
nextRowIndex =
|
|
717
|
+
nextRowIndex = rowCount - 1;
|
|
742
718
|
}
|
|
743
|
-
|
|
719
|
+
const { length: colCount } = columns;
|
|
720
|
+
let nextColIndex = colIndex;
|
|
721
|
+
if (nextColIndex > colCount - 1) {
|
|
744
722
|
// col index not existing after update to new
|
|
745
|
-
nextColIndex =
|
|
723
|
+
nextColIndex = colCount - 1;
|
|
746
724
|
}
|
|
747
725
|
const nextActiveCell = getCellFromIndexes(
|
|
748
726
|
state,
|
|
749
727
|
nextRowIndex,
|
|
750
728
|
nextColIndex
|
|
751
729
|
);
|
|
730
|
+
// Untracked state changes.
|
|
752
731
|
if (nextActiveCell) {
|
|
753
732
|
state.activeCell = nextActiveCell;
|
|
754
733
|
} else {
|
|
755
734
|
setDefaultActiveCell(state);
|
|
756
735
|
}
|
|
757
|
-
state.keyboardMode =
|
|
736
|
+
state.keyboardMode = KEYBOARD_NAVIGATION_MODE;
|
|
758
737
|
}
|
|
759
738
|
|
|
760
739
|
/**
|
|
761
740
|
* Check if we're in an escape/exit cell (first or last of grid)
|
|
762
|
-
* @param {
|
|
763
|
-
* @param {
|
|
764
|
-
* @returns {
|
|
741
|
+
* @param {Object} state - The datatable state
|
|
742
|
+
* @param {String} direction - 'FORWARD' or 'BACKWARD'
|
|
743
|
+
* @returns {Boolean} - if the current cell is or isn't an exit cell
|
|
765
744
|
*/
|
|
766
745
|
export function isActiveCellAnExitCell(state, direction) {
|
|
767
746
|
// get next tab index values
|
|
@@ -790,60 +769,65 @@ export function getIndexesActiveCell(state) {
|
|
|
790
769
|
return getIndexesByKeys(state, rowKeyValue, colKeyValue);
|
|
791
770
|
}
|
|
792
771
|
|
|
793
|
-
function setModeActiveCell(
|
|
794
|
-
const cellElement = getActiveCellElement(
|
|
772
|
+
function setModeActiveCell(state, template, info) {
|
|
773
|
+
const cellElement = getActiveCellElement(template, state);
|
|
795
774
|
if (cellElement) {
|
|
796
775
|
cellElement.setMode(state.keyboardMode, info);
|
|
797
776
|
}
|
|
798
777
|
}
|
|
799
778
|
|
|
800
779
|
function stillValidActiveCell(state) {
|
|
801
|
-
const {
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
780
|
+
const { activeCell, indexes } = state;
|
|
781
|
+
const { rowKeyValue, colKeyValue } = activeCell;
|
|
782
|
+
if (rowKeyValue === HEADER_ROW_KEY) {
|
|
783
|
+
if (state.rows.length) {
|
|
784
|
+
const { columns } = state;
|
|
785
|
+
let sortable = false;
|
|
786
|
+
for (let colIndex = 0; colIndex < columns.length; colIndex += 1) {
|
|
787
|
+
if (columns[colIndex].sortable) {
|
|
788
|
+
sortable = true;
|
|
789
|
+
break;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
if (!sortable) {
|
|
793
|
+
return false;
|
|
794
|
+
}
|
|
810
795
|
}
|
|
811
796
|
return state.headerIndexes[colKeyValue] !== undefined;
|
|
812
797
|
}
|
|
813
|
-
return !!(
|
|
814
|
-
state.indexes[rowKeyValue] && state.indexes[rowKeyValue][colKeyValue]
|
|
815
|
-
);
|
|
798
|
+
return !!(indexes[rowKeyValue] && indexes[rowKeyValue][colKeyValue]);
|
|
816
799
|
}
|
|
817
800
|
|
|
818
801
|
/***************************** FOCUS MANAGEMENT *****************************/
|
|
819
802
|
|
|
820
803
|
/**
|
|
821
804
|
* It set the focus to the current activeCell, this operation imply multiple changes
|
|
822
|
-
* - update the
|
|
805
|
+
* - update the tabIndex of the activeCell
|
|
823
806
|
* - set the current keyboard mode
|
|
824
807
|
* - set the focus to the cell
|
|
825
|
-
* @param {
|
|
826
|
-
* @param {
|
|
827
|
-
* @param {
|
|
828
|
-
* @param {
|
|
829
|
-
* @param {
|
|
808
|
+
* @param {Object} state - The datatable state
|
|
809
|
+
* @param {Node} template - The custom element template `this.template`
|
|
810
|
+
* @param {Integer} direction - The direction (-1 left, 1 right and 0 for no direction) its used to know which actionable element to activate.
|
|
811
|
+
* @param {Object} info - Extra information when setting the cell mode; currently only set when pressing tab
|
|
812
|
+
* @param {Boolean} [shouldScroll = true] - Whether scrollTop should be adjusted when setting focus
|
|
830
813
|
*/
|
|
831
814
|
export function setFocusActiveCell(
|
|
832
|
-
template,
|
|
833
815
|
state,
|
|
816
|
+
template,
|
|
834
817
|
direction,
|
|
835
818
|
info,
|
|
836
819
|
shouldScroll = true
|
|
837
820
|
) {
|
|
838
821
|
const { keyboardMode } = state;
|
|
839
822
|
const { rowIndex, colIndex } = getIndexesActiveCell(state);
|
|
823
|
+
let cellElement = getActiveCellElement(template, state);
|
|
840
824
|
|
|
841
825
|
state.activeCell.focused = !(info && isActiveCellValid(state));
|
|
842
|
-
updateTabIndex(state, rowIndex, colIndex);
|
|
843
826
|
|
|
844
|
-
|
|
827
|
+
updateCellTabIndex(state, rowIndex, colIndex);
|
|
828
|
+
|
|
845
829
|
// if the cell wasn't found, but does exist in the table, scroll to where it should be
|
|
846
|
-
if (!cellElement && isActiveCellValid(state)
|
|
830
|
+
if (shouldScroll && !cellElement && isActiveCellValid(state)) {
|
|
847
831
|
scrollToCell(state, template, rowIndex);
|
|
848
832
|
}
|
|
849
833
|
|
|
@@ -883,15 +867,15 @@ export function setFocusActiveCell(
|
|
|
883
867
|
/**
|
|
884
868
|
* It blur to the current activeCell, this operation imply multiple changes
|
|
885
869
|
* - blur the activeCell
|
|
886
|
-
* - update the
|
|
887
|
-
* @param {
|
|
888
|
-
* @param {
|
|
870
|
+
* - update the tabIndex to -1
|
|
871
|
+
* @param {Object} state - The datatable state
|
|
872
|
+
* @param {Node} template - The custom element root `this.template`
|
|
889
873
|
*/
|
|
890
|
-
export function setBlurActiveCell(
|
|
874
|
+
export function setBlurActiveCell(state, template) {
|
|
891
875
|
if (state.activeCell) {
|
|
892
876
|
const { rowIndex, colIndex } = getIndexesActiveCell(state);
|
|
893
|
-
let cellElement = getActiveCellElement(template, state);
|
|
894
877
|
state.activeCell.focused = false;
|
|
878
|
+
let cellElement = getActiveCellElement(template, state);
|
|
895
879
|
// eslint-disable-next-line @lwc/lwc/no-async-operation
|
|
896
880
|
setTimeout(() => {
|
|
897
881
|
// check cellElement; value may have changed
|
|
@@ -913,7 +897,7 @@ export function setBlurActiveCell(template, state) {
|
|
|
913
897
|
cellElement.parentElement.classList.remove(FOCUS_CLASS);
|
|
914
898
|
}
|
|
915
899
|
}, 0);
|
|
916
|
-
|
|
900
|
+
updateCellTabIndex(state, rowIndex, colIndex, -1);
|
|
917
901
|
}
|
|
918
902
|
}
|
|
919
903
|
|
|
@@ -924,23 +908,26 @@ export function setBlurActiveCell(template, state) {
|
|
|
924
908
|
* there is state.indexes
|
|
925
909
|
* there is no previously set state.cellToFocusNext
|
|
926
910
|
* Indexes are calculated as to what to focus on next
|
|
927
|
-
* @param {
|
|
928
|
-
* @param {
|
|
911
|
+
* @param {Object} state - The datatable state
|
|
912
|
+
* @param {Object} template - The datatable element
|
|
929
913
|
*/
|
|
930
914
|
export function setCellToFocusFromPrev(state, template) {
|
|
931
915
|
if (
|
|
932
916
|
state.activeCell &&
|
|
933
|
-
|
|
934
|
-
state
|
|
935
|
-
!state.cellToFocusNext
|
|
917
|
+
!state.cellToFocusNext &&
|
|
918
|
+
datatableHasFocus(state, template)
|
|
936
919
|
) {
|
|
920
|
+
const { length: rowCount } = state.rows;
|
|
921
|
+
const lastIndex = rowCount - 1;
|
|
922
|
+
const { length: colCount } = state.columns;
|
|
937
923
|
let { rowIndex, colIndex } = getIndexesActiveCell(state);
|
|
938
924
|
colIndex = 0; // default point to the first column
|
|
939
|
-
if (
|
|
925
|
+
if (rowIndex === lastIndex) {
|
|
940
926
|
// if it is last row, make it point to its previous row
|
|
941
|
-
rowIndex =
|
|
942
|
-
colIndex =
|
|
927
|
+
rowIndex = lastIndex;
|
|
928
|
+
colIndex = colCount ? colCount - 1 : 0;
|
|
943
929
|
}
|
|
930
|
+
// Untracked state change.
|
|
944
931
|
state.cellToFocusNext = {
|
|
945
932
|
rowIndex,
|
|
946
933
|
colIndex,
|
|
@@ -949,8 +936,8 @@ export function setCellToFocusFromPrev(state, template) {
|
|
|
949
936
|
}
|
|
950
937
|
|
|
951
938
|
/**
|
|
952
|
-
*
|
|
953
|
-
* @param {
|
|
939
|
+
* If the current new active still is valid (exists) then set the celltofocusnext to null.
|
|
940
|
+
* @param {Object} state - The datatable state
|
|
954
941
|
*/
|
|
955
942
|
export function updateCellToFocusFromPrev(state) {
|
|
956
943
|
if (
|
|
@@ -958,29 +945,20 @@ export function updateCellToFocusFromPrev(state) {
|
|
|
958
945
|
state.cellToFocusNext &&
|
|
959
946
|
stillValidActiveCell(state)
|
|
960
947
|
) {
|
|
961
|
-
//
|
|
948
|
+
// If the previous focus is there and valid, don't set the prevActiveFocusedCell.
|
|
962
949
|
state.cellToFocusNext = null;
|
|
963
950
|
}
|
|
964
951
|
}
|
|
965
952
|
|
|
966
|
-
/**
|
|
967
|
-
* reset celltofocusnext to null (used after render)
|
|
968
|
-
* @param {object} state - datatable state
|
|
969
|
-
*/
|
|
970
|
-
export function resetCellToFocusFromPrev(state) {
|
|
971
|
-
state.cellToFocusNext = null;
|
|
972
|
-
}
|
|
973
|
-
|
|
974
953
|
/**
|
|
975
954
|
* It adds and the focus classes to the th/td or div[role=gridcell/rowheader].
|
|
976
955
|
*
|
|
977
|
-
* @param {
|
|
978
|
-
* @param {
|
|
956
|
+
* @param {Object} state - The datatable state
|
|
957
|
+
* @param {Node} template - The custom element template `this.template`
|
|
979
958
|
*/
|
|
980
|
-
export function addFocusStylesToActiveCell(
|
|
981
|
-
const cellElement = getActiveCellElement(template, state);
|
|
959
|
+
export function addFocusStylesToActiveCell(state, template) {
|
|
982
960
|
state.activeCell.focused = true;
|
|
983
|
-
|
|
961
|
+
const cellElement = getActiveCellElement(template, state);
|
|
984
962
|
if (cellElement) {
|
|
985
963
|
cellElement.parentElement.classList.add(FOCUS_CLASS);
|
|
986
964
|
}
|
|
@@ -988,53 +966,54 @@ export function addFocusStylesToActiveCell(template, state) {
|
|
|
988
966
|
|
|
989
967
|
/**
|
|
990
968
|
* It set the focus to the row of current activeCell, this operation implies multiple changes
|
|
991
|
-
* - update the
|
|
969
|
+
* - update the tabIndex of the activeCell
|
|
992
970
|
* - set the current keyboard mode
|
|
993
971
|
* - set the focus to the row
|
|
994
|
-
*
|
|
995
|
-
* @param {
|
|
972
|
+
*
|
|
973
|
+
* @param {Object} state - The datatable state
|
|
974
|
+
* @param {Node} template - the custom element root `this.template`
|
|
996
975
|
*/
|
|
997
|
-
function setFocusActiveRow(
|
|
976
|
+
function setFocusActiveRow(state, template) {
|
|
998
977
|
const { rowIndex } = getIndexesActiveCell(state);
|
|
999
|
-
const
|
|
978
|
+
const rowElement = getActiveCellRowElement(template, state);
|
|
1000
979
|
|
|
1001
|
-
|
|
980
|
+
updateRowTabIndex(state, rowIndex);
|
|
1002
981
|
// eslint-disable-next-line @lwc/lwc/no-async-operation
|
|
1003
982
|
setTimeout(() => {
|
|
1004
|
-
|
|
1005
|
-
updateScrollTop(state, template,
|
|
983
|
+
rowElement.focus({ preventScroll: true });
|
|
984
|
+
updateScrollTop(state, template, rowElement);
|
|
1006
985
|
}, 0);
|
|
1007
986
|
}
|
|
1008
987
|
|
|
1009
988
|
/**
|
|
1010
989
|
* It blurs the active row, this operation implies multiple changes
|
|
1011
990
|
* - blur the active row
|
|
1012
|
-
* - update the
|
|
1013
|
-
* @param {
|
|
1014
|
-
* @param {
|
|
991
|
+
* - update the tabIndex to -1
|
|
992
|
+
* @param {Object} state - The datatable state
|
|
993
|
+
* @param {Node} template - The custom element root `this.template`
|
|
1015
994
|
*/
|
|
1016
|
-
function setBlurActiveRow(
|
|
995
|
+
function setBlurActiveRow(state, template) {
|
|
1017
996
|
if (state.activeCell) {
|
|
1018
997
|
const { rowIndex } = getIndexesActiveCell(state);
|
|
1019
998
|
// eslint-disable-next-line @lwc/lwc/no-async-operation
|
|
1020
999
|
setTimeout(() => {
|
|
1021
|
-
const
|
|
1022
|
-
if (document.activeElement ===
|
|
1023
|
-
|
|
1000
|
+
const rowElement = getActiveCellRowElement(template, state);
|
|
1001
|
+
if (document.activeElement === rowElement) {
|
|
1002
|
+
rowElement.blur();
|
|
1024
1003
|
}
|
|
1025
1004
|
}, 0);
|
|
1026
|
-
|
|
1005
|
+
updateRowTabIndex(state, rowIndex, -1);
|
|
1027
1006
|
}
|
|
1028
1007
|
}
|
|
1029
1008
|
|
|
1030
1009
|
/**
|
|
1031
1010
|
* This method is needed in IE11 where clicking on the cell (factory) makes the div or the span active element
|
|
1032
1011
|
* It refocuses on the cell element td or th or div[role=gridcell/rowheader]
|
|
1033
|
-
* @param {
|
|
1034
|
-
* @param {
|
|
1035
|
-
* @param {
|
|
1012
|
+
* @param {Object} state - The datatable state
|
|
1013
|
+
* @param {Object} template - The datatable element
|
|
1014
|
+
* @param {Boolean} needsRefocusOnCellElement - flag indicating whether or not to refocus on the cell td/th or div[role=gridcell/rowheader]
|
|
1036
1015
|
*/
|
|
1037
|
-
export function refocusCellElement(
|
|
1016
|
+
export function refocusCellElement(state, template, needsRefocusOnCellElement) {
|
|
1038
1017
|
if (needsRefocusOnCellElement) {
|
|
1039
1018
|
const cellElement = getActiveCellElement(template, state);
|
|
1040
1019
|
if (cellElement) {
|
|
@@ -1052,23 +1031,28 @@ export function refocusCellElement(template, state, needsRefocusOnCellElement) {
|
|
|
1052
1031
|
}
|
|
1053
1032
|
|
|
1054
1033
|
export function datatableHasFocus(state, template) {
|
|
1055
|
-
return isFocusInside(template)
|
|
1034
|
+
return state.cellClicked || isFocusInside(template);
|
|
1056
1035
|
}
|
|
1057
1036
|
|
|
1058
1037
|
function isFocusInside(currentTarget) {
|
|
1059
1038
|
const activeElements = getShadowActiveElements();
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1039
|
+
for (let i = 0, { length } = activeElements; i < length; i += 1) {
|
|
1040
|
+
if (currentTarget.contains(activeElements[i])) {
|
|
1041
|
+
return true;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
return false;
|
|
1063
1045
|
}
|
|
1064
1046
|
|
|
1065
1047
|
export function handleDatatableFocusIn(event) {
|
|
1066
1048
|
const { state } = this;
|
|
1049
|
+
|
|
1050
|
+
// Untracked state change.
|
|
1067
1051
|
state.isExitingActionMode = false;
|
|
1068
1052
|
|
|
1069
1053
|
// workaround for delegatesFocus issue that focusin is called when not supposed to W-6220418
|
|
1070
1054
|
if (isFocusInside(event.currentTarget)) {
|
|
1071
|
-
if (
|
|
1055
|
+
if (state.activeCell && !state.rowMode) {
|
|
1072
1056
|
state.activeCell.focused = true;
|
|
1073
1057
|
const cellElement = getActiveCellElement(this.template, state);
|
|
1074
1058
|
// we need to check because of the tree,
|
|
@@ -1085,17 +1069,17 @@ export function handleDatatableFocusIn(event) {
|
|
|
1085
1069
|
|
|
1086
1070
|
export function handleDatatableFocusOut(event) {
|
|
1087
1071
|
const { state } = this;
|
|
1072
|
+
const { currentTarget, relatedTarget } = event;
|
|
1073
|
+
const containsRelatedTarget =
|
|
1074
|
+
relatedTarget && currentTarget.contains(relatedTarget);
|
|
1088
1075
|
// workarounds for delegatesFocus issues
|
|
1089
1076
|
if (
|
|
1090
1077
|
// needed for initial focus where relatedTarget is empty
|
|
1091
|
-
!
|
|
1078
|
+
!relatedTarget ||
|
|
1092
1079
|
// needed when clicked outside
|
|
1093
|
-
(
|
|
1094
|
-
!event.currentTarget.contains(event.relatedTarget)) ||
|
|
1080
|
+
(relatedTarget && !containsRelatedTarget) ||
|
|
1095
1081
|
// needed when datatable leaves focus and related target is still within datatable W-6185154
|
|
1096
|
-
(
|
|
1097
|
-
event.currentTarget.contains(event.relatedTarget) &&
|
|
1098
|
-
state.isExitingActionMode)
|
|
1082
|
+
(relatedTarget && containsRelatedTarget && state.isExitingActionMode)
|
|
1099
1083
|
) {
|
|
1100
1084
|
if (state.activeCell && !state.rowMode) {
|
|
1101
1085
|
const cellElement = getActiveCellElement(this.template, state);
|
|
@@ -1111,7 +1095,7 @@ export function handleDatatableFocusOut(event) {
|
|
|
1111
1095
|
|
|
1112
1096
|
/**
|
|
1113
1097
|
* This is needed to check if datatable has lost focus but cell has been clicked recently
|
|
1114
|
-
* @param {
|
|
1098
|
+
* @param {Object} state - The datatable state
|
|
1115
1099
|
*/
|
|
1116
1100
|
export function setCellClickedForFocus(state) {
|
|
1117
1101
|
state.cellClicked = true;
|
|
@@ -1119,7 +1103,7 @@ export function setCellClickedForFocus(state) {
|
|
|
1119
1103
|
|
|
1120
1104
|
/**
|
|
1121
1105
|
* Once the dt regains focus there is no need to set this
|
|
1122
|
-
* @param {
|
|
1106
|
+
* @param {Object} state - The datatable state
|
|
1123
1107
|
*/
|
|
1124
1108
|
function resetCellClickedForFocus(state) {
|
|
1125
1109
|
state.cellClicked = false;
|
|
@@ -1130,19 +1114,18 @@ function resetCellClickedForFocus(state) {
|
|
|
1130
1114
|
/**
|
|
1131
1115
|
* It update the tabIndex value of a cell in the state for the rowIndex, colIndex passed
|
|
1132
1116
|
* as consequence of this change
|
|
1133
|
-
* datatable is gonna re-render the cell affected with the new
|
|
1117
|
+
* datatable is gonna re-render the cell affected with the new tabIndex value
|
|
1134
1118
|
*
|
|
1135
|
-
* @param {
|
|
1119
|
+
* @param {Object} state - The datatable state
|
|
1136
1120
|
* @param {number} rowIndex - the row index
|
|
1137
1121
|
* @param {number} colIndex - the column index
|
|
1138
|
-
* @param {number} [
|
|
1122
|
+
* @param {number} [tabIndex = 0] - the value for the tabIndex
|
|
1139
1123
|
*/
|
|
1140
|
-
export function
|
|
1124
|
+
export function updateCellTabIndex(state, rowIndex, colIndex, tabIndex = 0) {
|
|
1141
1125
|
if (isHeaderRow(rowIndex)) {
|
|
1142
|
-
|
|
1143
|
-
columns[colIndex].tabIndex = index;
|
|
1126
|
+
state.columns[colIndex].tabIndex = tabIndex;
|
|
1144
1127
|
} else {
|
|
1145
|
-
state.rows[rowIndex].cells[colIndex].tabIndex =
|
|
1128
|
+
state.rows[rowIndex].cells[colIndex].tabIndex = tabIndex;
|
|
1146
1129
|
}
|
|
1147
1130
|
}
|
|
1148
1131
|
|
|
@@ -1151,50 +1134,47 @@ export function updateTabIndex(state, rowIndex, colIndex, index = 0) {
|
|
|
1151
1134
|
* as consequence of this change
|
|
1152
1135
|
* datatable is gonna re-render the row affected with the new tabindex value
|
|
1153
1136
|
*
|
|
1154
|
-
* @param {
|
|
1137
|
+
* @param {Object} state - The datatable state
|
|
1155
1138
|
* @param {number} rowIndex - the row index
|
|
1156
1139
|
* @param {number} [index = 0] - the value for the tabindex
|
|
1157
1140
|
*/
|
|
1158
|
-
export function
|
|
1141
|
+
export function updateRowTabIndex(state, rowIndex, tabIndex = 0) {
|
|
1159
1142
|
if (!isHeaderRow(rowIndex)) {
|
|
1160
1143
|
// TODO what to do when rowIndex is header row
|
|
1161
|
-
state.rows[rowIndex].tabIndex =
|
|
1144
|
+
state.rows[rowIndex].tabIndex = tabIndex;
|
|
1162
1145
|
}
|
|
1163
1146
|
}
|
|
1147
|
+
|
|
1164
1148
|
/**
|
|
1165
|
-
*
|
|
1166
|
-
*
|
|
1149
|
+
* Updates the tabIndex for the current activeCell.
|
|
1150
|
+
*
|
|
1151
|
+
* @param {Object} state - The datatable state
|
|
1167
1152
|
* @param {number} [index = 0] - the value for the tabindex
|
|
1168
|
-
* @returns {object} state - mutated state
|
|
1169
1153
|
*/
|
|
1170
1154
|
export function updateTabIndexActiveCell(state, index = 0) {
|
|
1171
1155
|
if (state.activeCell && !stillValidActiveCell(state)) {
|
|
1156
|
+
// Untracked state change.
|
|
1172
1157
|
syncActiveCell(state);
|
|
1173
1158
|
}
|
|
1174
|
-
|
|
1175
|
-
//
|
|
1159
|
+
// Tracked state change.
|
|
1160
|
+
// We need to check again because maybe there is no active cell after sync.
|
|
1176
1161
|
updateActiveCellTabIndexAfterSync(state, index);
|
|
1177
|
-
return state;
|
|
1178
1162
|
}
|
|
1179
1163
|
|
|
1180
1164
|
/**
|
|
1181
|
-
* It updates the
|
|
1182
|
-
* This happens in rowMode of
|
|
1183
|
-
* @param {
|
|
1165
|
+
* It updates the tabIndex for the row of the current activeCell.
|
|
1166
|
+
* This happens in rowMode of KEYBOARD_NAVIGATION_MODE
|
|
1167
|
+
* @param {Object} state - The datatable state
|
|
1184
1168
|
* @param {number} [index = 0] - the value for the tabindex
|
|
1185
|
-
* @returns {object} state - mutated state
|
|
1186
1169
|
*/
|
|
1187
1170
|
export function updateTabIndexActiveRow(state, index = 0) {
|
|
1188
1171
|
if (state.activeCell && !stillValidActiveCell(state)) {
|
|
1172
|
+
// Untracked state change.
|
|
1189
1173
|
syncActiveCell(state);
|
|
1190
1174
|
}
|
|
1191
|
-
|
|
1192
|
-
//
|
|
1193
|
-
|
|
1194
|
-
const { rowIndex } = getIndexesActiveCell(state);
|
|
1195
|
-
updateTabIndexRow(state, rowIndex, index);
|
|
1196
|
-
}
|
|
1197
|
-
return state;
|
|
1175
|
+
// Tracked state change.
|
|
1176
|
+
// We need to check again because maybe there is no active cell after sync.
|
|
1177
|
+
updateActiveRowTabIndexAfterSync(state, index);
|
|
1198
1178
|
}
|
|
1199
1179
|
|
|
1200
1180
|
/***************************** INDEX COMPUTATIONS *****************************/
|
|
@@ -1208,7 +1188,7 @@ export function updateTabIndexActiveRow(state, index = 0) {
|
|
|
1208
1188
|
* @returns {object} - {rowIndex, colIndex}
|
|
1209
1189
|
*/
|
|
1210
1190
|
export function getIndexesByKeys(state, rowKeyValue, colKeyValue) {
|
|
1211
|
-
if (rowKeyValue ===
|
|
1191
|
+
if (rowKeyValue === HEADER_ROW_KEY) {
|
|
1212
1192
|
return {
|
|
1213
1193
|
rowIndex: -1,
|
|
1214
1194
|
colIndex: state.headerIndexes[colKeyValue],
|
|
@@ -1239,42 +1219,48 @@ function getPrevColumnIndex(colIndex) {
|
|
|
1239
1219
|
}
|
|
1240
1220
|
|
|
1241
1221
|
function getNextIndexRight(state, colIndex) {
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
return getNextColumnIndex(state.columns.length, colIndex);
|
|
1222
|
+
return isRTL()
|
|
1223
|
+
? getPrevColumnIndex(colIndex)
|
|
1224
|
+
: getNextColumnIndex(state.columns.length, colIndex);
|
|
1247
1225
|
}
|
|
1248
1226
|
|
|
1249
1227
|
function getNextIndexLeft(state, colIndex) {
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
return getPrevColumnIndex(colIndex);
|
|
1228
|
+
return isRTL()
|
|
1229
|
+
? getNextColumnIndex(state.columns.length, colIndex)
|
|
1230
|
+
: getPrevColumnIndex(colIndex);
|
|
1254
1231
|
}
|
|
1255
1232
|
|
|
1256
1233
|
function getNextIndexUpWrapped(state, rowIndex) {
|
|
1257
|
-
const
|
|
1258
|
-
return rowIndex ===
|
|
1234
|
+
const { length: rowCount } = state.rows;
|
|
1235
|
+
return rowIndex === -1 ? rowCount - 1 : rowIndex - 1;
|
|
1259
1236
|
}
|
|
1260
1237
|
|
|
1261
1238
|
function getNextIndexDownWrapped(state, rowIndex) {
|
|
1262
|
-
const
|
|
1263
|
-
return rowIndex + 1 <
|
|
1239
|
+
const { length: rowCount } = state.rows;
|
|
1240
|
+
return rowIndex + 1 < rowCount ? rowIndex + 1 : -1;
|
|
1264
1241
|
}
|
|
1265
1242
|
|
|
1266
1243
|
/***************************** ROW NAVIGATION MODE *****************************/
|
|
1267
1244
|
|
|
1268
1245
|
function canBeRowNavigationMode(state) {
|
|
1269
|
-
return
|
|
1246
|
+
return (
|
|
1247
|
+
state.keyboardMode === KEYBOARD_NAVIGATION_MODE &&
|
|
1248
|
+
hasTreeDataType(state)
|
|
1249
|
+
);
|
|
1270
1250
|
}
|
|
1271
1251
|
|
|
1272
1252
|
function isRowNavigationMode(state) {
|
|
1273
|
-
return
|
|
1253
|
+
return (
|
|
1254
|
+
state.keyboardMode === KEYBOARD_NAVIGATION_MODE &&
|
|
1255
|
+
state.rowMode === true
|
|
1256
|
+
);
|
|
1274
1257
|
}
|
|
1275
1258
|
|
|
1276
1259
|
function setRowNavigationMode(state) {
|
|
1277
|
-
if (
|
|
1260
|
+
if (
|
|
1261
|
+
hasTreeDataType(state) &&
|
|
1262
|
+
state.keyboardMode === KEYBOARD_NAVIGATION_MODE
|
|
1263
|
+
) {
|
|
1278
1264
|
state.rowMode = true;
|
|
1279
1265
|
}
|
|
1280
1266
|
}
|
|
@@ -1284,15 +1270,14 @@ export function unsetRowNavigationMode(state) {
|
|
|
1284
1270
|
}
|
|
1285
1271
|
|
|
1286
1272
|
/**
|
|
1287
|
-
* If new set of columns
|
|
1273
|
+
* If new set of columns doesn't have tree data, mark it to false, as it
|
|
1288
1274
|
* could be true earlier
|
|
1289
1275
|
* Else if it has tree data, check if rowMode is false
|
|
1290
|
-
* Earlier it
|
|
1276
|
+
* Earlier it didn't have tree data, set rowMode to true to start
|
|
1291
1277
|
* if rowMode is false and earlier it has tree data, keep it false
|
|
1292
1278
|
* if rowMode is true and it has tree data, keep it true
|
|
1293
|
-
* @param {
|
|
1294
|
-
* @param {
|
|
1295
|
-
* @returns {object} state - mutated state
|
|
1279
|
+
* @param {Boolean} hadTreeDataTypePreviously - state object
|
|
1280
|
+
* @param {Object} state - The state object
|
|
1296
1281
|
*/
|
|
1297
1282
|
export function updateRowNavigationMode(hadTreeDataTypePreviously, state) {
|
|
1298
1283
|
if (!hasTreeDataType(state)) {
|
|
@@ -1300,15 +1285,14 @@ export function updateRowNavigationMode(hadTreeDataTypePreviously, state) {
|
|
|
1300
1285
|
} else if (state.rowMode === false && !hadTreeDataTypePreviously) {
|
|
1301
1286
|
state.rowMode = true;
|
|
1302
1287
|
}
|
|
1303
|
-
return state;
|
|
1304
1288
|
}
|
|
1305
1289
|
|
|
1306
1290
|
/***************************** HELPER FUNCTIONS *****************************/
|
|
1307
1291
|
|
|
1308
|
-
export function isCellElement(
|
|
1292
|
+
export function isCellElement(target) {
|
|
1293
|
+
const role = target.getAttribute('role');
|
|
1309
1294
|
return (
|
|
1310
|
-
|
|
1311
|
-
SELECTORS.cell.roleBased.includes(role)
|
|
1295
|
+
role === 'gridcell' || role === 'columnheader' || role === 'rowheader'
|
|
1312
1296
|
);
|
|
1313
1297
|
}
|
|
1314
1298
|
|
|
@@ -1316,31 +1300,27 @@ function isHeaderRow(rowIndex) {
|
|
|
1316
1300
|
return rowIndex === -1;
|
|
1317
1301
|
}
|
|
1318
1302
|
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
}
|
|
1322
|
-
|
|
1323
|
-
export function getCellElementByKeys(template, rowKeyValue, colKeyValue) {
|
|
1324
|
-
const selector = `${getDataRow(
|
|
1325
|
-
rowKeyValue
|
|
1326
|
-
)} [data-col-key-value="${escapeDoubleQuotes(
|
|
1303
|
+
function getCellElementByKeys(template, rowKeyValue, colKeyValue) {
|
|
1304
|
+
const selector = `${getRowDataSelector(rowKeyValue)} ${getColDataSelector(
|
|
1327
1305
|
colKeyValue
|
|
1328
|
-
)}
|
|
1306
|
+
)} > :first-child`;
|
|
1329
1307
|
return template.querySelector(selector);
|
|
1330
1308
|
}
|
|
1331
1309
|
|
|
1332
|
-
function
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1310
|
+
function getActiveCellRowElement(template, state) {
|
|
1311
|
+
let result;
|
|
1312
|
+
const { activeCell } = state;
|
|
1313
|
+
if (activeCell) {
|
|
1314
|
+
result = template.querySelector(
|
|
1315
|
+
getRowDataSelector(activeCell.rowKeyValue)
|
|
1316
|
+
);
|
|
1337
1317
|
}
|
|
1338
|
-
return null;
|
|
1318
|
+
return result || null;
|
|
1339
1319
|
}
|
|
1340
1320
|
|
|
1341
|
-
export function
|
|
1321
|
+
export function getRowParentIndex(state, rowLevel, rowIndex) {
|
|
1342
1322
|
const parentIndex = rowIndex - 1;
|
|
1343
|
-
const rows = state
|
|
1323
|
+
const { rows } = state;
|
|
1344
1324
|
for (let i = parentIndex; i >= 0; i--) {
|
|
1345
1325
|
if (rows[i].level === rowLevel - 1) {
|
|
1346
1326
|
return i;
|
|
@@ -1349,19 +1329,8 @@ export function getRowParent(state, rowLevel, rowIndex) {
|
|
|
1349
1329
|
return -1;
|
|
1350
1330
|
}
|
|
1351
1331
|
|
|
1352
|
-
function getCellFromIndexes(state, rowIndex, colIndex) {
|
|
1353
|
-
const { columns, rows } = state;
|
|
1354
|
-
if (columns.length > 0) {
|
|
1355
|
-
return {
|
|
1356
|
-
rowKeyValue: rowIndex === -1 ? HEADER_ROW : rows[rowIndex].key,
|
|
1357
|
-
colKeyValue: generateColKeyValue(columns[colIndex], colIndex),
|
|
1358
|
-
};
|
|
1359
|
-
}
|
|
1360
|
-
return undefined;
|
|
1361
|
-
}
|
|
1362
|
-
|
|
1363
1332
|
function updateScrollTop(state, template, element) {
|
|
1364
|
-
const scrollableY = template
|
|
1333
|
+
const scrollableY = getScrollerY(template);
|
|
1365
1334
|
const scrollingParent = scrollableY.parentElement;
|
|
1366
1335
|
const parentRect = scrollingParent.getBoundingClientRect();
|
|
1367
1336
|
const findMeRect = element.getBoundingClientRect();
|
|
@@ -1383,22 +1352,21 @@ function scrollToCell(state, template, rowIndex) {
|
|
|
1383
1352
|
scrollTop = Math.max(scrollTop - rowsInViewport * rowHeight, 0);
|
|
1384
1353
|
}
|
|
1385
1354
|
|
|
1386
|
-
const scrollableY = template
|
|
1355
|
+
const scrollableY = getScrollerY(template);
|
|
1387
1356
|
scrollableY.scrollTop = scrollTop;
|
|
1388
1357
|
findFirstVisibleIndex(state, scrollTop);
|
|
1389
1358
|
}
|
|
1390
1359
|
|
|
1391
1360
|
export function isActiveCellEditable(state) {
|
|
1392
|
-
|
|
1393
|
-
if (activeCell) {
|
|
1361
|
+
if (state.activeCell) {
|
|
1394
1362
|
const { rowIndex, colIndex } = getIndexesActiveCell(state);
|
|
1395
|
-
return isCellEditable(rows[rowIndex], columns[colIndex]);
|
|
1363
|
+
return isCellEditable(state.rows[rowIndex], state.columns[colIndex]);
|
|
1396
1364
|
}
|
|
1397
1365
|
return false;
|
|
1398
1366
|
}
|
|
1399
1367
|
|
|
1400
1368
|
export function isValidCell(state, rowKeyValue, colKeyValue) {
|
|
1401
|
-
if (rowKeyValue ===
|
|
1369
|
+
if (rowKeyValue === HEADER_ROW_KEY) {
|
|
1402
1370
|
return state.headerIndexes[colKeyValue] !== undefined;
|
|
1403
1371
|
}
|
|
1404
1372
|
const row = getRowByKey(state, rowKeyValue);
|
|
@@ -1408,16 +1376,28 @@ export function isValidCell(state, rowKeyValue, colKeyValue) {
|
|
|
1408
1376
|
}
|
|
1409
1377
|
|
|
1410
1378
|
function isActiveCellValid(state) {
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
return isValidCell(
|
|
1379
|
+
const { activeCell } = state;
|
|
1380
|
+
if (activeCell) {
|
|
1381
|
+
return isValidCell(
|
|
1382
|
+
state,
|
|
1383
|
+
activeCell.rowKeyValue,
|
|
1384
|
+
activeCell.colKeyValue
|
|
1385
|
+
);
|
|
1414
1386
|
}
|
|
1415
1387
|
return false;
|
|
1416
1388
|
}
|
|
1417
1389
|
|
|
1418
|
-
export function updateActiveCellTabIndexAfterSync(state,
|
|
1390
|
+
export function updateActiveCellTabIndexAfterSync(state, tabIndex = 0) {
|
|
1419
1391
|
if (state.activeCell && !isRowNavigationMode(state)) {
|
|
1420
1392
|
const { rowIndex, colIndex } = getIndexesActiveCell(state);
|
|
1421
|
-
|
|
1393
|
+
updateCellTabIndex(state, rowIndex, colIndex, tabIndex);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
export function updateActiveRowTabIndexAfterSync(state, tabIndex = 0) {
|
|
1398
|
+
const { activeCell } = state;
|
|
1399
|
+
if (activeCell && isRowNavigationMode(state)) {
|
|
1400
|
+
const { rowIndex } = getIndexesActiveCell(state);
|
|
1401
|
+
updateRowTabIndex(state, rowIndex, tabIndex);
|
|
1422
1402
|
}
|
|
1423
1403
|
}
|