UNPKG

@audira/carbon-react-native

Version:

Build React Native apps with component and shared patterns using Carbon

296 lines (295 loc) 10.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Switch = void 0; var _react = require("react"); var _reactNative = require("react-native"); var _carbonReactNativeElements = require("@audira/carbon-react-native-elements"); var _checkmark = _interopRequireDefault(require("@carbon/icons/svg/32/checkmark.svg")); var _index = require("../../_internal/contexts/index.js"); var _index2 = require("../../_internal/style-sheets/index.js"); var _index3 = require("../../carbon-style-sheet/index.js"); var _index4 = require("../../contexts/index.js"); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const Switch = exports.Switch = /*#__PURE__*/(0, _react.forwardRef)(function ({ size = 'default', state = 'normal', defaultValue, value: valueProp, trackColor: trackColorProp, thumbColor: thumbColorProp, motion = { false: motionDefault, true: motionDefault }, style, role = 'switch', 'aria-checked': ariaChecked, onChange, onBlur, onFocus, onPress, ...props }, forwardedRef) { const viewRef = (0, _react.useRef)(null), ref = (0, _react.useRef)({ onChangeEffect: false, value: defaultValue ?? false }), globalConfigContext = (0, _react.useContext)(_index.GlobalConfigContext), themeContext = (0, _react.useContext)(_index4.ThemeContext), [isFocused, setIsFocused] = (0, _react.useState)(false), [valueSelf, setValueSelf] = (0, _react.useState)(ref.current.value), controlled = typeof valueProp === 'boolean', value = controlled ? !!valueProp : valueSelf, /** * 0 -> false/inactive * 1 -> true/active */ sharedValue = (0, _react.useRef)(new _reactNative.Animated.Value(value ? 1 : 0)), { trackColor, thumbColor } = (0, _react.useMemo)(() => { const trackColor_ = mapSwitchTrackColorToken[state], thumbColor_ = mapSwitchThumbColorToken[state]; return { trackColor: trackColorProp ?? { false: trackColor_.false?.[themeContext.colorScheme] ?? 'transparent', true: trackColor_.true?.[themeContext.colorScheme] ?? 'transparent' }, thumbColor: thumbColorProp ?? { false: thumbColor_[themeContext.colorScheme], true: thumbColor_[themeContext.colorScheme] } }; }, [state, trackColorProp, thumbColorProp, themeContext.colorScheme]), blurHandler = (0, _react.useCallback)(event => { onBlur?.(event); setIsFocused(false); }, [onBlur]), focusHandler = (0, _react.useCallback)(event => { onFocus?.(event); setIsFocused(true); }, [onFocus]), pressHandler = (0, _react.useCallback)(event => { onPress?.(event); if (!controlled) { ref.current.onChangeEffect = true; setValueSelf(self => !self); } else { onChange?.(!ref.current.value); } }, [controlled, onPress, onChange]), transformInterpolationOutputRange = (0, _react.useMemo)(() => { const ltr = [ /** * i can't find how IBM tell this gap between the container and the thumb/handle * i have to look at the Carbon React just to find this padding (they are using inset-inline-start there) */ 3, sizeStyle[size].width - thumbSizeStyle[size].width - 3]; if (globalConfigContext.rtl) { return ltr.reverse(); } return ltr; }, [size, globalConfigContext.rtl]); (0, _react.useEffect)(() => { if (value) { _reactNative.Animated.timing(sharedValue.current, { toValue: 1, duration: motion.true.duration, easing: motion.true.easing, useNativeDriver: true }).start(); } else { _reactNative.Animated.timing(sharedValue.current, { toValue: 0, duration: motion.false.duration, easing: motion.false.easing, useNativeDriver: true }).start(); } }, [motion, sharedValue, value]); (0, _react.useEffect)(() => { if (ref.current.onChangeEffect) { ref.current.onChangeEffect = false; ref.current.value = value; onChange?.(value); } }, [value, onChange]); (0, _react.useImperativeHandle)(forwardedRef, () => { return Object.assign(viewRef.current ?? {}, { get value() { return value; }, setValue(valueParam) { if (!controlled) { ref.current.onChangeEffect = true; if (typeof valueParam === 'boolean') { setValueSelf(valueParam); } else { setValueSelf(valueParam(ref.current.value)); } } } }); }, [controlled, value]); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(PressableAnimated, { ...props, role: role, "aria-checked": ariaChecked ?? value, style: [_index2.FlexStyleSheet.justify_center, baseStyle.container, sizeStyle[size], { backgroundColor: sharedValue.current.interpolate({ inputRange: interpolationRange, outputRange: [trackColor.false, trackColor.true] }) }, state === 'read_only' ? baseStyleCarbon.containerReadonly : null, style], onBlur: blurHandler, onFocus: focusHandler, onPress: pressHandler, ref: viewRef, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.View, { style: [_index2.FlexStyleSheet.items_center, _index2.FlexStyleSheet.justify_center, baseStyle.thumb, thumbSizeStyle[size], // thumbAnimatedStyle, { transform: [{ translateX: sharedValue.current.interpolate({ inputRange: interpolationRange, outputRange: transformInterpolationOutputRange }) }], backgroundColor: sharedValue.current.interpolate({ inputRange: interpolationRange, outputRange: [thumbColor.false, thumbColor.true] }) }], children: size === 'small' && /*#__PURE__*/(0, _jsxRuntime.jsx)(IconCheckmarkAnimated, { fill: mapIconAnimatedFillColor[themeContext.colorScheme], style: { opacity: sharedValue.current } }) }), isFocused && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: [_index2.CommonStyleSheet.absolute, focusBoxSizeStyle[size], baseStyle.focusBox, baseStyleCarbon.focusBoxBorderColor] })] }); }); const baseStyle = _reactNative.StyleSheet.create({ container: { borderRadius: 24 }, thumb: { borderRadius: 18 }, focusBox: { borderWidth: 2, borderRadius: 24, transform: [{ translateX: -3 }] } }), baseStyleCarbon = _index3.CarbonStyleSheet.create({ containerReadonly: { borderWidth: 1, borderColor: _index3.CarbonStyleSheet.color.border_subtle_00 }, focusBoxBorderColor: { borderColor: _index3.CarbonStyleSheet.color.focus } }), sizeStyle = _reactNative.StyleSheet.create({ default: { width: 48, height: 24 }, small: { width: 32, height: 16 } }), thumbSizeStyle = _reactNative.StyleSheet.create({ default: { width: 18, height: 18 }, small: { width: 10, height: 10 } }), focusBoxSizeStyle = _reactNative.StyleSheet.create({ default: { width: sizeStyle.default.width + 6, height: sizeStyle.default.height + 6 }, small: { width: sizeStyle.small.width + 6, height: sizeStyle.small.height + 6 } }), mapSwitchTrackColorToken = { normal: { false: { gray_10: _carbonReactNativeElements.Color.Token.gray_10.toggle_off, gray_100: _carbonReactNativeElements.Color.Token.gray_100.toggle_off }, true: { gray_10: _carbonReactNativeElements.Color.Token.gray_10.support_success, gray_100: _carbonReactNativeElements.Color.Token.gray_100.support_success } }, disabled: { false: { gray_10: _carbonReactNativeElements.Color.Token.gray_10.button_disabled, gray_100: _carbonReactNativeElements.Color.Token.gray_100.button_disabled }, true: { gray_10: _carbonReactNativeElements.Color.Token.gray_10.button_disabled, gray_100: _carbonReactNativeElements.Color.Token.gray_100.button_disabled } }, read_only: {}, focused: { false: { gray_10: _carbonReactNativeElements.Color.Token.gray_10.toggle_off, gray_100: _carbonReactNativeElements.Color.Token.gray_100.toggle_off }, true: { gray_10: _carbonReactNativeElements.Color.Token.gray_10.support_success, gray_100: _carbonReactNativeElements.Color.Token.gray_100.support_success } } }, mapSwitchThumbColorToken = { normal: { gray_10: _carbonReactNativeElements.Color.Token.gray_10.icon_on_color, gray_100: _carbonReactNativeElements.Color.Token.gray_100.icon_on_color }, disabled: { gray_10: _carbonReactNativeElements.Color.Token.gray_10.icon_on_color_disabled, gray_100: _carbonReactNativeElements.Color.Token.gray_100.icon_on_color_disabled }, read_only: { gray_10: _carbonReactNativeElements.Color.Token.gray_10.icon_primary, gray_100: _carbonReactNativeElements.Color.Token.gray_100.icon_primary }, focused: { gray_10: _carbonReactNativeElements.Color.Token.gray_10.icon_on_color, gray_100: _carbonReactNativeElements.Color.Token.gray_100.icon_on_color } }, interpolationRange = [0, 1], motionDefault = { duration: _carbonReactNativeElements.Motion.Duration.fast_01, easing: _reactNative.Easing.bezier(_carbonReactNativeElements.Motion.Easing.exit.productive.x1, _carbonReactNativeElements.Motion.Easing.exit.productive.y1, _carbonReactNativeElements.Motion.Easing.exit.productive.x2, _carbonReactNativeElements.Motion.Easing.exit.productive.y2) }, PressableAnimated = _reactNative.Animated.createAnimatedComponent(_reactNative.Pressable), IconCheckmarkAnimated = _reactNative.Animated.createAnimatedComponent(_checkmark.default), mapIconAnimatedFillColor = { gray_10: _carbonReactNativeElements.Color.Token.gray_10.support_success, gray_100: _carbonReactNativeElements.Color.Token.gray_100.support_success }; //# sourceMappingURL=Switch.js.map