@hh.ru/magritte-ui-tree-selector 5.5.80 → 5.5.81
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/Action.d.ts +1 -1
- package/Action.js +15 -12
- package/Action.js.map +1 -1
- package/Item.d.ts +3 -3
- package/Item.js +106 -54
- package/Item.js.map +1 -1
- package/ItemContent.d.ts +2 -2
- package/ItemContent.js +69 -15
- package/ItemContent.js.map +1 -1
- package/ItemsList.d.ts +3 -3
- package/ItemsList.js +243 -159
- package/ItemsList.js.map +1 -1
- package/MobileDelimiter.js +1 -1
- package/MobileDelimiter.js.map +1 -1
- package/MobileItem.d.ts +2 -2
- package/MobileItem.js +26 -5
- package/MobileItem.js.map +1 -1
- package/MobileItemsList.d.ts +2 -2
- package/MobileItemsList.js +259 -132
- package/MobileItemsList.js.map +1 -1
- package/MobileParentItem.d.ts +3 -3
- package/MobileParentItem.js +33 -14
- package/MobileParentItem.js.map +1 -1
- package/TreeSelector.d.ts +2 -2
- package/TreeSelector.js +49 -20
- package/TreeSelector.js.map +1 -1
- package/TreeSelectorDummy.d.ts +2 -2
- package/TreeSelectorDummy.js +178 -109
- package/TreeSelectorDummy.js.map +1 -1
- package/TreeSelectorItemBase.d.ts +2 -2
- package/TreeSelectorItemBase.js +12 -6
- package/TreeSelectorItemBase.js.map +1 -1
- package/TreeSelectorWrapper.js +38 -24
- package/TreeSelectorWrapper.js.map +1 -1
- package/collection/treeCollection.d.ts +1 -1
- package/collection/treeCollection.js +178 -184
- package/collection/treeCollection.js.map +1 -1
- package/collection/treeCollectionHelper.d.ts +9 -3
- package/collection/treeCollectionHelper.js +68 -105
- package/collection/treeCollectionHelper.js.map +1 -1
- package/collection/types.d.ts +1 -1
- package/index.css +45 -45
- package/index.d.ts +9 -9
- package/index.js +1 -1
- package/index.mock.d.ts +6 -6
- package/index.mock.js +14 -6
- package/index.mock.js.map +1 -1
- package/package.json +13 -13
- package/strategy/createSingleValueToggler.d.ts +1 -1
- package/strategy/createSingleValueToggler.js +17 -41
- package/strategy/createSingleValueToggler.js.map +1 -1
- package/strategy/createTreeCollectionToggler.d.ts +3 -3
- package/strategy/createTreeCollectionToggler.js +42 -58
- package/strategy/createTreeCollectionToggler.js.map +1 -1
- package/strategy/dummyToggle.d.ts +1 -1
- package/strategy/dummyToggle.js +10 -13
- package/strategy/dummyToggle.js.map +1 -1
- package/strategy/immutableSelectionStrategy.d.ts +3 -3
- package/strategy/immutableSelectionStrategy.js +27 -26
- package/strategy/immutableSelectionStrategy.js.map +1 -1
- package/strategy/selectionStrategy.d.ts +3 -3
- package/strategy/selectionStrategy.js +47 -56
- package/strategy/selectionStrategy.js.map +1 -1
- package/strategy/types.d.ts +1 -1
- package/tree-selector-item-DiHx85es.js +5 -0
- package/tree-selector-item-DiHx85es.js.map +1 -0
- package/types.d.ts +2 -2
- package/useAnimationTimeout.js +14 -14
- package/useAnimationTimeout.js.map +1 -1
- package/useDisabled.d.ts +2 -2
- package/useDisabled.js +7 -10
- package/useDisabled.js.map +1 -1
- package/useExpanded.d.ts +2 -2
- package/useExpanded.js +65 -54
- package/useExpanded.js.map +1 -1
- package/useIndeterminate.d.ts +2 -2
- package/useIndeterminate.js +17 -18
- package/useIndeterminate.js.map +1 -1
- package/useRenderInput.d.ts +1 -1
- package/useRenderInput.js +44 -32
- package/useRenderInput.js.map +1 -1
- package/useSelected.d.ts +3 -3
- package/useSelected.js +36 -31
- package/useSelected.js.map +1 -1
- package/tree-selector-item-BOEDcwrO.js +0 -5
- package/tree-selector-item-BOEDcwrO.js.map +0 -1
package/Action.d.ts
CHANGED
package/Action.js
CHANGED
|
@@ -4,19 +4,22 @@ import { memo, useCallback } from 'react';
|
|
|
4
4
|
import { Radio, Checkbox } from '@hh.ru/magritte-ui-checkbox-radio';
|
|
5
5
|
|
|
6
6
|
const Action = memo(({ id, name, singleChoice, indeterminate, selected, onChange }) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
const handleChange = useCallback(
|
|
8
|
+
(event) => {
|
|
9
|
+
onChange(id, event.target.checked);
|
|
10
|
+
},
|
|
11
|
+
[id, onChange]
|
|
12
|
+
);
|
|
13
|
+
const inputProps = {
|
|
14
|
+
checked: selected,
|
|
15
|
+
onChange: handleChange,
|
|
16
|
+
name,
|
|
17
|
+
tabIndex: -1,
|
|
18
|
+
"data-qa": `tree-selector-input tree-selector-input-${id}`
|
|
19
|
+
};
|
|
20
|
+
return singleChoice ? /* @__PURE__ */ jsx(Radio, { ...inputProps }) : /* @__PURE__ */ jsx(Checkbox, { ...inputProps, indeterminate });
|
|
18
21
|
});
|
|
19
|
-
Action.displayName =
|
|
22
|
+
Action.displayName = "TreeSelectorAction";
|
|
20
23
|
|
|
21
24
|
export { Action };
|
|
22
25
|
//# sourceMappingURL=Action.js.map
|
package/Action.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Action.js","sources":["src/Action.tsx"],"sourcesContent":["import { ChangeEventHandler, FC, useCallback, memo } from 'react';\n\nimport { Checkbox, Radio } from '@hh.ru/magritte-ui-checkbox-radio';\nimport { TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\n\ninterface ActionProps {\n singleChoice?: boolean;\n onChange: (id: string, isSelected: boolean) => void;\n id: TreeModel['id'];\n name?: string;\n selected: boolean;\n indeterminate?: boolean;\n}\n\nexport const Action: FC<ActionProps> = memo(({ id, name, singleChoice, indeterminate, selected, onChange }) => {\n const handleChange: ChangeEventHandler<HTMLInputElement> = useCallback(\n (event) => {\n onChange(id, event.target.checked);\n },\n [id, onChange]\n );\n\n const inputProps = {\n checked: selected,\n onChange: handleChange,\n name,\n tabIndex: -1,\n 'data-qa': `tree-selector-input tree-selector-input-${id}`,\n };\n\n return singleChoice ? <Radio {...inputProps} /> : <Checkbox {...inputProps} indeterminate={indeterminate} />;\n});\n\nAction.displayName = 'TreeSelectorAction';\n"],"names":[
|
|
1
|
+
{"version":3,"file":"Action.js","sources":["src/Action.tsx"],"sourcesContent":["import { ChangeEventHandler, FC, useCallback, memo } from 'react';\n\nimport { Checkbox, Radio } from '@hh.ru/magritte-ui-checkbox-radio';\nimport { TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\n\ninterface ActionProps {\n singleChoice?: boolean;\n onChange: (id: string, isSelected: boolean) => void;\n id: TreeModel['id'];\n name?: string;\n selected: boolean;\n indeterminate?: boolean;\n}\n\nexport const Action: FC<ActionProps> = memo(({ id, name, singleChoice, indeterminate, selected, onChange }) => {\n const handleChange: ChangeEventHandler<HTMLInputElement> = useCallback(\n (event) => {\n onChange(id, event.target.checked);\n },\n [id, onChange]\n );\n\n const inputProps = {\n checked: selected,\n onChange: handleChange,\n name,\n tabIndex: -1,\n 'data-qa': `tree-selector-input tree-selector-input-${id}`,\n };\n\n return singleChoice ? <Radio {...inputProps} /> : <Checkbox {...inputProps} indeterminate={indeterminate} />;\n});\n\nAction.displayName = 'TreeSelectorAction';\n"],"names":[],"mappings":";;;;AAca,MAAA,MAAA,GAA0B,IAAK,CAAA,CAAC,EAAE,EAAA,EAAI,MAAM,YAAc,EAAA,aAAA,EAAe,QAAU,EAAA,QAAA,EAAe,KAAA;AAC3G,EAAA,MAAM,YAAqD,GAAA,WAAA;AAAA,IACvD,CAAC,KAAU,KAAA;AACP,MAAS,QAAA,CAAA,EAAA,EAAI,KAAM,CAAA,MAAA,CAAO,OAAO,CAAA,CAAA;AAAA,KACrC;AAAA,IACA,CAAC,IAAI,QAAQ,CAAA;AAAA,GACjB,CAAA;AAEA,EAAA,MAAM,UAAa,GAAA;AAAA,IACf,OAAS,EAAA,QAAA;AAAA,IACT,QAAU,EAAA,YAAA;AAAA,IACV,IAAA;AAAA,IACA,QAAU,EAAA,CAAA,CAAA;AAAA,IACV,SAAA,EAAW,2CAA2C,EAAE,CAAA,CAAA;AAAA,GAC5D,CAAA;AAEA,EAAO,OAAA,YAAA,mBAAgB,GAAA,CAAA,KAAA,EAAA,EAAO,GAAG,UAAA,EAAY,oBAAM,GAAA,CAAA,QAAA,EAAA,EAAU,GAAG,UAAA,EAAY,aAA8B,EAAA,CAAA,CAAA;AAC9G,CAAC,EAAA;AAED,MAAA,CAAO,WAAc,GAAA,oBAAA;;;;"}
|
package/Item.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PropsWithChildren, ReactElement, KeyboardEventHandler, AriaAttributes } from 'react';
|
|
2
|
-
import TreeCollection from '
|
|
3
|
-
import { AdditionalDefault, IdCollectionPredicate, TreeModel } from '
|
|
4
|
-
import { RenderItem } from '
|
|
2
|
+
import TreeCollection from './collection/treeCollection';
|
|
3
|
+
import { AdditionalDefault, IdCollectionPredicate, TreeModel } from './collection/types';
|
|
4
|
+
import { RenderItem } from './types';
|
|
5
5
|
interface ItemProps<Additional extends AdditionalDefault> extends PropsWithChildren {
|
|
6
6
|
collection: TreeCollection<Additional>;
|
|
7
7
|
parentId?: TreeModel<Additional>['id'];
|
package/Item.js
CHANGED
|
@@ -9,64 +9,116 @@ import '@hh.ru/magritte-ui-checkbox-radio';
|
|
|
9
9
|
import './TreeSelectorItemBase.js';
|
|
10
10
|
import '@hh.ru/magritte-ui-cell';
|
|
11
11
|
import '@hh.ru/magritte-ui-typography';
|
|
12
|
-
import './tree-selector-item-
|
|
12
|
+
import './tree-selector-item-DiHx85es.js';
|
|
13
13
|
|
|
14
14
|
const ONE_BOX_MARGIN = 36;
|
|
15
15
|
const getMargin = (allBoxesCount, hasShift, hasIndent) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
return margin;
|
|
16
|
+
let margin = 0;
|
|
17
|
+
if (allBoxesCount === 2) {
|
|
18
|
+
margin = ONE_BOX_MARGIN * 2;
|
|
19
|
+
} else if (allBoxesCount === 3) {
|
|
20
|
+
margin = ONE_BOX_MARGIN * 3;
|
|
21
|
+
} else {
|
|
22
|
+
margin = ONE_BOX_MARGIN;
|
|
23
|
+
}
|
|
24
|
+
if (hasIndent) {
|
|
25
|
+
return margin + ONE_BOX_MARGIN;
|
|
26
|
+
}
|
|
27
|
+
if (hasShift) {
|
|
28
|
+
return margin - ONE_BOX_MARGIN;
|
|
29
|
+
}
|
|
30
|
+
return margin;
|
|
33
31
|
};
|
|
34
|
-
const ItemComponent = ({
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
32
|
+
const ItemComponent = ({
|
|
33
|
+
collection,
|
|
34
|
+
item,
|
|
35
|
+
parentId,
|
|
36
|
+
isExpanded,
|
|
37
|
+
isSelected,
|
|
38
|
+
isIndeterminate,
|
|
39
|
+
isDisabled,
|
|
40
|
+
leavesOnly,
|
|
41
|
+
singleChoice,
|
|
42
|
+
isSearch,
|
|
43
|
+
checkSelectable,
|
|
44
|
+
onExpansion,
|
|
45
|
+
onChange,
|
|
46
|
+
renderItemForDesktop,
|
|
47
|
+
cache,
|
|
48
|
+
isTabbed,
|
|
49
|
+
children,
|
|
50
|
+
focusedId,
|
|
51
|
+
...ariaProps
|
|
52
|
+
}) => {
|
|
53
|
+
const modelsOnLevel = useMemo(
|
|
54
|
+
() => parentId ? collection.getChildren(parentId) : collection.getTopLevel(),
|
|
55
|
+
[parentId, collection]
|
|
56
|
+
);
|
|
57
|
+
const hasLetterOnLevel = useMemo(() => {
|
|
58
|
+
return !isSearch && modelsOnLevel.some((model) => model.additional?.char);
|
|
59
|
+
}, [modelsOnLevel, isSearch]);
|
|
60
|
+
const maxControlsOnLevel = useMemo(() => {
|
|
61
|
+
return modelsOnLevel.reduce((currentMax, model) => {
|
|
62
|
+
const hasChildren2 = collection.hasChildren(model.id);
|
|
63
|
+
const hasAction2 = !(leavesOnly && hasChildren2) && checkSelectable?.(model.id, collection);
|
|
64
|
+
const actionCount = +hasChildren2 + +!!hasAction2;
|
|
65
|
+
return Math.max(currentMax, actionCount);
|
|
66
|
+
}, 0);
|
|
67
|
+
}, [modelsOnLevel, checkSelectable, leavesOnly, collection]);
|
|
68
|
+
const hasChildren = collection.hasChildren(item.id);
|
|
69
|
+
const hasAction = !(leavesOnly && hasChildren) && checkSelectable?.(item.id, collection);
|
|
70
|
+
const hasLetter = item.additional?.char && !isSearch;
|
|
71
|
+
const realControlsCount = +hasChildren + +!!hasAction;
|
|
72
|
+
const hasDot = realControlsCount < maxControlsOnLevel && (hasAction || hasChildren);
|
|
73
|
+
const hasParentAction = parentId ? !leavesOnly && checkSelectable?.(parentId, collection) : false;
|
|
74
|
+
const allBoxesCount = +hasLetterOnLevel + maxControlsOnLevel;
|
|
75
|
+
const hasShift = allBoxesCount > 1 && parentId && (hasParentAction && (hasLetterOnLevel || hasChildren || hasDot) || !hasParentAction && hasLetterOnLevel);
|
|
76
|
+
const hasIndent = allBoxesCount === 0;
|
|
77
|
+
useMemo(() => {
|
|
78
|
+
cache[item.id] = getMargin(allBoxesCount, !!hasShift, hasIndent) + (parentId ? cache[parentId] : 0);
|
|
79
|
+
}, [item.id, parentId]);
|
|
80
|
+
let margin = parentId ? cache[parentId] : 0;
|
|
81
|
+
margin = margin + (hasShift ? -ONE_BOX_MARGIN : 0) + (hasIndent ? ONE_BOX_MARGIN : 0);
|
|
82
|
+
return /* @__PURE__ */ jsxs(
|
|
83
|
+
"div",
|
|
84
|
+
{
|
|
85
|
+
style: { paddingLeft: margin },
|
|
86
|
+
"data-qa": classnames("tree-selector-item", `tree-selector-item-${item.id}`, {
|
|
87
|
+
"tree-selector-item-expanded": isExpanded,
|
|
88
|
+
[`tree-selector-child-${parentId}`]: parentId
|
|
89
|
+
}),
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ jsx(
|
|
92
|
+
ItemContent,
|
|
93
|
+
{
|
|
94
|
+
item,
|
|
95
|
+
parentId,
|
|
96
|
+
hasChildren,
|
|
97
|
+
hasAction: !!hasAction,
|
|
98
|
+
letter: hasLetter ? item.additional?.char : void 0,
|
|
99
|
+
isExpanded,
|
|
100
|
+
onExpansion,
|
|
101
|
+
isSelected,
|
|
102
|
+
onChange,
|
|
103
|
+
singleChoice,
|
|
104
|
+
isIndeterminate,
|
|
105
|
+
isDisabled,
|
|
106
|
+
hasLetterOnLevel,
|
|
107
|
+
hasDot,
|
|
108
|
+
maxControlsOnLevel,
|
|
109
|
+
isSearch,
|
|
110
|
+
renderItemForDesktop,
|
|
111
|
+
"aria-expanded": hasChildren ? isExpanded : void 0,
|
|
112
|
+
"aria-selected": hasAction ? isSelected : void 0,
|
|
113
|
+
...ariaProps,
|
|
114
|
+
tabIndex: isTabbed ? 0 : -1,
|
|
115
|
+
focusedId
|
|
116
|
+
}
|
|
117
|
+
),
|
|
118
|
+
children
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
);
|
|
70
122
|
};
|
|
71
123
|
const Item = memo(ItemComponent);
|
|
72
124
|
|
package/Item.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Item.js","sources":["src/Item.tsx"],"sourcesContent":["import { PropsWithChildren, ReactElement, useMemo, memo, KeyboardEventHandler, AriaAttributes } from 'react';\nimport classnames from 'classnames';\n\nimport { ItemContent } from '@hh.ru/magritte-ui-tree-selector/ItemContent';\nimport TreeCollection from '@hh.ru/magritte-ui-tree-selector/collection/treeCollection';\nimport { AdditionalDefault, IdCollectionPredicate, TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\nimport { RenderItem } from '@hh.ru/magritte-ui-tree-selector/types';\n\nconst ONE_BOX_MARGIN = 36;\n\nconst getMargin = (allBoxesCount: number, hasShift: boolean, hasIndent: boolean): number => {\n let margin = 0;\n if (allBoxesCount === 2) {\n margin = ONE_BOX_MARGIN * 2;\n } else if (allBoxesCount === 3) {\n margin = ONE_BOX_MARGIN * 3;\n } else {\n margin = ONE_BOX_MARGIN;\n }\n if (hasIndent) {\n return margin + ONE_BOX_MARGIN;\n }\n\n if (hasShift) {\n return margin - ONE_BOX_MARGIN;\n }\n\n return margin;\n};\n\ninterface ItemProps<Additional extends AdditionalDefault> extends PropsWithChildren {\n collection: TreeCollection<Additional>;\n parentId?: TreeModel<Additional>['id'];\n item: TreeModel<Additional>;\n leavesOnly?: boolean;\n checkSelectable?: IdCollectionPredicate;\n isExpanded: boolean;\n isSelected: boolean;\n isDisabled: boolean;\n singleChoice?: boolean;\n isIndeterminate: boolean;\n isSearch: boolean;\n onExpansion: (id: string) => void;\n onChange: (id: string, isSelected: boolean) => void;\n renderItemForDesktop?: RenderItem<Additional>;\n cache: Record<string, number>;\n isTabbed: boolean;\n focusedId?: string;\n onKeyDown?: KeyboardEventHandler;\n}\n\nconst ItemComponent = <Additional extends AdditionalDefault>({\n collection,\n item,\n parentId,\n isExpanded,\n isSelected,\n isIndeterminate,\n isDisabled,\n leavesOnly,\n singleChoice,\n isSearch,\n checkSelectable,\n onExpansion,\n onChange,\n renderItemForDesktop,\n cache,\n isTabbed,\n children,\n focusedId,\n ...ariaProps\n}: ItemProps<Additional> & AriaAttributes): ReactElement => {\n const modelsOnLevel = useMemo(\n () => (parentId ? collection.getChildren(parentId) : collection.getTopLevel()),\n [parentId, collection]\n );\n\n const hasLetterOnLevel = useMemo(() => {\n return !isSearch && modelsOnLevel.some((model) => model.additional?.char);\n }, [modelsOnLevel, isSearch]);\n\n // максимальное кол-во контролов на уровне, максимум может быть 2 - шеврон + чекбокс/радио\n const maxControlsOnLevel = useMemo(() => {\n return modelsOnLevel.reduce((currentMax, model) => {\n const hasChildren = collection.hasChildren(model.id);\n const hasAction = !(leavesOnly && hasChildren) && checkSelectable?.(model.id, collection);\n const actionCount = +hasChildren + +!!hasAction;\n return Math.max(currentMax, actionCount);\n }, 0);\n }, [modelsOnLevel, checkSelectable, leavesOnly, collection]);\n\n const hasChildren = collection.hasChildren(item.id);\n const hasAction = !(leavesOnly && hasChildren) && checkSelectable?.(item.id, collection);\n const hasLetter = item.additional?.char && !isSearch;\n const realControlsCount = +hasChildren + +!!hasAction;\n\n // точка заменяет недостающий контрол, если их суммарное кол-во на уровне больше суммарного значения на текущем уровне\n const hasDot = realControlsCount < maxControlsOnLevel && (hasAction || hasChildren);\n const hasParentAction = parentId ? !leavesOnly && checkSelectable?.(parentId, collection) : false;\n\n const allBoxesCount = +hasLetterOnLevel + maxControlsOnLevel;\n\n const hasShift =\n allBoxesCount > 1 &&\n parentId &&\n ((hasParentAction && (hasLetterOnLevel || hasChildren || hasDot)) || (!hasParentAction && hasLetterOnLevel));\n\n const hasIndent = allBoxesCount === 0;\n\n useMemo(() => {\n cache[item.id] = getMargin(allBoxesCount, !!hasShift, hasIndent) + (parentId ? cache[parentId] : 0);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [item.id, parentId]);\n\n let margin = parentId ? cache[parentId] : 0;\n\n margin = margin + (hasShift ? -ONE_BOX_MARGIN : 0) + (hasIndent ? ONE_BOX_MARGIN : 0);\n\n return (\n <div\n style={{ paddingLeft: margin }}\n data-qa={classnames('tree-selector-item', `tree-selector-item-${item.id}`, {\n 'tree-selector-item-expanded': isExpanded,\n [`tree-selector-child-${parentId}`]: parentId,\n })}\n >\n <ItemContent\n item={item}\n parentId={parentId}\n hasChildren={hasChildren}\n hasAction={!!hasAction}\n letter={hasLetter ? item.additional?.char : undefined}\n isExpanded={isExpanded}\n onExpansion={onExpansion}\n isSelected={isSelected}\n onChange={onChange}\n singleChoice={singleChoice}\n isIndeterminate={isIndeterminate}\n isDisabled={isDisabled}\n hasLetterOnLevel={hasLetterOnLevel}\n hasDot={hasDot}\n maxControlsOnLevel={maxControlsOnLevel}\n isSearch={isSearch}\n renderItemForDesktop={renderItemForDesktop}\n aria-expanded={hasChildren ? isExpanded : undefined}\n aria-selected={hasAction ? isSelected : undefined}\n {...ariaProps}\n tabIndex={isTabbed ? 0 : -1}\n focusedId={focusedId}\n />\n\n {children}\n </div>\n );\n};\n\nexport const Item = memo(ItemComponent) as <Additional extends AdditionalDefault>(\n props: ItemProps<Additional> & AriaAttributes\n) => ReactElement;\n"],"names":["
|
|
1
|
+
{"version":3,"file":"Item.js","sources":["src/Item.tsx"],"sourcesContent":["import { PropsWithChildren, ReactElement, useMemo, memo, KeyboardEventHandler, AriaAttributes } from 'react';\nimport classnames from 'classnames';\n\nimport { ItemContent } from '@hh.ru/magritte-ui-tree-selector/ItemContent';\nimport TreeCollection from '@hh.ru/magritte-ui-tree-selector/collection/treeCollection';\nimport { AdditionalDefault, IdCollectionPredicate, TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\nimport { RenderItem } from '@hh.ru/magritte-ui-tree-selector/types';\n\nconst ONE_BOX_MARGIN = 36;\n\nconst getMargin = (allBoxesCount: number, hasShift: boolean, hasIndent: boolean): number => {\n let margin = 0;\n if (allBoxesCount === 2) {\n margin = ONE_BOX_MARGIN * 2;\n } else if (allBoxesCount === 3) {\n margin = ONE_BOX_MARGIN * 3;\n } else {\n margin = ONE_BOX_MARGIN;\n }\n if (hasIndent) {\n return margin + ONE_BOX_MARGIN;\n }\n\n if (hasShift) {\n return margin - ONE_BOX_MARGIN;\n }\n\n return margin;\n};\n\ninterface ItemProps<Additional extends AdditionalDefault> extends PropsWithChildren {\n collection: TreeCollection<Additional>;\n parentId?: TreeModel<Additional>['id'];\n item: TreeModel<Additional>;\n leavesOnly?: boolean;\n checkSelectable?: IdCollectionPredicate;\n isExpanded: boolean;\n isSelected: boolean;\n isDisabled: boolean;\n singleChoice?: boolean;\n isIndeterminate: boolean;\n isSearch: boolean;\n onExpansion: (id: string) => void;\n onChange: (id: string, isSelected: boolean) => void;\n renderItemForDesktop?: RenderItem<Additional>;\n cache: Record<string, number>;\n isTabbed: boolean;\n focusedId?: string;\n onKeyDown?: KeyboardEventHandler;\n}\n\nconst ItemComponent = <Additional extends AdditionalDefault>({\n collection,\n item,\n parentId,\n isExpanded,\n isSelected,\n isIndeterminate,\n isDisabled,\n leavesOnly,\n singleChoice,\n isSearch,\n checkSelectable,\n onExpansion,\n onChange,\n renderItemForDesktop,\n cache,\n isTabbed,\n children,\n focusedId,\n ...ariaProps\n}: ItemProps<Additional> & AriaAttributes): ReactElement => {\n const modelsOnLevel = useMemo(\n () => (parentId ? collection.getChildren(parentId) : collection.getTopLevel()),\n [parentId, collection]\n );\n\n const hasLetterOnLevel = useMemo(() => {\n return !isSearch && modelsOnLevel.some((model) => model.additional?.char);\n }, [modelsOnLevel, isSearch]);\n\n // максимальное кол-во контролов на уровне, максимум может быть 2 - шеврон + чекбокс/радио\n const maxControlsOnLevel = useMemo(() => {\n return modelsOnLevel.reduce((currentMax, model) => {\n const hasChildren = collection.hasChildren(model.id);\n const hasAction = !(leavesOnly && hasChildren) && checkSelectable?.(model.id, collection);\n const actionCount = +hasChildren + +!!hasAction;\n return Math.max(currentMax, actionCount);\n }, 0);\n }, [modelsOnLevel, checkSelectable, leavesOnly, collection]);\n\n const hasChildren = collection.hasChildren(item.id);\n const hasAction = !(leavesOnly && hasChildren) && checkSelectable?.(item.id, collection);\n const hasLetter = item.additional?.char && !isSearch;\n const realControlsCount = +hasChildren + +!!hasAction;\n\n // точка заменяет недостающий контрол, если их суммарное кол-во на уровне больше суммарного значения на текущем уровне\n const hasDot = realControlsCount < maxControlsOnLevel && (hasAction || hasChildren);\n const hasParentAction = parentId ? !leavesOnly && checkSelectable?.(parentId, collection) : false;\n\n const allBoxesCount = +hasLetterOnLevel + maxControlsOnLevel;\n\n const hasShift =\n allBoxesCount > 1 &&\n parentId &&\n ((hasParentAction && (hasLetterOnLevel || hasChildren || hasDot)) || (!hasParentAction && hasLetterOnLevel));\n\n const hasIndent = allBoxesCount === 0;\n\n useMemo(() => {\n cache[item.id] = getMargin(allBoxesCount, !!hasShift, hasIndent) + (parentId ? cache[parentId] : 0);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [item.id, parentId]);\n\n let margin = parentId ? cache[parentId] : 0;\n\n margin = margin + (hasShift ? -ONE_BOX_MARGIN : 0) + (hasIndent ? ONE_BOX_MARGIN : 0);\n\n return (\n <div\n style={{ paddingLeft: margin }}\n data-qa={classnames('tree-selector-item', `tree-selector-item-${item.id}`, {\n 'tree-selector-item-expanded': isExpanded,\n [`tree-selector-child-${parentId}`]: parentId,\n })}\n >\n <ItemContent\n item={item}\n parentId={parentId}\n hasChildren={hasChildren}\n hasAction={!!hasAction}\n letter={hasLetter ? item.additional?.char : undefined}\n isExpanded={isExpanded}\n onExpansion={onExpansion}\n isSelected={isSelected}\n onChange={onChange}\n singleChoice={singleChoice}\n isIndeterminate={isIndeterminate}\n isDisabled={isDisabled}\n hasLetterOnLevel={hasLetterOnLevel}\n hasDot={hasDot}\n maxControlsOnLevel={maxControlsOnLevel}\n isSearch={isSearch}\n renderItemForDesktop={renderItemForDesktop}\n aria-expanded={hasChildren ? isExpanded : undefined}\n aria-selected={hasAction ? isSelected : undefined}\n {...ariaProps}\n tabIndex={isTabbed ? 0 : -1}\n focusedId={focusedId}\n />\n\n {children}\n </div>\n );\n};\n\nexport const Item = memo(ItemComponent) as <Additional extends AdditionalDefault>(\n props: ItemProps<Additional> & AriaAttributes\n) => ReactElement;\n"],"names":["hasChildren","hasAction"],"mappings":";;;;;;;;;;;;AAQA,MAAM,cAAiB,GAAA,EAAA,CAAA;AAEvB,MAAM,SAAY,GAAA,CAAC,aAAuB,EAAA,QAAA,EAAmB,SAA+B,KAAA;AACxF,EAAA,IAAI,MAAS,GAAA,CAAA,CAAA;AACb,EAAA,IAAI,kBAAkB,CAAG,EAAA;AACrB,IAAA,MAAA,GAAS,cAAiB,GAAA,CAAA,CAAA;AAAA,GAC9B,MAAA,IAAW,kBAAkB,CAAG,EAAA;AAC5B,IAAA,MAAA,GAAS,cAAiB,GAAA,CAAA,CAAA;AAAA,GACvB,MAAA;AACH,IAAS,MAAA,GAAA,cAAA,CAAA;AAAA,GACb;AACA,EAAA,IAAI,SAAW,EAAA;AACX,IAAA,OAAO,MAAS,GAAA,cAAA,CAAA;AAAA,GACpB;AAEA,EAAA,IAAI,QAAU,EAAA;AACV,IAAA,OAAO,MAAS,GAAA,cAAA,CAAA;AAAA,GACpB;AAEA,EAAO,OAAA,MAAA,CAAA;AACX,CAAA,CAAA;AAuBA,MAAM,gBAAgB,CAAuC;AAAA,EACzD,UAAA;AAAA,EACA,IAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,eAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,eAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA,oBAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAG,SAAA;AACP,CAA4D,KAAA;AACxD,EAAA,MAAM,aAAgB,GAAA,OAAA;AAAA,IAClB,MAAO,QAAW,GAAA,UAAA,CAAW,YAAY,QAAQ,CAAA,GAAI,WAAW,WAAY,EAAA;AAAA,IAC5E,CAAC,UAAU,UAAU,CAAA;AAAA,GACzB,CAAA;AAEA,EAAM,MAAA,gBAAA,GAAmB,QAAQ,MAAM;AACnC,IAAO,OAAA,CAAC,YAAY,aAAc,CAAA,IAAA,CAAK,CAAC,KAAU,KAAA,KAAA,CAAM,YAAY,IAAI,CAAA,CAAA;AAAA,GACzE,EAAA,CAAC,aAAe,EAAA,QAAQ,CAAC,CAAA,CAAA;AAG5B,EAAM,MAAA,kBAAA,GAAqB,QAAQ,MAAM;AACrC,IAAA,OAAO,aAAc,CAAA,MAAA,CAAO,CAAC,UAAA,EAAY,KAAU,KAAA;AAC/C,MAAA,MAAMA,YAAc,GAAA,UAAA,CAAW,WAAY,CAAA,KAAA,CAAM,EAAE,CAAA,CAAA;AACnD,MAAA,MAAMC,aAAY,EAAE,UAAA,IAAcD,iBAAgB,eAAkB,GAAA,KAAA,CAAM,IAAI,UAAU,CAAA,CAAA;AACxF,MAAA,MAAM,WAAc,GAAA,CAACA,YAAc,GAAA,CAAC,CAAC,CAACC,UAAAA,CAAAA;AACtC,MAAO,OAAA,IAAA,CAAK,GAAI,CAAA,UAAA,EAAY,WAAW,CAAA,CAAA;AAAA,OACxC,CAAC,CAAA,CAAA;AAAA,KACL,CAAC,aAAA,EAAe,eAAiB,EAAA,UAAA,EAAY,UAAU,CAAC,CAAA,CAAA;AAE3D,EAAA,MAAM,WAAc,GAAA,UAAA,CAAW,WAAY,CAAA,IAAA,CAAK,EAAE,CAAA,CAAA;AAClD,EAAA,MAAM,YAAY,EAAE,UAAA,IAAc,gBAAgB,eAAkB,GAAA,IAAA,CAAK,IAAI,UAAU,CAAA,CAAA;AACvF,EAAA,MAAM,SAAY,GAAA,IAAA,CAAK,UAAY,EAAA,IAAA,IAAQ,CAAC,QAAA,CAAA;AAC5C,EAAA,MAAM,iBAAoB,GAAA,CAAC,WAAc,GAAA,CAAC,CAAC,CAAC,SAAA,CAAA;AAG5C,EAAM,MAAA,MAAA,GAAS,iBAAoB,GAAA,kBAAA,KAAuB,SAAa,IAAA,WAAA,CAAA,CAAA;AACvE,EAAA,MAAM,kBAAkB,QAAW,GAAA,CAAC,cAAc,eAAkB,GAAA,QAAA,EAAU,UAAU,CAAI,GAAA,KAAA,CAAA;AAE5F,EAAM,MAAA,aAAA,GAAgB,CAAC,gBAAmB,GAAA,kBAAA,CAAA;AAE1C,EAAM,MAAA,QAAA,GACF,gBAAgB,CAChB,IAAA,QAAA,KACE,oBAAoB,gBAAoB,IAAA,WAAA,IAAe,MAAa,CAAA,IAAA,CAAC,eAAmB,IAAA,gBAAA,CAAA,CAAA;AAE9F,EAAA,MAAM,YAAY,aAAkB,KAAA,CAAA,CAAA;AAEpC,EAAA,OAAA,CAAQ,MAAM;AACV,IAAA,KAAA,CAAM,IAAK,CAAA,EAAE,CAAI,GAAA,SAAA,CAAU,aAAe,EAAA,CAAC,CAAC,QAAA,EAAU,SAAS,CAAA,IAAK,QAAW,GAAA,KAAA,CAAM,QAAQ,CAAI,GAAA,CAAA,CAAA,CAAA;AAAA,GAElG,EAAA,CAAC,IAAK,CAAA,EAAA,EAAI,QAAQ,CAAC,CAAA,CAAA;AAEtB,EAAA,IAAI,MAAS,GAAA,QAAA,GAAW,KAAM,CAAA,QAAQ,CAAI,GAAA,CAAA,CAAA;AAE1C,EAAA,MAAA,GAAS,UAAU,QAAW,GAAA,CAAC,cAAiB,GAAA,CAAA,CAAA,IAAM,YAAY,cAAiB,GAAA,CAAA,CAAA,CAAA;AAEnF,EACI,uBAAA,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACG,KAAA,EAAO,EAAE,WAAA,EAAa,MAAO,EAAA;AAAA,MAC7B,WAAS,UAAW,CAAA,oBAAA,EAAsB,CAAsB,mBAAA,EAAA,IAAA,CAAK,EAAE,CAAI,CAAA,EAAA;AAAA,QACvE,6BAA+B,EAAA,UAAA;AAAA,QAC/B,CAAC,CAAA,oBAAA,EAAuB,QAAQ,CAAA,CAAE,GAAG,QAAA;AAAA,OACxC,CAAA;AAAA,MAED,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,WAAA;AAAA,UAAA;AAAA,YACG,IAAA;AAAA,YACA,QAAA;AAAA,YACA,WAAA;AAAA,YACA,SAAA,EAAW,CAAC,CAAC,SAAA;AAAA,YACb,MAAQ,EAAA,SAAA,GAAY,IAAK,CAAA,UAAA,EAAY,IAAO,GAAA,KAAA,CAAA;AAAA,YAC5C,UAAA;AAAA,YACA,WAAA;AAAA,YACA,UAAA;AAAA,YACA,QAAA;AAAA,YACA,YAAA;AAAA,YACA,eAAA;AAAA,YACA,UAAA;AAAA,YACA,gBAAA;AAAA,YACA,MAAA;AAAA,YACA,kBAAA;AAAA,YACA,QAAA;AAAA,YACA,oBAAA;AAAA,YACA,eAAA,EAAe,cAAc,UAAa,GAAA,KAAA,CAAA;AAAA,YAC1C,eAAA,EAAe,YAAY,UAAa,GAAA,KAAA,CAAA;AAAA,YACvC,GAAG,SAAA;AAAA,YACJ,QAAA,EAAU,WAAW,CAAI,GAAA,CAAA,CAAA;AAAA,YACzB,SAAA;AAAA,WAAA;AAAA,SACJ;AAAA,QAEC,QAAA;AAAA,OAAA;AAAA,KAAA;AAAA,GACL,CAAA;AAER,CAAA,CAAA;AAEa,MAAA,IAAA,GAAO,KAAK,aAAa;;;;"}
|
package/ItemContent.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
|
-
import { AdditionalDefault, TreeModel } from '
|
|
3
|
-
import { RenderItem } from '
|
|
2
|
+
import { AdditionalDefault, TreeModel } from './collection/types';
|
|
3
|
+
import { RenderItem } from './types';
|
|
4
4
|
interface ItemContent<Additional extends AdditionalDefault> {
|
|
5
5
|
item: TreeModel<Additional>;
|
|
6
6
|
parentId?: TreeModel<Additional>['id'];
|
package/ItemContent.js
CHANGED
|
@@ -6,24 +6,78 @@ import { DotFilledSize24, ChevronRightOutlinedSize24 } from '@hh.ru/magritte-ui-
|
|
|
6
6
|
import { Action } from './Action.js';
|
|
7
7
|
import { TreeSelectorItemBase } from './TreeSelectorItemBase.js';
|
|
8
8
|
import { Text } from '@hh.ru/magritte-ui-typography';
|
|
9
|
-
import { s as styles } from './tree-selector-item-
|
|
9
|
+
import { s as styles } from './tree-selector-item-DiHx85es.js';
|
|
10
10
|
import '@hh.ru/magritte-ui-checkbox-radio';
|
|
11
11
|
import '@hh.ru/magritte-ui-cell';
|
|
12
12
|
|
|
13
|
-
const ItemContentComponent = ({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
const ItemContentComponent = ({
|
|
14
|
+
item,
|
|
15
|
+
parentId,
|
|
16
|
+
hasAction,
|
|
17
|
+
hasChildren,
|
|
18
|
+
letter,
|
|
19
|
+
isExpanded,
|
|
20
|
+
isDisabled,
|
|
21
|
+
onExpansion,
|
|
22
|
+
hasLetterOnLevel,
|
|
23
|
+
isSelected,
|
|
24
|
+
onChange,
|
|
25
|
+
isIndeterminate,
|
|
26
|
+
singleChoice,
|
|
27
|
+
hasDot,
|
|
28
|
+
maxControlsOnLevel,
|
|
29
|
+
isSearch,
|
|
30
|
+
renderItemForDesktop = TreeSelectorItemBase,
|
|
31
|
+
focusedId,
|
|
32
|
+
...ariaProps
|
|
33
|
+
}) => {
|
|
34
|
+
const handleExpandableClick = useCallback(() => onExpansion && onExpansion(item.id), [item.id, onExpansion]);
|
|
35
|
+
const currentActionCount = +hasDot + +hasAction + +hasChildren;
|
|
36
|
+
const neededSpacesCount = maxControlsOnLevel - currentActionCount;
|
|
37
|
+
const ref = useRef(null);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (focusedId === item.id && ref.current) {
|
|
40
|
+
ref.current.focus();
|
|
41
|
+
}
|
|
42
|
+
}, [focusedId, item.id]);
|
|
43
|
+
const input = hasAction ? /* @__PURE__ */ jsx(
|
|
44
|
+
Action,
|
|
45
|
+
{
|
|
46
|
+
selected: isSelected,
|
|
47
|
+
onChange,
|
|
48
|
+
id: item.id,
|
|
49
|
+
indeterminate: isIndeterminate,
|
|
50
|
+
singleChoice,
|
|
51
|
+
name: `tree-selector-item-${parentId || "top"}-${item.id}`
|
|
52
|
+
}
|
|
53
|
+
) : void 0;
|
|
54
|
+
return /* @__PURE__ */ jsxs(
|
|
55
|
+
"div",
|
|
56
|
+
{
|
|
57
|
+
className: classnames(styles.wrapper, { [styles.wrapperActive]: hasChildren || hasAction }),
|
|
58
|
+
onClick: hasChildren && !hasAction ? handleExpandableClick : void 0,
|
|
59
|
+
role: "treeitem",
|
|
60
|
+
ref,
|
|
61
|
+
...ariaProps,
|
|
62
|
+
children: [
|
|
63
|
+
(letter || hasLetterOnLevel) && /* @__PURE__ */ jsx("div", { className: styles.letter, children: letter && /* @__PURE__ */ jsx(Text, { typography: "subtitle-1-semibold", style: "secondary", Element: "span", children: letter }) }),
|
|
64
|
+
hasDot && /* @__PURE__ */ jsx("div", { className: styles.icon, children: /* @__PURE__ */ jsx(DotFilledSize24, { initialColor: "tertiary" }) }),
|
|
65
|
+
[...Array(neededSpacesCount).keys()].map((_, i) => /* @__PURE__ */ jsx("div", { className: styles.space }, i)),
|
|
66
|
+
hasChildren && /* @__PURE__ */ jsx(
|
|
67
|
+
"div",
|
|
68
|
+
{
|
|
69
|
+
className: classnames(styles.icon, styles.iconActive, {
|
|
70
|
+
[styles.iconUp]: isExpanded
|
|
71
|
+
}),
|
|
72
|
+
"data-qa": `tree-selector-chevron tree-selector-chevron-${item.id}`,
|
|
73
|
+
onClick: hasAction ? handleExpandableClick : void 0,
|
|
74
|
+
children: /* @__PURE__ */ jsx(ChevronRightOutlinedSize24, { initialColor: "tertiary" })
|
|
75
|
+
}
|
|
76
|
+
),
|
|
77
|
+
renderItemForDesktop({ disabled: isDisabled, input, item, isSearch, isParent: hasChildren })
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
);
|
|
27
81
|
};
|
|
28
82
|
const ItemContent = memo(ItemContentComponent);
|
|
29
83
|
|
package/ItemContent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ItemContent.js","sources":["src/ItemContent.tsx"],"sourcesContent":["import { ReactElement, useCallback, memo, useRef, useEffect, AriaAttributes } from 'react';\nimport classnames from 'classnames';\n\nimport { DotFilledSize24, ChevronRightOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { Action } from '@hh.ru/magritte-ui-tree-selector/Action';\nimport { TreeSelectorItemBase } from '@hh.ru/magritte-ui-tree-selector/TreeSelectorItemBase';\nimport { AdditionalDefault, TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\nimport { RenderItem } from '@hh.ru/magritte-ui-tree-selector/types';\nimport { Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from './tree-selector-item.less';\n\ninterface ItemContent<Additional extends AdditionalDefault> {\n item: TreeModel<Additional>;\n parentId?: TreeModel<Additional>['id'];\n hasChildren: boolean;\n hasAction: boolean;\n letter?: string;\n onExpansion: (id: string) => void;\n isExpanded: boolean;\n isSelected: boolean;\n isDisabled: boolean;\n onChange: (id: string, isSelected: boolean) => void;\n isIndeterminate: boolean;\n singleChoice?: boolean;\n hasLetterOnLevel: boolean;\n hasDot: boolean;\n maxControlsOnLevel: number;\n renderItemForDesktop?: RenderItem<Additional>;\n isSearch: boolean;\n tabIndex?: number;\n focusedId?: string;\n}\n\nconst ItemContentComponent = <Additional extends AdditionalDefault>({\n item,\n parentId,\n hasAction,\n hasChildren,\n letter,\n isExpanded,\n isDisabled,\n onExpansion,\n hasLetterOnLevel,\n isSelected,\n onChange,\n isIndeterminate,\n singleChoice,\n hasDot,\n maxControlsOnLevel,\n isSearch,\n renderItemForDesktop = TreeSelectorItemBase,\n focusedId,\n ...ariaProps\n}: ItemContent<Additional> & AriaAttributes): ReactElement => {\n const handleExpandableClick = useCallback(() => onExpansion && onExpansion(item.id), [item.id, onExpansion]);\n const currentActionCount = +hasDot + +hasAction + +hasChildren;\n const neededSpacesCount = maxControlsOnLevel - currentActionCount;\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (focusedId === item.id && ref.current) {\n ref.current.focus();\n }\n }, [focusedId, item.id]);\n\n const input = hasAction ? (\n <Action\n selected={isSelected}\n onChange={onChange}\n id={item.id}\n indeterminate={isIndeterminate}\n singleChoice={singleChoice}\n name={`tree-selector-item-${parentId || 'top'}-${item.id}`}\n />\n ) : undefined;\n\n return (\n <div\n className={classnames(styles.wrapper, { [styles.wrapperActive]: hasChildren || hasAction })}\n onClick={hasChildren && !hasAction ? handleExpandableClick : undefined}\n role=\"treeitem\"\n ref={ref}\n {...ariaProps}\n >\n {(letter || hasLetterOnLevel) && (\n <div className={styles.letter}>\n {letter && (\n <Text typography=\"subtitle-1-semibold\" style=\"secondary\" Element=\"span\">\n {letter}\n </Text>\n )}\n </div>\n )}\n {hasDot && (\n <div className={styles.icon}>\n <DotFilledSize24 initialColor=\"tertiary\" />\n </div>\n )}\n\n {[...Array(neededSpacesCount).keys()].map((_, i) => (\n <div key={i} className={styles.space} />\n ))}\n\n {hasChildren && (\n <div\n className={classnames(styles.icon, styles.iconActive, {\n [styles.iconUp]: isExpanded,\n })}\n data-qa={`tree-selector-chevron tree-selector-chevron-${item.id}`}\n onClick={hasAction ? handleExpandableClick : undefined}\n >\n <ChevronRightOutlinedSize24 initialColor=\"tertiary\" />\n </div>\n )}\n {renderItemForDesktop({ disabled: isDisabled, input, item, isSearch, isParent: hasChildren })}\n </div>\n );\n};\n\nexport const ItemContent = memo(ItemContentComponent) as <Additional extends AdditionalDefault>(\n props: ItemContent<Additional>\n) => ReactElement;\n"],"names":[
|
|
1
|
+
{"version":3,"file":"ItemContent.js","sources":["src/ItemContent.tsx"],"sourcesContent":["import { ReactElement, useCallback, memo, useRef, useEffect, AriaAttributes } from 'react';\nimport classnames from 'classnames';\n\nimport { DotFilledSize24, ChevronRightOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { Action } from '@hh.ru/magritte-ui-tree-selector/Action';\nimport { TreeSelectorItemBase } from '@hh.ru/magritte-ui-tree-selector/TreeSelectorItemBase';\nimport { AdditionalDefault, TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\nimport { RenderItem } from '@hh.ru/magritte-ui-tree-selector/types';\nimport { Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from './tree-selector-item.less';\n\ninterface ItemContent<Additional extends AdditionalDefault> {\n item: TreeModel<Additional>;\n parentId?: TreeModel<Additional>['id'];\n hasChildren: boolean;\n hasAction: boolean;\n letter?: string;\n onExpansion: (id: string) => void;\n isExpanded: boolean;\n isSelected: boolean;\n isDisabled: boolean;\n onChange: (id: string, isSelected: boolean) => void;\n isIndeterminate: boolean;\n singleChoice?: boolean;\n hasLetterOnLevel: boolean;\n hasDot: boolean;\n maxControlsOnLevel: number;\n renderItemForDesktop?: RenderItem<Additional>;\n isSearch: boolean;\n tabIndex?: number;\n focusedId?: string;\n}\n\nconst ItemContentComponent = <Additional extends AdditionalDefault>({\n item,\n parentId,\n hasAction,\n hasChildren,\n letter,\n isExpanded,\n isDisabled,\n onExpansion,\n hasLetterOnLevel,\n isSelected,\n onChange,\n isIndeterminate,\n singleChoice,\n hasDot,\n maxControlsOnLevel,\n isSearch,\n renderItemForDesktop = TreeSelectorItemBase,\n focusedId,\n ...ariaProps\n}: ItemContent<Additional> & AriaAttributes): ReactElement => {\n const handleExpandableClick = useCallback(() => onExpansion && onExpansion(item.id), [item.id, onExpansion]);\n const currentActionCount = +hasDot + +hasAction + +hasChildren;\n const neededSpacesCount = maxControlsOnLevel - currentActionCount;\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (focusedId === item.id && ref.current) {\n ref.current.focus();\n }\n }, [focusedId, item.id]);\n\n const input = hasAction ? (\n <Action\n selected={isSelected}\n onChange={onChange}\n id={item.id}\n indeterminate={isIndeterminate}\n singleChoice={singleChoice}\n name={`tree-selector-item-${parentId || 'top'}-${item.id}`}\n />\n ) : undefined;\n\n return (\n <div\n className={classnames(styles.wrapper, { [styles.wrapperActive]: hasChildren || hasAction })}\n onClick={hasChildren && !hasAction ? handleExpandableClick : undefined}\n role=\"treeitem\"\n ref={ref}\n {...ariaProps}\n >\n {(letter || hasLetterOnLevel) && (\n <div className={styles.letter}>\n {letter && (\n <Text typography=\"subtitle-1-semibold\" style=\"secondary\" Element=\"span\">\n {letter}\n </Text>\n )}\n </div>\n )}\n {hasDot && (\n <div className={styles.icon}>\n <DotFilledSize24 initialColor=\"tertiary\" />\n </div>\n )}\n\n {[...Array(neededSpacesCount).keys()].map((_, i) => (\n <div key={i} className={styles.space} />\n ))}\n\n {hasChildren && (\n <div\n className={classnames(styles.icon, styles.iconActive, {\n [styles.iconUp]: isExpanded,\n })}\n data-qa={`tree-selector-chevron tree-selector-chevron-${item.id}`}\n onClick={hasAction ? handleExpandableClick : undefined}\n >\n <ChevronRightOutlinedSize24 initialColor=\"tertiary\" />\n </div>\n )}\n {renderItemForDesktop({ disabled: isDisabled, input, item, isSearch, isParent: hasChildren })}\n </div>\n );\n};\n\nexport const ItemContent = memo(ItemContentComponent) as <Additional extends AdditionalDefault>(\n props: ItemContent<Additional>\n) => ReactElement;\n"],"names":[],"mappings":"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"}
|
package/ItemsList.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ReactElement, ReactNode } from 'react';
|
|
2
|
-
import TreeCollection from '
|
|
3
|
-
import { AdditionalDefault, IdCollectionPredicate } from '
|
|
4
|
-
import { RenderItem } from '
|
|
2
|
+
import TreeCollection from './collection/treeCollection';
|
|
3
|
+
import { AdditionalDefault, IdCollectionPredicate } from './collection/types';
|
|
4
|
+
import { RenderItem } from './types';
|
|
5
5
|
interface ItemsListProps<Additional extends AdditionalDefault> {
|
|
6
6
|
collection: TreeCollection<Additional>;
|
|
7
7
|
leavesOnly?: boolean;
|