UNPKG

@yamada-ui/segmented-control

Version:

Yamada UI segmented control components

320 lines (319 loc) • 11.3 kB
"use client" "use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/segmented-control.tsx var segmented_control_exports = {}; __export(segmented_control_exports, { SegmentedControl: () => SegmentedControl, SegmentedControlButton: () => SegmentedControlButton }); module.exports = __toCommonJS(segmented_control_exports); var import_core = require("@yamada-ui/core"); var import_motion = require("@yamada-ui/motion"); var import_use_controllable_state = require("@yamada-ui/use-controllable-state"); var import_use_descendant = require("@yamada-ui/use-descendant"); var import_use_focus_visible = require("@yamada-ui/use-focus-visible"); var import_utils = require("@yamada-ui/utils"); var import_react = require("react"); var import_jsx_runtime = require("react/jsx-runtime"); var { DescendantsContextProvider, useDescendant, useDescendants } = (0, import_use_descendant.createDescendant)(); var [SegmentedControlProvider, useSegmentedControl] = (0, import_utils.createContext)({ name: "SegmentedControlContext", errorMessage: `useSegmentedControl returned is 'undefined'. Seems you forgot to wrap the components in "<SegmentedControl />"` }); var SegmentedControl = (0, import_core.forwardRef)( (props, ref) => { const [styles, mergedProps] = (0, import_core.useComponentMultiStyle)( "SegmentedControl", props ); const uuid = (0, import_react.useId)(); const { id = uuid, name = `segmented-control-${uuid}`, className, children, defaultValue, isDisabled, disabled = isDisabled, isReadOnly, items = [], readOnly = isReadOnly, value: valueProp, onChange: onChangeProp, ...rest } = (0, import_core.omitThemeProps)(mergedProps); const containerRef = (0, import_react.useRef)(null); const descendants = useDescendants(); const [focusedIndex, setFocusedIndex] = (0, import_react.useState)(-1); const [focusVisible, setFocusVisible] = (0, import_react.useState)(false); const onChangeRef = (0, import_utils.useCallbackRef)(onChangeProp); const [value, setValue] = (0, import_use_controllable_state.useControllableState)({ defaultValue, value: valueProp, onChange: onChangeRef }); const onChange = (0, import_react.useCallback)( (ev) => { if (disabled || readOnly) { ev.preventDefault(); return; } setValue(ev.target.value); }, [disabled, readOnly, setValue] ); const onFocus = (0, import_react.useCallback)( (index, skip) => { if (disabled) return; if (skip) { const next = descendants.enabledNextValue(index); if (next) setFocusedIndex(next.index); } else { setFocusedIndex(index); } }, [descendants, disabled] ); const onBlur = (0, import_react.useCallback)(() => setFocusedIndex(-1), []); const getContainerProps = (0, import_react.useCallback)( (props2 = {}, ref2 = null) => ({ "aria-disabled": (0, import_utils.ariaAttr)(disabled), "data-readonly": (0, import_utils.dataAttr)(readOnly), role: "radiogroup", ...rest, ...props2, id, ref: (0, import_utils.mergeRefs)(containerRef, ref2), onBlur: (0, import_utils.handlerAll)(props2.onBlur, onBlur) }), [id, disabled, readOnly, onBlur, rest] ); const getInputProps = (0, import_react.useCallback)( ({ index, ...props2 }, ref2 = null) => { var _a, _b; const trulyDisabled = (_a = props2.disabled) != null ? _a : disabled; const trulyReadOnly = (_b = props2.readOnly) != null ? _b : readOnly; const checked = props2.value === value; return { ...props2, id: `${id}-${index}`, ref: ref2, type: "radio", name, style: { border: "0px", clip: "rect(0px, 0px, 0px, 0px)", height: "1px", margin: "-1px", overflow: "hidden", padding: "0px", position: "absolute", whiteSpace: "nowrap", width: "1px" }, "aria-disabled": (0, import_utils.ariaAttr)(trulyDisabled), "data-checked": (0, import_utils.dataAttr)(checked), "data-focus": (0, import_utils.dataAttr)(index === focusedIndex), "data-readonly": (0, import_utils.dataAttr)(trulyReadOnly), checked, disabled: trulyDisabled || trulyReadOnly, readOnly: trulyReadOnly, onChange: (0, import_utils.handlerAll)( props2.onChange, (ev) => !trulyDisabled && !trulyReadOnly ? onChange(ev) : {} ) }; }, [disabled, readOnly, value, id, name, focusedIndex, onChange] ); const getLabelProps = (0, import_react.useCallback)( ({ index, ...props2 }, ref2 = null) => { var _a, _b; const trulyDisabled = (_a = props2.disabled) != null ? _a : disabled; const trulyReadOnly = (_b = props2.readOnly) != null ? _b : readOnly; const checked = props2.value === value; const focused = index === focusedIndex; return { ...props2, ref: ref2, "aria-disabled": (0, import_utils.ariaAttr)(trulyDisabled), "data-checked": (0, import_utils.dataAttr)(checked), "data-focus": (0, import_utils.dataAttr)(focused), "data-focus-visible": (0, import_utils.dataAttr)(focused && focusVisible), "data-readonly": (0, import_utils.dataAttr)(trulyReadOnly), onFocus: (0, import_utils.handlerAll)( props2.onFocus, () => onFocus(index, trulyDisabled || trulyReadOnly || false) ), ...trulyDisabled || trulyReadOnly ? { _active: {}, _focus: {}, _focusVisible: {}, _hover: {}, _invalid: {} } : {} }; }, [focusedIndex, disabled, readOnly, focusVisible, onFocus, value] ); (0, import_react.useEffect)(() => { return (0, import_use_focus_visible.trackFocusVisible)(setFocusVisible); }, []); const css = { alignItems: "center", display: "inline-flex", ...styles.container }; const validChildren = (0, import_utils.getValidChildren)(children); let computedChildren = []; if (!validChildren.length && items.length) { computedChildren = items.map(({ label, value: value2, ...props2 }, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SegmentedControlButton, { value: value2, ...props2, children: label }, i)); } else { computedChildren = validChildren; } if (value == null && defaultValue == null) { for (const child of computedChildren) { if (child.type !== SegmentedControlButton) { if (child.type.displayName !== SegmentedControlButton.displayName) continue; } const value2 = child.props.value; setValue(value2); break; } } return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DescendantsContextProvider, { value: descendants, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( SegmentedControlProvider, { value: { styles, value, getInputProps, getLabelProps }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_motion.LayoutGroup, { id, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_core.ui.div, { ...getContainerProps({}, ref), className: (0, import_utils.cx)("ui-segmented-control", className), __css: css, children: computedChildren } ) }) } ) }); } ); SegmentedControl.displayName = "SegmentedControl"; SegmentedControl.__ui__ = "SegmentedControl"; var SegmentedControlButton = (0, import_core.forwardRef)( ({ className, children, isDisabled, disabled = isDisabled, isReadOnly, readOnly = isReadOnly, value, motionProps, onChange, ...rest }, ref) => { const [, mounted] = (0, import_utils.useMounted)({ rerender: true }); const { styles, value: selectedValue, getInputProps, getLabelProps } = useSegmentedControl(); const { index, register } = useDescendant({ disabled: disabled || readOnly }); const props = { disabled, index, readOnly, value }; const css = { alignItems: "center", cursor: "pointer", display: "inline-flex", flex: "1 1 0%", justifyContent: "center", position: "relative", ...styles.button }; const selected = value === selectedValue; return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( import_core.ui.label, { ...getLabelProps(props), className: (0, import_utils.cx)("ui-segmented-control__button", className), __css: css, ...rest, children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_core.ui.input, { ...getInputProps({ onChange, ...props }, (0, import_utils.mergeRefs)(register, ref)) } ), selected && mounted ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SegmentedControlCursor, { ...motionProps }) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.ui.span, { zIndex: "1", children }) ] } ); } ); SegmentedControlButton.displayName = "SegmentedControlButton"; SegmentedControlButton.__ui__ = "SegmentedControlButton"; var SegmentedControlCursor = ({ className, transition, ...rest }) => { const { styles } = useSegmentedControl(); const css = { h: "100%", position: "absolute", w: "100%", ...styles.cursor }; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_motion.motion.div, { className: (0, import_utils.cx)("ui-segmented-control__cursor", className), layoutDependency: false, layoutId: "cursor", transition: { type: "spring", bounce: 0.15, duration: 0.4, ...transition }, __css: css, ...rest } ); }; SegmentedControlCursor.displayName = "SegmentedControlCursor"; SegmentedControlCursor.__ui__ = "SegmentedControlCursor"; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { SegmentedControl, SegmentedControlButton }); //# sourceMappingURL=segmented-control.js.map