@snack-uikit/button-combo 0.0.1-preview-a2f98ef7.0 → 0.1.1

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +12 -7
  3. package/dist/cjs/ButtonCombo.d.ts +42 -0
  4. package/dist/cjs/{components/ButtonCombo.js → ButtonCombo.js} +39 -27
  5. package/dist/cjs/constants.d.ts +2 -2
  6. package/dist/cjs/constants.js +4 -5
  7. package/dist/cjs/index.d.ts +1 -1
  8. package/dist/cjs/index.js +1 -1
  9. package/dist/cjs/styles.module.css +91 -0
  10. package/dist/cjs/types.d.ts +1 -12
  11. package/dist/cjs/utils.d.ts +2 -0
  12. package/dist/cjs/{components/utils.js → utils.js} +0 -6
  13. package/dist/esm/ButtonCombo.d.ts +42 -0
  14. package/dist/esm/ButtonCombo.js +40 -0
  15. package/dist/esm/constants.d.ts +2 -2
  16. package/dist/esm/constants.js +4 -5
  17. package/dist/esm/index.d.ts +1 -1
  18. package/dist/esm/index.js +1 -1
  19. package/dist/esm/styles.module.css +91 -0
  20. package/dist/esm/types.d.ts +1 -12
  21. package/dist/esm/utils.d.ts +2 -0
  22. package/dist/esm/{components/utils.js → utils.js} +0 -5
  23. package/package.json +4 -4
  24. package/src/ButtonCombo.tsx +127 -0
  25. package/src/constants.ts +6 -6
  26. package/src/index.ts +1 -1
  27. package/src/styles.module.scss +28 -64
  28. package/src/types.ts +5 -19
  29. package/src/utils.ts +13 -0
  30. package/dist/cjs/components/ButtonCombo.d.ts +0 -11
  31. package/dist/cjs/components/index.d.ts +0 -1
  32. package/dist/cjs/components/index.js +0 -25
  33. package/dist/cjs/components/styles.module.css +0 -221
  34. package/dist/cjs/components/utils.d.ts +0 -3
  35. package/dist/esm/components/ButtonCombo.d.ts +0 -11
  36. package/dist/esm/components/ButtonCombo.js +0 -44
  37. package/dist/esm/components/index.d.ts +0 -1
  38. package/dist/esm/components/index.js +0 -1
  39. package/dist/esm/components/styles.module.css +0 -221
  40. package/dist/esm/components/utils.d.ts +0 -3
  41. package/src/components/ButtonCombo.tsx +0 -105
  42. package/src/components/index.ts +0 -1
  43. package/src/components/styles.module.scss +0 -114
  44. package/src/components/utils.ts +0 -25
