@elliemae/ds-menu-button 3.46.0-rc.0 → 3.46.0-rc.10
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/cjs/config/useMenuButton.js +10 -19
- package/dist/cjs/config/useMenuButton.js.map +2 -2
- package/dist/cjs/config/useSplitInherithedProps.js +33 -15
- package/dist/cjs/config/useSplitInherithedProps.js.map +2 -2
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/parts/DSFlyoutMenu/DSFlyoutMenu.js +36 -12
- package/dist/cjs/parts/DSFlyoutMenu/DSFlyoutMenu.js.map +3 -3
- package/dist/cjs/parts/DSFlyoutMenu/react-desc-prop-types.js +1 -1
- package/dist/cjs/parts/DSFlyoutMenu/react-desc-prop-types.js.map +3 -3
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/config/useAdvancedValidation.js +86 -0
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/config/useAdvancedValidation.js.map +7 -0
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/config/useFocusTracker.js +40 -30
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/config/useFocusTracker.js.map +2 -2
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/config/useMenuBehaviouralContextProvider.js +2 -0
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/config/useMenuBehaviouralContextProvider.js.map +2 -2
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/config/useMenuItemEventsHandlers.js +77 -33
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/config/useMenuItemEventsHandlers.js.map +2 -2
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/react-desc-prop-types.js +3 -0
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/react-desc-prop-types.js.map +2 -2
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/utils/multipleSelectionHelpers.js +14 -14
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/utils/multipleSelectionHelpers.js.map +1 -1
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/utils/singleSelectionHelpers.js +2 -2
- package/dist/cjs/parts/DSMenuBehaviouralContextProvider/utils/singleSelectionHelpers.js.map +1 -1
- package/dist/cjs/parts/DSMenuItemRendererFactory/ActivableMenuItem.js +13 -9
- package/dist/cjs/parts/DSMenuItemRendererFactory/ActivableMenuItem.js.map +2 -2
- package/dist/cjs/parts/DSMenuItemRendererFactory/ActivableWithSubmenuMenuItem.js +13 -9
- package/dist/cjs/parts/DSMenuItemRendererFactory/ActivableWithSubmenuMenuItem.js.map +2 -2
- package/dist/cjs/parts/DSMenuItemRendererFactory/DSMenuItemRendererFactory.js +10 -9
- package/dist/cjs/parts/DSMenuItemRendererFactory/DSMenuItemRendererFactory.js.map +2 -2
- package/dist/cjs/parts/DSMenuItemRendererFactory/MultipleSelectMenuItem.js +15 -11
- package/dist/cjs/parts/DSMenuItemRendererFactory/MultipleSelectMenuItem.js.map +2 -2
- package/dist/cjs/parts/DSMenuItemRendererFactory/MultipleSelectWithSubmenuMenuItem.js +18 -12
- package/dist/cjs/parts/DSMenuItemRendererFactory/MultipleSelectWithSubmenuMenuItem.js.map +2 -2
- package/dist/cjs/parts/DSMenuItemRendererFactory/SingleSelectMenuItem.js +15 -11
- package/dist/cjs/parts/DSMenuItemRendererFactory/SingleSelectMenuItem.js.map +2 -2
- package/dist/cjs/parts/DSMenuItemRendererFactory/SingleSelectWithSubmenuMenuItem.js +15 -11
- package/dist/cjs/parts/DSMenuItemRendererFactory/SingleSelectWithSubmenuMenuItem.js.map +2 -2
- package/dist/cjs/parts/DSMenuItemRendererFactory/SkeletonMenuItem.js +112 -0
- package/dist/cjs/parts/DSMenuItemRendererFactory/SkeletonMenuItem.js.map +7 -0
- package/dist/cjs/parts/DSMenuItemRendererFactory/WithSubmenuMenuItem.js +13 -9
- package/dist/cjs/parts/DSMenuItemRendererFactory/WithSubmenuMenuItem.js.map +2 -2
- package/dist/cjs/parts/DSMenuItemRendererFactory/config/useMenuItemRendererFactory.js +1 -1
- package/dist/cjs/parts/DSMenuItemRendererFactory/config/useMenuItemRendererFactory.js.map +2 -2
- package/dist/cjs/parts/DSMenuItemRendererFactory/focusNodeRacingConditionSolved.js +43 -0
- package/dist/cjs/parts/DSMenuItemRendererFactory/focusNodeRacingConditionSolved.js.map +7 -0
- package/dist/cjs/parts/DSMenuItemRendererFactory/react-desc-prop-types.js.map +2 -2
- package/dist/cjs/parts/DSOpinionatedButton/react-desc-prop-types.js.map +2 -2
- package/dist/cjs/react-desc-prop-types.js +16 -15
- package/dist/cjs/react-desc-prop-types.js.map +2 -2
- package/dist/cjs/utils/nodesTypeguardsAndGetters.js +18 -56
- package/dist/cjs/utils/nodesTypeguardsAndGetters.js.map +2 -2
- package/dist/cjs/utils/useOptionsArrayToDsTree.js +10 -3
- package/dist/cjs/utils/useOptionsArrayToDsTree.js.map +2 -2
- package/dist/esm/config/useMenuButton.js +11 -20
- package/dist/esm/config/useMenuButton.js.map +2 -2
- package/dist/esm/config/useSplitInherithedProps.js +33 -15
- package/dist/esm/config/useSplitInherithedProps.js.map +2 -2
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/parts/DSFlyoutMenu/DSFlyoutMenu.js +34 -10
- package/dist/esm/parts/DSFlyoutMenu/DSFlyoutMenu.js.map +2 -2
- package/dist/esm/parts/DSFlyoutMenu/react-desc-prop-types.js +1 -4
- package/dist/esm/parts/DSFlyoutMenu/react-desc-prop-types.js.map +2 -2
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/config/useAdvancedValidation.js +56 -0
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/config/useAdvancedValidation.js.map +7 -0
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/config/useFocusTracker.js +40 -30
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/config/useFocusTracker.js.map +2 -2
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/config/useMenuBehaviouralContextProvider.js +2 -0
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/config/useMenuBehaviouralContextProvider.js.map +2 -2
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/config/useMenuItemEventsHandlers.js +77 -33
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/config/useMenuItemEventsHandlers.js.map +2 -2
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/react-desc-prop-types.js +3 -0
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/react-desc-prop-types.js.map +2 -2
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/utils/multipleSelectionHelpers.js +14 -14
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/utils/multipleSelectionHelpers.js.map +1 -1
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/utils/singleSelectionHelpers.js +2 -2
- package/dist/esm/parts/DSMenuBehaviouralContextProvider/utils/singleSelectionHelpers.js.map +1 -1
- package/dist/esm/parts/DSMenuItemRendererFactory/ActivableMenuItem.js +13 -9
- package/dist/esm/parts/DSMenuItemRendererFactory/ActivableMenuItem.js.map +2 -2
- package/dist/esm/parts/DSMenuItemRendererFactory/ActivableWithSubmenuMenuItem.js +13 -9
- package/dist/esm/parts/DSMenuItemRendererFactory/ActivableWithSubmenuMenuItem.js.map +2 -2
- package/dist/esm/parts/DSMenuItemRendererFactory/DSMenuItemRendererFactory.js +19 -18
- package/dist/esm/parts/DSMenuItemRendererFactory/DSMenuItemRendererFactory.js.map +2 -2
- package/dist/esm/parts/DSMenuItemRendererFactory/MultipleSelectMenuItem.js +15 -11
- package/dist/esm/parts/DSMenuItemRendererFactory/MultipleSelectMenuItem.js.map +2 -2
- package/dist/esm/parts/DSMenuItemRendererFactory/MultipleSelectWithSubmenuMenuItem.js +18 -12
- package/dist/esm/parts/DSMenuItemRendererFactory/MultipleSelectWithSubmenuMenuItem.js.map +2 -2
- package/dist/esm/parts/DSMenuItemRendererFactory/SingleSelectMenuItem.js +15 -11
- package/dist/esm/parts/DSMenuItemRendererFactory/SingleSelectMenuItem.js.map +2 -2
- package/dist/esm/parts/DSMenuItemRendererFactory/SingleSelectWithSubmenuMenuItem.js +15 -11
- package/dist/esm/parts/DSMenuItemRendererFactory/SingleSelectWithSubmenuMenuItem.js.map +2 -2
- package/dist/esm/parts/DSMenuItemRendererFactory/SkeletonMenuItem.js +82 -0
- package/dist/esm/parts/DSMenuItemRendererFactory/SkeletonMenuItem.js.map +7 -0
- package/dist/esm/parts/DSMenuItemRendererFactory/WithSubmenuMenuItem.js +13 -9
- package/dist/esm/parts/DSMenuItemRendererFactory/WithSubmenuMenuItem.js.map +2 -2
- package/dist/esm/parts/DSMenuItemRendererFactory/config/useMenuItemRendererFactory.js +1 -1
- package/dist/esm/parts/DSMenuItemRendererFactory/config/useMenuItemRendererFactory.js.map +2 -2
- package/dist/esm/parts/DSMenuItemRendererFactory/focusNodeRacingConditionSolved.js +13 -0
- package/dist/esm/parts/DSMenuItemRendererFactory/focusNodeRacingConditionSolved.js.map +7 -0
- package/dist/esm/parts/DSMenuItemRendererFactory/react-desc-prop-types.js.map +2 -2
- package/dist/esm/parts/DSOpinionatedButton/react-desc-prop-types.js +1 -1
- package/dist/esm/parts/DSOpinionatedButton/react-desc-prop-types.js.map +2 -2
- package/dist/esm/react-desc-prop-types.js +16 -15
- package/dist/esm/react-desc-prop-types.js.map +2 -2
- package/dist/esm/utils/nodesTypeguardsAndGetters.js +18 -56
- package/dist/esm/utils/nodesTypeguardsAndGetters.js.map +2 -2
- package/dist/esm/utils/useOptionsArrayToDsTree.js +10 -3
- package/dist/esm/utils/useOptionsArrayToDsTree.js.map +2 -2
- package/dist/types/config/useSplitInherithedProps.d.ts +8 -9
- package/dist/types/index.d.ts +1 -1
- package/dist/types/parts/DSFlyoutMenu/react-desc-prop-types.d.ts +1 -1
- package/dist/types/parts/DSMenuBehaviouralContextProvider/config/useAdvancedValidation.d.ts +6 -0
- package/dist/types/parts/DSMenuBehaviouralContextProvider/config/useFocusTracker.d.ts +6 -6
- package/dist/types/parts/DSMenuBehaviouralContextProvider/config/useMenuItemEventsHandlers.d.ts +2 -1
- package/dist/types/parts/DSMenuBehaviouralContextProvider/react-desc-prop-types.d.ts +1 -0
- package/dist/types/parts/DSMenuBehaviouralContextProvider/utils/multipleSelectionHelpers.d.ts +3 -3
- package/dist/types/parts/DSMenuBehaviouralContextProvider/utils/singleSelectionHelpers.d.ts +2 -2
- package/dist/types/parts/DSMenuItemRendererFactory/SkeletonMenuItem.d.ts +5 -0
- package/dist/types/parts/DSMenuItemRendererFactory/focusNodeRacingConditionSolved.d.ts +2 -0
- package/dist/types/parts/DSMenuItemRendererFactory/react-desc-prop-types.d.ts +2 -2
- package/dist/types/parts/DSOpinionatedButton/config/useOpinionatedButton.d.ts +1 -1
- package/dist/types/parts/DSOpinionatedButton/react-desc-prop-types.d.ts +1 -1
- package/dist/types/react-desc-prop-types.d.ts +23 -17
- package/dist/types/utils/nodesTypeguardsAndGetters.d.ts +113 -1
- package/dist/types/utils/useOptionsArrayToDsTree.d.ts +2 -1
- package/package.json +12 -13
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"version": 3,
|
3
3
|
"sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/DSMenuBehaviouralContextProvider/react-desc-prop-types.ts"],
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-empty-interface */\nimport type { DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport { PropTypes } from '@elliemae/ds-props-helpers';\nimport { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { type DSMenuButtonT, MenuBehaviouralLayerPropTypes } from '../../react-desc-prop-types.js';\n\nexport declare namespace DSMenuBehaviouralContextProviderT {\n /*\n * everything that is specifically added in this namespace declaration and is not part of the original component\n * is because the original component is an \"opinionated widget\" that offloads a chunk of responsibilities from dev to dimsum\n * as such, the widget generates those interfaces,\n * but the app developer is not supposed to know about them\n * untill they go atomic composition (this namespace)\n */\n export interface RequiredProps extends DSMenuButtonT.MenuBehaviouralLayerRequiredProps {\n buttonDOMNodeRef: React.MutableRefObject<HTMLElement | null>;\n optionsTree: DSMenuButtonT.MenuNode;\n children: TypescriptHelpersT.ReactChildrenComplete;\n focusableNodes: DSMenuButtonT.PseudoFocusableMenuNodes[];\n }\n\n export interface DefaultProps extends DSMenuButtonT.MenuBehaviouralLayerDefaultProps {}\n\n export interface OptionalProps extends DSMenuButtonT.MenuBehaviouralLayerOptionalProps {}\n export interface Props extends Partial<DefaultProps>, OptionalProps, RequiredProps {}\n\n export interface InternalProps extends DefaultProps, OptionalProps, RequiredProps {}\n}\n\nexport const defaultProps: DSMenuBehaviouralContextProviderT.DefaultProps = {};\n\nexport const DSMenuBehaviouralContextProviderPropTypes: DSPropTypesSchema<DSMenuBehaviouralContextProviderT.Props> = {\n buttonDOMNodeRef: PropTypes.object.description(\n 'The DOM node of the button as a mutable Refs (required for performance reasons)',\n ).isRequired,\n children: PropTypes.node.description('the menu trigger and the menu components').isRequired,\n optionsTree: PropTypes.object.description('DSTree node to build branches from').isRequired,\n focusableNodes: PropTypes.arrayOf(PropTypes.object).description(\n 'an array of nodes that can receive pseudoFocus, obtainable via ds-tree flatten + filter(isFocusable)',\n ).isRequired,\n ...MenuBehaviouralLayerPropTypes,\n};\n\nexport const DSMenuBehaviouralContextProviderPropTypesSchema =\n DSMenuBehaviouralContextProviderPropTypes as unknown as ValidationMap<DSMenuBehaviouralContextProviderT.Props>;\n"],
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;ACEvB,SAAS,iBAAiB;AAE1B,SAA6B,qCAAqC;
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-empty-interface */\nimport type { DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport { PropTypes } from '@elliemae/ds-props-helpers';\nimport { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { type DSMenuButtonT, MenuBehaviouralLayerPropTypes } from '../../react-desc-prop-types.js';\n\nexport declare namespace DSMenuBehaviouralContextProviderT {\n /*\n * everything that is specifically added in this namespace declaration and is not part of the original component\n * is because the original component is an \"opinionated widget\" that offloads a chunk of responsibilities from dev to dimsum\n * as such, the widget generates those interfaces,\n * but the app developer is not supposed to know about them\n * untill they go atomic composition (this namespace)\n */\n export interface RequiredProps extends DSMenuButtonT.MenuBehaviouralLayerRequiredProps {\n buttonDOMNodeRef: React.MutableRefObject<HTMLElement | null>;\n optionsTree: DSMenuButtonT.MenuNode;\n children: TypescriptHelpersT.ReactChildrenComplete;\n focusableNodes: DSMenuButtonT.PseudoFocusableMenuNodes[];\n }\n\n export interface DefaultProps extends DSMenuButtonT.MenuBehaviouralLayerDefaultProps {}\n\n export interface OptionalProps extends DSMenuButtonT.MenuBehaviouralLayerOptionalProps {\n selectedNodes?: DSMenuButtonT.SelectionableMenuNodes[];\n }\n export interface Props extends Partial<DefaultProps>, OptionalProps, RequiredProps {}\n\n export interface InternalProps extends DefaultProps, OptionalProps, RequiredProps {}\n}\n\nexport const defaultProps: DSMenuBehaviouralContextProviderT.DefaultProps = {};\n\nexport const DSMenuBehaviouralContextProviderPropTypes: DSPropTypesSchema<DSMenuBehaviouralContextProviderT.Props> = {\n buttonDOMNodeRef: PropTypes.object.description(\n 'The DOM node of the button as a mutable Refs (required for performance reasons)',\n ).isRequired,\n children: PropTypes.node.description('the menu trigger and the menu components').isRequired,\n optionsTree: PropTypes.object.description('DSTree node to build branches from').isRequired,\n focusableNodes: PropTypes.arrayOf(PropTypes.object).description(\n 'an array of nodes that can receive pseudoFocus, obtainable via ds-tree flatten + filter(isFocusable)',\n ).isRequired,\n selectedNodes: PropTypes.arrayOf(PropTypes.object).description(\n 'an array of tree-nodes that have to be marked as selected in the GUI, required if the menu has selectionable items',\n ),\n ...MenuBehaviouralLayerPropTypes,\n};\n\nexport const DSMenuBehaviouralContextProviderPropTypesSchema =\n DSMenuBehaviouralContextProviderPropTypes as unknown as ValidationMap<DSMenuBehaviouralContextProviderT.Props>;\n"],
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;ACEvB,SAAS,iBAAiB;AAE1B,SAA6B,qCAAqC;AA2B3D,MAAM,eAA+D,CAAC;AAEtE,MAAM,4CAAwG;AAAA,EACnH,kBAAkB,UAAU,OAAO;AAAA,IACjC;AAAA,EACF,EAAE;AAAA,EACF,UAAU,UAAU,KAAK,YAAY,0CAA0C,EAAE;AAAA,EACjF,aAAa,UAAU,OAAO,YAAY,oCAAoC,EAAE;AAAA,EAChF,gBAAgB,UAAU,QAAQ,UAAU,MAAM,EAAE;AAAA,IAClD;AAAA,EACF,EAAE;AAAA,EACF,eAAe,UAAU,QAAQ,UAAU,MAAM,EAAE;AAAA,IACjD;AAAA,EACF;AAAA,EACA,GAAG;AACL;AAEO,MAAM,kDACX;",
|
6
6
|
"names": []
|
7
7
|
}
|
@@ -8,13 +8,13 @@ import { UNEXPECTED_INTERNAL_ERRORS } from "../constants/Errors.js";
|
|
8
8
|
import { getChildrenByCriterias } from "./nodeGettersByCriterias.js";
|
9
9
|
const getIsMultipleSelectNodeWithSubmenuSelected = ({
|
10
10
|
itemNode,
|
11
|
-
|
11
|
+
selectedNodes
|
12
12
|
}) => {
|
13
|
-
if (
|
13
|
+
if (selectedNodes.length === 0) return false;
|
14
14
|
const { multiSelectionableChilrens } = getChildrenByCriterias(itemNode);
|
15
15
|
const selectedMultiChildren = [];
|
16
16
|
let isSelectedItself = false;
|
17
|
-
|
17
|
+
selectedNodes.forEach((itemMarkesAsSelected) => {
|
18
18
|
if (itemMarkesAsSelected.dsId === itemNode.dsId) isSelectedItself = true;
|
19
19
|
if (isMultipleSelectNode(itemMarkesAsSelected)) {
|
20
20
|
if (multiSelectionableChilrens.some((child) => child.dsId === itemMarkesAsSelected.dsId))
|
@@ -27,9 +27,9 @@ const getIsMultipleSelectNodeWithSubmenuSelected = ({
|
|
27
27
|
if (selectedMultiChildren.length !== multiSelectionableChilrens.length) return "mixed";
|
28
28
|
return true;
|
29
29
|
};
|
30
|
-
const getNewSelectionForMultipleSelectOnlyNode = (
|
31
|
-
const isDeselectingItem =
|
32
|
-
let newSelection = isDeselectingItem ?
|
30
|
+
const getNewSelectionForMultipleSelectOnlyNode = (selectedNodes, selectedItem) => {
|
31
|
+
const isDeselectingItem = selectedNodes.find((item) => item.dsId === selectedItem.dsId) ?? false;
|
32
|
+
let newSelection = isDeselectingItem ? selectedNodes.filter(({ dsId }) => dsId !== selectedItem.dsId) : [...selectedNodes, selectedItem];
|
33
33
|
const notSelectedMultiParents = [];
|
34
34
|
const selectedMultiParents = [];
|
35
35
|
const multiParentsToDeselect = [];
|
@@ -42,7 +42,7 @@ const getNewSelectionForMultipleSelectOnlyNode = (selectedItems, selectedItem) =
|
|
42
42
|
selectedMultiParents.push(typedParent);
|
43
43
|
const isParentSelected = getIsMultipleSelectNodeWithSubmenuSelected({
|
44
44
|
itemNode: typedParent,
|
45
|
-
|
45
|
+
selectedNodes: newSelection
|
46
46
|
});
|
47
47
|
if (isParentSelected === false) multiParentsToDeselect.push(typedParent);
|
48
48
|
} else notSelectedMultiParents.push(typedParent);
|
@@ -56,13 +56,13 @@ const getNewSelectionForMultipleSelectOnlyNode = (selectedItems, selectedItem) =
|
|
56
56
|
}
|
57
57
|
return newSelection;
|
58
58
|
};
|
59
|
-
const getNewSelectionForMultipleSelectionWithSubmenuNode = (
|
59
|
+
const getNewSelectionForMultipleSelectionWithSubmenuNode = (selectedNodes, selectedItem) => {
|
60
60
|
const currentStatus = getIsMultipleSelectNodeWithSubmenuSelected({
|
61
61
|
itemNode: selectedItem,
|
62
|
-
|
62
|
+
selectedNodes
|
63
63
|
});
|
64
64
|
const isDeselectingItem = currentStatus === true;
|
65
|
-
let newSelection = isDeselectingItem ?
|
65
|
+
let newSelection = isDeselectingItem ? selectedNodes.filter(({ dsId }) => dsId !== selectedItem.dsId) : [...selectedNodes, selectedItem];
|
66
66
|
selectedItem.walk((child) => {
|
67
67
|
const typedChild = child;
|
68
68
|
if (isDeselectingItem) {
|
@@ -84,7 +84,7 @@ const getNewSelectionForMultipleSelectionWithSubmenuNode = (selectedItems, selec
|
|
84
84
|
selectedMultiParents.push(typedParent);
|
85
85
|
const isParentSelected = getIsMultipleSelectNodeWithSubmenuSelected({
|
86
86
|
itemNode: typedParent,
|
87
|
-
|
87
|
+
selectedNodes: newSelection
|
88
88
|
});
|
89
89
|
if (isParentSelected === false) multiParentsToDeselect.push(typedParent);
|
90
90
|
} else notSelectedMultiParents.push(typedParent);
|
@@ -98,11 +98,11 @@ const getNewSelectionForMultipleSelectionWithSubmenuNode = (selectedItems, selec
|
|
98
98
|
}
|
99
99
|
return newSelection;
|
100
100
|
};
|
101
|
-
const getNewSelectionMultipleSelect = (
|
101
|
+
const getNewSelectionMultipleSelect = (selectedNodes, selectedItem) => {
|
102
102
|
if (isMultipleSelectOnlyNode(selectedItem))
|
103
|
-
return getNewSelectionForMultipleSelectOnlyNode(
|
103
|
+
return getNewSelectionForMultipleSelectOnlyNode(selectedNodes, selectedItem);
|
104
104
|
if (isMultipleSelectWithSubmenuNode(selectedItem))
|
105
|
-
return getNewSelectionForMultipleSelectionWithSubmenuNode(
|
105
|
+
return getNewSelectionForMultipleSelectionWithSubmenuNode(selectedNodes, selectedItem);
|
106
106
|
console.log(selectedItem);
|
107
107
|
throw UNEXPECTED_INTERNAL_ERRORS.CALCULATING_MULTI_SELECTION_OF_NON_MULTI_SELECTION_NODE;
|
108
108
|
};
|
package/dist/esm/parts/DSMenuBehaviouralContextProvider/utils/multipleSelectionHelpers.js.map
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"version": 3,
|
3
3
|
"sources": ["../../../../../../../../scripts/build/transpile/react-shim.js", "../../../../../src/parts/DSMenuBehaviouralContextProvider/utils/multipleSelectionHelpers.ts"],
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable no-console */\n/* eslint-disable max-statements */\nimport { type DSMenuButtonT } from '../../../react-desc-prop-types.js';\nimport {\n isMultipleSelectNode,\n isMultipleSelectOnlyNode,\n isMultipleSelectWithSubmenuNode,\n} from '../../../utils/nodesTypeguardsAndGetters.js';\nimport { UNEXPECTED_INTERNAL_ERRORS } from '../constants/Errors.js';\nimport { getChildrenByCriterias } from './nodeGettersByCriterias.js';\n\nexport const getIsMultipleSelectNodeWithSubmenuSelected = ({\n itemNode,\n selectedItems,\n}: {\n itemNode: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem;\n selectedItems: DSMenuButtonT.SelectionableMenuNodes[];\n}) => {\n // no selected items, nothing is selected <- this is not selected neither, nothing else to check\n if (selectedItems.length === 0) return false;\n\n const { multiSelectionableChilrens } = getChildrenByCriterias(itemNode);\n const selectedMultiChildren: DSMenuButtonT.MultipleSelectionableMenuNodes[] = [];\n let isSelectedItself = false;\n selectedItems.forEach((itemMarkesAsSelected) => {\n if (itemMarkesAsSelected.dsId === itemNode.dsId) isSelectedItself = true;\n if (isMultipleSelectNode(itemMarkesAsSelected)) {\n // we reduce scenarios of O(n*m), if the node is not a multi-selectable node, we don't iterate the multiSelectionable childrens\n if (multiSelectionableChilrens.some((child) => child.dsId === itemMarkesAsSelected.dsId))\n selectedMultiChildren.push(itemMarkesAsSelected);\n }\n });\n // console.group(`${itemNode.dsId} > getting \"selected\" (true/false/mixed) status`);\n // console.log({\n // itemNode: itemNode.dsId,\n // selectedItems: selectedItems.map((itm) => itm.dsId),\n // multiSelectionableChilrens: multiSelectionableChilrens.map((itm) => itm.dsId),\n // selectedMultiChildren: selectedMultiChildren.map((itm) => itm.dsId),\n // isSelectedItself,\n // });\n // console.groupEnd();\n // if it's not marked as selected, it's not selected.\n if (!isSelectedItself) return false;\n // if the node doesn't even have multi children, to calculate 'mixed' status upon (it may still have radios)\n // (and is selected itself), it's selected\n if (multiSelectionableChilrens.length === 0) return true;\n\n // multi children exist and the node is selected\n // it can be\n // true if all the multi children are selected\n // mixed if not all the multi children are selected\n // false if all the multi children are not selected\n\n // multi children exist but none are selected at all?\n if (selectedMultiChildren.length === 0) return false;\n // any multi children is not selected?\n if (selectedMultiChildren.length !== multiSelectionableChilrens.length) return 'mixed';\n // there is a multi selection, and everything is selected\n return true;\n};\n\nconst getNewSelectionForMultipleSelectOnlyNode = (\n selectedItems: DSMenuButtonT.SelectionableMenuNodes[],\n selectedItem: DSMenuButtonT.MenuNodeMultipleSelectItem,\n) => {\n const isDeselectingItem = selectedItems.find((item) => item.dsId === selectedItem.dsId) ?? false;\n\n let newSelection = isDeselectingItem\n ? selectedItems.filter(({ dsId }) => dsId !== selectedItem.dsId)\n : [...selectedItems, selectedItem];\n const notSelectedMultiParents: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n const selectedMultiParents: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n const multiParentsToDeselect: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n\n // we walk the parents and track info about them\n selectedItem.walkParents((parent) => {\n // discard ourself, only interested in the parents\n if (parent.dsId === selectedItem.dsId) return true;\n // DSTree typescripst doesn't understand ethereogenic nodes, so we need to typecast\n const typedParent = parent as unknown as DSMenuButtonT.MenuNode;\n if (isMultipleSelectWithSubmenuNode(typedParent)) {\n // before we add the parent, we need to check if it's already in the selection\n const isAlreadySelected = newSelection.find((item) => item.dsId === typedParent.dsId);\n if (isAlreadySelected) {\n selectedMultiParents.push(typedParent);\n // we check if the parent is mixed or should be false (so we can deselect it)\n const isParentSelected = getIsMultipleSelectNodeWithSubmenuSelected({\n itemNode: typedParent,\n selectedItems: newSelection,\n });\n if (isParentSelected === false) multiParentsToDeselect.push(typedParent);\n } else notSelectedMultiParents.push(typedParent);\n }\n return true;\n });\n\n if (isDeselectingItem) {\n // if we are deselecting:\n // we need to remove the parent nodes that are not selected anymore\n // (they transition from mixed to not selected because of this item deselection)\n newSelection = newSelection.filter(({ dsId }) => !multiParentsToDeselect.some((parent) => parent.dsId === dsId));\n } else {\n // if we are selecting:\n // we need to add the parent nodes that are not selected yet\n // (they transition from not selected to mixed because of this item selection)\n newSelection.push(...notSelectedMultiParents);\n }\n\n return newSelection;\n};\n\nconst getNewSelectionForMultipleSelectionWithSubmenuNode = (\n selectedItems: DSMenuButtonT.SelectionableMenuNodes[],\n selectedItem: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem,\n) => {\n // when selecting/deselecting a node with a submenu, we need to consider the hierarchy of the selection starting from here\n // both upwards and downwards\n // - upwards\n // we have to check if any multi-selectable-with-submenu parent transition from not selected to mixed || mixed to selected\n // - downwards\n // - Deselect\n // we have to deselect all the selectable children (regarless of the depth of the children and kind of selection)\n // - Select\n // we have to select all the multi-selectable children that are not selected yet (both with and without submenu)\n\n // console.group(`${selectedItem.dsId} > getting new selection`);\n const currentStatus = getIsMultipleSelectNodeWithSubmenuSelected({\n itemNode: selectedItem,\n selectedItems,\n });\n const isDeselectingItem = currentStatus === true;\n\n let newSelection = isDeselectingItem\n ? selectedItems.filter(({ dsId }) => dsId !== selectedItem.dsId)\n : [...selectedItems, selectedItem];\n\n // console.log(\n // 'starting newSelection',\n // newSelection.map(({ dsId }) => dsId),\n // );\n\n // we walk the children first and update the new selection accordingly\n // (it's important we first traverse the children, so we can update the selection of the parents accordingly to the new selection)\n selectedItem.walk((child) => {\n // DSTree typescripst doesn't understand ethereogenic nodes, so we need to typecast\n const typedChild = child as unknown as DSMenuButtonT.SelectionableMenuNodes;\n if (isDeselectingItem) {\n // if we are deselecting, we need to remove the children from the selection\n newSelection = newSelection.filter(({ dsId }) => dsId !== typedChild.dsId);\n } else if (isMultipleSelectNode(typedChild) && !newSelection.find((item) => item.dsId === typedChild.dsId)) {\n // if we are selecting, we need to add all the multi children to the selection (if they are not already there)\n // (we don't do anything with single-selectable nodes, they are not affected by this operation by definition)\n newSelection.push(typedChild);\n }\n return true;\n });\n\n // console.log(\n // 'newSelection after applying logic to children, pre parents traversal',\n // newSelection.map(({ dsId }) => dsId),\n // );\n\n // now newSelection has the correct information about the node itself and its children\n // we need to update the parents accordingly\n\n const notSelectedMultiParents: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n const selectedMultiParents: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n const multiParentsToDeselect: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n // we walk the parents and track info about them\n selectedItem.walkParents((parent) => {\n // discard ourself, only interested in the parents\n if (parent.dsId === selectedItem.dsId) return true;\n // DSTree typescripst doesn't understand ethereogenic nodes, so we need to typecast\n const typedParent = parent as unknown as DSMenuButtonT.MenuNode;\n if (isMultipleSelectWithSubmenuNode(typedParent)) {\n // before we add the parent, we need to check if it's already in the selection\n const isAlreadySelected = newSelection.find((item) => item.dsId === typedParent.dsId);\n if (isAlreadySelected) {\n selectedMultiParents.push(typedParent);\n // we check if the parent is mixed or should be false (so we can deselect it)\n const isParentSelected = getIsMultipleSelectNodeWithSubmenuSelected({\n itemNode: typedParent,\n selectedItems: newSelection,\n });\n if (isParentSelected === false) multiParentsToDeselect.push(typedParent);\n } else notSelectedMultiParents.push(typedParent);\n }\n return true;\n });\n\n // console.log(\n // 'parents info > notSelectedMultiParents',\n // notSelectedMultiParents.map(({ dsId }) => dsId),\n // );\n // console.log(\n // 'parents info > selectedMultiParents',\n // selectedMultiParents.map(({ dsId }) => dsId),\n // );\n // console.log(\n // 'parents info > multiParentsToDeselect',\n // multiParentsToDeselect.map(({ dsId }) => dsId),\n // );\n\n // finally we use the info we gathered to update the selection\n if (isDeselectingItem) {\n // if we are deselecting:\n // we need to remove the parent nodes that are not selected anymore\n // (they transition from mixed to not selected because of this item deselection)\n newSelection = newSelection.filter(({ dsId }) => !multiParentsToDeselect.some((parent) => parent.dsId === dsId));\n } else {\n // if we are selecting:\n // we need to add the parent nodes that are not selected yet\n // (they transition from not selected to mixed because of this item selection)\n newSelection.push(...notSelectedMultiParents);\n }\n\n // console.log(\n // 'final newSelection',\n // newSelection.map(({ dsId }) => dsId),\n // );\n\n // console.groupEnd();\n return newSelection;\n};\n\nexport const getNewSelectionMultipleSelect = (\n selectedItems: DSMenuButtonT.SelectionableMenuNodes[],\n selectedItem: DSMenuButtonT.MultipleSelectionableMenuNodes,\n) => {\n // depending on if we are selecting/deselecting an item with/without submenu, we need to handle the selection differently\n if (isMultipleSelectOnlyNode(selectedItem))\n return getNewSelectionForMultipleSelectOnlyNode(selectedItems, selectedItem);\n\n if (isMultipleSelectWithSubmenuNode(selectedItem))\n return getNewSelectionForMultipleSelectionWithSubmenuNode(selectedItems, selectedItem);\n\n // if we reach this point, we are in an invalid state, we should never reach here\n console.log(selectedItem);\n throw UNEXPECTED_INTERNAL_ERRORS.CALCULATING_MULTI_SELECTION_OF_NON_MULTI_SELECTION_NODE;\n};\n"],
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable no-console */\n/* eslint-disable max-statements */\nimport { type DSMenuButtonT } from '../../../react-desc-prop-types.js';\nimport {\n isMultipleSelectNode,\n isMultipleSelectOnlyNode,\n isMultipleSelectWithSubmenuNode,\n} from '../../../utils/nodesTypeguardsAndGetters.js';\nimport { UNEXPECTED_INTERNAL_ERRORS } from '../constants/Errors.js';\nimport { getChildrenByCriterias } from './nodeGettersByCriterias.js';\n\nexport const getIsMultipleSelectNodeWithSubmenuSelected = ({\n itemNode,\n selectedNodes,\n}: {\n itemNode: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem;\n selectedNodes: DSMenuButtonT.SelectionableMenuNodes[];\n}) => {\n // no selected items, nothing is selected <- this is not selected neither, nothing else to check\n if (selectedNodes.length === 0) return false;\n\n const { multiSelectionableChilrens } = getChildrenByCriterias(itemNode);\n const selectedMultiChildren: DSMenuButtonT.MultipleSelectionableMenuNodes[] = [];\n let isSelectedItself = false;\n selectedNodes.forEach((itemMarkesAsSelected) => {\n if (itemMarkesAsSelected.dsId === itemNode.dsId) isSelectedItself = true;\n if (isMultipleSelectNode(itemMarkesAsSelected)) {\n // we reduce scenarios of O(n*m), if the node is not a multi-selectable node, we don't iterate the multiSelectionable childrens\n if (multiSelectionableChilrens.some((child) => child.dsId === itemMarkesAsSelected.dsId))\n selectedMultiChildren.push(itemMarkesAsSelected);\n }\n });\n // console.group(`${itemNode.dsId} > getting \"selected\" (true/false/mixed) status`);\n // console.log({\n // itemNode: itemNode.dsId,\n // selectedNodes: selectedNodes.map((itm) => itm.dsId),\n // multiSelectionableChilrens: multiSelectionableChilrens.map((itm) => itm.dsId),\n // selectedMultiChildren: selectedMultiChildren.map((itm) => itm.dsId),\n // isSelectedItself,\n // });\n // console.groupEnd();\n // if it's not marked as selected, it's not selected.\n if (!isSelectedItself) return false;\n // if the node doesn't even have multi children, to calculate 'mixed' status upon (it may still have radios)\n // (and is selected itself), it's selected\n if (multiSelectionableChilrens.length === 0) return true;\n\n // multi children exist and the node is selected\n // it can be\n // true if all the multi children are selected\n // mixed if not all the multi children are selected\n // false if all the multi children are not selected\n\n // multi children exist but none are selected at all?\n if (selectedMultiChildren.length === 0) return false;\n // any multi children is not selected?\n if (selectedMultiChildren.length !== multiSelectionableChilrens.length) return 'mixed';\n // there is a multi selection, and everything is selected\n return true;\n};\n\nconst getNewSelectionForMultipleSelectOnlyNode = (\n selectedNodes: DSMenuButtonT.SelectionableMenuNodes[],\n selectedItem: DSMenuButtonT.MenuNodeMultipleSelectItem,\n) => {\n const isDeselectingItem = selectedNodes.find((item) => item.dsId === selectedItem.dsId) ?? false;\n\n let newSelection = isDeselectingItem\n ? selectedNodes.filter(({ dsId }) => dsId !== selectedItem.dsId)\n : [...selectedNodes, selectedItem];\n const notSelectedMultiParents: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n const selectedMultiParents: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n const multiParentsToDeselect: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n\n // we walk the parents and track info about them\n selectedItem.walkParents((parent) => {\n // discard ourself, only interested in the parents\n if (parent.dsId === selectedItem.dsId) return true;\n // DSTree typescripst doesn't understand ethereogenic nodes, so we need to typecast\n const typedParent = parent as unknown as DSMenuButtonT.MenuNode;\n if (isMultipleSelectWithSubmenuNode(typedParent)) {\n // before we add the parent, we need to check if it's already in the selection\n const isAlreadySelected = newSelection.find((item) => item.dsId === typedParent.dsId);\n if (isAlreadySelected) {\n selectedMultiParents.push(typedParent);\n // we check if the parent is mixed or should be false (so we can deselect it)\n const isParentSelected = getIsMultipleSelectNodeWithSubmenuSelected({\n itemNode: typedParent,\n selectedNodes: newSelection,\n });\n if (isParentSelected === false) multiParentsToDeselect.push(typedParent);\n } else notSelectedMultiParents.push(typedParent);\n }\n return true;\n });\n\n if (isDeselectingItem) {\n // if we are deselecting:\n // we need to remove the parent nodes that are not selected anymore\n // (they transition from mixed to not selected because of this item deselection)\n newSelection = newSelection.filter(({ dsId }) => !multiParentsToDeselect.some((parent) => parent.dsId === dsId));\n } else {\n // if we are selecting:\n // we need to add the parent nodes that are not selected yet\n // (they transition from not selected to mixed because of this item selection)\n newSelection.push(...notSelectedMultiParents);\n }\n\n return newSelection;\n};\n\nconst getNewSelectionForMultipleSelectionWithSubmenuNode = (\n selectedNodes: DSMenuButtonT.SelectionableMenuNodes[],\n selectedItem: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem,\n) => {\n // when selecting/deselecting a node with a submenu, we need to consider the hierarchy of the selection starting from here\n // both upwards and downwards\n // - upwards\n // we have to check if any multi-selectable-with-submenu parent transition from not selected to mixed || mixed to selected\n // - downwards\n // - Deselect\n // we have to deselect all the selectable children (regarless of the depth of the children and kind of selection)\n // - Select\n // we have to select all the multi-selectable children that are not selected yet (both with and without submenu)\n\n // console.group(`${selectedItem.dsId} > getting new selection`);\n const currentStatus = getIsMultipleSelectNodeWithSubmenuSelected({\n itemNode: selectedItem,\n selectedNodes,\n });\n const isDeselectingItem = currentStatus === true;\n\n let newSelection = isDeselectingItem\n ? selectedNodes.filter(({ dsId }) => dsId !== selectedItem.dsId)\n : [...selectedNodes, selectedItem];\n\n // console.log(\n // 'starting newSelection',\n // newSelection.map(({ dsId }) => dsId),\n // );\n\n // we walk the children first and update the new selection accordingly\n // (it's important we first traverse the children, so we can update the selection of the parents accordingly to the new selection)\n selectedItem.walk((child) => {\n // DSTree typescripst doesn't understand ethereogenic nodes, so we need to typecast\n const typedChild = child as unknown as DSMenuButtonT.SelectionableMenuNodes;\n if (isDeselectingItem) {\n // if we are deselecting, we need to remove the children from the selection\n newSelection = newSelection.filter(({ dsId }) => dsId !== typedChild.dsId);\n } else if (isMultipleSelectNode(typedChild) && !newSelection.find((item) => item.dsId === typedChild.dsId)) {\n // if we are selecting, we need to add all the multi children to the selection (if they are not already there)\n // (we don't do anything with single-selectable nodes, they are not affected by this operation by definition)\n newSelection.push(typedChild);\n }\n return true;\n });\n\n // console.log(\n // 'newSelection after applying logic to children, pre parents traversal',\n // newSelection.map(({ dsId }) => dsId),\n // );\n\n // now newSelection has the correct information about the node itself and its children\n // we need to update the parents accordingly\n\n const notSelectedMultiParents: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n const selectedMultiParents: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n const multiParentsToDeselect: DSMenuButtonT.MenuNodeMultipleSelectWithSubmenuItem[] = [];\n // we walk the parents and track info about them\n selectedItem.walkParents((parent) => {\n // discard ourself, only interested in the parents\n if (parent.dsId === selectedItem.dsId) return true;\n // DSTree typescripst doesn't understand ethereogenic nodes, so we need to typecast\n const typedParent = parent as unknown as DSMenuButtonT.MenuNode;\n if (isMultipleSelectWithSubmenuNode(typedParent)) {\n // before we add the parent, we need to check if it's already in the selection\n const isAlreadySelected = newSelection.find((item) => item.dsId === typedParent.dsId);\n if (isAlreadySelected) {\n selectedMultiParents.push(typedParent);\n // we check if the parent is mixed or should be false (so we can deselect it)\n const isParentSelected = getIsMultipleSelectNodeWithSubmenuSelected({\n itemNode: typedParent,\n selectedNodes: newSelection,\n });\n if (isParentSelected === false) multiParentsToDeselect.push(typedParent);\n } else notSelectedMultiParents.push(typedParent);\n }\n return true;\n });\n\n // console.log(\n // 'parents info > notSelectedMultiParents',\n // notSelectedMultiParents.map(({ dsId }) => dsId),\n // );\n // console.log(\n // 'parents info > selectedMultiParents',\n // selectedMultiParents.map(({ dsId }) => dsId),\n // );\n // console.log(\n // 'parents info > multiParentsToDeselect',\n // multiParentsToDeselect.map(({ dsId }) => dsId),\n // );\n\n // finally we use the info we gathered to update the selection\n if (isDeselectingItem) {\n // if we are deselecting:\n // we need to remove the parent nodes that are not selected anymore\n // (they transition from mixed to not selected because of this item deselection)\n newSelection = newSelection.filter(({ dsId }) => !multiParentsToDeselect.some((parent) => parent.dsId === dsId));\n } else {\n // if we are selecting:\n // we need to add the parent nodes that are not selected yet\n // (they transition from not selected to mixed because of this item selection)\n newSelection.push(...notSelectedMultiParents);\n }\n\n // console.log(\n // 'final newSelection',\n // newSelection.map(({ dsId }) => dsId),\n // );\n\n // console.groupEnd();\n return newSelection;\n};\n\nexport const getNewSelectionMultipleSelect = (\n selectedNodes: DSMenuButtonT.SelectionableMenuNodes[],\n selectedItem: DSMenuButtonT.MultipleSelectionableMenuNodes,\n) => {\n // depending on if we are selecting/deselecting an item with/without submenu, we need to handle the selection differently\n if (isMultipleSelectOnlyNode(selectedItem))\n return getNewSelectionForMultipleSelectOnlyNode(selectedNodes, selectedItem);\n\n if (isMultipleSelectWithSubmenuNode(selectedItem))\n return getNewSelectionForMultipleSelectionWithSubmenuNode(selectedNodes, selectedItem);\n\n // if we reach this point, we are in an invalid state, we should never reach here\n console.log(selectedItem);\n throw UNEXPECTED_INTERNAL_ERRORS.CALCULATING_MULTI_SELECTION_OF_NON_MULTI_SELECTION_NODE;\n};\n"],
|
5
5
|
"mappings": "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",
|
6
6
|
"names": []
|
7
7
|
}
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import * as React from "react";
|
2
2
|
import { getAllSingleSelectIdsFromParent, getParentsByCriterias } from "./nodeGettersByCriterias.js";
|
3
|
-
const getNewSelectionSingleSelect = (
|
3
|
+
const getNewSelectionSingleSelect = (selectedNodes, selectedItem) => {
|
4
4
|
const { oldestGroup, selectionableParentsWithSubmenu } = getParentsByCriterias(selectedItem);
|
5
5
|
const itemsIdsToDeselect = getAllSingleSelectIdsFromParent(oldestGroup);
|
6
|
-
const newSelection =
|
6
|
+
const newSelection = selectedNodes.filter((item) => !itemsIdsToDeselect.includes(item.plainItem.dsId));
|
7
7
|
newSelection.push(...selectionableParentsWithSubmenu);
|
8
8
|
newSelection.push(selectedItem);
|
9
9
|
return newSelection;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"version": 3,
|
3
3
|
"sources": ["../../../../../../../../scripts/build/transpile/react-shim.js", "../../../../../src/parts/DSMenuBehaviouralContextProvider/utils/singleSelectionHelpers.ts"],
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { type DSMenuButtonT } from '../../../react-desc-prop-types.js';\nimport { getAllSingleSelectIdsFromParent, getParentsByCriterias } from './nodeGettersByCriterias.js';\n\n/**\n * When a single-selectable item is selected, all other single-selectable items in the same group are deselected;\n *\n * If the (visual) parent is a single-select-with-submenu,\n * the selection must be propagated because\n * a single-select within a single-select-with-submenu can't be selected without implying the selection of the parent single-select-with-submenu\n *\n * @param
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { type DSMenuButtonT } from '../../../react-desc-prop-types.js';\nimport { getAllSingleSelectIdsFromParent, getParentsByCriterias } from './nodeGettersByCriterias.js';\n\n/**\n * When a single-selectable item is selected, all other single-selectable items in the same group are deselected;\n *\n * If the (visual) parent is a single-select-with-submenu,\n * the selection must be propagated because\n * a single-select within a single-select-with-submenu can't be selected without implying the selection of the parent single-select-with-submenu\n *\n * @param selectedNodes - the current selected items\n * @param selectedItem - the newly selected item\n * @returns DSMenuButtonT.SelectionableMenuNodes[] - the new selection\n */\nexport const getNewSelectionSingleSelect = (\n selectedNodes: DSMenuButtonT.SelectionableMenuNodes[],\n selectedItem: DSMenuButtonT.MenuNodeSingleSelectItem | DSMenuButtonT.MenuNodeSingleSelectWithSubmenuItem,\n) => {\n const { oldestGroup, selectionableParentsWithSubmenu } = getParentsByCriterias(selectedItem);\n const itemsIdsToDeselect = getAllSingleSelectIdsFromParent(oldestGroup);\n // we remove all the ids of single selection parents from the previous selection\n const newSelection = selectedNodes.filter((item) => !itemsIdsToDeselect.includes(item.plainItem.dsId));\n // we add all the parents submenus to the selection\n newSelection.push(...selectionableParentsWithSubmenu);\n // finally we add the newly selected item\n newSelection.push(selectedItem);\n\n return newSelection;\n};\n"],
|
5
5
|
"mappings": "AAAA,YAAY,WAAW;ACCvB,SAAS,iCAAiC,6BAA6B;AAahE,MAAM,8BAA8B,CACzC,eACA,iBACG;AACH,QAAM,EAAE,aAAa,gCAAgC,IAAI,sBAAsB,YAAY;AAC3F,QAAM,qBAAqB,gCAAgC,WAAW;AAEtE,QAAM,eAAe,cAAc,OAAO,CAAC,SAAS,CAAC,mBAAmB,SAAS,KAAK,UAAU,IAAI,CAAC;AAErG,eAAa,KAAK,GAAG,+BAA+B;AAEpD,eAAa,KAAK,YAAY;AAE9B,SAAO;AACT;",
|
6
6
|
"names": []
|
7
7
|
}
|
@@ -9,6 +9,7 @@ import {
|
|
9
9
|
import React2 from "react";
|
10
10
|
import { MenuBehaviouralContextProviderContext } from "../DSMenuBehaviouralContextProvider/MenuBehaviouralContextProviderCTX.js";
|
11
11
|
import { MENU_FOCUS_REGIONS } from "../DSMenuBehaviouralContextProvider/constants/index.js";
|
12
|
+
import { focusNodeRacingConditionSolved } from "./focusNodeRacingConditionSolved.js";
|
12
13
|
const ActivableMenuItem = ({
|
13
14
|
itemNode
|
14
15
|
}) => {
|
@@ -19,7 +20,8 @@ const ActivableMenuItem = ({
|
|
19
20
|
menuItemEventsHandlers: {
|
20
21
|
handleFocusableMenuItemKeyDown,
|
21
22
|
handleFocusableMenuItemClick,
|
22
|
-
handleFocusableMenuItemOnMouseEnter
|
23
|
+
handleFocusableMenuItemOnMouseEnter,
|
24
|
+
handleFocusableMenuItemNativeFocusEvent
|
23
25
|
}
|
24
26
|
} = React2.useContext(MenuBehaviouralContextProviderContext);
|
25
27
|
const gridLayout = React2.useMemo(() => {
|
@@ -32,11 +34,9 @@ const ActivableMenuItem = ({
|
|
32
34
|
const isFocused = focusRegion === MENU_FOCUS_REGIONS.ITEM_BY_DSID(dsId);
|
33
35
|
const handleFocusOnRender = React2.useCallback(
|
34
36
|
(node) => {
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
}
|
39
|
-
});
|
37
|
+
if (node && focusRegion === MENU_FOCUS_REGIONS.ITEM_BY_DSID(dsId)) {
|
38
|
+
focusNodeRacingConditionSolved(node);
|
39
|
+
}
|
40
40
|
},
|
41
41
|
// we need to change the callback reference every time the focusRegion changes or else the focus will not be set
|
42
42
|
[dsId, focusRegion]
|
@@ -44,11 +44,14 @@ const ActivableMenuItem = ({
|
|
44
44
|
// the logic here actually receives a ref to a HTMLDivElement,
|
45
45
|
// but the component must think this is a HTMLLIElement ref callback
|
46
46
|
);
|
47
|
-
const handleOnMouseEnter = React2.useCallback(
|
47
|
+
const handleOnMouseEnter = React2.useCallback(() => {
|
48
|
+
handleFocusableMenuItemOnMouseEnter(itemNode);
|
49
|
+
}, [handleFocusableMenuItemOnMouseEnter, itemNode]);
|
50
|
+
const handleOnFocus = React2.useCallback(
|
48
51
|
(e) => {
|
49
|
-
|
52
|
+
handleFocusableMenuItemNativeFocusEvent(itemNode, e);
|
50
53
|
},
|
51
|
-
[
|
54
|
+
[handleFocusableMenuItemNativeFocusEvent, itemNode]
|
52
55
|
);
|
53
56
|
const spacelessDsIdForDom = `ds-menu-item-${`${dsId}`.replace(/\s/g, "")}`;
|
54
57
|
return /* @__PURE__ */ jsx(
|
@@ -58,6 +61,7 @@ const ActivableMenuItem = ({
|
|
58
61
|
onKeyDown: handleFocusableMenuItemKeyDown,
|
59
62
|
onClick: handleFocusableMenuItemClick,
|
60
63
|
onMouseEnter: handleOnMouseEnter,
|
64
|
+
onFocus: handleOnFocus,
|
61
65
|
as: "div",
|
62
66
|
id: `${spacelessDsIdForDom}`,
|
63
67
|
role: "menuitem",
|
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"version": 3,
|
3
3
|
"sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/DSMenuItemRendererFactory/ActivableMenuItem.tsx"],
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-lines */\nimport {\n StyleMenuItemLabel,\n StyleMenuItemSecondaryLabel,\n StyledContentWrapper,\n StyledGlobalMenuItemWrapper,\n} from '@elliemae/ds-menu-items-commons';\nimport React from 'react';\nimport type { DSMenuButtonT } from '../../react-desc-prop-types.js';\nimport { MenuBehaviouralContextProviderContext } from '../DSMenuBehaviouralContextProvider/MenuBehaviouralContextProviderCTX.js';\nimport { MENU_FOCUS_REGIONS } from '../DSMenuBehaviouralContextProvider/constants/index.js';\n\nexport const ActivableMenuItem: React.ComponentType<{ itemNode: DSMenuButtonT.MenuNodeActivableItem }> = ({\n itemNode,\n}) => {\n const { dsId, plainItem } = itemNode;\n const { label, secondaryLabel, leftDecoration: LeftDecComponent, minWidth, disabled } = plainItem;\n\n const {\n focusRegion,\n menuItemEventsHandlers: {\n handleFocusableMenuItemKeyDown,\n handleFocusableMenuItemClick,\n handleFocusableMenuItemOnMouseEnter,\n },\n } = React.useContext(MenuBehaviouralContextProviderContext);\n\n const gridLayout = React.useMemo(() => {\n const cols = LeftDecComponent ? ['min-content', 'auto'] : ['auto'];\n if (secondaryLabel) cols.push('auto');\n return cols;\n }, [LeftDecComponent, secondaryLabel]);\n\n const focusedRegionPerformanceHelper = React.useRef(focusRegion);\n focusedRegionPerformanceHelper.current = focusRegion;\n\n const isFocused = focusRegion === MENU_FOCUS_REGIONS.ITEM_BY_DSID(dsId);\n\n const handleFocusOnRender = React.useCallback(\n (node: HTMLDivElement) => {\n
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-lines */\nimport {\n StyleMenuItemLabel,\n StyleMenuItemSecondaryLabel,\n StyledContentWrapper,\n StyledGlobalMenuItemWrapper,\n} from '@elliemae/ds-menu-items-commons';\nimport React from 'react';\nimport type { DSMenuButtonT } from '../../react-desc-prop-types.js';\nimport { MenuBehaviouralContextProviderContext } from '../DSMenuBehaviouralContextProvider/MenuBehaviouralContextProviderCTX.js';\nimport { MENU_FOCUS_REGIONS } from '../DSMenuBehaviouralContextProvider/constants/index.js';\nimport { focusNodeRacingConditionSolved } from './focusNodeRacingConditionSolved.js';\n\nexport const ActivableMenuItem: React.ComponentType<{ itemNode: DSMenuButtonT.MenuNodeActivableItem }> = ({\n itemNode,\n}) => {\n const { dsId, plainItem } = itemNode;\n const { label, secondaryLabel, leftDecoration: LeftDecComponent, minWidth, disabled } = plainItem;\n\n const {\n focusRegion,\n menuItemEventsHandlers: {\n handleFocusableMenuItemKeyDown,\n handleFocusableMenuItemClick,\n handleFocusableMenuItemOnMouseEnter,\n handleFocusableMenuItemNativeFocusEvent,\n },\n } = React.useContext(MenuBehaviouralContextProviderContext);\n\n const gridLayout = React.useMemo(() => {\n const cols = LeftDecComponent ? ['min-content', 'auto'] : ['auto'];\n if (secondaryLabel) cols.push('auto');\n return cols;\n }, [LeftDecComponent, secondaryLabel]);\n\n const focusedRegionPerformanceHelper = React.useRef(focusRegion);\n focusedRegionPerformanceHelper.current = focusRegion;\n\n const isFocused = focusRegion === MENU_FOCUS_REGIONS.ITEM_BY_DSID(dsId);\n\n const handleFocusOnRender = React.useCallback(\n (node: HTMLDivElement) => {\n if (node && focusRegion === MENU_FOCUS_REGIONS.ITEM_BY_DSID(dsId)) {\n focusNodeRacingConditionSolved(node);\n }\n },\n // we need to change the callback reference every time the focusRegion changes or else the focus will not be set\n [dsId, focusRegion],\n // we are using the \"as='div'\", typescript is not able to infer the correct type\n // the logic here actually receives a ref to a HTMLDivElement,\n // but the component must think this is a HTMLLIElement ref callback\n ) as unknown as React.RefCallback<HTMLLIElement>;\n const handleOnMouseEnter = React.useCallback<React.MouseEventHandler<HTMLDivElement>>(() => {\n handleFocusableMenuItemOnMouseEnter(itemNode);\n }, [handleFocusableMenuItemOnMouseEnter, itemNode]);\n const handleOnFocus = React.useCallback<React.FocusEventHandler<HTMLDivElement>>(\n (e) => {\n handleFocusableMenuItemNativeFocusEvent(itemNode, e);\n },\n [handleFocusableMenuItemNativeFocusEvent, itemNode],\n );\n\n const spacelessDsIdForDom = `ds-menu-item-${`${dsId}`.replace(/\\s/g, '')}`;\n\n return (\n <StyledGlobalMenuItemWrapper\n innerRef={handleFocusOnRender}\n onKeyDown={handleFocusableMenuItemKeyDown}\n onClick={handleFocusableMenuItemClick}\n onMouseEnter={handleOnMouseEnter}\n onFocus={handleOnFocus}\n as=\"div\"\n id={`${spacelessDsIdForDom}`}\n role=\"menuitem\"\n tabIndex={isFocused ? 0 : -1}\n aria-disabled={disabled}\n applyAriaDisabled={disabled}\n >\n <StyledContentWrapper\n cols={gridLayout}\n minHeight=\"16px\"\n gutter=\"xxs\"\n alignItems=\"center\"\n minWidth={minWidth ?? undefined}\n >\n {LeftDecComponent ? <LeftDecComponent /> : null}\n <StyleMenuItemLabel>{label}</StyleMenuItemLabel>\n {secondaryLabel !== undefined && (\n <StyleMenuItemSecondaryLabel disabled={disabled}>{secondaryLabel}</StyleMenuItemSecondaryLabel>\n )}\n </StyledContentWrapper>\n </StyledGlobalMenuItemWrapper>\n );\n};\n"],
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;AC8EjB,SAOsB,KAPtB;AA7EN;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,OAAOA,YAAW;AAElB,SAAS,6CAA6C;AACtD,SAAS,0BAA0B;AACnC,SAAS,sCAAsC;AAExC,MAAM,oBAA4F,CAAC;AAAA,EACxG;AACF,MAAM;AACJ,QAAM,EAAE,MAAM,UAAU,IAAI;AAC5B,QAAM,EAAE,OAAO,gBAAgB,gBAAgB,kBAAkB,UAAU,SAAS,IAAI;AAExF,QAAM;AAAA,IACJ;AAAA,IACA,wBAAwB;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,IAAIA,OAAM,WAAW,qCAAqC;AAE1D,QAAM,aAAaA,OAAM,QAAQ,MAAM;AACrC,UAAM,OAAO,mBAAmB,CAAC,eAAe,MAAM,IAAI,CAAC,MAAM;AACjE,QAAI,eAAgB,MAAK,KAAK,MAAM;AACpC,WAAO;AAAA,EACT,GAAG,CAAC,kBAAkB,cAAc,CAAC;AAErC,QAAM,iCAAiCA,OAAM,OAAO,WAAW;AAC/D,iCAA+B,UAAU;AAEzC,QAAM,YAAY,gBAAgB,mBAAmB,aAAa,IAAI;AAEtE,QAAM,sBAAsBA,OAAM;AAAA,IAChC,CAAC,SAAyB;AACxB,UAAI,QAAQ,gBAAgB,mBAAmB,aAAa,IAAI,GAAG;AACjE,uCAA+B,IAAI;AAAA,MACrC;AAAA,IACF;AAAA;AAAA,IAEA,CAAC,MAAM,WAAW;AAAA;AAAA;AAAA;AAAA,EAIpB;AACA,QAAM,qBAAqBA,OAAM,YAAqD,MAAM;AAC1F,wCAAoC,QAAQ;AAAA,EAC9C,GAAG,CAAC,qCAAqC,QAAQ,CAAC;AAClD,QAAM,gBAAgBA,OAAM;AAAA,IAC1B,CAAC,MAAM;AACL,8CAAwC,UAAU,CAAC;AAAA,IACrD;AAAA,IACA,CAAC,yCAAyC,QAAQ;AAAA,EACpD;AAEA,QAAM,sBAAsB,gBAAgB,GAAG,IAAI,GAAG,QAAQ,OAAO,EAAE,CAAC;AAExE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV,WAAW;AAAA,MACX,SAAS;AAAA,MACT,cAAc;AAAA,MACd,SAAS;AAAA,MACT,IAAG;AAAA,MACH,IAAI,GAAG,mBAAmB;AAAA,MAC1B,MAAK;AAAA,MACL,UAAU,YAAY,IAAI;AAAA,MAC1B,iBAAe;AAAA,MACf,mBAAmB;AAAA,MAEnB;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN,WAAU;AAAA,UACV,QAAO;AAAA,UACP,YAAW;AAAA,UACX,UAAU,YAAY;AAAA,UAErB;AAAA,+BAAmB,oBAAC,oBAAiB,IAAK;AAAA,YAC3C,oBAAC,sBAAoB,iBAAM;AAAA,YAC1B,mBAAmB,UAClB,oBAAC,+BAA4B,UAAqB,0BAAe;AAAA;AAAA;AAAA,MAErE;AAAA;AAAA,EACF;AAEJ;",
|
6
6
|
"names": ["React"]
|
7
7
|
}
|
@@ -10,6 +10,7 @@ import React2 from "react";
|
|
10
10
|
import { useFloatingContext } from "@elliemae/ds-floating-context";
|
11
11
|
import { MenuBehaviouralContextProviderContext } from "../DSMenuBehaviouralContextProvider/MenuBehaviouralContextProviderCTX.js";
|
12
12
|
import { MENU_FOCUS_REGIONS } from "../DSMenuBehaviouralContextProvider/constants/index.js";
|
13
|
+
import { focusNodeRacingConditionSolved } from "./focusNodeRacingConditionSolved.js";
|
13
14
|
const placementOrderPreference = [
|
14
15
|
"right-start",
|
15
16
|
"right-start",
|
@@ -36,7 +37,8 @@ const ActivableWithSubmenuMenuItem = ({ itemNode, FlyoutMenuCircularDepInject })
|
|
36
37
|
menuItemEventsHandlers: {
|
37
38
|
handleFocusableMenuItemKeyDown,
|
38
39
|
handleFocusableMenuItemClick,
|
39
|
-
handleFocusableMenuItemOnMouseEnter
|
40
|
+
handleFocusableMenuItemOnMouseEnter,
|
41
|
+
handleFocusableMenuItemNativeFocusEvent
|
40
42
|
}
|
41
43
|
} = React2.useContext(MenuBehaviouralContextProviderContext);
|
42
44
|
const gridLayout = React2.useMemo(() => {
|
@@ -51,11 +53,9 @@ const ActivableWithSubmenuMenuItem = ({ itemNode, FlyoutMenuCircularDepInject })
|
|
51
53
|
const handleFocusOnRender = React2.useCallback(
|
52
54
|
(node) => {
|
53
55
|
setReference(node);
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
}
|
58
|
-
});
|
56
|
+
if (node && focusRegion === MENU_FOCUS_REGIONS.ITEM_BY_DSID(dsId)) {
|
57
|
+
focusNodeRacingConditionSolved(node);
|
58
|
+
}
|
59
59
|
},
|
60
60
|
// we need to change the callback reference every time the focusRegion changes or else the focus will not be set
|
61
61
|
[dsId, focusRegion, setReference]
|
@@ -63,11 +63,14 @@ const ActivableWithSubmenuMenuItem = ({ itemNode, FlyoutMenuCircularDepInject })
|
|
63
63
|
// the logic here actually receives a ref to a HTMLDivElement,
|
64
64
|
// but the component must think this is a HTMLLIElement ref callback
|
65
65
|
);
|
66
|
-
const handleOnMouseEnter = React2.useCallback(
|
66
|
+
const handleOnMouseEnter = React2.useCallback(() => {
|
67
|
+
handleFocusableMenuItemOnMouseEnter(itemNode);
|
68
|
+
}, [handleFocusableMenuItemOnMouseEnter, itemNode]);
|
69
|
+
const handleOnFocus = React2.useCallback(
|
67
70
|
(e) => {
|
68
|
-
|
71
|
+
handleFocusableMenuItemNativeFocusEvent(itemNode, e);
|
69
72
|
},
|
70
|
-
[
|
73
|
+
[handleFocusableMenuItemNativeFocusEvent, itemNode]
|
71
74
|
);
|
72
75
|
const spacelessDsIdForDom = `ds-menu-item-${`${dsId}`.replace(/\s/g, "")}`;
|
73
76
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
@@ -78,6 +81,7 @@ const ActivableWithSubmenuMenuItem = ({ itemNode, FlyoutMenuCircularDepInject })
|
|
78
81
|
onKeyDown: handleFocusableMenuItemKeyDown,
|
79
82
|
onClick: handleFocusableMenuItemClick,
|
80
83
|
onMouseEnter: handleOnMouseEnter,
|
84
|
+
onFocus: handleOnFocus,
|
81
85
|
as: "div",
|
82
86
|
id: `${spacelessDsIdForDom}`,
|
83
87
|
tabIndex: isFocused ? 0 : -1,
|
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"version": 3,
|
3
3
|
"sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/DSMenuItemRendererFactory/ActivableWithSubmenuMenuItem.tsx"],
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-lines */\nimport {\n StyleMenuItemLabel,\n StyleMenuItemSecondaryLabel,\n StyledContentWrapper,\n StyledGlobalMenuItemWrapper,\n} from '@elliemae/ds-menu-items-commons';\nimport React from 'react';\nimport { useFloatingContext, type DSHookFloatingContextT } from '@elliemae/ds-floating-context';\nimport type { DSMenuButtonT } from '../../react-desc-prop-types.js';\nimport { MenuBehaviouralContextProviderContext } from '../DSMenuBehaviouralContextProvider/MenuBehaviouralContextProviderCTX.js';\nimport { MENU_FOCUS_REGIONS } from '../DSMenuBehaviouralContextProvider/constants/index.js';\nimport { type DSMenuItemRendererFactoryT } from './react-desc-prop-types.js';\nconst placementOrderPreference: Required<DSHookFloatingContextT.Props>['placementOrderPreference'] = [\n 'right-start',\n 'right-start',\n 'right',\n 'left-start',\n 'left-end',\n 'left',\n];\nexport const ActivableWithSubmenuMenuItem: React.ComponentType<{\n itemNode: DSMenuButtonT.MenuNodeActivableWithSubmenuItem;\n FlyoutMenuCircularDepInject: DSMenuItemRendererFactoryT.RequiredProps['FlyoutMenuCircularDepInject'];\n}> = ({ itemNode, FlyoutMenuCircularDepInject }) => {\n const { dsId, plainItem } = itemNode;\n const { label, secondaryLabel, leftDecoration: LeftDecComponent, minWidth, disabled } = plainItem;\n const floatingContext = useFloatingContext({\n placement: placementOrderPreference[0],\n placementOrderPreference,\n animationDuration: 100,\n customOffset: [0, 0],\n });\n const {\n refs: { setReference },\n } = floatingContext;\n\n const {\n focusRegion,\n openedSubItems,\n menuItemEventsHandlers: {\n handleFocusableMenuItemKeyDown,\n handleFocusableMenuItemClick,\n handleFocusableMenuItemOnMouseEnter,\n },\n } = React.useContext(MenuBehaviouralContextProviderContext);\n\n const gridLayout = React.useMemo(() => {\n const cols = LeftDecComponent ? ['min-content', 'auto'] : ['auto'];\n if (secondaryLabel) cols.push('auto');\n return cols;\n }, [LeftDecComponent, secondaryLabel]);\n\n const focusedRegionPerformanceHelper = React.useRef(focusRegion);\n focusedRegionPerformanceHelper.current = focusRegion;\n\n const isExpanded = openedSubItems.some((itemWithOpenSubmenu) => itemWithOpenSubmenu.dsId === dsId);\n const isFocused = focusRegion === MENU_FOCUS_REGIONS.ITEM_BY_DSID(dsId);\n\n const handleFocusOnRender = React.useCallback(\n (node: HTMLDivElement) => {\n setReference(node);\n
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-lines */\nimport {\n StyleMenuItemLabel,\n StyleMenuItemSecondaryLabel,\n StyledContentWrapper,\n StyledGlobalMenuItemWrapper,\n} from '@elliemae/ds-menu-items-commons';\nimport React from 'react';\nimport { useFloatingContext, type DSHookFloatingContextT } from '@elliemae/ds-floating-context';\nimport type { DSMenuButtonT } from '../../react-desc-prop-types.js';\nimport { MenuBehaviouralContextProviderContext } from '../DSMenuBehaviouralContextProvider/MenuBehaviouralContextProviderCTX.js';\nimport { MENU_FOCUS_REGIONS } from '../DSMenuBehaviouralContextProvider/constants/index.js';\nimport { type DSMenuItemRendererFactoryT } from './react-desc-prop-types.js';\nimport { focusNodeRacingConditionSolved } from './focusNodeRacingConditionSolved.js';\n\nconst placementOrderPreference: Required<DSHookFloatingContextT.Props>['placementOrderPreference'] = [\n 'right-start',\n 'right-start',\n 'right',\n 'left-start',\n 'left-end',\n 'left',\n];\nexport const ActivableWithSubmenuMenuItem: React.ComponentType<{\n itemNode: DSMenuButtonT.MenuNodeActivableWithSubmenuItem;\n FlyoutMenuCircularDepInject: DSMenuItemRendererFactoryT.RequiredProps['FlyoutMenuCircularDepInject'];\n}> = ({ itemNode, FlyoutMenuCircularDepInject }) => {\n const { dsId, plainItem } = itemNode;\n const { label, secondaryLabel, leftDecoration: LeftDecComponent, minWidth, disabled } = plainItem;\n const floatingContext = useFloatingContext({\n placement: placementOrderPreference[0],\n placementOrderPreference,\n animationDuration: 100,\n customOffset: [0, 0],\n });\n const {\n refs: { setReference },\n } = floatingContext;\n\n const {\n focusRegion,\n openedSubItems,\n menuItemEventsHandlers: {\n handleFocusableMenuItemKeyDown,\n handleFocusableMenuItemClick,\n handleFocusableMenuItemOnMouseEnter,\n handleFocusableMenuItemNativeFocusEvent,\n },\n } = React.useContext(MenuBehaviouralContextProviderContext);\n\n const gridLayout = React.useMemo(() => {\n const cols = LeftDecComponent ? ['min-content', 'auto'] : ['auto'];\n if (secondaryLabel) cols.push('auto');\n return cols;\n }, [LeftDecComponent, secondaryLabel]);\n\n const focusedRegionPerformanceHelper = React.useRef(focusRegion);\n focusedRegionPerformanceHelper.current = focusRegion;\n\n const isExpanded = openedSubItems.some((itemWithOpenSubmenu) => itemWithOpenSubmenu.dsId === dsId);\n const isFocused = focusRegion === MENU_FOCUS_REGIONS.ITEM_BY_DSID(dsId);\n\n const handleFocusOnRender = React.useCallback(\n (node: HTMLDivElement) => {\n setReference(node);\n if (node && focusRegion === MENU_FOCUS_REGIONS.ITEM_BY_DSID(dsId)) {\n focusNodeRacingConditionSolved(node);\n }\n },\n // we need to change the callback reference every time the focusRegion changes or else the focus will not be set\n [dsId, focusRegion, setReference],\n // we are using the \"as='div'\", typescript is not able to infer the correct type\n // the logic here actually receives a ref to a HTMLDivElement,\n // but the component must think this is a HTMLLIElement ref callback\n ) as unknown as React.RefCallback<HTMLLIElement>;\n\n const handleOnMouseEnter = React.useCallback<React.MouseEventHandler<HTMLDivElement>>(() => {\n handleFocusableMenuItemOnMouseEnter(itemNode);\n }, [handleFocusableMenuItemOnMouseEnter, itemNode]);\n const handleOnFocus = React.useCallback<React.FocusEventHandler<HTMLDivElement>>(\n (e) => {\n handleFocusableMenuItemNativeFocusEvent(itemNode, e);\n },\n [handleFocusableMenuItemNativeFocusEvent, itemNode],\n );\n\n const spacelessDsIdForDom = `ds-menu-item-${`${dsId}`.replace(/\\s/g, '')}`;\n return (\n <>\n <StyledGlobalMenuItemWrapper\n innerRef={handleFocusOnRender}\n onKeyDown={handleFocusableMenuItemKeyDown}\n onClick={handleFocusableMenuItemClick}\n onMouseEnter={handleOnMouseEnter}\n onFocus={handleOnFocus}\n as=\"div\"\n id={`${spacelessDsIdForDom}`}\n tabIndex={isFocused ? 0 : -1}\n role=\"menuitem\"\n aria-controls={\n /* ********************************************************************************************************************\n * https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls\n * The aria-controls only needs to be set when the popup is visible, but it is valid and easier to program to reference an element that is not visible.\n * ********************************************************************************************************************\n * ^^^ some automated tools will mark an error if the aria-controls references an element that does (yet) exist in the DOM\n * so, while technically valid to not check if expanded, we are doing it to avoid automated tools marking an error\n * ******************************************************************************************************************** */\n isExpanded\n ? itemNode.plainChildren.map((child) => `ds-menu-item-${`${child.dsId}`.replace(/\\s/g, '')}`).join(' ')\n : undefined\n }\n aria-haspopup=\"menu\"\n aria-expanded={isExpanded}\n aria-disabled={disabled}\n applyAriaDisabled={disabled}\n >\n <StyledContentWrapper\n cols={gridLayout}\n minHeight=\"16px\"\n gutter=\"xxs\"\n alignItems=\"center\"\n minWidth={minWidth ?? undefined}\n >\n {LeftDecComponent ? <LeftDecComponent /> : null}\n <StyleMenuItemLabel>{label}</StyleMenuItemLabel>\n {secondaryLabel !== undefined && (\n <StyleMenuItemSecondaryLabel disabled={disabled}>{secondaryLabel}</StyleMenuItemSecondaryLabel>\n )}\n </StyledContentWrapper>\n </StyledGlobalMenuItemWrapper>\n <FlyoutMenuCircularDepInject\n isMenuOpen={isExpanded}\n floatingContext={floatingContext.context}\n floatingStyles={floatingContext.floatingStyles}\n setFloatingRef={floatingContext.refs.setFloating}\n itemNode={itemNode}\n />\n </>\n );\n};\n"],
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;ACwFnB,mBAmC0B,KAPtB,YA5BJ;AAvFJ;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,OAAOA,YAAW;AAClB,SAAS,0BAAuD;AAEhE,SAAS,6CAA6C;AACtD,SAAS,0BAA0B;AAEnC,SAAS,sCAAsC;AAE/C,MAAM,2BAA+F;AAAA,EACnG;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACO,MAAM,+BAGR,CAAC,EAAE,UAAU,4BAA4B,MAAM;AAClD,QAAM,EAAE,MAAM,UAAU,IAAI;AAC5B,QAAM,EAAE,OAAO,gBAAgB,gBAAgB,kBAAkB,UAAU,SAAS,IAAI;AACxF,QAAM,kBAAkB,mBAAmB;AAAA,IACzC,WAAW,yBAAyB,CAAC;AAAA,IACrC;AAAA,IACA,mBAAmB;AAAA,IACnB,cAAc,CAAC,GAAG,CAAC;AAAA,EACrB,CAAC;AACD,QAAM;AAAA,IACJ,MAAM,EAAE,aAAa;AAAA,EACvB,IAAI;AAEJ,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,wBAAwB;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,IAAIA,OAAM,WAAW,qCAAqC;AAE1D,QAAM,aAAaA,OAAM,QAAQ,MAAM;AACrC,UAAM,OAAO,mBAAmB,CAAC,eAAe,MAAM,IAAI,CAAC,MAAM;AACjE,QAAI,eAAgB,MAAK,KAAK,MAAM;AACpC,WAAO;AAAA,EACT,GAAG,CAAC,kBAAkB,cAAc,CAAC;AAErC,QAAM,iCAAiCA,OAAM,OAAO,WAAW;AAC/D,iCAA+B,UAAU;AAEzC,QAAM,aAAa,eAAe,KAAK,CAAC,wBAAwB,oBAAoB,SAAS,IAAI;AACjG,QAAM,YAAY,gBAAgB,mBAAmB,aAAa,IAAI;AAEtE,QAAM,sBAAsBA,OAAM;AAAA,IAChC,CAAC,SAAyB;AACxB,mBAAa,IAAI;AACjB,UAAI,QAAQ,gBAAgB,mBAAmB,aAAa,IAAI,GAAG;AACjE,uCAA+B,IAAI;AAAA,MACrC;AAAA,IACF;AAAA;AAAA,IAEA,CAAC,MAAM,aAAa,YAAY;AAAA;AAAA;AAAA;AAAA,EAIlC;AAEA,QAAM,qBAAqBA,OAAM,YAAqD,MAAM;AAC1F,wCAAoC,QAAQ;AAAA,EAC9C,GAAG,CAAC,qCAAqC,QAAQ,CAAC;AAClD,QAAM,gBAAgBA,OAAM;AAAA,IAC1B,CAAC,MAAM;AACL,8CAAwC,UAAU,CAAC;AAAA,IACrD;AAAA,IACA,CAAC,yCAAyC,QAAQ;AAAA,EACpD;AAEA,QAAM,sBAAsB,gBAAgB,GAAG,IAAI,GAAG,QAAQ,OAAO,EAAE,CAAC;AACxE,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU;AAAA,QACV,WAAW;AAAA,QACX,SAAS;AAAA,QACT,cAAc;AAAA,QACd,SAAS;AAAA,QACT,IAAG;AAAA,QACH,IAAI,GAAG,mBAAmB;AAAA,QAC1B,UAAU,YAAY,IAAI;AAAA,QAC1B,MAAK;AAAA,QACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAQE,aACI,SAAS,cAAc,IAAI,CAAC,UAAU,gBAAgB,GAAG,MAAM,IAAI,GAAG,QAAQ,OAAO,EAAE,CAAC,EAAE,EAAE,KAAK,GAAG,IACpG;AAAA;AAAA,QAEN,iBAAc;AAAA,QACd,iBAAe;AAAA,QACf,iBAAe;AAAA,QACf,mBAAmB;AAAA,QAEnB;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,WAAU;AAAA,YACV,QAAO;AAAA,YACP,YAAW;AAAA,YACX,UAAU,YAAY;AAAA,YAErB;AAAA,iCAAmB,oBAAC,oBAAiB,IAAK;AAAA,cAC3C,oBAAC,sBAAoB,iBAAM;AAAA,cAC1B,mBAAmB,UAClB,oBAAC,+BAA4B,UAAqB,0BAAe;AAAA;AAAA;AAAA,QAErE;AAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,YAAY;AAAA,QACZ,iBAAiB,gBAAgB;AAAA,QACjC,gBAAgB,gBAAgB;AAAA,QAChC,gBAAgB,gBAAgB,KAAK;AAAA,QACrC;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;",
|
6
6
|
"names": ["React"]
|
7
7
|
}
|
@@ -1,31 +1,32 @@
|
|
1
1
|
import * as React from "react";
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
3
3
|
import { Grid } from "@elliemae/ds-grid";
|
4
|
-
import { describe } from "@elliemae/ds-props-helpers";
|
5
4
|
import { StyledGroupLabel, StyledSeparator, StyledSeparatorWrapper } from "@elliemae/ds-menu-items-commons";
|
5
|
+
import { describe } from "@elliemae/ds-props-helpers";
|
6
6
|
import { styled } from "@elliemae/ds-system";
|
7
|
-
import { useMenuItemRendererFactory } from "./config/useMenuItemRendererFactory.js";
|
8
|
-
import { DSMenuItemRendererFactoryName, MENU_ITEM_RENDERER_FACTORY_SLOTS } from "./constants/index.js";
|
9
|
-
import { DSMenuItemRendererFactoryPropTypesSchema } from "./react-desc-prop-types.js";
|
10
|
-
import { ActivableMenuItem } from "./ActivableMenuItem.js";
|
11
|
-
import { SingleSelectMenuItem } from "./SingleSelectMenuItem.js";
|
12
|
-
import { SingleSelectWithSubmenuMenuItem } from "./SingleSelectWithSubmenuMenuItem.js";
|
13
|
-
import { MultipleSelectMenuItem } from "./MultipleSelectMenuItem.js";
|
14
|
-
import { WithSubmenuMenuItem } from "./WithSubmenuMenuItem.js";
|
15
|
-
import { MultipleSelectWithSubmenuMenuItem } from "./MultipleSelectWithSubmenuMenuItem.js";
|
16
|
-
import { ActivableWithSubmenuMenuItem } from "./ActivableWithSubmenuMenuItem.js";
|
17
7
|
import {
|
18
8
|
isActivableNode,
|
19
|
-
|
9
|
+
isActivableWithSubmenuNode,
|
10
|
+
isGroup,
|
20
11
|
isMultipleSelectOnlyNode,
|
21
|
-
|
12
|
+
isMultipleSelectWithSubmenuNode,
|
22
13
|
isSeparatorNode,
|
23
|
-
isGroup,
|
24
|
-
isWithSubmenuOnlyNode,
|
25
14
|
isSingleSelectNodeWithSubmenu,
|
26
|
-
|
27
|
-
|
15
|
+
isSingleSelectOnlyNode,
|
16
|
+
isSkeletonNode,
|
17
|
+
isWithSubmenuOnlyNode
|
28
18
|
} from "../../utils/nodesTypeguardsAndGetters.js";
|
19
|
+
import { ActivableMenuItem } from "./ActivableMenuItem.js";
|
20
|
+
import { ActivableWithSubmenuMenuItem } from "./ActivableWithSubmenuMenuItem.js";
|
21
|
+
import { MultipleSelectMenuItem } from "./MultipleSelectMenuItem.js";
|
22
|
+
import { MultipleSelectWithSubmenuMenuItem } from "./MultipleSelectWithSubmenuMenuItem.js";
|
23
|
+
import { SingleSelectMenuItem } from "./SingleSelectMenuItem.js";
|
24
|
+
import { SingleSelectWithSubmenuMenuItem } from "./SingleSelectWithSubmenuMenuItem.js";
|
25
|
+
import { SkeletonMenuItem } from "./SkeletonMenuItem.js";
|
26
|
+
import { WithSubmenuMenuItem } from "./WithSubmenuMenuItem.js";
|
27
|
+
import { useMenuItemRendererFactory } from "./config/useMenuItemRendererFactory.js";
|
28
|
+
import { DSMenuItemRendererFactoryName, MENU_ITEM_RENDERER_FACTORY_SLOTS } from "./constants/index.js";
|
29
|
+
import { DSMenuItemRendererFactoryPropTypesSchema } from "./react-desc-prop-types.js";
|
29
30
|
const StyledGroupLabelWrapper = styled(Grid, {
|
30
31
|
name: DSMenuItemRendererFactoryName,
|
31
32
|
slot: MENU_ITEM_RENDERER_FACTORY_SLOTS.GROUP_LABEL_WRAPPER
|
@@ -44,7 +45,7 @@ const DSMenuItemRendererFactory = (props) => {
|
|
44
45
|
if (ItemRenderer) return /* @__PURE__ */ jsx(ItemRenderer, { itemNode });
|
45
46
|
if (isSeparatorNode(itemNode))
|
46
47
|
return /* @__PURE__ */ jsx(StyledSeparatorWrapper, { as: "div", role: "presentation", children: /* @__PURE__ */ jsx(StyledSeparator, {}) });
|
47
|
-
if (isSkeletonNode(itemNode)) return /* @__PURE__ */ jsx(
|
48
|
+
if (isSkeletonNode(itemNode)) return /* @__PURE__ */ jsx(SkeletonMenuItem, { itemNode });
|
48
49
|
if (isActivableNode(itemNode)) return /* @__PURE__ */ jsx(ActivableMenuItem, { itemNode });
|
49
50
|
if (isMultipleSelectOnlyNode(itemNode)) return /* @__PURE__ */ jsx(MultipleSelectMenuItem, { itemNode });
|
50
51
|
if (isSingleSelectOnlyNode(itemNode)) return /* @__PURE__ */ jsx(SingleSelectMenuItem, { itemNode });
|
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"version": 3,
|
3
3
|
"sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/DSMenuItemRendererFactory/DSMenuItemRendererFactory.tsx"],
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\nimport { Grid } from '@elliemae/ds-grid';\nimport {
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\nimport { Grid } from '@elliemae/ds-grid';\nimport { StyledGroupLabel, StyledSeparator, StyledSeparatorWrapper } from '@elliemae/ds-menu-items-commons';\nimport { describe } from '@elliemae/ds-props-helpers';\nimport { styled } from '@elliemae/ds-system';\nimport React from 'react';\nimport {\n isActivableNode,\n isActivableWithSubmenuNode,\n isGroup,\n isMultipleSelectOnlyNode,\n isMultipleSelectWithSubmenuNode,\n isSeparatorNode,\n isSingleSelectNodeWithSubmenu,\n isSingleSelectOnlyNode,\n isSkeletonNode,\n isWithSubmenuOnlyNode,\n} from '../../utils/nodesTypeguardsAndGetters.js';\nimport { ActivableMenuItem } from './ActivableMenuItem.js';\nimport { ActivableWithSubmenuMenuItem } from './ActivableWithSubmenuMenuItem.js';\nimport { MultipleSelectMenuItem } from './MultipleSelectMenuItem.js';\nimport { MultipleSelectWithSubmenuMenuItem } from './MultipleSelectWithSubmenuMenuItem.js';\nimport { SingleSelectMenuItem } from './SingleSelectMenuItem.js';\nimport { SingleSelectWithSubmenuMenuItem } from './SingleSelectWithSubmenuMenuItem.js';\nimport { SkeletonMenuItem } from './SkeletonMenuItem.js';\nimport { WithSubmenuMenuItem } from './WithSubmenuMenuItem.js';\nimport { useMenuItemRendererFactory } from './config/useMenuItemRendererFactory.js';\nimport { DSMenuItemRendererFactoryName, MENU_ITEM_RENDERER_FACTORY_SLOTS } from './constants/index.js';\nimport { DSMenuItemRendererFactoryPropTypesSchema, type DSMenuItemRendererFactoryT } from './react-desc-prop-types.js';\n\nconst StyledGroupLabelWrapper = styled(Grid, {\n name: DSMenuItemRendererFactoryName,\n slot: MENU_ITEM_RENDERER_FACTORY_SLOTS.GROUP_LABEL_WRAPPER,\n})`\n padding: ${({ theme }) => theme.space.xxxs} ${({ theme }) => theme.space.xs};\n`;\n\nconst StyledLabelWithLeftDecWrapper = styled(Grid, {\n name: DSMenuItemRendererFactoryName,\n slot: MENU_ITEM_RENDERER_FACTORY_SLOTS.LABEL_WITH_LEFT_DEC_WRAPPER,\n})`\n padding-left: ${({ theme }) => theme.space.xxs};\n`;\n\nconst DSMenuItemRendererFactory: React.ComponentType<DSMenuItemRendererFactoryT.Props> = (props) => {\n const { propsWithDefault, instanceUid } = useMenuItemRendererFactory(props);\n const { itemNode, ItemRenderer, FlyoutMenuCircularDepInject } = propsWithDefault;\n\n if (ItemRenderer) return <ItemRenderer itemNode={itemNode} />;\n\n if (isSeparatorNode(itemNode))\n return (\n <StyledSeparatorWrapper as=\"div\" role=\"presentation\">\n <StyledSeparator />\n </StyledSeparatorWrapper>\n );\n if (isSkeletonNode(itemNode)) return <SkeletonMenuItem itemNode={itemNode} />;\n if (isActivableNode(itemNode)) return <ActivableMenuItem itemNode={itemNode} />;\n if (isMultipleSelectOnlyNode(itemNode)) return <MultipleSelectMenuItem itemNode={itemNode} />;\n if (isSingleSelectOnlyNode(itemNode)) return <SingleSelectMenuItem itemNode={itemNode} />;\n\n if (isWithSubmenuOnlyNode(itemNode))\n return <WithSubmenuMenuItem itemNode={itemNode} FlyoutMenuCircularDepInject={FlyoutMenuCircularDepInject} />;\n if (isSingleSelectNodeWithSubmenu(itemNode))\n return (\n <SingleSelectWithSubmenuMenuItem itemNode={itemNode} FlyoutMenuCircularDepInject={FlyoutMenuCircularDepInject} />\n );\n if (isMultipleSelectWithSubmenuNode(itemNode))\n return (\n <MultipleSelectWithSubmenuMenuItem\n itemNode={itemNode}\n FlyoutMenuCircularDepInject={FlyoutMenuCircularDepInject}\n />\n );\n if (isActivableWithSubmenuNode(itemNode))\n return (\n <ActivableWithSubmenuMenuItem itemNode={itemNode} FlyoutMenuCircularDepInject={FlyoutMenuCircularDepInject} />\n );\n\n // defined in this file to avoid to have to inject the ItemRendererFactory prop in the \"GroupMenuItem\" component\n // if we eventually move this to a separate file,\n // we will have to inject the ItemRendererFactory prop in the \"GroupMenuItem\" component to avoid circular dependencies\n if (isGroup(itemNode)) {\n const { leftDecoration: LeftDecComponent, label, minWidth } = itemNode.plainItem;\n const spacelessIdForGroup = label ? `label-${label.replace(/\\s/g, '')}` : undefined;\n\n return (\n <div role=\"group\" aria-labelledby={spacelessIdForGroup} style={minWidth ? { minWidth } : {}}>\n {label ? (\n <StyledGroupLabelWrapper cols={LeftDecComponent ? ['min-content', '1fr'] : ['1fr']}>\n {LeftDecComponent ? <LeftDecComponent /> : null}\n <StyledGroupLabel role=\"presentation\" id={spacelessIdForGroup}>\n {LeftDecComponent ? <StyledLabelWithLeftDecWrapper>{label}</StyledLabelWithLeftDecWrapper> : label}\n </StyledGroupLabel>\n </StyledGroupLabelWrapper>\n ) : null}\n {itemNode.children.map((subItemNode) => (\n <DSMenuItemRendererFactory\n key={`item-factory-${subItemNode.dsId}-${instanceUid}`}\n itemNode={subItemNode}\n FlyoutMenuCircularDepInject={FlyoutMenuCircularDepInject}\n />\n ))}\n </div>\n );\n }\n\n // if we get here either\n // - a new type of item has been added and this component wasn't updated\n // -> update this component to handle the new type\n // - developer provided an invalid type for the item\n // -> developer should fix the item type\n // ----------\n // the following rule is disabled because this is LITERALLY an error throwing section,\n // of course typescript thinks type is never, that's why we are throwing an error...\n // ----------\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n throw new Error(`Invalid item type: ${JSON.stringify(itemNode)}`);\n};\n\nDSMenuItemRendererFactory.displayName = DSMenuItemRendererFactoryName;\nconst DSMenuItemRendererFactoryWithSchema = describe(DSMenuItemRendererFactory);\nDSMenuItemRendererFactoryWithSchema.propTypes = DSMenuItemRendererFactoryPropTypesSchema;\n\nexport { DSMenuItemRendererFactory, DSMenuItemRendererFactoryWithSchema };\n"],
|
5
|
+
"mappings": "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",
|
6
6
|
"names": []
|
7
7
|
}
|
@@ -11,6 +11,7 @@ import {
|
|
11
11
|
import React2 from "react";
|
12
12
|
import { MenuBehaviouralContextProviderContext } from "../DSMenuBehaviouralContextProvider/MenuBehaviouralContextProviderCTX.js";
|
13
13
|
import { MENU_FOCUS_REGIONS } from "../DSMenuBehaviouralContextProvider/constants/index.js";
|
14
|
+
import { focusNodeRacingConditionSolved } from "./focusNodeRacingConditionSolved.js";
|
14
15
|
const LeftBoxlessCheckbox = React2.memo(({ isSelected }) => /* @__PURE__ */ jsx(Grid, { width: "16px", children: isSelected ? /* @__PURE__ */ jsx(Checkmark, { size: "s", color: ["brand-primary", "600"] }) : /* @__PURE__ */ jsx("div", {}) }));
|
15
16
|
const MultipleSelectMenuItem = ({ itemNode }) => {
|
16
17
|
const { dsId, plainItem } = itemNode;
|
@@ -21,10 +22,11 @@ const MultipleSelectMenuItem = ({ itemNode }) => {
|
|
21
22
|
menuItemEventsHandlers: {
|
22
23
|
handleFocusableMenuItemKeyDown,
|
23
24
|
handleFocusableMenuItemClick,
|
24
|
-
handleFocusableMenuItemOnMouseEnter
|
25
|
+
handleFocusableMenuItemOnMouseEnter,
|
26
|
+
handleFocusableMenuItemNativeFocusEvent
|
25
27
|
}
|
26
28
|
} = React2.useContext(MenuBehaviouralContextProviderContext);
|
27
|
-
const {
|
29
|
+
const { selectedNodes } = propsWithDefault;
|
28
30
|
const gridLayout = React2.useMemo(() => {
|
29
31
|
const cols = LeftDecComponent ? ["min-content", "min-content", "auto"] : ["min-content", "auto"];
|
30
32
|
if (secondaryLabel) cols.push("auto");
|
@@ -33,14 +35,12 @@ const MultipleSelectMenuItem = ({ itemNode }) => {
|
|
33
35
|
const focusedRegionPerformanceHelper = React2.useRef(focusRegion);
|
34
36
|
focusedRegionPerformanceHelper.current = focusRegion;
|
35
37
|
const isFocused = focusRegion === MENU_FOCUS_REGIONS.ITEM_BY_DSID(dsId);
|
36
|
-
const isSelected =
|
38
|
+
const isSelected = selectedNodes.some((itemMarkesAsSelected) => itemMarkesAsSelected.dsId === dsId);
|
37
39
|
const handleFocusOnRender = React2.useCallback(
|
38
40
|
(node) => {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
}
|
43
|
-
});
|
41
|
+
if (node && focusRegion === MENU_FOCUS_REGIONS.ITEM_BY_DSID(dsId)) {
|
42
|
+
focusNodeRacingConditionSolved(node);
|
43
|
+
}
|
44
44
|
},
|
45
45
|
// we need to change the callback reference every time the focusRegion changes or else the focus will not be set
|
46
46
|
[dsId, focusRegion]
|
@@ -48,11 +48,14 @@ const MultipleSelectMenuItem = ({ itemNode }) => {
|
|
48
48
|
// the logic here actually receives a ref to a HTMLDivElement,
|
49
49
|
// but the component must think this is a HTMLLIElement ref callback
|
50
50
|
);
|
51
|
-
const handleOnMouseEnter = React2.useCallback(
|
51
|
+
const handleOnMouseEnter = React2.useCallback(() => {
|
52
|
+
handleFocusableMenuItemOnMouseEnter(itemNode);
|
53
|
+
}, [handleFocusableMenuItemOnMouseEnter, itemNode]);
|
54
|
+
const handleOnFocus = React2.useCallback(
|
52
55
|
(e) => {
|
53
|
-
|
56
|
+
handleFocusableMenuItemNativeFocusEvent(itemNode, e);
|
54
57
|
},
|
55
|
-
[
|
58
|
+
[handleFocusableMenuItemNativeFocusEvent, itemNode]
|
56
59
|
);
|
57
60
|
const spacelessDsIdForDom = `ds-menu-item-${`${dsId}`.replace(/\s/g, "")}`;
|
58
61
|
return /* @__PURE__ */ jsx(
|
@@ -62,6 +65,7 @@ const MultipleSelectMenuItem = ({ itemNode }) => {
|
|
62
65
|
onKeyDown: handleFocusableMenuItemKeyDown,
|
63
66
|
onClick: handleFocusableMenuItemClick,
|
64
67
|
onMouseEnter: handleOnMouseEnter,
|
68
|
+
onFocus: handleOnFocus,
|
65
69
|
as: "div",
|
66
70
|
id: `${spacelessDsIdForDom}`,
|
67
71
|
tabIndex: isFocused ? 0 : -1,
|