@yamada-ui/segmented-control 0.2.7 → 0.2.8

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.
@@ -1,274 +0,0 @@
1
- // src/segmented-control.tsx
2
- import {
3
- ui,
4
- forwardRef,
5
- useMultiComponentStyle,
6
- omitThemeProps
7
- } from "@yamada-ui/core";
8
- import { useControllableState } from "@yamada-ui/use-controllable-state";
9
- import { createDescendant } from "@yamada-ui/use-descendant";
10
- import { trackFocusVisible } from "@yamada-ui/use-focus-visible";
11
- import { useResizeObserver } from "@yamada-ui/use-resize-observer";
12
- import {
13
- ariaAttr,
14
- createContext,
15
- cx,
16
- dataAttr,
17
- getValidChildren,
18
- handlerAll,
19
- mergeRefs,
20
- omitObject,
21
- useCallbackRef
22
- } from "@yamada-ui/utils";
23
- import {
24
- useCallback,
25
- useEffect,
26
- useId,
27
- useRef,
28
- useState
29
- } from "react";
30
- import { jsx, jsxs } from "react/jsx-runtime";
31
- var { DescendantsContextProvider, useDescendants, useDescendant } = createDescendant();
32
- var [SegmentedControlProvider, useSegmentedControl] = createContext({
33
- strict: false,
34
- name: "SegmentedControlContext"
35
- });
36
- var SegmentedControl = forwardRef((props, ref) => {
37
- const [styles, mergedProps] = useMultiComponentStyle("SegmentedControl", props);
38
- let { className, id, name, isReadOnly, isDisabled, children, ...rest } = omitThemeProps(mergedProps);
39
- id = id != null ? id : useId();
40
- name = name != null ? name : `segmented-control-${useId()}`;
41
- rest.onChange = useCallbackRef(rest.onChange);
42
- const descendants = useDescendants();
43
- const [focusedIndex, setFocusedIndex] = useState(-1);
44
- const [isFocusVisible, setIsFocusVisible] = useState(false);
45
- const [observerRef, containerRect] = useResizeObserver();
46
- const containerRef = useRef(null);
47
- const labelRefs = useRef(/* @__PURE__ */ new Map());
48
- const [activePosition, setActivePosition] = useState({
49
- width: 0,
50
- height: 0,
51
- x: 0,
52
- y: 0
53
- });
54
- const [value, setValue] = useControllableState({
55
- value: rest.value,
56
- defaultValue: rest.defaultValue,
57
- onChange: rest.onChange
58
- });
59
- useEffect(() => {
60
- return trackFocusVisible(setIsFocusVisible);
61
- }, []);
62
- useEffect(() => {
63
- const el = labelRefs.current.get(value);
64
- if (!el || !containerRef.current || !observerRef.current)
65
- return;
66
- const { paddingLeft, paddingTop } = getComputedStyle(containerRef.current);
67
- const gutterX = parseFloat(paddingLeft) || 0;
68
- const gutterY = parseFloat(paddingTop) || 0;
69
- let { width, height } = el.getBoundingClientRect();
70
- const x = el.offsetLeft - gutterX;
71
- const y = el.offsetTop - gutterY;
72
- width = width * (el.offsetWidth / width) || 0;
73
- height = height * (el.offsetWidth / width) || 0;
74
- setActivePosition({ width, height, x, y });
75
- }, [focusedIndex, containerRect, labelRefs, observerRef, value]);
76
- const onChange = useCallback(
77
- (ev) => {
78
- if (isDisabled || isReadOnly) {
79
- ev.preventDefault();
80
- return;
81
- }
82
- setValue(ev.target.value);
83
- },
84
- [isDisabled, isReadOnly, setValue]
85
- );
86
- const onFocus = useCallback(
87
- (index, skip) => {
88
- if (isDisabled)
89
- return;
90
- if (skip) {
91
- const next = descendants.enabledNextValue(index);
92
- if (next)
93
- setFocusedIndex(next.index);
94
- } else {
95
- setFocusedIndex(index);
96
- }
97
- },
98
- [descendants, isDisabled]
99
- );
100
- const onBlur = useCallback(() => setFocusedIndex(-1), []);
101
- const getContainerProps = useCallback(
102
- (props2 = {}, ref2 = null) => ({
103
- ...omitObject(rest, ["value", "defaultValue", "onChange"]),
104
- ...props2,
105
- ref: mergeRefs(containerRef, observerRef, ref2),
106
- id,
107
- "aria-disabled": ariaAttr(isDisabled),
108
- "aria-readonly": ariaAttr(isReadOnly),
109
- onBlur: handlerAll(props2.onBlur, onBlur)
110
- }),
111
- [id, isDisabled, isReadOnly, observerRef, onBlur, rest]
112
- );
113
- const getActiveProps = useCallback(
114
- (props2 = {}, ref2 = null) => {
115
- const { width, height, x, y } = activePosition;
116
- return {
117
- ...props2,
118
- ref: ref2,
119
- style: {
120
- position: "absolute",
121
- zIndex: 1,
122
- width,
123
- height,
124
- transform: `translate(${x}px, ${y}px)`
125
- }
126
- };
127
- },
128
- [activePosition]
129
- );
130
- const getInputProps = useCallback(
131
- ({ index, ...props2 } = {}, ref2 = null) => {
132
- var _a, _b, _c, _d;
133
- const disabled = (_b = (_a = props2.disabled) != null ? _a : props2.isDisabled) != null ? _b : isDisabled;
134
- const readOnly = (_d = (_c = props2.readOnly) != null ? _c : props2.isReadOnly) != null ? _d : isReadOnly;
135
- const checked = props2.value === value;
136
- return {
137
- ...omitObject(props2, ["isDisabled", "isReadOnly"]),
138
- ref: ref2,
139
- id: `${id}-${index}`,
140
- type: "radio",
141
- name,
142
- disabled: disabled || readOnly,
143
- readOnly,
144
- checked,
145
- "aria-disabled": ariaAttr(disabled),
146
- "aria-readonly": ariaAttr(readOnly),
147
- "data-checked": dataAttr(checked),
148
- "data-focus": dataAttr(index === focusedIndex),
149
- style: {
150
- border: "0px",
151
- clip: "rect(0px, 0px, 0px, 0px)",
152
- height: "1px",
153
- width: "1px",
154
- margin: "-1px",
155
- padding: "0px",
156
- overflow: "hidden",
157
- whiteSpace: "nowrap",
158
- position: "absolute"
159
- },
160
- onChange: handlerAll(
161
- props2.onChange,
162
- (ev) => !disabled && !readOnly ? onChange(ev) : {}
163
- )
164
- };
165
- },
166
- [isDisabled, isReadOnly, value, id, name, focusedIndex, onChange]
167
- );
168
- const getLabelProps = useCallback(
169
- ({ index, ...props2 } = {}, ref2 = null) => {
170
- var _a, _b, _c, _d;
171
- const disabled = (_b = (_a = props2.disabled) != null ? _a : props2.isDisabled) != null ? _b : isDisabled;
172
- const readOnly = (_d = (_c = props2.readOnly) != null ? _c : props2.isReadOnly) != null ? _d : isReadOnly;
173
- const checked = props2.value === value;
174
- const focused = index === focusedIndex;
175
- return {
176
- props: props2,
177
- ref: mergeRefs((node) => labelRefs.current.set(props2.value, node), ref2),
178
- "aria-disabled": ariaAttr(disabled),
179
- "aria-readonly": ariaAttr(readOnly),
180
- "data-checked": dataAttr(checked),
181
- "data-focus": dataAttr(focused),
182
- "data-focus-visible": dataAttr(focused && isFocusVisible),
183
- onFocus: handlerAll(props2.onFocus, () => onFocus(index, disabled || readOnly)),
184
- ...disabled || readOnly ? {
185
- _hover: {},
186
- _active: {},
187
- _focus: {},
188
- _invalid: {},
189
- _focusVisible: {}
190
- } : {},
191
- style: { position: "relative", zIndex: 2 }
192
- };
193
- },
194
- [focusedIndex, isDisabled, isFocusVisible, isReadOnly, onFocus, value]
195
- );
196
- const css = {
197
- position: "relative",
198
- display: "inline-flex",
199
- alignItems: "center",
200
- ...styles.container
201
- };
202
- const validChildren = getValidChildren(children);
203
- if (value == null && rest.defaultValue == null) {
204
- for (const child of validChildren) {
205
- if (child.type !== SegmentedControlButton)
206
- continue;
207
- const value2 = child.props.value;
208
- setValue(value2);
209
- break;
210
- }
211
- }
212
- return /* @__PURE__ */ jsx(DescendantsContextProvider, { value: descendants, children: /* @__PURE__ */ jsx(SegmentedControlProvider, { value: { getInputProps, getLabelProps, styles }, children: /* @__PURE__ */ jsxs(
213
- ui.div,
214
- {
215
- ...getContainerProps({}, ref),
216
- className: cx("ui-segmented-control", className),
217
- __css: css,
218
- children: [
219
- /* @__PURE__ */ jsx(
220
- ui.span,
221
- {
222
- className: "ui-segmented-control-active",
223
- ...getActiveProps(),
224
- __css: styles.active
225
- }
226
- ),
227
- validChildren
228
- ]
229
- }
230
- ) }) });
231
- });
232
- var SegmentedControlButton = forwardRef(
233
- ({ className, disabled, readOnly, isDisabled, isReadOnly, value, onChange, children, ...rest }, ref) => {
234
- const { getInputProps, getLabelProps, styles } = useSegmentedControl();
235
- const { index, register } = useDescendant({
236
- disabled: isDisabled || isReadOnly
237
- });
238
- const props = {
239
- index,
240
- value,
241
- onChange,
242
- disabled,
243
- readOnly,
244
- isDisabled,
245
- isReadOnly
246
- };
247
- const css = {
248
- cursor: "pointer",
249
- flex: "1 1 0%",
250
- display: "inline-flex",
251
- justifyContent: "center",
252
- alignItems: "center",
253
- ...styles.button
254
- };
255
- return /* @__PURE__ */ jsxs(
256
- ui.label,
257
- {
258
- ...getLabelProps(omitObject(props, ["onChange"])),
259
- className: cx("ui-segmented-control-button", className),
260
- __css: css,
261
- ...rest,
262
- children: [
263
- /* @__PURE__ */ jsx(ui.input, { ...getInputProps(props, mergeRefs(register, ref)) }),
264
- /* @__PURE__ */ jsx(ui.span, { children })
265
- ]
266
- }
267
- );
268
- }
269
- );
270
-
271
- export {
272
- SegmentedControl,
273
- SegmentedControlButton
274
- };