@impulse-ui-native/switch 4.0.0 → 5.0.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @impulse-ui-native/switch
2
2
 
3
- Accessible, token-aware animated switch controls for React Native and React Native Web.
3
+ Token-aware animated switch controls for React Native mobile applications.
4
4
 
5
5
  ## Installation
6
6
 
@@ -27,7 +27,6 @@ export function NotificationsSwitch() {
27
27
 
28
28
  return (
29
29
  <Switch
30
- accessibilityLabel="Notifications"
31
30
  checked={checked}
32
31
  onCheckedChange={setChecked}
33
32
  size="medium"
@@ -37,8 +36,6 @@ export function NotificationsSwitch() {
37
36
  }
38
37
  ```
39
38
 
40
- Use `defaultChecked` for uncontrolled state. The thumb position and track colors animate when the state changes. System reduced-motion preferences disable the transition while preserving the state change.
39
+ Use `defaultChecked` for uncontrolled state. The thumb position and track colors animate when the state changes.
41
40
 
42
- Set `loading` while an update is pending. Loading switches expose a busy accessibility state, show an activity indicator, and block further presses until loading ends. Disabled switches also block interaction.
43
-
44
- The standalone switch does not render a label, so provide `accessibilityLabel` unless a surrounding labelled control supplies an accessible name.
41
+ Set `loading` while an update is pending. Loading switches show an activity indicator and block further presses until loading ends. Disabled switches also block interaction.
@@ -4,6 +4,6 @@ import { SwitchProps } from '../types/switch.types.mjs';
4
4
  import '@impulse-ui-native/primitives';
5
5
  import '@impulse-ui-native/theme';
6
6
 
7
- declare const Switch: react.MemoExoticComponent<({ accessibilityState, checked: checkedProp, defaultChecked, disabled, hitSlop, loading, onCheckedChange, onPress, size, style, variant, ...props }: SwitchProps) => react_jsx_runtime.JSX.Element>;
7
+ declare const Switch: react.MemoExoticComponent<({ checked: checkedProp, defaultChecked, disabled, hitSlop, loading, onCheckedChange, onPress, size, style, variant, ...props }: SwitchProps) => react_jsx_runtime.JSX.Element>;
8
8
 
9
9
  export { Switch };
@@ -8,7 +8,6 @@ import { useThemedStyles } from "@impulse-ui-native/theme";
8
8
  import { useSwitchAnimation, useSwitchTokens } from "../hooks";
9
9
  import { switchStyles } from "./switch.styles";
10
10
  const Switch = memo(function Switch2({
11
- accessibilityState,
12
11
  checked: checkedProp,
13
12
  defaultChecked = false,
14
13
  disabled,
@@ -42,15 +41,6 @@ const Switch = memo(function Switch2({
42
41
  colors,
43
42
  sizeTokens
44
43
  });
45
- const resolvedAccessibilityState = useMemo(
46
- () => ({
47
- ...accessibilityState,
48
- busy: loading,
49
- checked,
50
- disabled: interactionDisabled
51
- }),
52
- [accessibilityState, checked, interactionDisabled, loading]
53
- );
54
44
  const switchStyle = useCallback(
55
45
  (state) => StyleSheet.flatten([
56
46
  styles.root,
@@ -77,8 +67,6 @@ const Switch = memo(function Switch2({
77
67
  Pressable,
78
68
  {
79
69
  ...props,
80
- accessibilityRole: "switch",
81
- accessibilityState: resolvedAccessibilityState,
82
70
  disabled: interactionDisabled,
83
71
  hitSlop: hitSlop ?? sizeTokens.hitSlop,
84
72
  onPress: handlePress,
@@ -86,7 +74,6 @@ const Switch = memo(function Switch2({
86
74
  children: /* @__PURE__ */ jsx(Animated.View, { pointerEvents: "none", style: trackAnimatedStyle, children: /* @__PURE__ */ jsx(Animated.View, { style: thumbAnimatedStyle, children: loading ? /* @__PURE__ */ jsx(
87
75
  Spinner,
88
76
  {
89
- accessible: false,
90
77
  color: loadingIndicatorColor,
91
78
  size: "medium",
92
79
  style: styles.loadingIndicator
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/switch.tsx"],"sourcesContent":["import type {\n AccessibilityState,\n GestureResponderEvent,\n PressableStateCallbackType,\n StyleProp,\n ViewStyle,\n} from \"react-native\";\nimport { memo, useCallback, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\nimport Animated from \"react-native-reanimated\";\n\nimport { useControllableState } from \"@impulse-ui-native/core\";\nimport { Pressable, Spinner } from \"@impulse-ui-native/primitives\";\nimport { useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { SwitchProps } from \"../types\";\nimport { useSwitchAnimation, useSwitchTokens } from \"../hooks\";\nimport { switchStyles } from \"./switch.styles\";\n\nexport const Switch = memo(function Switch({\n accessibilityState,\n checked: checkedProp,\n defaultChecked = false,\n disabled,\n hitSlop,\n loading = false,\n onCheckedChange,\n onPress,\n size = \"medium\",\n style,\n variant = \"filled\",\n ...props\n}: SwitchProps) {\n const [checked, setChecked] = useControllableState<boolean>({\n prop: checkedProp,\n defaultProp: defaultChecked,\n onChange: onCheckedChange,\n });\n const interactionDisabled = disabled === true || loading;\n const {\n animationDuration,\n borderWidth,\n colors,\n loadingIndicatorColor,\n sizeTokens,\n } = useSwitchTokens({ disabled: interactionDisabled, size, variant });\n const styles = useThemedStyles(switchStyles, { size }, [size]);\n const { thumbStyle, trackStyle } = useSwitchAnimation({\n animationDuration,\n borderWidth,\n checked,\n colors,\n sizeTokens,\n });\n\n const resolvedAccessibilityState = useMemo<AccessibilityState>(\n () => ({\n ...accessibilityState,\n busy: loading,\n checked,\n disabled: interactionDisabled,\n }),\n [accessibilityState, checked, interactionDisabled, loading],\n );\n\n const switchStyle = useCallback(\n (state: PressableStateCallbackType): StyleProp<ViewStyle> =>\n StyleSheet.flatten([\n styles.root,\n typeof style === \"function\" ? style(state) : style,\n ]),\n [style, styles.root],\n );\n\n const handlePress = useCallback(\n (event: GestureResponderEvent) => {\n setChecked((current) => !current);\n onPress?.(event);\n },\n [onPress, setChecked],\n );\n\n const trackAnimatedStyle = useMemo(\n () => [styles.track, trackStyle],\n [styles.track, trackStyle],\n );\n\n const thumbAnimatedStyle = useMemo(\n () => [styles.thumb, thumbStyle],\n [styles.thumb, thumbStyle],\n );\n\n return (\n <Pressable\n {...props}\n accessibilityRole=\"switch\"\n accessibilityState={resolvedAccessibilityState}\n disabled={interactionDisabled}\n hitSlop={hitSlop ?? sizeTokens.hitSlop}\n onPress={handlePress}\n style={switchStyle}\n >\n <Animated.View pointerEvents=\"none\" style={trackAnimatedStyle}>\n <Animated.View style={thumbAnimatedStyle}>\n {loading ? (\n <Spinner\n accessible={false}\n color={loadingIndicatorColor}\n size=\"medium\"\n style={styles.loadingIndicator}\n />\n ) : null}\n </Animated.View>\n </Animated.View>\n </Pressable>\n );\n});\n"],"mappings":"AAyGY;AAlGZ,SAAS,MAAM,aAAa,eAAe;AAC3C,SAAS,kBAAkB;AAC3B,OAAO,cAAc;AAErB,SAAS,4BAA4B;AACrC,SAAS,WAAW,eAAe;AACnC,SAAS,uBAAuB;AAGhC,SAAS,oBAAoB,uBAAuB;AACpD,SAAS,oBAAoB;AAEtB,MAAM,SAAS,KAAK,SAASA,QAAO;AAAA,EACzC;AAAA,EACA,SAAS;AAAA,EACT,iBAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA,UAAU;AAAA,EACV,GAAG;AACL,GAAgB;AACd,QAAM,CAAC,SAAS,UAAU,IAAI,qBAA8B;AAAA,IAC1D,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EACZ,CAAC;AACD,QAAM,sBAAsB,aAAa,QAAQ;AACjD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,gBAAgB,EAAE,UAAU,qBAAqB,MAAM,QAAQ,CAAC;AACpE,QAAM,SAAS,gBAAgB,cAAc,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC;AAC7D,QAAM,EAAE,YAAY,WAAW,IAAI,mBAAmB;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,6BAA6B;AAAA,IACjC,OAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM;AAAA,MACN;AAAA,MACA,UAAU;AAAA,IACZ;AAAA,IACA,CAAC,oBAAoB,SAAS,qBAAqB,OAAO;AAAA,EAC5D;AAEA,QAAM,cAAc;AAAA,IAClB,CAAC,UACC,WAAW,QAAQ;AAAA,MACjB,OAAO;AAAA,MACP,OAAO,UAAU,aAAa,MAAM,KAAK,IAAI;AAAA,IAC/C,CAAC;AAAA,IACH,CAAC,OAAO,OAAO,IAAI;AAAA,EACrB;AAEA,QAAM,cAAc;AAAA,IAClB,CAAC,UAAiC;AAChC,iBAAW,CAAC,YAAY,CAAC,OAAO;AAChC,gBAAU,KAAK;AAAA,IACjB;AAAA,IACA,CAAC,SAAS,UAAU;AAAA,EACtB;AAEA,QAAM,qBAAqB;AAAA,IACzB,MAAM,CAAC,OAAO,OAAO,UAAU;AAAA,IAC/B,CAAC,OAAO,OAAO,UAAU;AAAA,EAC3B;AAEA,QAAM,qBAAqB;AAAA,IACzB,MAAM,CAAC,OAAO,OAAO,UAAU;AAAA,IAC/B,CAAC,OAAO,OAAO,UAAU;AAAA,EAC3B;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,mBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB,UAAU;AAAA,MACV,SAAS,WAAW,WAAW;AAAA,MAC/B,SAAS;AAAA,MACT,OAAO;AAAA,MAEP,8BAAC,SAAS,MAAT,EAAc,eAAc,QAAO,OAAO,oBACzC,8BAAC,SAAS,MAAT,EAAc,OAAO,oBACnB,oBACC;AAAA,QAAC;AAAA;AAAA,UACC,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,MAAK;AAAA,UACL,OAAO,OAAO;AAAA;AAAA,MAChB,IACE,MACN,GACF;AAAA;AAAA,EACF;AAEJ,CAAC;","names":["Switch"]}
1
+ {"version":3,"sources":["../../src/components/switch.tsx"],"sourcesContent":["import type {\n GestureResponderEvent,\n PressableStateCallbackType,\n StyleProp,\n ViewStyle,\n} from \"react-native\";\nimport { memo, useCallback, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\nimport Animated from \"react-native-reanimated\";\n\nimport { useControllableState } from \"@impulse-ui-native/core\";\nimport { Pressable, Spinner } from \"@impulse-ui-native/primitives\";\nimport { useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { SwitchProps } from \"../types\";\nimport { useSwitchAnimation, useSwitchTokens } from \"../hooks\";\nimport { switchStyles } from \"./switch.styles\";\n\nexport const Switch = memo(function Switch({\n checked: checkedProp,\n defaultChecked = false,\n disabled,\n hitSlop,\n loading = false,\n onCheckedChange,\n onPress,\n size = \"medium\",\n style,\n variant = \"filled\",\n ...props\n}: SwitchProps) {\n const [checked, setChecked] = useControllableState<boolean>({\n prop: checkedProp,\n defaultProp: defaultChecked,\n onChange: onCheckedChange,\n });\n const interactionDisabled = disabled === true || loading;\n const {\n animationDuration,\n borderWidth,\n colors,\n loadingIndicatorColor,\n sizeTokens,\n } = useSwitchTokens({ disabled: interactionDisabled, size, variant });\n const styles = useThemedStyles(switchStyles, { size }, [size]);\n const { thumbStyle, trackStyle } = useSwitchAnimation({\n animationDuration,\n borderWidth,\n checked,\n colors,\n sizeTokens,\n });\n\n const switchStyle = useCallback(\n (state: PressableStateCallbackType): StyleProp<ViewStyle> =>\n StyleSheet.flatten([\n styles.root,\n typeof style === \"function\" ? style(state) : style,\n ]),\n [style, styles.root],\n );\n\n const handlePress = useCallback(\n (event: GestureResponderEvent) => {\n setChecked((current) => !current);\n onPress?.(event);\n },\n [onPress, setChecked],\n );\n\n const trackAnimatedStyle = useMemo(\n () => [styles.track, trackStyle],\n [styles.track, trackStyle],\n );\n\n const thumbAnimatedStyle = useMemo(\n () => [styles.thumb, thumbStyle],\n [styles.thumb, thumbStyle],\n );\n\n return (\n <Pressable\n {...props}\n disabled={interactionDisabled}\n hitSlop={hitSlop ?? sizeTokens.hitSlop}\n onPress={handlePress}\n style={switchStyle}\n >\n <Animated.View pointerEvents=\"none\" style={trackAnimatedStyle}>\n <Animated.View style={thumbAnimatedStyle}>\n {loading ? (\n <Spinner\n color={loadingIndicatorColor}\n size=\"medium\"\n style={styles.loadingIndicator}\n />\n ) : null}\n </Animated.View>\n </Animated.View>\n </Pressable>\n );\n});\n"],"mappings":"AA2FY;AArFZ,SAAS,MAAM,aAAa,eAAe;AAC3C,SAAS,kBAAkB;AAC3B,OAAO,cAAc;AAErB,SAAS,4BAA4B;AACrC,SAAS,WAAW,eAAe;AACnC,SAAS,uBAAuB;AAGhC,SAAS,oBAAoB,uBAAuB;AACpD,SAAS,oBAAoB;AAEtB,MAAM,SAAS,KAAK,SAASA,QAAO;AAAA,EACzC,SAAS;AAAA,EACT,iBAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA,UAAU;AAAA,EACV,GAAG;AACL,GAAgB;AACd,QAAM,CAAC,SAAS,UAAU,IAAI,qBAA8B;AAAA,IAC1D,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EACZ,CAAC;AACD,QAAM,sBAAsB,aAAa,QAAQ;AACjD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,gBAAgB,EAAE,UAAU,qBAAqB,MAAM,QAAQ,CAAC;AACpE,QAAM,SAAS,gBAAgB,cAAc,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC;AAC7D,QAAM,EAAE,YAAY,WAAW,IAAI,mBAAmB;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,cAAc;AAAA,IAClB,CAAC,UACC,WAAW,QAAQ;AAAA,MACjB,OAAO;AAAA,MACP,OAAO,UAAU,aAAa,MAAM,KAAK,IAAI;AAAA,IAC/C,CAAC;AAAA,IACH,CAAC,OAAO,OAAO,IAAI;AAAA,EACrB;AAEA,QAAM,cAAc;AAAA,IAClB,CAAC,UAAiC;AAChC,iBAAW,CAAC,YAAY,CAAC,OAAO;AAChC,gBAAU,KAAK;AAAA,IACjB;AAAA,IACA,CAAC,SAAS,UAAU;AAAA,EACtB;AAEA,QAAM,qBAAqB;AAAA,IACzB,MAAM,CAAC,OAAO,OAAO,UAAU;AAAA,IAC/B,CAAC,OAAO,OAAO,UAAU;AAAA,EAC3B;AAEA,QAAM,qBAAqB;AAAA,IACzB,MAAM,CAAC,OAAO,OAAO,UAAU;AAAA,IAC/B,CAAC,OAAO,OAAO,UAAU;AAAA,EAC3B;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,UAAU;AAAA,MACV,SAAS,WAAW,WAAW;AAAA,MAC/B,SAAS;AAAA,MACT,OAAO;AAAA,MAEP,8BAAC,SAAS,MAAT,EAAc,eAAc,QAAO,OAAO,oBACzC,8BAAC,SAAS,MAAT,EAAc,OAAO,oBACnB,oBACC;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,MAAK;AAAA,UACL,OAAO,OAAO;AAAA;AAAA,MAChB,IACE,MACN,GACF;AAAA;AAAA,EACF;AAEJ,CAAC;","names":["Switch"]}
@@ -4,7 +4,6 @@ import {
4
4
  Easing,
5
5
  interpolateColor,
6
6
  useAnimatedStyle,
7
- useReducedMotion,
8
7
  useSharedValue,
9
8
  withTiming
10
9
  } from "react-native-reanimated";
@@ -15,7 +14,6 @@ function useSwitchAnimation({
15
14
  colors,
16
15
  sizeTokens
17
16
  }) {
18
- const reduceMotion = useReducedMotion();
19
17
  const progress = useSharedValue(checked ? 1 : 0);
20
18
  const thumbTravel = sizeTokens.width - sizeTokens.thumbSize - sizeTokens.trackPadding * 2 - borderWidth * 2;
21
19
  const direction = I18nManager.isRTL ? -1 : 1;
@@ -51,10 +49,10 @@ function useSwitchAnimation({
51
49
  );
52
50
  useEffect(() => {
53
51
  progress.value = withTiming(checked ? 1 : 0, {
54
- duration: reduceMotion ? 0 : animationDuration,
52
+ duration: animationDuration,
55
53
  easing: Easing.out(Easing.cubic)
56
54
  });
57
- }, [animationDuration, checked, progress, reduceMotion]);
55
+ }, [animationDuration, checked, progress]);
58
56
  return useMemo(() => ({ thumbStyle, trackStyle }), [thumbStyle, trackStyle]);
59
57
  }
60
58
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/use-switch-animation.hook.ts"],"sourcesContent":["import { useEffect, useMemo } from \"react\";\nimport { I18nManager } from \"react-native\";\nimport {\n Easing,\n interpolateColor,\n useAnimatedStyle,\n useReducedMotion,\n useSharedValue,\n withTiming,\n} from \"react-native-reanimated\";\n\nimport type { SwitchSizeTokens } from \"@impulse-ui-native/theme\";\n\nimport type { SwitchAnimationColors } from \"./use-switch-tokens.hook\";\n\ninterface UseSwitchAnimationOptions {\n animationDuration: number;\n borderWidth: number;\n checked: boolean;\n colors: SwitchAnimationColors;\n sizeTokens: SwitchSizeTokens[keyof SwitchSizeTokens];\n}\n\nexport function useSwitchAnimation({\n animationDuration,\n borderWidth,\n checked,\n colors,\n sizeTokens,\n}: UseSwitchAnimationOptions) {\n const reduceMotion = useReducedMotion();\n const progress = useSharedValue(checked ? 1 : 0);\n\n const thumbTravel =\n sizeTokens.width -\n sizeTokens.thumbSize -\n sizeTokens.trackPadding * 2 -\n borderWidth * 2;\n const direction = I18nManager.isRTL ? -1 : 1;\n\n const trackStyle = useAnimatedStyle(\n () => ({\n backgroundColor: interpolateColor(\n progress.value,\n [0, 1],\n [colors.inactiveBackgroundColor, colors.activeBackgroundColor],\n ),\n borderColor: interpolateColor(\n progress.value,\n [0, 1],\n [colors.inactiveBorderColor, colors.activeBorderColor],\n ),\n }),\n [colors],\n );\n\n const thumbStyle = useAnimatedStyle(\n () => ({\n backgroundColor: interpolateColor(\n progress.value,\n [0, 1],\n [colors.inactiveThumbColor, colors.activeThumbColor],\n ),\n transform: [\n {\n translateX: progress.value * thumbTravel * direction,\n },\n ],\n }),\n [colors, direction, thumbTravel],\n );\n\n useEffect(() => {\n // Reanimated shared values are mutable handles updated from React effects.\n // eslint-disable-next-line react-hooks/immutability\n progress.value = withTiming(checked ? 1 : 0, {\n duration: reduceMotion ? 0 : animationDuration,\n easing: Easing.out(Easing.cubic),\n });\n }, [animationDuration, checked, progress, reduceMotion]);\n\n return useMemo(() => ({ thumbStyle, trackStyle }), [thumbStyle, trackStyle]);\n}\n"],"mappings":"AAAA,SAAS,WAAW,eAAe;AACnC,SAAS,mBAAmB;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAcA,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,eAAe,iBAAiB;AACtC,QAAM,WAAW,eAAe,UAAU,IAAI,CAAC;AAE/C,QAAM,cACJ,WAAW,QACX,WAAW,YACX,WAAW,eAAe,IAC1B,cAAc;AAChB,QAAM,YAAY,YAAY,QAAQ,KAAK;AAE3C,QAAM,aAAa;AAAA,IACjB,OAAO;AAAA,MACL,iBAAiB;AAAA,QACf,SAAS;AAAA,QACT,CAAC,GAAG,CAAC;AAAA,QACL,CAAC,OAAO,yBAAyB,OAAO,qBAAqB;AAAA,MAC/D;AAAA,MACA,aAAa;AAAA,QACX,SAAS;AAAA,QACT,CAAC,GAAG,CAAC;AAAA,QACL,CAAC,OAAO,qBAAqB,OAAO,iBAAiB;AAAA,MACvD;AAAA,IACF;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,aAAa;AAAA,IACjB,OAAO;AAAA,MACL,iBAAiB;AAAA,QACf,SAAS;AAAA,QACT,CAAC,GAAG,CAAC;AAAA,QACL,CAAC,OAAO,oBAAoB,OAAO,gBAAgB;AAAA,MACrD;AAAA,MACA,WAAW;AAAA,QACT;AAAA,UACE,YAAY,SAAS,QAAQ,cAAc;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,WAAW,WAAW;AAAA,EACjC;AAEA,YAAU,MAAM;AAGd,aAAS,QAAQ,WAAW,UAAU,IAAI,GAAG;AAAA,MAC3C,UAAU,eAAe,IAAI;AAAA,MAC7B,QAAQ,OAAO,IAAI,OAAO,KAAK;AAAA,IACjC,CAAC;AAAA,EACH,GAAG,CAAC,mBAAmB,SAAS,UAAU,YAAY,CAAC;AAEvD,SAAO,QAAQ,OAAO,EAAE,YAAY,WAAW,IAAI,CAAC,YAAY,UAAU,CAAC;AAC7E;","names":[]}
1
+ {"version":3,"sources":["../../src/hooks/use-switch-animation.hook.ts"],"sourcesContent":["import { useEffect, useMemo } from \"react\";\nimport { I18nManager } from \"react-native\";\nimport {\n Easing,\n interpolateColor,\n useAnimatedStyle,\n useSharedValue,\n withTiming,\n} from \"react-native-reanimated\";\n\nimport type { SwitchSizeTokens } from \"@impulse-ui-native/theme\";\n\nimport type { SwitchAnimationColors } from \"./use-switch-tokens.hook\";\n\ninterface UseSwitchAnimationOptions {\n animationDuration: number;\n borderWidth: number;\n checked: boolean;\n colors: SwitchAnimationColors;\n sizeTokens: SwitchSizeTokens[keyof SwitchSizeTokens];\n}\n\nexport function useSwitchAnimation({\n animationDuration,\n borderWidth,\n checked,\n colors,\n sizeTokens,\n}: UseSwitchAnimationOptions) {\n const progress = useSharedValue(checked ? 1 : 0);\n\n const thumbTravel =\n sizeTokens.width -\n sizeTokens.thumbSize -\n sizeTokens.trackPadding * 2 -\n borderWidth * 2;\n const direction = I18nManager.isRTL ? -1 : 1;\n\n const trackStyle = useAnimatedStyle(\n () => ({\n backgroundColor: interpolateColor(\n progress.value,\n [0, 1],\n [colors.inactiveBackgroundColor, colors.activeBackgroundColor],\n ),\n borderColor: interpolateColor(\n progress.value,\n [0, 1],\n [colors.inactiveBorderColor, colors.activeBorderColor],\n ),\n }),\n [colors],\n );\n\n const thumbStyle = useAnimatedStyle(\n () => ({\n backgroundColor: interpolateColor(\n progress.value,\n [0, 1],\n [colors.inactiveThumbColor, colors.activeThumbColor],\n ),\n transform: [\n {\n translateX: progress.value * thumbTravel * direction,\n },\n ],\n }),\n [colors, direction, thumbTravel],\n );\n\n useEffect(() => {\n // Reanimated shared values are mutable handles updated from React effects.\n // eslint-disable-next-line react-hooks/immutability\n progress.value = withTiming(checked ? 1 : 0, {\n duration: animationDuration,\n easing: Easing.out(Easing.cubic),\n });\n }, [animationDuration, checked, progress]);\n\n return useMemo(() => ({ thumbStyle, trackStyle }), [thumbStyle, trackStyle]);\n}\n"],"mappings":"AAAA,SAAS,WAAW,eAAe;AACnC,SAAS,mBAAmB;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAcA,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,WAAW,eAAe,UAAU,IAAI,CAAC;AAE/C,QAAM,cACJ,WAAW,QACX,WAAW,YACX,WAAW,eAAe,IAC1B,cAAc;AAChB,QAAM,YAAY,YAAY,QAAQ,KAAK;AAE3C,QAAM,aAAa;AAAA,IACjB,OAAO;AAAA,MACL,iBAAiB;AAAA,QACf,SAAS;AAAA,QACT,CAAC,GAAG,CAAC;AAAA,QACL,CAAC,OAAO,yBAAyB,OAAO,qBAAqB;AAAA,MAC/D;AAAA,MACA,aAAa;AAAA,QACX,SAAS;AAAA,QACT,CAAC,GAAG,CAAC;AAAA,QACL,CAAC,OAAO,qBAAqB,OAAO,iBAAiB;AAAA,MACvD;AAAA,IACF;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,aAAa;AAAA,IACjB,OAAO;AAAA,MACL,iBAAiB;AAAA,QACf,SAAS;AAAA,QACT,CAAC,GAAG,CAAC;AAAA,QACL,CAAC,OAAO,oBAAoB,OAAO,gBAAgB;AAAA,MACrD;AAAA,MACA,WAAW;AAAA,QACT;AAAA,UACE,YAAY,SAAS,QAAQ,cAAc;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,WAAW,WAAW;AAAA,EACjC;AAEA,YAAU,MAAM;AAGd,aAAS,QAAQ,WAAW,UAAU,IAAI,GAAG;AAAA,MAC3C,UAAU;AAAA,MACV,QAAQ,OAAO,IAAI,OAAO,KAAK;AAAA,IACjC,CAAC;AAAA,EACH,GAAG,CAAC,mBAAmB,SAAS,QAAQ,CAAC;AAEzC,SAAO,QAAQ,OAAO,EAAE,YAAY,WAAW,IAAI,CAAC,YAAY,UAAU,CAAC;AAC7E;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@impulse-ui-native/switch",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Animated switch controls for ImpulseUI Native applications.",
5
5
  "keywords": [
6
6
  "react-native",
@@ -29,9 +29,9 @@
29
29
  ],
30
30
  "sideEffects": false,
31
31
  "dependencies": {
32
- "@impulse-ui-native/core": "4.0.0",
33
- "@impulse-ui-native/primitives": "4.0.0",
34
- "@impulse-ui-native/theme": "4.0.0"
32
+ "@impulse-ui-native/primitives": "5.0.0",
33
+ "@impulse-ui-native/core": "5.0.0",
34
+ "@impulse-ui-native/theme": "5.0.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/react": "~19.2.14",
@@ -43,8 +43,8 @@
43
43
  "react-native-worklets": "0.10.1",
44
44
  "typescript": "~6.0.3",
45
45
  "@impulse-ui-native/eslint-config": "1.0.0",
46
- "@impulse-ui-native/prettier-config": "1.0.0",
47
- "@impulse-ui-native/tsconfig": "1.0.0"
46
+ "@impulse-ui-native/tsconfig": "1.0.0",
47
+ "@impulse-ui-native/prettier-config": "1.0.0"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "react": ">=18",