@audira/carbon-react-native
Version:
Build React Native apps with component and shared patterns using Carbon
296 lines (295 loc) • 10.3 kB
JavaScript
"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