@snack-uikit/segmented-control 0.2.4 → 0.2.5-preview-71543426.0
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/dist/cjs/components/SegmentedControl.js +117 -0
- package/dist/cjs/components/index.js +25 -0
- package/dist/cjs/constants.js +15 -0
- package/dist/cjs/helperComponents/Segment/Segment.js +67 -0
- package/dist/cjs/helperComponents/Segment/index.js +25 -0
- package/dist/cjs/helperComponents/index.js +25 -0
- package/dist/cjs/hooks.js +69 -0
- package/dist/cjs/index.js +25 -0
- package/dist/cjs/types.js +5 -0
- package/dist/cjs/utils.js +16 -0
- package/dist/esm/components/SegmentedControl.d.ts +40 -0
- package/dist/esm/components/index.js +1 -0
- package/dist/esm/components/styles.module.css +82 -0
- package/dist/esm/constants.d.ts +9 -0
- package/dist/esm/helperComponents/Segment/Segment.d.ts +11 -0
- package/dist/esm/helperComponents/Segment/styles.module.css +126 -0
- package/dist/esm/helperComponents/index.d.ts +1 -0
- package/dist/esm/helperComponents/index.js +1 -0
- package/dist/esm/hooks.d.ts +12 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/types.d.ts +34 -0
- package/dist/esm/utils.d.ts +2 -0
- package/package.json +9 -7
- /package/dist/{components → cjs/components}/SegmentedControl.d.ts +0 -0
- /package/dist/{components → cjs/components}/index.d.ts +0 -0
- /package/dist/{components → cjs/components}/styles.module.css +0 -0
- /package/dist/{constants.d.ts → cjs/constants.d.ts} +0 -0
- /package/dist/{helperComponents → cjs/helperComponents}/Segment/Segment.d.ts +0 -0
- /package/dist/{helperComponents → cjs/helperComponents}/Segment/index.d.ts +0 -0
- /package/dist/{helperComponents → cjs/helperComponents}/Segment/styles.module.css +0 -0
- /package/dist/{helperComponents → cjs/helperComponents}/index.d.ts +0 -0
- /package/dist/{hooks.d.ts → cjs/hooks.d.ts} +0 -0
- /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
- /package/dist/{types.d.ts → cjs/types.d.ts} +0 -0
- /package/dist/{utils.d.ts → cjs/utils.d.ts} +0 -0
- /package/dist/{components → esm/components}/SegmentedControl.js +0 -0
- /package/dist/{components/index.js → esm/components/index.d.ts} +0 -0
- /package/dist/{constants.js → esm/constants.js} +0 -0
- /package/dist/{helperComponents → esm/helperComponents}/Segment/Segment.js +0 -0
- /package/dist/{helperComponents/Segment/index.js → esm/helperComponents/Segment/index.d.ts} +0 -0
- /package/dist/{helperComponents → esm/helperComponents/Segment}/index.js +0 -0
- /package/dist/{hooks.js → esm/hooks.js} +0 -0
- /package/dist/{index.js → esm/index.d.ts} +0 -0
- /package/dist/{types.js → esm/types.js} +0 -0
- /package/dist/{utils.js → esm/utils.js} +0 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __rest = void 0 && (void 0).__rest || function (s, e) {
|
|
4
|
+
var t = {};
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function") 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])) t[p[i]] = s[p[i]];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
12
|
+
return mod && mod.__esModule ? mod : {
|
|
13
|
+
"default": mod
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", {
|
|
17
|
+
value: true
|
|
18
|
+
});
|
|
19
|
+
exports.SegmentedControl = SegmentedControl;
|
|
20
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
21
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
22
|
+
const react_1 = require("react");
|
|
23
|
+
const uncontrollable_1 = require("uncontrollable");
|
|
24
|
+
const utils_1 = require("@snack-uikit/utils");
|
|
25
|
+
const constants_1 = require("../constants");
|
|
26
|
+
const helperComponents_1 = require("../helperComponents");
|
|
27
|
+
const hooks_1 = require("../hooks");
|
|
28
|
+
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
29
|
+
/**
|
|
30
|
+
* SegmentedControl
|
|
31
|
+
*/
|
|
32
|
+
function SegmentedControl(_a) {
|
|
33
|
+
var {
|
|
34
|
+
defaultValue,
|
|
35
|
+
size = 'm',
|
|
36
|
+
className,
|
|
37
|
+
onChange,
|
|
38
|
+
items,
|
|
39
|
+
value,
|
|
40
|
+
outline,
|
|
41
|
+
width = constants_1.WIDTH.Auto
|
|
42
|
+
} = _a,
|
|
43
|
+
other = __rest(_a, ["defaultValue", "size", "className", "onChange", "items", "value", "outline", "width"]);
|
|
44
|
+
const [selected, setSelected] = (0, uncontrollable_1.useUncontrolledProp)(value, defaultValue, onChange);
|
|
45
|
+
const {
|
|
46
|
+
focusableSegmentValue,
|
|
47
|
+
onGetFocusable,
|
|
48
|
+
onKeyDown
|
|
49
|
+
} = (0, hooks_1.useFocusControl)({
|
|
50
|
+
selected,
|
|
51
|
+
items
|
|
52
|
+
});
|
|
53
|
+
const containerRef = (0, react_1.useRef)(null);
|
|
54
|
+
const selectedElementRef = (0, react_1.useRef)();
|
|
55
|
+
const [selectionPosition, setSelectionPosition] = (0, react_1.useState)();
|
|
56
|
+
const updateSelectionPosition = (0, react_1.useCallback)(function () {
|
|
57
|
+
let element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : selectedElementRef.current;
|
|
58
|
+
if (!element) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
selectedElementRef.current = element;
|
|
62
|
+
setTimeout(() => {
|
|
63
|
+
setSelectionPosition({
|
|
64
|
+
top: element.offsetTop,
|
|
65
|
+
left: element.offsetLeft,
|
|
66
|
+
width: element.offsetWidth,
|
|
67
|
+
height: element.offsetHeight
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}, []);
|
|
71
|
+
(0, react_1.useEffect)(() => {
|
|
72
|
+
if (!containerRef.current) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const observer = new ResizeObserver(() => updateSelectionPosition());
|
|
76
|
+
observer.observe(containerRef.current);
|
|
77
|
+
const ob = new MutationObserver(() => updateSelectionPosition());
|
|
78
|
+
ob.observe(containerRef.current, {
|
|
79
|
+
childList: true
|
|
80
|
+
});
|
|
81
|
+
return () => {
|
|
82
|
+
observer.disconnect();
|
|
83
|
+
ob.disconnect();
|
|
84
|
+
};
|
|
85
|
+
}, [updateSelectionPosition]);
|
|
86
|
+
const itemsJSX = (0, react_1.useMemo)(() => items.map(props => (0, jsx_runtime_1.jsx)("div", {
|
|
87
|
+
className: styles_module_scss_1.default.segmentHolder,
|
|
88
|
+
"data-width": width,
|
|
89
|
+
children: (0, jsx_runtime_1.jsx)(helperComponents_1.Segment, Object.assign({}, props, {
|
|
90
|
+
size: size,
|
|
91
|
+
onGetFocusable: onGetFocusable,
|
|
92
|
+
selected: selected === props.value,
|
|
93
|
+
onClick: () => setSelected(props.value),
|
|
94
|
+
focusable: focusableSegmentValue === props.value,
|
|
95
|
+
onSelectionUpdated: updateSelectionPosition
|
|
96
|
+
}))
|
|
97
|
+
}, props.value)), [items, width, size, onGetFocusable, selected, focusableSegmentValue, updateSelectionPosition, setSelected]);
|
|
98
|
+
return (
|
|
99
|
+
// eslint-disable-next-line jsx-a11y/interactive-supports-focus
|
|
100
|
+
(0, jsx_runtime_1.jsxs)("div", Object.assign({
|
|
101
|
+
ref: containerRef,
|
|
102
|
+
"data-size": size,
|
|
103
|
+
onKeyDown: onKeyDown,
|
|
104
|
+
className: (0, classnames_1.default)(styles_module_scss_1.default.container, className),
|
|
105
|
+
role: 'radiogroup',
|
|
106
|
+
"data-outline": outline || undefined,
|
|
107
|
+
"data-width": width
|
|
108
|
+
}, (0, utils_1.extractDataTestProps)(other), (0, utils_1.extractSupportProps)(other), {
|
|
109
|
+
children: [(0, jsx_runtime_1.jsx)("div", {
|
|
110
|
+
"data-size": size,
|
|
111
|
+
style: selectionPosition,
|
|
112
|
+
className: styles_module_scss_1.default.selection,
|
|
113
|
+
"aria-hidden": true
|
|
114
|
+
}), itemsJSX]
|
|
115
|
+
}))
|
|
116
|
+
);
|
|
117
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () {
|
|
10
|
+
return m[k];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
} : function (o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
});
|
|
19
|
+
var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", {
|
|
23
|
+
value: true
|
|
24
|
+
});
|
|
25
|
+
__exportStar(require("./SegmentedControl"), exports);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
4
|
+
return mod && mod.__esModule ? mod : {
|
|
5
|
+
"default": mod
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", {
|
|
9
|
+
value: true
|
|
10
|
+
});
|
|
11
|
+
exports.Segment = Segment;
|
|
12
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
13
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
14
|
+
const react_1 = require("react");
|
|
15
|
+
const truncate_string_1 = require("@snack-uikit/truncate-string");
|
|
16
|
+
const utils_1 = require("../../utils");
|
|
17
|
+
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
18
|
+
function Segment(_ref) {
|
|
19
|
+
let {
|
|
20
|
+
size,
|
|
21
|
+
label,
|
|
22
|
+
value,
|
|
23
|
+
selected,
|
|
24
|
+
onClick,
|
|
25
|
+
disabled,
|
|
26
|
+
icon,
|
|
27
|
+
focusable,
|
|
28
|
+
onGetFocusable,
|
|
29
|
+
onSelectionUpdated,
|
|
30
|
+
renderWrapSegment
|
|
31
|
+
} = _ref;
|
|
32
|
+
const buttonRef = (0, react_1.useRef)(null);
|
|
33
|
+
(0, react_1.useEffect)(() => {
|
|
34
|
+
if (focusable) {
|
|
35
|
+
onGetFocusable === null || onGetFocusable === void 0 ? void 0 : onGetFocusable(buttonRef.current);
|
|
36
|
+
}
|
|
37
|
+
}, [focusable, onGetFocusable]);
|
|
38
|
+
(0, react_1.useEffect)(() => {
|
|
39
|
+
if (selected && buttonRef.current) {
|
|
40
|
+
onSelectionUpdated(buttonRef.current);
|
|
41
|
+
}
|
|
42
|
+
}, [selected, buttonRef, onSelectionUpdated]);
|
|
43
|
+
const segment = (0, jsx_runtime_1.jsxs)("button", {
|
|
44
|
+
ref: buttonRef,
|
|
45
|
+
"data-test-id": `section-${value}`,
|
|
46
|
+
"data-active": selected || undefined,
|
|
47
|
+
"data-disabled": disabled || undefined,
|
|
48
|
+
"data-layout": (0, utils_1.getLayout)(icon, label),
|
|
49
|
+
className: (0, classnames_1.default)(styles_module_scss_1.default.segment),
|
|
50
|
+
onClick: onClick,
|
|
51
|
+
"data-size": size,
|
|
52
|
+
disabled: disabled,
|
|
53
|
+
tabIndex: focusable ? 0 : -1,
|
|
54
|
+
"aria-checked": selected,
|
|
55
|
+
role: 'radio',
|
|
56
|
+
type: 'button',
|
|
57
|
+
children: [icon && (0, jsx_runtime_1.jsx)("div", {
|
|
58
|
+
className: styles_module_scss_1.default.icon,
|
|
59
|
+
children: icon
|
|
60
|
+
}), label && (0, jsx_runtime_1.jsx)(truncate_string_1.TruncateString, {
|
|
61
|
+
className: styles_module_scss_1.default.label,
|
|
62
|
+
"data-size": size,
|
|
63
|
+
text: label
|
|
64
|
+
})]
|
|
65
|
+
});
|
|
66
|
+
return renderWrapSegment ? renderWrapSegment(segment) : segment;
|
|
67
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () {
|
|
10
|
+
return m[k];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
} : function (o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
});
|
|
19
|
+
var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", {
|
|
23
|
+
value: true
|
|
24
|
+
});
|
|
25
|
+
__exportStar(require("./Segment"), exports);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () {
|
|
10
|
+
return m[k];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
} : function (o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
});
|
|
19
|
+
var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", {
|
|
23
|
+
value: true
|
|
24
|
+
});
|
|
25
|
+
__exportStar(require("./Segment"), exports);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useFocusControl = useFocusControl;
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
function useFocusControl(_ref) {
|
|
9
|
+
let {
|
|
10
|
+
selected,
|
|
11
|
+
items
|
|
12
|
+
} = _ref;
|
|
13
|
+
const [focusableSegmentValue, setFocusableSegmentValue] = (0, react_1.useState)(selected);
|
|
14
|
+
const [_, setNeedSetFocus] = (0, react_1.useState)(false);
|
|
15
|
+
const {
|
|
16
|
+
prev,
|
|
17
|
+
next
|
|
18
|
+
} = (0, react_1.useMemo)(() => items.reduce((res, item) => {
|
|
19
|
+
if (res._isNextSearching && !res.next) {
|
|
20
|
+
res.next = item.disabled ? res.next : item.value;
|
|
21
|
+
}
|
|
22
|
+
if (focusableSegmentValue === item.value) {
|
|
23
|
+
res._isNextSearching = true;
|
|
24
|
+
}
|
|
25
|
+
if (!res._isNextSearching) {
|
|
26
|
+
res.prev = item.disabled ? res.prev : item.value;
|
|
27
|
+
}
|
|
28
|
+
return res;
|
|
29
|
+
}, {
|
|
30
|
+
_isNextSearching: false
|
|
31
|
+
}), [focusableSegmentValue, items]);
|
|
32
|
+
const onKeyDown = (0, react_1.useCallback)(e => {
|
|
33
|
+
switch (e.key) {
|
|
34
|
+
case 'ArrowLeft':
|
|
35
|
+
{
|
|
36
|
+
if (prev) {
|
|
37
|
+
setNeedSetFocus(true);
|
|
38
|
+
setFocusableSegmentValue(prev);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
case 'ArrowRight':
|
|
43
|
+
{
|
|
44
|
+
if (next) {
|
|
45
|
+
setNeedSetFocus(true);
|
|
46
|
+
setFocusableSegmentValue(next);
|
|
47
|
+
}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
default:
|
|
51
|
+
{
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}, [next, prev]);
|
|
56
|
+
const onGetFocusable = (0, react_1.useCallback)(ref => {
|
|
57
|
+
setNeedSetFocus(needSetFocus => {
|
|
58
|
+
if (needSetFocus) {
|
|
59
|
+
ref === null || ref === void 0 ? void 0 : ref.focus();
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
});
|
|
63
|
+
}, []);
|
|
64
|
+
return {
|
|
65
|
+
onKeyDown,
|
|
66
|
+
focusableSegmentValue,
|
|
67
|
+
onGetFocusable
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () {
|
|
10
|
+
return m[k];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
} : function (o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
});
|
|
19
|
+
var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", {
|
|
23
|
+
value: true
|
|
24
|
+
});
|
|
25
|
+
__exportStar(require("./components"), exports);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getLayout = void 0;
|
|
7
|
+
const getLayout = (icon, label) => {
|
|
8
|
+
if (icon && label) {
|
|
9
|
+
return 'icon-before';
|
|
10
|
+
}
|
|
11
|
+
if (label) {
|
|
12
|
+
return 'label-only';
|
|
13
|
+
}
|
|
14
|
+
return 'icon-only';
|
|
15
|
+
};
|
|
16
|
+
exports.getLayout = getLayout;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { WithSupportProps } from '@snack-uikit/utils';
|
|
2
|
+
import { IdType, Segment as SegmentType, Size, Width } from '../types';
|
|
3
|
+
export type SegmentedControlProps<Value extends IdType = IdType> = WithSupportProps<{
|
|
4
|
+
/**
|
|
5
|
+
* Набор сегментов.
|
|
6
|
+
*/
|
|
7
|
+
items: SegmentType<Value>[];
|
|
8
|
+
/**
|
|
9
|
+
* Value выбранного сегмента.
|
|
10
|
+
*/
|
|
11
|
+
value?: Value;
|
|
12
|
+
/**
|
|
13
|
+
* ID выбранного по умолчанию сегмента. (в uncontrolled режиме)
|
|
14
|
+
*/
|
|
15
|
+
defaultValue?: Value;
|
|
16
|
+
/**
|
|
17
|
+
* Колбек смены выбранного сегмента.
|
|
18
|
+
*/
|
|
19
|
+
onChange?: (value: Value) => void;
|
|
20
|
+
/**
|
|
21
|
+
* CSS-класс контейнера.
|
|
22
|
+
*/
|
|
23
|
+
className?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Размер компонента.
|
|
26
|
+
*/
|
|
27
|
+
size?: Size;
|
|
28
|
+
/**
|
|
29
|
+
* Обводка
|
|
30
|
+
*/
|
|
31
|
+
outline?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Управление шириной компонента.
|
|
34
|
+
*/
|
|
35
|
+
width?: Width;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* SegmentedControl
|
|
39
|
+
*/
|
|
40
|
+
export declare function SegmentedControl<Value extends IdType>({ defaultValue, size, className, onChange, items, value, outline, width, ...other }: SegmentedControlProps<Value>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './SegmentedControl';
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
.container{
|
|
2
|
+
padding-top:var(--space-segmented-control-container-padding, 2px);
|
|
3
|
+
padding-bottom:var(--space-segmented-control-container-padding, 2px);
|
|
4
|
+
padding-left:var(--space-segmented-control-container-padding, 2px);
|
|
5
|
+
padding-right:var(--space-segmented-control-container-padding, 2px);
|
|
6
|
+
position:relative;
|
|
7
|
+
overflow:hidden;
|
|
8
|
+
display:inline-flex;
|
|
9
|
+
flex-direction:row;
|
|
10
|
+
justify-content:stretch;
|
|
11
|
+
max-width:100%;
|
|
12
|
+
}
|
|
13
|
+
.container::before{
|
|
14
|
+
content:" ";
|
|
15
|
+
position:absolute;
|
|
16
|
+
top:0;
|
|
17
|
+
left:0;
|
|
18
|
+
box-sizing:border-box;
|
|
19
|
+
width:100%;
|
|
20
|
+
height:100%;
|
|
21
|
+
background-color:var(--sys-neutral-background, #eeeff3);
|
|
22
|
+
border-color:var(--sys-neutral-background, #eeeff3);
|
|
23
|
+
border-style:solid;
|
|
24
|
+
}
|
|
25
|
+
.container[data-outline]::before{
|
|
26
|
+
border-color:var(--sys-neutral-decor-default, #dde0ea);
|
|
27
|
+
}
|
|
28
|
+
.container[data-width=full]{
|
|
29
|
+
display:flex;
|
|
30
|
+
}
|
|
31
|
+
.container[data-size=s]::before{
|
|
32
|
+
border-width:var(--border-width-segmented-control-single, 1px);
|
|
33
|
+
border-radius:var(--radius-segmented-control-container-s, 12px);
|
|
34
|
+
}
|
|
35
|
+
.container[data-size=m]::before{
|
|
36
|
+
border-width:var(--border-width-segmented-control-single, 1px);
|
|
37
|
+
border-radius:var(--radius-segmented-control-container-m, 14px);
|
|
38
|
+
}
|
|
39
|
+
.container[data-size=l]::before{
|
|
40
|
+
border-width:var(--border-width-segmented-control-single, 1px);
|
|
41
|
+
border-radius:var(--radius-segmented-control-container-l, 16px);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.segmentHolder{
|
|
45
|
+
overflow:hidden;
|
|
46
|
+
flex-grow:1;
|
|
47
|
+
flex-shrink:1;
|
|
48
|
+
justify-content:center;
|
|
49
|
+
min-width:0px;
|
|
50
|
+
}
|
|
51
|
+
.segmentHolder[data-outline]{
|
|
52
|
+
flex-basis:0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.selection{
|
|
56
|
+
position:absolute;
|
|
57
|
+
overflow:hidden;
|
|
58
|
+
box-sizing:border-box;
|
|
59
|
+
background-color:var(--sys-neutral-background2-level, #ffffff);
|
|
60
|
+
transition:left 0.15s ease-in-out, width 0.15s ease-in-out;
|
|
61
|
+
}
|
|
62
|
+
.selection[data-size=s]{
|
|
63
|
+
border-radius:var(--radius-segmented-control-segment-s, 10px);
|
|
64
|
+
padding-left:var(--space-segmented-control-segment-s-icon-only, 2px);
|
|
65
|
+
padding-right:var(--space-segmented-control-segment-s-icon-only, 2px);
|
|
66
|
+
gap:var(--space-segmented-control-segment-s-gap, 4px);
|
|
67
|
+
height:var(--size-segmented-control-segment-s, 28px);
|
|
68
|
+
}
|
|
69
|
+
.selection[data-size=m]{
|
|
70
|
+
border-radius:var(--radius-segmented-control-segment-m, 12px);
|
|
71
|
+
padding-left:var(--space-segmented-control-segment-m-icon-only, 6px);
|
|
72
|
+
padding-right:var(--space-segmented-control-segment-m-icon-only, 6px);
|
|
73
|
+
gap:var(--space-segmented-control-segment-m-gap, 4px);
|
|
74
|
+
height:var(--size-segmented-control-segment-m, 36px);
|
|
75
|
+
}
|
|
76
|
+
.selection[data-size=l]{
|
|
77
|
+
border-radius:var(--radius-segmented-control-segment-l, 14px);
|
|
78
|
+
padding-left:var(--space-segmented-control-segment-l-icon-only, 10px);
|
|
79
|
+
padding-right:var(--space-segmented-control-segment-l-icon-only, 10px);
|
|
80
|
+
gap:var(--space-segmented-control-segment-l-gap, 4px);
|
|
81
|
+
height:var(--size-segmented-control-segment-l, 44px);
|
|
82
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Segment as SegmentType, Size } from '../../types';
|
|
2
|
+
type SegmentProps = SegmentType & {
|
|
3
|
+
size: Size;
|
|
4
|
+
selected: boolean;
|
|
5
|
+
onClick: () => void;
|
|
6
|
+
focusable?: boolean;
|
|
7
|
+
onGetFocusable?: (ref: HTMLButtonElement | null) => void;
|
|
8
|
+
onSelectionUpdated: (element: HTMLButtonElement) => void;
|
|
9
|
+
};
|
|
10
|
+
export declare function Segment({ size, label, value, selected, onClick, disabled, icon, focusable, onGetFocusable, onSelectionUpdated, renderWrapSegment, }: SegmentProps): string | number | boolean | Iterable<import("react").ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
.segment{
|
|
2
|
+
cursor:pointer;
|
|
3
|
+
position:relative;
|
|
4
|
+
z-index:0;
|
|
5
|
+
display:flex;
|
|
6
|
+
align-items:center;
|
|
7
|
+
justify-content:center;
|
|
8
|
+
width:100%;
|
|
9
|
+
color:var(--sys-neutral-text-support, #6d707f);
|
|
10
|
+
background-color:transparent;
|
|
11
|
+
border-width:0;
|
|
12
|
+
}
|
|
13
|
+
.segment:hover{
|
|
14
|
+
color:var(--sys-neutral-text-main, #41424e);
|
|
15
|
+
}
|
|
16
|
+
.segment[data-disabled], .segment[data-disabled]:hover{
|
|
17
|
+
cursor:not-allowed;
|
|
18
|
+
color:var(--sys-neutral-text-disabled, #aaaebd);
|
|
19
|
+
}
|
|
20
|
+
.segment[data-active]{
|
|
21
|
+
color:var(--sys-neutral-text-main, #41424e);
|
|
22
|
+
}
|
|
23
|
+
.segment[data-active][data-disabled], .segment[data-active][data-disabled]:hover{
|
|
24
|
+
color:var(--sys-neutral-text-disabled, #aaaebd);
|
|
25
|
+
}
|
|
26
|
+
.segment:focus-visible{
|
|
27
|
+
outline-width:var(--border-state-focus-s-border-width, 2px);
|
|
28
|
+
outline-style:var(--border-state-focus-s-border-style, solid);
|
|
29
|
+
outline-color:var(--border-state-focus-s-border-color, );
|
|
30
|
+
outline-offset:calc(var(--border-state-focus-s-border-width, 2px) * -1);
|
|
31
|
+
outline-color:var(--sys-available-complementary, #1c1c24);
|
|
32
|
+
}
|
|
33
|
+
.segment[data-size=s][data-layout=label-only]{
|
|
34
|
+
border-radius:var(--radius-segmented-control-segment-s, 10px);
|
|
35
|
+
padding-left:var(--space-segmented-control-segment-s-from-label, 16px);
|
|
36
|
+
padding-right:var(--space-segmented-control-segment-s-from-label, 16px);
|
|
37
|
+
gap:var(--space-segmented-control-segment-s-gap, 4px);
|
|
38
|
+
height:var(--size-segmented-control-segment-s, 28px);
|
|
39
|
+
}
|
|
40
|
+
.segment[data-size=s][data-layout=icon-before]{
|
|
41
|
+
border-radius:var(--radius-segmented-control-segment-s, 10px);
|
|
42
|
+
padding-left:var(--space-segmented-control-segment-s-from-icon, 8px);
|
|
43
|
+
padding-right:var(--space-segmented-control-segment-s-from-label, 16px);
|
|
44
|
+
gap:var(--space-segmented-control-segment-s-gap, 4px);
|
|
45
|
+
height:var(--size-segmented-control-segment-s, 28px);
|
|
46
|
+
}
|
|
47
|
+
.segment[data-size=s][data-layout=icon-only]{
|
|
48
|
+
border-radius:var(--radius-segmented-control-segment-s, 10px);
|
|
49
|
+
padding-left:var(--space-segmented-control-segment-s-icon-only, 2px);
|
|
50
|
+
padding-right:var(--space-segmented-control-segment-s-icon-only, 2px);
|
|
51
|
+
gap:var(--space-segmented-control-segment-s-gap, 4px);
|
|
52
|
+
height:var(--size-segmented-control-segment-s, 28px);
|
|
53
|
+
}
|
|
54
|
+
.segment[data-size=m][data-layout=label-only]{
|
|
55
|
+
border-radius:var(--radius-segmented-control-segment-m, 12px);
|
|
56
|
+
padding-left:var(--space-segmented-control-segment-m-from-label, 24px);
|
|
57
|
+
padding-right:var(--space-segmented-control-segment-m-from-label, 24px);
|
|
58
|
+
gap:var(--space-segmented-control-segment-m-gap, 4px);
|
|
59
|
+
height:var(--size-segmented-control-segment-m, 36px);
|
|
60
|
+
}
|
|
61
|
+
.segment[data-size=m][data-layout=icon-before]{
|
|
62
|
+
border-radius:var(--radius-segmented-control-segment-m, 12px);
|
|
63
|
+
padding-left:var(--space-segmented-control-segment-m-from-icon, 16px);
|
|
64
|
+
padding-right:var(--space-segmented-control-segment-m-from-label, 24px);
|
|
65
|
+
gap:var(--space-segmented-control-segment-m-gap, 4px);
|
|
66
|
+
height:var(--size-segmented-control-segment-m, 36px);
|
|
67
|
+
}
|
|
68
|
+
.segment[data-size=m][data-layout=icon-only]{
|
|
69
|
+
border-radius:var(--radius-segmented-control-segment-m, 12px);
|
|
70
|
+
padding-left:var(--space-segmented-control-segment-m-icon-only, 6px);
|
|
71
|
+
padding-right:var(--space-segmented-control-segment-m-icon-only, 6px);
|
|
72
|
+
gap:var(--space-segmented-control-segment-m-gap, 4px);
|
|
73
|
+
height:var(--size-segmented-control-segment-m, 36px);
|
|
74
|
+
}
|
|
75
|
+
.segment[data-size=l][data-layout=label-only]{
|
|
76
|
+
border-radius:var(--radius-segmented-control-segment-l, 14px);
|
|
77
|
+
padding-left:var(--space-segmented-control-segment-l-from-label, 32px);
|
|
78
|
+
padding-right:var(--space-segmented-control-segment-l-from-label, 32px);
|
|
79
|
+
gap:var(--space-segmented-control-segment-l-gap, 4px);
|
|
80
|
+
height:var(--size-segmented-control-segment-l, 44px);
|
|
81
|
+
}
|
|
82
|
+
.segment[data-size=l][data-layout=icon-before]{
|
|
83
|
+
border-radius:var(--radius-segmented-control-segment-l, 14px);
|
|
84
|
+
padding-left:var(--space-segmented-control-segment-l-from-icon, 24px);
|
|
85
|
+
padding-right:var(--space-segmented-control-segment-l-from-label, 32px);
|
|
86
|
+
gap:var(--space-segmented-control-segment-l-gap, 4px);
|
|
87
|
+
height:var(--size-segmented-control-segment-l, 44px);
|
|
88
|
+
}
|
|
89
|
+
.segment[data-size=l][data-layout=icon-only]{
|
|
90
|
+
border-radius:var(--radius-segmented-control-segment-l, 14px);
|
|
91
|
+
padding-left:var(--space-segmented-control-segment-l-icon-only, 10px);
|
|
92
|
+
padding-right:var(--space-segmented-control-segment-l-icon-only, 10px);
|
|
93
|
+
gap:var(--space-segmented-control-segment-l-gap, 4px);
|
|
94
|
+
height:var(--size-segmented-control-segment-l, 44px);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.icon{
|
|
98
|
+
display:flex;
|
|
99
|
+
flex-shrink:0;
|
|
100
|
+
align-items:center;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.label[data-size=s]{
|
|
104
|
+
font-family:var(--sans-label-m-font-family, SB Sans Interface);
|
|
105
|
+
font-weight:var(--sans-label-m-font-weight, Semibold);
|
|
106
|
+
line-height:var(--sans-label-m-line-height, 16px);
|
|
107
|
+
font-size:var(--sans-label-m-font-size, 12px);
|
|
108
|
+
letter-spacing:var(--sans-label-m-letter-spacing, 0px);
|
|
109
|
+
paragraph-spacing:var(--sans-label-m-paragraph-spacing, 6.6px);
|
|
110
|
+
}
|
|
111
|
+
.label[data-size=m]{
|
|
112
|
+
font-family:var(--sans-label-m-font-family, SB Sans Interface);
|
|
113
|
+
font-weight:var(--sans-label-m-font-weight, Semibold);
|
|
114
|
+
line-height:var(--sans-label-m-line-height, 16px);
|
|
115
|
+
font-size:var(--sans-label-m-font-size, 12px);
|
|
116
|
+
letter-spacing:var(--sans-label-m-letter-spacing, 0px);
|
|
117
|
+
paragraph-spacing:var(--sans-label-m-paragraph-spacing, 6.6px);
|
|
118
|
+
}
|
|
119
|
+
.label[data-size=l]{
|
|
120
|
+
font-family:var(--sans-label-l-font-family, SB Sans Interface);
|
|
121
|
+
font-weight:var(--sans-label-l-font-weight, Semibold);
|
|
122
|
+
line-height:var(--sans-label-l-line-height, 20px);
|
|
123
|
+
font-size:var(--sans-label-l-font-size, 14px);
|
|
124
|
+
letter-spacing:var(--sans-label-l-letter-spacing, 0px);
|
|
125
|
+
paragraph-spacing:var(--sans-label-l-paragraph-spacing, 7.7px);
|
|
126
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Segment';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Segment';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { KeyboardEventHandler } from 'react';
|
|
2
|
+
import { IdType, Segment } from './types';
|
|
3
|
+
type useFocusControlParams = {
|
|
4
|
+
items: Segment[];
|
|
5
|
+
selected?: IdType;
|
|
6
|
+
};
|
|
7
|
+
export declare function useFocusControl({ selected, items }: useFocusControlParams): {
|
|
8
|
+
onKeyDown: KeyboardEventHandler<HTMLDivElement>;
|
|
9
|
+
focusableSegmentValue: string | number | undefined;
|
|
10
|
+
onGetFocusable: (ref: HTMLButtonElement | null) => void;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './components';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ValueOf } from '@snack-uikit/utils';
|
|
3
|
+
import { SIZE, WIDTH } from './constants';
|
|
4
|
+
export type IdType = string | number;
|
|
5
|
+
export type Size = ValueOf<typeof SIZE>;
|
|
6
|
+
export type Width = ValueOf<typeof WIDTH>;
|
|
7
|
+
export type Segment<Value extends IdType = IdType> = {
|
|
8
|
+
/**
|
|
9
|
+
* Идентификатор сегмента.
|
|
10
|
+
*/
|
|
11
|
+
value: Value;
|
|
12
|
+
/**
|
|
13
|
+
* Текстовый заголовок сегмента.
|
|
14
|
+
*/
|
|
15
|
+
label?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Состояние активности сегмента.
|
|
18
|
+
*/
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Иконка сегмента.
|
|
22
|
+
*/
|
|
23
|
+
icon?: ReactNode;
|
|
24
|
+
/**
|
|
25
|
+
* Render-обертка над сегментом.
|
|
26
|
+
*/
|
|
27
|
+
renderWrapSegment?: (segment: ReactNode) => ReactNode;
|
|
28
|
+
};
|
|
29
|
+
export type SelectionPosition = {
|
|
30
|
+
top: number;
|
|
31
|
+
left: number;
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
};
|
package/package.json
CHANGED
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "Segmented Control",
|
|
7
|
-
"version": "0.2.
|
|
7
|
+
"version": "0.2.5-preview-71543426.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
11
11
|
"*.woff2"
|
|
12
12
|
],
|
|
13
13
|
"description": "",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
14
|
+
"types": "./dist/esm/index.d.ts",
|
|
15
|
+
"main": "./dist/cjs/index.js",
|
|
16
|
+
"module": "./dist/esm/index.js",
|
|
16
17
|
"homepage": "https://cloud-ru-tech.github.io/snack-uikit/packages/segmented-control",
|
|
17
18
|
"repository": {
|
|
18
19
|
"type": "git",
|
|
@@ -24,7 +25,8 @@
|
|
|
24
25
|
"Sergei Khlupin <svhlupin@cloud.ru>"
|
|
25
26
|
],
|
|
26
27
|
"files": [
|
|
27
|
-
"dist",
|
|
28
|
+
"dist/cjs",
|
|
29
|
+
"dist/esm",
|
|
28
30
|
"src",
|
|
29
31
|
"./CHANGELOG.md",
|
|
30
32
|
"./LICENSE"
|
|
@@ -32,10 +34,10 @@
|
|
|
32
34
|
"license": "Apache-2.0",
|
|
33
35
|
"scripts": {},
|
|
34
36
|
"dependencies": {
|
|
35
|
-
"@snack-uikit/truncate-string": "0.4.
|
|
36
|
-
"@snack-uikit/utils": "3.4.0",
|
|
37
|
+
"@snack-uikit/truncate-string": "0.4.25-preview-71543426.0",
|
|
38
|
+
"@snack-uikit/utils": "3.4.1-preview-71543426.0",
|
|
37
39
|
"classnames": "2.5.1",
|
|
38
40
|
"uncontrollable": "8.0.4"
|
|
39
41
|
},
|
|
40
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "3102614275e261c8f41db0f6c00a1f6b6276b2a9"
|
|
41
43
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|