package/CHANGELOG.md CHANGED
@@ -1,3 +1,30 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## 0.1.1 (2025-01-23)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **PDS-53:** disappeared loading-icon in option button ([a6ca36c](https://github.com/cloud-ru-tech/snack-uikit/commit/a6ca36c7042cd01809b3cff7252c801412b68ea8))
12
+
13
+
14
+
15
+
16
+
17
+ # 0.1.0 (2025-01-23)
18
+
19
+
20
+ ### Features
21
+
22
+ * **PDS-53:** added ButtonCombo component ([a4ce25c](https://github.com/cloud-ru-tech/snack-uikit/commit/a4ce25c0f79120002445188413355f9b75e13159))
23
+
24
+
25
+
26
+
27
+
1
28
  ## CHANGELOG
2
29
 
3
30
  ### v0.0.0
package/README.md CHANGED
@@ -14,14 +14,19 @@
14
14
  | name | type | default value | description |
15
15
  |------|------|---------------|-------------|
16
16
  | items* | `Item[]` | - | Основные элементы списка |
17
- | fullWidth* | `BaseButtonProps` | - | |
18
- | tabIndex* | `BaseButtonProps` | - | |
19
- | loading* | `BaseButtonProps` | - | |
20
- | disabled* | `BaseButtonProps` | - | |
21
- | className* | `BaseButtonProps` | - | CSS-класс |
22
- | size | `BaseButtonProps` | SIZE.S | |
23
- | type | `BaseButtonProps` | HTML_TYPE.Button | |
17
+ | className | `string` | - | CSS-класс |
18
+ | disabled | `boolean` | - | Флаг неактивности компонента |
19
+ | loading | `boolean` | - | Флаг состояния загрузки |
20
+ | size | enum Size: `"xs"`, `"s"`, `"m"`, `"l"` | s | Размер |
21
+ | tabIndex | `number` | - | HTML-аттрибут tab-index |
22
+ | fullWidth | `boolean` | - | Сделать кнопку во всю ширину |
23
+ | open | `boolean` | - | Управляет состоянием показан/не показан. |
24
+ | onOpenChange | `(isOpen: boolean) => void` | - | Колбек отображения компонента. Срабатывает при изменении состояния open. |
24
25
  | dropdownClassName | `string` | - | CSS-класс Dropdown |
26
+ | optionClassName | `string` | - | CSS-класс Option кнопки |
27
+ | dropdownTriggerClassName | `string` | - | CSS-класс Dropdown trigger кнопки |
28
+ | value | `ItemId` | - | Controlled состояние |
29
+ | onChange | `(value: ItemId) => void` | - | Controlled обработчик измения состояния |
25
30
  | defaultValue | `string` | - | Начальное состояние |
26
31
  | defaultLabel | `string` | - | Начальное состояние лейбла |
27
32
  | ref | `LegacyRef<HTMLDivElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see {@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs} |
@@ -0,0 +1,42 @@
1
+ import { ButtonFilledProps } from '@snack-uikit/button';
2
+ import { DroplistProps, ItemId } from '@snack-uikit/list';
3
+ import { WithSupportProps } from '@snack-uikit/utils';
4
+ import { Item } from './types';
5
+ export type ButtonComboProps = WithSupportProps<Pick<ButtonFilledProps, 'className' | 'disabled' | 'loading' | 'size' | 'tabIndex' | 'fullWidth'> & Pick<DroplistProps, 'open' | 'onOpenChange'> & {
6
+ /** CSS-класс Dropdown */
7
+ dropdownClassName?: string;
8
+ /** CSS-класс Option кнопки */
9
+ optionClassName?: string;
10
+ /** CSS-класс Dropdown trigger кнопки */
11
+ dropdownTriggerClassName?: string;
12
+ /** Controlled состояние */
13
+ value?: ItemId;
14
+ /** Controlled обработчик измения состояния */
15
+ onChange?(value: ItemId): void;
16
+ /** Начальное состояние */
17
+ defaultValue?: string;
18
+ /** Начальное состояние лейбла */
19
+ defaultLabel?: string;
20
+ /** Основные элементы списка */
21
+ items: Item[];
22
+ }>;
23
+ export declare const ButtonCombo: import("react").ForwardRefExoticComponent<{
24
+ 'data-test-id'?: string;
25
+ } & import("react").AriaAttributes & Pick<ButtonFilledProps, "className" | "disabled" | "loading" | "size" | "tabIndex" | "fullWidth"> & Pick<DroplistProps, "open" | "onOpenChange"> & {
26
+ /** CSS-класс Dropdown */
27
+ dropdownClassName?: string;
28
+ /** CSS-класс Option кнопки */
29
+ optionClassName?: string;
30
+ /** CSS-класс Dropdown trigger кнопки */
31
+ dropdownTriggerClassName?: string;
32
+ /** Controlled состояние */
33
+ value?: ItemId;
34
+ /** Controlled обработчик измения состояния */
35
+ onChange?(value: ItemId): void;
36
+ /** Начальное состояние */
37
+ defaultValue?: string;
38
+ /** Начальное состояние лейбла */
39
+ defaultLabel?: string;
40
+ /** Основные элементы списка */
41
+ items: Item[];
42
+ } & import("react").RefAttributes<HTMLDivElement>>;
@@ -20,59 +20,70 @@ exports.ButtonCombo = void 0;
20
20
  const jsx_runtime_1 = require("react/jsx-runtime");
21
21
  const classnames_1 = __importDefault(require("classnames"));
22
22
  const react_1 = require("react");
23
- const button_private_1 = require("@snack-uikit/button-private");
23
+ const button_1 = require("@snack-uikit/button");
24
24
  const icons_1 = require("@snack-uikit/icons");
25
25
  const list_1 = require("@snack-uikit/list");
26
26
  const utils_1 = require("@snack-uikit/utils");
27
- const constants_1 = require("../constants");
27
+ const constants_1 = require("./constants");
28
28
  const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
29
29
  const utils_2 = require("./utils");
30
30
  exports.ButtonCombo = (0, react_1.forwardRef)((_a, ref) => {
31
31
  var _b;
32
32
  var {
33
- size = button_private_1.SIZE.S,
34
- type = button_private_1.HTML_TYPE.Button,
33
+ size = 's',
35
34
  defaultLabel = '',
36
35
  className,
37
36
  dropdownClassName,
37
+ optionClassName,
38
+ dropdownTriggerClassName,
38
39
  defaultValue,
39
40
  items,
40
41
  tabIndex,
41
- fullWidth
42
+ fullWidth,
43
+ disabled,
44
+ loading,
45
+ value: valueProp,
46
+ open: openProp,
47
+ onOpenChange,
48
+ onChange
42
49
  } = _a,
43
- rest = __rest(_a, ["size", "type", "defaultLabel", "className", "dropdownClassName", "defaultValue", "items", "tabIndex", "fullWidth"]);
44
- const [open, setOpen] = (0, react_1.useState)(false);
45
- const [activeOption, setActiveOption] = (0, react_1.useState)({});
50
+ rest = __rest(_a, ["size", "defaultLabel", "className", "dropdownClassName", "optionClassName", "dropdownTriggerClassName", "defaultValue", "items", "tabIndex", "fullWidth", "disabled", "loading", "value", "open", "onOpenChange", "onChange"]);
51
+ const [open, setOpen] = (0, utils_1.useValueControl)({
52
+ value: openProp,
53
+ onChange: onOpenChange
54
+ });
55
+ const [value, setValue] = (0, utils_1.useValueControl)({
56
+ value: valueProp,
57
+ defaultValue,
58
+ onChange
59
+ });
46
60
  const droplistItems = (0, react_1.useMemo)(() => items.map(utils_2.extractDroplistItemProps).map(item => Object.assign(Object.assign({}, item), {
47
61
  id: item === null || item === void 0 ? void 0 : item.id,
48
62
  content: item === null || item === void 0 ? void 0 : item.label
49
63
  })), [items]);
50
- const handleSelectionChange = (0, react_1.useCallback)(value => {
51
- if (value) {
52
- const option = items.find(item => (item === null || item === void 0 ? void 0 : item.id) === value);
53
- option && setActiveOption(option);
64
+ const activeOption = (0, react_1.useMemo)(() => items.find(item => (item === null || item === void 0 ? void 0 : item.id) === value), [items, value]);
65
+ const handleSelectionChange = (0, react_1.useCallback)(selectionValue => {
66
+ if (selectionValue) {
67
+ const option = items.find(item => (item === null || item === void 0 ? void 0 : item.id) === selectionValue);
68
+ option && setValue(selectionValue);
54
69
  }
55
- }, [items]);
56
- (0, utils_1.useLayoutEffect)(() => {
57
- if (defaultValue) {
58
- handleSelectionChange(defaultValue);
59
- }
60
- }, [defaultValue, handleSelectionChange]);
70
+ }, [items, setValue]);
61
71
  return (0, jsx_runtime_1.jsxs)("div", Object.assign({}, (0, utils_1.extractSupportProps)(rest), {
62
72
  ref: ref,
63
73
  className: (0, classnames_1.default)(styles_module_scss_1.default.buttonComboWrapper, className),
64
74
  tabIndex: tabIndex,
65
75
  "data-full-width": fullWidth || undefined,
66
- children: [(0, jsx_runtime_1.jsx)(button_private_1.ButtonPrivate, Object.assign({}, (0, button_private_1.extractCommonButtonProps)(rest), (0, utils_2.extractButtonActionsProps)(activeOption), {
76
+ children: [(0, jsx_runtime_1.jsx)(button_1.ButtonFilled, {
67
77
  "data-type": 'option',
68
78
  size: size,
69
79
  label: (_b = activeOption === null || activeOption === void 0 ? void 0 : activeOption.label) !== null && _b !== void 0 ? _b : defaultLabel,
70
- type: type,
80
+ onClick: activeOption === null || activeOption === void 0 ? void 0 : activeOption.onClick,
81
+ className: optionClassName,
71
82
  fullWidth: fullWidth,
72
- iconClassName: styles_module_scss_1.default.icon,
73
- labelClassName: styles_module_scss_1.default.label,
83
+ disabled: disabled,
84
+ loading: loading,
74
85
  "data-test-id": 'button-combo__option'
75
- })), (0, jsx_runtime_1.jsx)(list_1.Droplist, {
86
+ }), (0, jsx_runtime_1.jsx)(list_1.Droplist, {
76
87
  items: droplistItems,
77
88
  open: open,
78
89
  onOpenChange: setOpen,
@@ -86,14 +97,15 @@ exports.ButtonCombo = (0, react_1.forwardRef)((_a, ref) => {
86
97
  placement: 'bottom-end',
87
98
  closeDroplistOnItemClick: true,
88
99
  "data-test-id": 'button-combo__dropdown',
89
- children: (0, jsx_runtime_1.jsx)(button_private_1.ButtonPrivate, Object.assign({}, (0, button_private_1.extractCommonButtonProps)(rest), {
100
+ children: (0, jsx_runtime_1.jsx)(button_1.ButtonFilled, {
90
101
  "data-type": 'dropdown',
102
+ className: dropdownTriggerClassName,
91
103
  size: size,
92
- iconClassName: styles_module_scss_1.default.icon,
93
- labelClassName: styles_module_scss_1.default.label,
104
+ disabled: disabled,
105
+ loading: loading,
94
106
  icon: open ? (0, jsx_runtime_1.jsx)(icons_1.ChevronUpSVG, {}) : (0, jsx_runtime_1.jsx)(icons_1.ChevronDownSVG, {}),
95
107
  "data-test-id": 'button-combo__dropdown-button'
96
- }))
108
+ })
97
109
  })]
98
110
  }));
99
111
  });
@@ -1,3 +1,3 @@
1
- import { Size } from '@snack-uikit/button-private';
1
+ import { ButtonFilledProps } from '@snack-uikit/button';
2
2
  import { DroplistProps } from '@snack-uikit/list';
3
- export declare const DROPLIST_SIZE_MAP: Record<Size, DroplistProps['size']>;
3
+ export declare const DROPLIST_SIZE_MAP: Record<NonNullable<ButtonFilledProps['size']>, DroplistProps['size']>;
@@ -4,10 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.DROPLIST_SIZE_MAP = void 0;
7
- const button_private_1 = require("@snack-uikit/button-private");
8
7
  exports.DROPLIST_SIZE_MAP = {
9
- [button_private_1.SIZE.Xs]: 's',
10
- [button_private_1.SIZE.S]: 's',
11
- [button_private_1.SIZE.M]: 'm',
12
- [button_private_1.SIZE.L]: 'l'
8
+ xs: 's',
9
+ s: 's',
10
+ m: 'm',
11
+ l: 'l'
13
12
  };
@@ -1 +1 @@
1
- export * from './components';
1
+ export * from './ButtonCombo';
package/dist/cjs/index.js CHANGED
@@ -22,4 +22,4 @@ var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
22
22
  Object.defineProperty(exports, "__esModule", {
23
23
  value: true
24
24
  });
25
- __exportStar(require("./components"), exports);
25
+ __exportStar(require("./ButtonCombo"), exports);
@@ -0,0 +1,91 @@
1
+ .buttonComboWrapper{
2
+ display:inline-flex;
3
+ align-items:center;
4
+ }
5
+ .buttonComboWrapper[data-full-width]{
6
+ flex-grow:1;
7
+ flex-shrink:1;
8
+ width:100%;
9
+ }
10
+ .buttonComboWrapper button:focus-visible + button{
11
+ position:static;
12
+ }
13
+ .buttonComboWrapper button[data-type=option]{
14
+ border-right:var(--border-width-button-combo-divider, 1px) solid var(--sys-neutral-decor-default, #dde0ea);
15
+ }
16
+ .buttonComboWrapper button[data-type=option][data-size=xs]{
17
+ min-width:auto;
18
+ height:var(--size-button-xs, 24px);
19
+ border-top-left-radius:var(--radius-button-xs, 8px);
20
+ border-bottom-left-radius:var(--radius-button-xs, 8px);
21
+ border-top-right-radius:var(--dimension-0m, 0px);
22
+ border-bottom-right-radius:var(--dimension-0m, 0px);
23
+ padding-right:var(--space-button-xs-from-label, 8px);
24
+ padding-left:var(--space-button-xs-from-label, 8px);
25
+ border-right-width:var(--border-width-button-combo-divider, 1px);
26
+ }
27
+ .buttonComboWrapper button[data-type=option][data-size=s]{
28
+ min-width:auto;
29
+ height:var(--size-button-s, 32px);
30
+ border-top-left-radius:var(--radius-button-s, 12px);
31
+ border-bottom-left-radius:var(--radius-button-s, 12px);
32
+ border-top-right-radius:var(--dimension-0m, 0px);
33
+ border-bottom-right-radius:var(--dimension-0m, 0px);
34
+ padding-right:var(--space-button-s-from-label, 16px);
35
+ padding-left:var(--space-button-s-from-label, 16px);
36
+ border-right-width:var(--border-width-button-combo-divider, 1px);
37
+ }
38
+ .buttonComboWrapper button[data-type=option][data-size=m]{
39
+ min-width:auto;
40
+ height:var(--size-button-m, 40px);
41
+ border-top-left-radius:var(--radius-button-m, 14px);
42
+ border-bottom-left-radius:var(--radius-button-m, 14px);
43
+ border-top-right-radius:var(--dimension-0m, 0px);
44
+ border-bottom-right-radius:var(--dimension-0m, 0px);
45
+ padding-right:var(--space-button-m-from-label, 24px);
46
+ padding-left:var(--space-button-m-from-label, 24px);
47
+ border-right-width:var(--border-width-button-combo-divider, 1px);
48
+ }
49
+ .buttonComboWrapper button[data-type=option][data-size=l]{
50
+ min-width:auto;
51
+ height:var(--size-button-l, 48px);
52
+ border-top-left-radius:var(--radius-button-l, 16px);
53
+ border-bottom-left-radius:var(--radius-button-l, 16px);
54
+ border-top-right-radius:var(--dimension-0m, 0px);
55
+ border-bottom-right-radius:var(--dimension-0m, 0px);
56
+ padding-right:var(--space-button-l-from-label, 32px);
57
+ padding-left:var(--space-button-l-from-label, 32px);
58
+ border-right-width:var(--border-width-button-combo-divider, 1px);
59
+ }
60
+ .buttonComboWrapper button[data-type=dropdown][data-size=xs]{
61
+ border-top-left-radius:var(--dimension-0m, 0px);
62
+ border-bottom-left-radius:var(--dimension-0m, 0px);
63
+ border-top-right-radius:var(--radius-button-xs, 8px);
64
+ border-bottom-right-radius:var(--radius-button-xs, 8px);
65
+ width:var(--size-button-xs, 24px);
66
+ height:var(--size-button-xs, 24px);
67
+ }
68
+ .buttonComboWrapper button[data-type=dropdown][data-size=s]{
69
+ border-top-left-radius:var(--dimension-0m, 0px);
70
+ border-bottom-left-radius:var(--dimension-0m, 0px);
71
+ border-top-right-radius:var(--radius-button-s, 12px);
72
+ border-bottom-right-radius:var(--radius-button-s, 12px);
73
+ width:var(--size-button-s, 32px);
74
+ height:var(--size-button-s, 32px);
75
+ }
76
+ .buttonComboWrapper button[data-type=dropdown][data-size=m]{
77
+ border-top-left-radius:var(--dimension-0m, 0px);
78
+ border-bottom-left-radius:var(--dimension-0m, 0px);
79
+ border-top-right-radius:var(--radius-button-m, 14px);
80
+ border-bottom-right-radius:var(--radius-button-m, 14px);
81
+ width:var(--size-button-m, 40px);
82
+ height:var(--size-button-m, 40px);
83
+ }
84
+ .buttonComboWrapper button[data-type=dropdown][data-size=l]{
85
+ border-top-left-radius:var(--dimension-0m, 0px);
86
+ border-bottom-left-radius:var(--dimension-0m, 0px);
87
+ border-top-right-radius:var(--radius-button-l, 16px);
88
+ border-bottom-right-radius:var(--radius-button-l, 16px);
89
+ width:var(--size-button-l, 48px);
90
+ height:var(--size-button-l, 48px);
91
+ }
@@ -1,16 +1,5 @@
1
- import { BaseButtonProps } from '@snack-uikit/button-private';
2
1
  import { BaseItemProps } from '@snack-uikit/list';
3
- export type Item = BaseItemProps & {
2
+ export type Item = Omit<BaseItemProps, 'onClick' | 'onMouseDown' | 'onKeyDown' | 'onFocus' | 'onBlur'> & Required<Pick<BaseItemProps, 'onClick'>> & {
4
3
  /** Название */
5
4
  label?: string;
6
5
  };
7
- export type BaseButtonComboProps = Pick<BaseButtonProps, 'className' | 'disabled' | 'loading' | 'size' | 'type' | 'tabIndex' | 'fullWidth'> & {
8
- /** CSS-класс Dropdown */
9
- dropdownClassName?: string;
10
- /** Начальное состояние */
11
- defaultValue?: string;
12
- /** Начальное состояние лейбла */
13
- defaultLabel?: string;
14
- /** Основные элементы списка */
15
- items: Item[];
16
- };
@@ -0,0 +1,2 @@
1
+ import { Item } from './types';
2
+ export declare function extractDroplistItemProps(props: Item): Omit<Item, 'onClick'>;
@@ -4,14 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.extractDroplistItemProps = extractDroplistItemProps;
7
- exports.extractButtonActionsProps = extractButtonActionsProps;
8
7
  function extractDroplistItemProps(props) {
9
8
  return Object.keys(props).filter(item => !item.startsWith('on')).reduce((nextProps, prop) => Object.assign(Object.assign({}, nextProps), {
10
9
  [prop]: props[prop]
11
10
  }), {});
12
- }
13
- function extractButtonActionsProps(props) {
14
- return Object.keys(props).filter(item => item.startsWith('on')).reduce((nextProps, prop) => Object.assign(Object.assign({}, nextProps), {
15
- [prop]: props[prop]
16
- }), {});
17
11
  }
@@ -0,0 +1,42 @@
1
+ import { ButtonFilledProps } from '@snack-uikit/button';
2
+ import { DroplistProps, ItemId } from '@snack-uikit/list';
3
+ import { WithSupportProps } from '@snack-uikit/utils';
4
+ import { Item } from './types';
5
+ export type ButtonComboProps = WithSupportProps<Pick<ButtonFilledProps, 'className' | 'disabled' | 'loading' | 'size' | 'tabIndex' | 'fullWidth'> & Pick<DroplistProps, 'open' | 'onOpenChange'> & {
6
+ /** CSS-класс Dropdown */
7
+ dropdownClassName?: string;
8
+ /** CSS-класс Option кнопки */
9
+ optionClassName?: string;
10
+ /** CSS-класс Dropdown trigger кнопки */
11
+ dropdownTriggerClassName?: string;
12
+ /** Controlled состояние */
13
+ value?: ItemId;
14
+ /** Controlled обработчик измения состояния */
15
+ onChange?(value: ItemId): void;
16
+ /** Начальное состояние */
17
+ defaultValue?: string;
18
+ /** Начальное состояние лейбла */
19
+ defaultLabel?: string;
20
+ /** Основные элементы списка */
21
+ items: Item[];
22
+ }>;
23
+ export declare const ButtonCombo: import("react").ForwardRefExoticComponent<{
24
+ 'data-test-id'?: string;
25
+ } & import("react").AriaAttributes & Pick<ButtonFilledProps, "className" | "disabled" | "loading" | "size" | "tabIndex" | "fullWidth"> & Pick<DroplistProps, "open" | "onOpenChange"> & {
26
+ /** CSS-класс Dropdown */
27
+ dropdownClassName?: string;
28
+ /** CSS-класс Option кнопки */
29
+ optionClassName?: string;
30
+ /** CSS-класс Dropdown trigger кнопки */
31
+ dropdownTriggerClassName?: string;
32
+ /** Controlled состояние */
33
+ value?: ItemId;
34
+ /** Controlled обработчик измения состояния */
35
+ onChange?(value: ItemId): void;
36
+ /** Начальное состояние */
37
+ defaultValue?: string;
38
+ /** Начальное состояние лейбла */
39
+ defaultLabel?: string;
40
+ /** Основные элементы списка */
41
+ items: Item[];
42
+ } & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,40 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import cn from 'classnames';
14
+ import { forwardRef, useCallback, useMemo } from 'react';
15
+ import { ButtonFilled } from '@snack-uikit/button';
16
+ import { ChevronDownSVG, ChevronUpSVG } from '@snack-uikit/icons';
17
+ import { Droplist } from '@snack-uikit/list';
18
+ import { extractSupportProps, useValueControl } from '@snack-uikit/utils';
19
+ import { DROPLIST_SIZE_MAP } from './constants';
20
+ import styles from './styles.module.css';
21
+ import { extractDroplistItemProps } from './utils';
22
+ export const ButtonCombo = forwardRef((_a, ref) => {
23
+ var _b;
24
+ var { size = 's', defaultLabel = '', className, dropdownClassName, optionClassName, dropdownTriggerClassName, defaultValue, items, tabIndex, fullWidth, disabled, loading, value: valueProp, open: openProp, onOpenChange, onChange } = _a, rest = __rest(_a, ["size", "defaultLabel", "className", "dropdownClassName", "optionClassName", "dropdownTriggerClassName", "defaultValue", "items", "tabIndex", "fullWidth", "disabled", "loading", "value", "open", "onOpenChange", "onChange"]);
25
+ const [open, setOpen] = useValueControl({ value: openProp, onChange: onOpenChange });
26
+ const [value, setValue] = useValueControl({ value: valueProp, defaultValue, onChange });
27
+ const droplistItems = useMemo(() => items.map(extractDroplistItemProps).map(item => (Object.assign(Object.assign({}, item), { id: item === null || item === void 0 ? void 0 : item.id, content: item === null || item === void 0 ? void 0 : item.label }))), [items]);
28
+ const activeOption = useMemo(() => items.find(item => (item === null || item === void 0 ? void 0 : item.id) === value), [items, value]);
29
+ const handleSelectionChange = useCallback((selectionValue) => {
30
+ if (selectionValue) {
31
+ const option = items.find(item => (item === null || item === void 0 ? void 0 : item.id) === selectionValue);
32
+ option && setValue(selectionValue);
33
+ }
34
+ }, [items, setValue]);
35
+ return (_jsxs("div", Object.assign({}, extractSupportProps(rest), { ref: ref, className: cn(styles.buttonComboWrapper, className), tabIndex: tabIndex, "data-full-width": fullWidth || undefined, children: [_jsx(ButtonFilled, { "data-type": 'option', size: size, label: (_b = activeOption === null || activeOption === void 0 ? void 0 : activeOption.label) !== null && _b !== void 0 ? _b : defaultLabel, onClick: activeOption === null || activeOption === void 0 ? void 0 : activeOption.onClick, className: optionClassName, fullWidth: fullWidth, disabled: disabled, loading: loading, "data-test-id": 'button-combo__option' }), _jsx(Droplist, { items: droplistItems, open: open, onOpenChange: setOpen, selection: {
36
+ defaultValue,
37
+ mode: 'single',
38
+ onChange: handleSelectionChange,
39
+ }, className: dropdownClassName, size: DROPLIST_SIZE_MAP[size], placement: 'bottom-end', closeDroplistOnItemClick: true, "data-test-id": 'button-combo__dropdown', children: _jsx(ButtonFilled, { "data-type": 'dropdown', className: dropdownTriggerClassName, size: size, disabled: disabled, loading: loading, icon: open ? _jsx(ChevronUpSVG, {}) : _jsx(ChevronDownSVG, {}), "data-test-id": 'button-combo__dropdown-button' }) })] })));
40
+ });
@@ -1,3 +1,3 @@
1
- import { Size } from '@snack-uikit/button-private';
1
+ import { ButtonFilledProps } from '@snack-uikit/button';
2
2
  import { DroplistProps } from '@snack-uikit/list';
3
- export declare const DROPLIST_SIZE_MAP: Record<Size, DroplistProps['size']>;
3
+ export declare const DROPLIST_SIZE_MAP: Record<NonNullable<ButtonFilledProps['size']>, DroplistProps['size']>;
@@ -1,7 +1,6 @@
1
- import { SIZE } from '@snack-uikit/button-private';
2
1
  export const DROPLIST_SIZE_MAP = {
3
- [SIZE.Xs]: 's',
4
- [SIZE.S]: 's',
5
- [SIZE.M]: 'm',
6
- [SIZE.L]: 'l',
2
+ xs: 's',
3
+ s: 's',
4
+ m: 'm',
5
+ l: 'l',
7
6
  };
@@ -1 +1 @@
1
- export * from './components';
1
+ export * from './ButtonCombo';
package/dist/esm/index.js CHANGED
@@ -1 +1 @@
1
- export * from './components';
1
+ export * from './ButtonCombo';
@@ -0,0 +1,91 @@
1
+ .buttonComboWrapper{
2
+ display:inline-flex;
3
+ align-items:center;
4
+ }
5
+ .buttonComboWrapper[data-full-width]{
6
+ flex-grow:1;
7
+ flex-shrink:1;
8
+ width:100%;
9
+ }
10
+ .buttonComboWrapper button:focus-visible + button{
11
+ position:static;
12
+ }
13
+ .buttonComboWrapper button[data-type=option]{
14
+ border-right:var(--border-width-button-combo-divider, 1px) solid var(--sys-neutral-decor-default, #dde0ea);
15
+ }
16
+ .buttonComboWrapper button[data-type=option][data-size=xs]{
17
+ min-width:auto;
18
+ height:var(--size-button-xs, 24px);
19
+ border-top-left-radius:var(--radius-button-xs, 8px);
20
+ border-bottom-left-radius:var(--radius-button-xs, 8px);
21
+ border-top-right-radius:var(--dimension-0m, 0px);
22
+ border-bottom-right-radius:var(--dimension-0m, 0px);
23
+ padding-right:var(--space-button-xs-from-label, 8px);
24
+ padding-left:var(--space-button-xs-from-label, 8px);
25
+ border-right-width:var(--border-width-button-combo-divider, 1px);
26
+ }
27
+ .buttonComboWrapper button[data-type=option][data-size=s]{
28
+ min-width:auto;
29
+ height:var(--size-button-s, 32px);
30
+ border-top-left-radius:var(--radius-button-s, 12px);
31
+ border-bottom-left-radius:var(--radius-button-s, 12px);
32
+ border-top-right-radius:var(--dimension-0m, 0px);
33
+ border-bottom-right-radius:var(--dimension-0m, 0px);
34
+ padding-right:var(--space-button-s-from-label, 16px);
35
+ padding-left:var(--space-button-s-from-label, 16px);
36
+ border-right-width:var(--border-width-button-combo-divider, 1px);
37
+ }
38
+ .buttonComboWrapper button[data-type=option][data-size=m]{
39
+ min-width:auto;
40
+ height:var(--size-button-m, 40px);
41
+ border-top-left-radius:var(--radius-button-m, 14px);
42
+ border-bottom-left-radius:var(--radius-button-m, 14px);
43
+ border-top-right-radius:var(--dimension-0m, 0px);
44
+ border-bottom-right-radius:var(--dimension-0m, 0px);
45
+ padding-right:var(--space-button-m-from-label, 24px);
46
+ padding-left:var(--space-button-m-from-label, 24px);
47
+ border-right-width:var(--border-width-button-combo-divider, 1px);
48
+ }
49
+ .buttonComboWrapper button[data-type=option][data-size=l]{
50
+ min-width:auto;
51
+ height:var(--size-button-l, 48px);
52
+ border-top-left-radius:var(--radius-button-l, 16px);
53
+ border-bottom-left-radius:var(--radius-button-l, 16px);
54
+ border-top-right-radius:var(--dimension-0m, 0px);
55
+ border-bottom-right-radius:var(--dimension-0m, 0px);
56
+ padding-right:var(--space-button-l-from-label, 32px);
57
+ padding-left:var(--space-button-l-from-label, 32px);
58
+ border-right-width:var(--border-width-button-combo-divider, 1px);
59
+ }
60
+ .buttonComboWrapper button[data-type=dropdown][data-size=xs]{
61
+ border-top-left-radius:var(--dimension-0m, 0px);
62
+ border-bottom-left-radius:var(--dimension-0m, 0px);
63
+ border-top-right-radius:var(--radius-button-xs, 8px);
64
+ border-bottom-right-radius:var(--radius-button-xs, 8px);
65
+ width:var(--size-button-xs, 24px);
66
+ height:var(--size-button-xs, 24px);
67
+ }
68
+ .buttonComboWrapper button[data-type=dropdown][data-size=s]{
69
+ border-top-left-radius:var(--dimension-0m, 0px);
70
+ border-bottom-left-radius:var(--dimension-0m, 0px);
71
+ border-top-right-radius:var(--radius-button-s, 12px);
72
+ border-bottom-right-radius:var(--radius-button-s, 12px);
73
+ width:var(--size-button-s, 32px);
74
+ height:var(--size-button-s, 32px);
75
+ }
76
+ .buttonComboWrapper button[data-type=dropdown][data-size=m]{
77
+ border-top-left-radius:var(--dimension-0m, 0px);
78
+ border-bottom-left-radius:var(--dimension-0m, 0px);
79
+ border-top-right-radius:var(--radius-button-m, 14px);
80
+ border-bottom-right-radius:var(--radius-button-m, 14px);
81
+ width:var(--size-button-m, 40px);
82
+ height:var(--size-button-m, 40px);
83
+ }
84
+ .buttonComboWrapper button[data-type=dropdown][data-size=l]{
85
+ border-top-left-radius:var(--dimension-0m, 0px);
86
+ border-bottom-left-radius:var(--dimension-0m, 0px);
87
+ border-top-right-radius:var(--radius-button-l, 16px);
88
+ border-bottom-right-radius:var(--radius-button-l, 16px);
89
+ width:var(--size-button-l, 48px);
90
+ height:var(--size-button-l, 48px);
91
+ }
@@ -1,16 +1,5 @@
1
- import { BaseButtonProps } from '@snack-uikit/button-private';
2
1
  import { BaseItemProps } from '@snack-uikit/list';
3
- export type Item = BaseItemProps & {
2
+ export type Item = Omit<BaseItemProps, 'onClick' | 'onMouseDown' | 'onKeyDown' | 'onFocus' | 'onBlur'> & Required<Pick<BaseItemProps, 'onClick'>> & {
4
3
  /** Название */
5
4
  label?: string;
6
5
  };
7
- export type BaseButtonComboProps = Pick<BaseButtonProps, 'className' | 'disabled' | 'loading' | 'size' | 'type' | 'tabIndex' | 'fullWidth'> & {
8
- /** CSS-класс Dropdown */
9
- dropdownClassName?: string;
10
- /** Начальное состояние */
11
- defaultValue?: string;
12
- /** Начальное состояние лейбла */
13
- defaultLabel?: string;
14
- /** Основные элементы списка */
15
- items: Item[];
16
- };
@@ -0,0 +1,2 @@
1
+ import { Item } from './types';
2
+ export declare function extractDroplistItemProps(props: Item): Omit<Item, 'onClick'>;
@@ -3,8 +3,3 @@ export function extractDroplistItemProps(props) {
3
3
  .filter(item => !item.startsWith('on'))
4
4
  .reduce((nextProps, prop) => (Object.assign(Object.assign({}, nextProps), { [prop]: props[prop] })), {});
5
5
  }
6
- export function extractButtonActionsProps(props) {
7
- return Object.keys(props)
8
- .filter(item => item.startsWith('on'))
9
- .reduce((nextProps, prop) => (Object.assign(Object.assign({}, nextProps), { [prop]: props[prop] })), {});
10
- }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Button Combo",
7
- "version": "0.0.1-preview-a2f98ef7.0",
7
+ "version": "0.1.1",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -36,11 +36,11 @@
36
36
  "license": "Apache-2.0",
37
37
  "scripts": {},
38
38
  "dependencies": {
39
- "@snack-uikit/button-private": "0.0.1-preview-a2f98ef7.0",
39
+ "@snack-uikit/button": "0.19.5",
40
40
  "@snack-uikit/icons": "0.24.1",
41
- "@snack-uikit/list": "0.22.3-preview-a2f98ef7.0",
41
+ "@snack-uikit/list": "0.23.0",
42
42
  "@snack-uikit/utils": "3.6.0",
43
43
  "classnames": "2.5.1"
44
44
  },
45
- "gitHead": "16999df080b0b870c1a90ba74aa6c296cd4d480b"
45
+ "gitHead": "7e01ebe58fd9bf9a4c06064e6415ed6c16cc06e5"
46
46
  }