@tamagui/switch 1.0.2 → 1.0.4
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/dist/cjs/Switch.js +12 -8
- package/dist/cjs/Switch.js.map +2 -2
- package/dist/esm/Switch.js +11 -8
- package/dist/esm/Switch.js.map +2 -2
- package/dist/jsx/Switch.js +11 -8
- package/dist/jsx/Switch.js.map +2 -2
- package/package.json +10 -9
- package/src/Switch.tsx +11 -8
package/dist/cjs/Switch.js
CHANGED
|
@@ -37,12 +37,13 @@ var import_compose_refs = require("@tamagui/compose-refs");
|
|
|
37
37
|
var import_core = require("@tamagui/core");
|
|
38
38
|
var import_create_context = require("@tamagui/create-context");
|
|
39
39
|
var import_focusable = require("@tamagui/focusable");
|
|
40
|
+
var import_get_size = require("@tamagui/get-size");
|
|
40
41
|
var import_label = require("@tamagui/label");
|
|
41
42
|
var import_stacks = require("@tamagui/stacks");
|
|
42
43
|
var import_use_controllable_state = require("@tamagui/use-controllable-state");
|
|
43
44
|
var React = __toESM(require("react"));
|
|
44
45
|
const SWITCH_NAME = "Switch";
|
|
45
|
-
const getSwitchHeight = (val) => Math.round((0, import_core.getVariableValue)((0,
|
|
46
|
+
const getSwitchHeight = (val) => Math.round((0, import_core.getVariableValue)((0, import_get_size.getSize)(val)) * 0.65);
|
|
46
47
|
const getSwitchWidth = (val) => getSwitchHeight(val) * 2;
|
|
47
48
|
const scopeContexts = (0, import_create_context.createContextScope)(SWITCH_NAME);
|
|
48
49
|
const [createSwitchContext] = scopeContexts;
|
|
@@ -55,14 +56,17 @@ const SwitchThumbFrame = (0, import_core.styled)(import_stacks.ThemeableStack, {
|
|
|
55
56
|
borderRadius: 1e3,
|
|
56
57
|
variants: {
|
|
57
58
|
size: {
|
|
58
|
-
"...size": (val) =>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
"...size": (val) => {
|
|
60
|
+
const size = getSwitchHeight(val);
|
|
61
|
+
return {
|
|
62
|
+
height: size,
|
|
63
|
+
width: size
|
|
64
|
+
};
|
|
65
|
+
}
|
|
62
66
|
}
|
|
63
67
|
},
|
|
64
68
|
defaultVariants: {
|
|
65
|
-
size: "$
|
|
69
|
+
size: "$true"
|
|
66
70
|
}
|
|
67
71
|
});
|
|
68
72
|
const SwitchThumb = SwitchThumbFrame.extractable(
|
|
@@ -106,7 +110,7 @@ const SwitchFrame = (0, import_core.styled)(import_stacks.XStack, {
|
|
|
106
110
|
}
|
|
107
111
|
},
|
|
108
112
|
defaultVariants: {
|
|
109
|
-
size: "$
|
|
113
|
+
size: "$true"
|
|
110
114
|
}
|
|
111
115
|
});
|
|
112
116
|
const Switch = (0, import_core.withStaticProperties)(
|
|
@@ -123,7 +127,7 @@ const Switch = (0, import_core.withStaticProperties)(
|
|
|
123
127
|
disabled,
|
|
124
128
|
value = "on",
|
|
125
129
|
onCheckedChange,
|
|
126
|
-
size = "$
|
|
130
|
+
size = "$true",
|
|
127
131
|
...switchProps
|
|
128
132
|
} = props;
|
|
129
133
|
const [button, setButton] = React.useState(null);
|
package/dist/cjs/Switch.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Switch.tsx"],
|
|
4
|
-
"sourcesContent": ["// via radix\n// https://github.com/radix-ui/primitives/blob/main/packages/react/switch/src/Switch.tsx\n\nimport { usePrevious } from '@radix-ui/react-use-previous'\nimport { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n SizeTokens,\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["// via radix\n// https://github.com/radix-ui/primitives/blob/main/packages/react/switch/src/Switch.tsx\n\nimport { usePrevious } from '@radix-ui/react-use-previous'\nimport { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n SizeTokens,\n getVariableValue,\n isWeb,\n styled,\n withStaticProperties,\n} from '@tamagui/core'\nimport { ScopedProps, createContextScope } from '@tamagui/create-context'\nimport { registerFocusable } from '@tamagui/focusable'\nimport { getSize } from '@tamagui/get-size'\nimport { useLabelContext } from '@tamagui/label'\nimport { ThemeableStack, XStack } from '@tamagui/stacks'\nimport { useControllableState } from '@tamagui/use-controllable-state'\nimport * as React from 'react'\nimport { View } from 'react-native'\n\nconst SWITCH_NAME = 'Switch'\n\n// TODO make customizable\nconst getSwitchHeight = (val: SizeTokens) =>\n Math.round(getVariableValue(getSize(val)) * 0.65)\nconst getSwitchWidth = (val: SizeTokens) => getSwitchHeight(val) * 2\n\nconst scopeContexts = createContextScope(SWITCH_NAME)\nconst [createSwitchContext] = scopeContexts\nexport const createSwitchScope = scopeContexts[1]\n\nconst [SwitchProvider, useSwitchContext] = createSwitchContext<{\n checked: boolean\n disabled?: boolean\n size: SizeTokens\n}>(SWITCH_NAME)\n\n/* -------------------------------------------------------------------------------------------------\n * SwitchThumb\n * -----------------------------------------------------------------------------------------------*/\n\nconst THUMB_NAME = 'SwitchThumb'\n\nexport const SwitchThumbFrame = styled(ThemeableStack, {\n name: 'SwitchThumb',\n backgroundColor: '$background',\n borderRadius: 1000,\n\n variants: {\n size: {\n '...size': (val) => {\n const size = getSwitchHeight(val)\n return {\n height: size,\n width: size,\n }\n },\n },\n } as const,\n\n defaultVariants: {\n size: '$true',\n },\n})\n\nexport type SwitchThumbProps = GetProps<typeof SwitchThumbFrame>\n\nexport const SwitchThumb = SwitchThumbFrame.extractable(\n React.forwardRef<React.ElementRef<'span'>, SwitchThumbProps>(\n (props: ScopedProps<SwitchThumbProps, 'Switch'>, forwardedRef) => {\n const { __scopeSwitch, ...thumbProps } = props\n const { size, disabled, checked } = useSwitchContext(THUMB_NAME, __scopeSwitch)\n return (\n <SwitchThumbFrame\n size={size}\n data-state={getState(checked)}\n data-disabled={disabled ? '' : undefined}\n {...thumbProps}\n x={\n checked\n ? getVariableValue(getSwitchWidth(size)) -\n getVariableValue(getSwitchHeight(size))\n : 0\n }\n ref={forwardedRef}\n />\n )\n }\n )\n)\n\nSwitchThumb.displayName = THUMB_NAME\n\n/* -------------------------------------------------------------------------------------------------\n * Switch\n * -----------------------------------------------------------------------------------------------*/\n\nexport const SwitchFrame = styled(XStack, {\n name: 'Switch',\n tag: 'button',\n borderRadius: 1000,\n borderWidth: 2,\n borderColor: 'transparent',\n backgroundColor: '$background',\n\n focusStyle: {\n borderColor: '$borderColorFocus',\n },\n\n variants: {\n size: {\n '...size': (val) => {\n const height = getSwitchHeight(val) + 4\n const width = getSwitchWidth(val) + 4\n return {\n height,\n minHeight: height,\n width,\n }\n },\n },\n } as const,\n\n defaultVariants: {\n size: '$true',\n },\n})\n\ntype SwitchButtonProps = GetProps<typeof SwitchFrame>\n\nexport type SwitchProps = SwitchButtonProps & {\n labeledBy?: string\n name?: string\n value?: string\n checked?: boolean\n defaultChecked?: boolean\n required?: boolean\n onCheckedChange?(checked: boolean): void\n}\n\nexport const Switch = withStaticProperties(\n SwitchFrame.extractable(\n React.forwardRef<HTMLButtonElement | View, SwitchProps>(\n (props: ScopedProps<SwitchProps, 'Switch'>, forwardedRef) => {\n const {\n __scopeSwitch,\n labeledBy: ariaLabelledby,\n name,\n checked: checkedProp,\n defaultChecked,\n required,\n disabled,\n value = 'on',\n onCheckedChange,\n size = '$true',\n ...switchProps\n } = props\n const [button, setButton] = React.useState<HTMLButtonElement | null>(null)\n const composedRefs = useComposedRefs(forwardedRef, (node) =>\n setButton(node as any)\n )\n const labelId = useLabelContext(button)\n const labelledBy = ariaLabelledby || labelId\n const hasConsumerStoppedPropagationRef = React.useRef(false)\n // We set this to true by default so that events bubble to forms without JS (SSR)\n const isFormControl = isWeb\n ? button\n ? Boolean(button.closest('form'))\n : true\n : false\n const [checked = false, setChecked] = useControllableState({\n prop: checkedProp,\n defaultProp: defaultChecked || false,\n onChange: onCheckedChange,\n transition: true,\n })\n\n if (!isWeb) {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useEffect(() => {\n if (!props.id) return\n return registerFocusable(props.id, {\n focus: () => {\n setChecked((x) => !x)\n },\n })\n }, [props.id, setChecked])\n }\n\n return (\n <SwitchProvider\n scope={__scopeSwitch}\n checked={checked}\n disabled={disabled}\n size={size}\n >\n <SwitchFrame\n size={size}\n // @ts-ignore\n role=\"switch\"\n aria-checked={checked}\n aria-labelledby={labelledBy}\n aria-required={required}\n data-state={getState(checked)}\n data-disabled={disabled ? '' : undefined}\n disabled={disabled}\n theme={checked ? 'active' : null}\n themeShallow\n // @ts-ignore\n tabIndex={disabled ? undefined : 0}\n // @ts-ignore\n value={value}\n {...switchProps}\n ref={composedRefs}\n onPress={(event) => {\n props.onPress?.(event)\n setChecked((prevChecked) => !prevChecked)\n if (isWeb && isFormControl) {\n hasConsumerStoppedPropagationRef.current = event.isPropagationStopped()\n // if switch is in a form, stop propagation from the button so that we only propagate\n // one click event (from the input). We propagate changes from an input so that native\n // form validation works and form events reflect switch updates.\n if (!hasConsumerStoppedPropagationRef.current) event.stopPropagation()\n }\n }}\n />\n {isWeb && isFormControl && (\n <BubbleInput\n control={button}\n bubbles={!hasConsumerStoppedPropagationRef.current}\n name={name}\n value={value}\n checked={checked}\n required={required}\n disabled={disabled}\n // We transform because the input is absolutely positioned but we have\n // rendered it **after** the button. This pulls it back to sit on top\n // of the button.\n style={{ transform: 'translateX(-100%)' }}\n />\n )}\n </SwitchProvider>\n )\n }\n )\n ),\n {\n Thumb: SwitchThumb,\n }\n)\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype InputProps = any //Radix.ComponentPropsWithoutRef<'input'>\ninterface BubbleInputProps extends Omit<InputProps, 'checked'> {\n checked: boolean\n control: HTMLElement | null\n bubbles: boolean\n}\n\n// TODO make this native friendly\nconst BubbleInput = (props: BubbleInputProps) => {\n const { control, checked, bubbles = true, ...inputProps } = props\n const ref = React.useRef<HTMLInputElement>(null)\n const prevChecked = usePrevious(checked)\n // const controlSize = useSize(control)\n\n // Bubble checked change to parents (e.g form change event)\n React.useEffect(() => {\n const input = ref.current!\n const inputProto = window.HTMLInputElement.prototype\n const descriptor = Object.getOwnPropertyDescriptor(\n inputProto,\n 'checked'\n ) as PropertyDescriptor\n const setChecked = descriptor.set\n if (prevChecked !== checked && setChecked) {\n const event = new Event('click', { bubbles })\n setChecked.call(input, checked)\n input.dispatchEvent(event)\n }\n }, [prevChecked, checked, bubbles])\n\n return (\n <input\n type=\"checkbox\"\n aria-hidden\n defaultChecked={checked}\n {...inputProps}\n tabIndex={-1}\n ref={ref}\n style={{\n ...props.style,\n // ...controlSize,\n position: 'absolute',\n pointerEvents: 'none',\n opacity: 0,\n margin: 0,\n }}\n />\n )\n}\n\nfunction getState(checked: boolean) {\n return checked ? 'checked' : 'unchecked'\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/Switch.js
CHANGED
|
@@ -2,7 +2,6 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { usePrevious } from "@radix-ui/react-use-previous";
|
|
3
3
|
import { useComposedRefs } from "@tamagui/compose-refs";
|
|
4
4
|
import {
|
|
5
|
-
getSize,
|
|
6
5
|
getVariableValue,
|
|
7
6
|
isWeb,
|
|
8
7
|
styled,
|
|
@@ -10,6 +9,7 @@ import {
|
|
|
10
9
|
} from "@tamagui/core";
|
|
11
10
|
import { createContextScope } from "@tamagui/create-context";
|
|
12
11
|
import { registerFocusable } from "@tamagui/focusable";
|
|
12
|
+
import { getSize } from "@tamagui/get-size";
|
|
13
13
|
import { useLabelContext } from "@tamagui/label";
|
|
14
14
|
import { ThemeableStack, XStack } from "@tamagui/stacks";
|
|
15
15
|
import { useControllableState } from "@tamagui/use-controllable-state";
|
|
@@ -28,14 +28,17 @@ const SwitchThumbFrame = styled(ThemeableStack, {
|
|
|
28
28
|
borderRadius: 1e3,
|
|
29
29
|
variants: {
|
|
30
30
|
size: {
|
|
31
|
-
"...size": (val) =>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
"...size": (val) => {
|
|
32
|
+
const size = getSwitchHeight(val);
|
|
33
|
+
return {
|
|
34
|
+
height: size,
|
|
35
|
+
width: size
|
|
36
|
+
};
|
|
37
|
+
}
|
|
35
38
|
}
|
|
36
39
|
},
|
|
37
40
|
defaultVariants: {
|
|
38
|
-
size: "$
|
|
41
|
+
size: "$true"
|
|
39
42
|
}
|
|
40
43
|
});
|
|
41
44
|
const SwitchThumb = SwitchThumbFrame.extractable(
|
|
@@ -79,7 +82,7 @@ const SwitchFrame = styled(XStack, {
|
|
|
79
82
|
}
|
|
80
83
|
},
|
|
81
84
|
defaultVariants: {
|
|
82
|
-
size: "$
|
|
85
|
+
size: "$true"
|
|
83
86
|
}
|
|
84
87
|
});
|
|
85
88
|
const Switch = withStaticProperties(
|
|
@@ -96,7 +99,7 @@ const Switch = withStaticProperties(
|
|
|
96
99
|
disabled,
|
|
97
100
|
value = "on",
|
|
98
101
|
onCheckedChange,
|
|
99
|
-
size = "$
|
|
102
|
+
size = "$true",
|
|
100
103
|
...switchProps
|
|
101
104
|
} = props;
|
|
102
105
|
const [button, setButton] = React.useState(null);
|
package/dist/esm/Switch.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Switch.tsx"],
|
|
4
|
-
"sourcesContent": ["// via radix\n// https://github.com/radix-ui/primitives/blob/main/packages/react/switch/src/Switch.tsx\n\nimport { usePrevious } from '@radix-ui/react-use-previous'\nimport { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n SizeTokens,\n
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["// via radix\n// https://github.com/radix-ui/primitives/blob/main/packages/react/switch/src/Switch.tsx\n\nimport { usePrevious } from '@radix-ui/react-use-previous'\nimport { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n SizeTokens,\n getVariableValue,\n isWeb,\n styled,\n withStaticProperties,\n} from '@tamagui/core'\nimport { ScopedProps, createContextScope } from '@tamagui/create-context'\nimport { registerFocusable } from '@tamagui/focusable'\nimport { getSize } from '@tamagui/get-size'\nimport { useLabelContext } from '@tamagui/label'\nimport { ThemeableStack, XStack } from '@tamagui/stacks'\nimport { useControllableState } from '@tamagui/use-controllable-state'\nimport * as React from 'react'\nimport { View } from 'react-native'\n\nconst SWITCH_NAME = 'Switch'\n\n// TODO make customizable\nconst getSwitchHeight = (val: SizeTokens) =>\n Math.round(getVariableValue(getSize(val)) * 0.65)\nconst getSwitchWidth = (val: SizeTokens) => getSwitchHeight(val) * 2\n\nconst scopeContexts = createContextScope(SWITCH_NAME)\nconst [createSwitchContext] = scopeContexts\nexport const createSwitchScope = scopeContexts[1]\n\nconst [SwitchProvider, useSwitchContext] = createSwitchContext<{\n checked: boolean\n disabled?: boolean\n size: SizeTokens\n}>(SWITCH_NAME)\n\n/* -------------------------------------------------------------------------------------------------\n * SwitchThumb\n * -----------------------------------------------------------------------------------------------*/\n\nconst THUMB_NAME = 'SwitchThumb'\n\nexport const SwitchThumbFrame = styled(ThemeableStack, {\n name: 'SwitchThumb',\n backgroundColor: '$background',\n borderRadius: 1000,\n\n variants: {\n size: {\n '...size': (val) => {\n const size = getSwitchHeight(val)\n return {\n height: size,\n width: size,\n }\n },\n },\n } as const,\n\n defaultVariants: {\n size: '$true',\n },\n})\n\nexport type SwitchThumbProps = GetProps<typeof SwitchThumbFrame>\n\nexport const SwitchThumb = SwitchThumbFrame.extractable(\n React.forwardRef<React.ElementRef<'span'>, SwitchThumbProps>(\n (props: ScopedProps<SwitchThumbProps, 'Switch'>, forwardedRef) => {\n const { __scopeSwitch, ...thumbProps } = props\n const { size, disabled, checked } = useSwitchContext(THUMB_NAME, __scopeSwitch)\n return (\n <SwitchThumbFrame\n size={size}\n data-state={getState(checked)}\n data-disabled={disabled ? '' : undefined}\n {...thumbProps}\n x={\n checked\n ? getVariableValue(getSwitchWidth(size)) -\n getVariableValue(getSwitchHeight(size))\n : 0\n }\n ref={forwardedRef}\n />\n )\n }\n )\n)\n\nSwitchThumb.displayName = THUMB_NAME\n\n/* -------------------------------------------------------------------------------------------------\n * Switch\n * -----------------------------------------------------------------------------------------------*/\n\nexport const SwitchFrame = styled(XStack, {\n name: 'Switch',\n tag: 'button',\n borderRadius: 1000,\n borderWidth: 2,\n borderColor: 'transparent',\n backgroundColor: '$background',\n\n focusStyle: {\n borderColor: '$borderColorFocus',\n },\n\n variants: {\n size: {\n '...size': (val) => {\n const height = getSwitchHeight(val) + 4\n const width = getSwitchWidth(val) + 4\n return {\n height,\n minHeight: height,\n width,\n }\n },\n },\n } as const,\n\n defaultVariants: {\n size: '$true',\n },\n})\n\ntype SwitchButtonProps = GetProps<typeof SwitchFrame>\n\nexport type SwitchProps = SwitchButtonProps & {\n labeledBy?: string\n name?: string\n value?: string\n checked?: boolean\n defaultChecked?: boolean\n required?: boolean\n onCheckedChange?(checked: boolean): void\n}\n\nexport const Switch = withStaticProperties(\n SwitchFrame.extractable(\n React.forwardRef<HTMLButtonElement | View, SwitchProps>(\n (props: ScopedProps<SwitchProps, 'Switch'>, forwardedRef) => {\n const {\n __scopeSwitch,\n labeledBy: ariaLabelledby,\n name,\n checked: checkedProp,\n defaultChecked,\n required,\n disabled,\n value = 'on',\n onCheckedChange,\n size = '$true',\n ...switchProps\n } = props\n const [button, setButton] = React.useState<HTMLButtonElement | null>(null)\n const composedRefs = useComposedRefs(forwardedRef, (node) =>\n setButton(node as any)\n )\n const labelId = useLabelContext(button)\n const labelledBy = ariaLabelledby || labelId\n const hasConsumerStoppedPropagationRef = React.useRef(false)\n // We set this to true by default so that events bubble to forms without JS (SSR)\n const isFormControl = isWeb\n ? button\n ? Boolean(button.closest('form'))\n : true\n : false\n const [checked = false, setChecked] = useControllableState({\n prop: checkedProp,\n defaultProp: defaultChecked || false,\n onChange: onCheckedChange,\n transition: true,\n })\n\n if (!isWeb) {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useEffect(() => {\n if (!props.id) return\n return registerFocusable(props.id, {\n focus: () => {\n setChecked((x) => !x)\n },\n })\n }, [props.id, setChecked])\n }\n\n return (\n <SwitchProvider\n scope={__scopeSwitch}\n checked={checked}\n disabled={disabled}\n size={size}\n >\n <SwitchFrame\n size={size}\n // @ts-ignore\n role=\"switch\"\n aria-checked={checked}\n aria-labelledby={labelledBy}\n aria-required={required}\n data-state={getState(checked)}\n data-disabled={disabled ? '' : undefined}\n disabled={disabled}\n theme={checked ? 'active' : null}\n themeShallow\n // @ts-ignore\n tabIndex={disabled ? undefined : 0}\n // @ts-ignore\n value={value}\n {...switchProps}\n ref={composedRefs}\n onPress={(event) => {\n props.onPress?.(event)\n setChecked((prevChecked) => !prevChecked)\n if (isWeb && isFormControl) {\n hasConsumerStoppedPropagationRef.current = event.isPropagationStopped()\n // if switch is in a form, stop propagation from the button so that we only propagate\n // one click event (from the input). We propagate changes from an input so that native\n // form validation works and form events reflect switch updates.\n if (!hasConsumerStoppedPropagationRef.current) event.stopPropagation()\n }\n }}\n />\n {isWeb && isFormControl && (\n <BubbleInput\n control={button}\n bubbles={!hasConsumerStoppedPropagationRef.current}\n name={name}\n value={value}\n checked={checked}\n required={required}\n disabled={disabled}\n // We transform because the input is absolutely positioned but we have\n // rendered it **after** the button. This pulls it back to sit on top\n // of the button.\n style={{ transform: 'translateX(-100%)' }}\n />\n )}\n </SwitchProvider>\n )\n }\n )\n ),\n {\n Thumb: SwitchThumb,\n }\n)\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype InputProps = any //Radix.ComponentPropsWithoutRef<'input'>\ninterface BubbleInputProps extends Omit<InputProps, 'checked'> {\n checked: boolean\n control: HTMLElement | null\n bubbles: boolean\n}\n\n// TODO make this native friendly\nconst BubbleInput = (props: BubbleInputProps) => {\n const { control, checked, bubbles = true, ...inputProps } = props\n const ref = React.useRef<HTMLInputElement>(null)\n const prevChecked = usePrevious(checked)\n // const controlSize = useSize(control)\n\n // Bubble checked change to parents (e.g form change event)\n React.useEffect(() => {\n const input = ref.current!\n const inputProto = window.HTMLInputElement.prototype\n const descriptor = Object.getOwnPropertyDescriptor(\n inputProto,\n 'checked'\n ) as PropertyDescriptor\n const setChecked = descriptor.set\n if (prevChecked !== checked && setChecked) {\n const event = new Event('click', { bubbles })\n setChecked.call(input, checked)\n input.dispatchEvent(event)\n }\n }, [prevChecked, checked, bubbles])\n\n return (\n <input\n type=\"checkbox\"\n aria-hidden\n defaultChecked={checked}\n {...inputProps}\n tabIndex={-1}\n ref={ref}\n style={{\n ...props.style,\n // ...controlSize,\n position: 'absolute',\n pointerEvents: 'none',\n opacity: 0,\n margin: 0,\n }}\n />\n )\n}\n\nfunction getState(checked: boolean) {\n return checked ? 'checked' : 'unchecked'\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/jsx/Switch.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { usePrevious } from "@radix-ui/react-use-previous";
|
|
2
2
|
import { useComposedRefs } from "@tamagui/compose-refs";
|
|
3
3
|
import {
|
|
4
|
-
getSize,
|
|
5
4
|
getVariableValue,
|
|
6
5
|
isWeb,
|
|
7
6
|
styled,
|
|
@@ -9,6 +8,7 @@ import {
|
|
|
9
8
|
} from "@tamagui/core";
|
|
10
9
|
import { createContextScope } from "@tamagui/create-context";
|
|
11
10
|
import { registerFocusable } from "@tamagui/focusable";
|
|
11
|
+
import { getSize } from "@tamagui/get-size";
|
|
12
12
|
import { useLabelContext } from "@tamagui/label";
|
|
13
13
|
import { ThemeableStack, XStack } from "@tamagui/stacks";
|
|
14
14
|
import { useControllableState } from "@tamagui/use-controllable-state";
|
|
@@ -27,14 +27,17 @@ const SwitchThumbFrame = styled(ThemeableStack, {
|
|
|
27
27
|
borderRadius: 1e3,
|
|
28
28
|
variants: {
|
|
29
29
|
size: {
|
|
30
|
-
"...size": (val) =>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
"...size": (val) => {
|
|
31
|
+
const size = getSwitchHeight(val);
|
|
32
|
+
return {
|
|
33
|
+
height: size,
|
|
34
|
+
width: size
|
|
35
|
+
};
|
|
36
|
+
}
|
|
34
37
|
}
|
|
35
38
|
},
|
|
36
39
|
defaultVariants: {
|
|
37
|
-
size: "$
|
|
40
|
+
size: "$true"
|
|
38
41
|
}
|
|
39
42
|
});
|
|
40
43
|
const SwitchThumb = SwitchThumbFrame.extractable(
|
|
@@ -71,7 +74,7 @@ const SwitchFrame = styled(XStack, {
|
|
|
71
74
|
}
|
|
72
75
|
},
|
|
73
76
|
defaultVariants: {
|
|
74
|
-
size: "$
|
|
77
|
+
size: "$true"
|
|
75
78
|
}
|
|
76
79
|
});
|
|
77
80
|
const Switch = withStaticProperties(
|
|
@@ -88,7 +91,7 @@ const Switch = withStaticProperties(
|
|
|
88
91
|
disabled,
|
|
89
92
|
value = "on",
|
|
90
93
|
onCheckedChange,
|
|
91
|
-
size = "$
|
|
94
|
+
size = "$true",
|
|
92
95
|
...switchProps
|
|
93
96
|
} = props;
|
|
94
97
|
const [button, setButton] = React.useState(null);
|
package/dist/jsx/Switch.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Switch.tsx"],
|
|
4
|
-
"sourcesContent": ["// via radix\n// https://github.com/radix-ui/primitives/blob/main/packages/react/switch/src/Switch.tsx\n\nimport { usePrevious } from '@radix-ui/react-use-previous'\nimport { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n SizeTokens,\n
|
|
5
|
-
"mappings": "AAGA,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAChC;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,
|
|
4
|
+
"sourcesContent": ["// via radix\n// https://github.com/radix-ui/primitives/blob/main/packages/react/switch/src/Switch.tsx\n\nimport { usePrevious } from '@radix-ui/react-use-previous'\nimport { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n SizeTokens,\n getVariableValue,\n isWeb,\n styled,\n withStaticProperties,\n} from '@tamagui/core'\nimport { ScopedProps, createContextScope } from '@tamagui/create-context'\nimport { registerFocusable } from '@tamagui/focusable'\nimport { getSize } from '@tamagui/get-size'\nimport { useLabelContext } from '@tamagui/label'\nimport { ThemeableStack, XStack } from '@tamagui/stacks'\nimport { useControllableState } from '@tamagui/use-controllable-state'\nimport * as React from 'react'\nimport { View } from 'react-native'\n\nconst SWITCH_NAME = 'Switch'\n\n// TODO make customizable\nconst getSwitchHeight = (val: SizeTokens) =>\n Math.round(getVariableValue(getSize(val)) * 0.65)\nconst getSwitchWidth = (val: SizeTokens) => getSwitchHeight(val) * 2\n\nconst scopeContexts = createContextScope(SWITCH_NAME)\nconst [createSwitchContext] = scopeContexts\nexport const createSwitchScope = scopeContexts[1]\n\nconst [SwitchProvider, useSwitchContext] = createSwitchContext<{\n checked: boolean\n disabled?: boolean\n size: SizeTokens\n}>(SWITCH_NAME)\n\n/* -------------------------------------------------------------------------------------------------\n * SwitchThumb\n * -----------------------------------------------------------------------------------------------*/\n\nconst THUMB_NAME = 'SwitchThumb'\n\nexport const SwitchThumbFrame = styled(ThemeableStack, {\n name: 'SwitchThumb',\n backgroundColor: '$background',\n borderRadius: 1000,\n\n variants: {\n size: {\n '...size': (val) => {\n const size = getSwitchHeight(val)\n return {\n height: size,\n width: size,\n }\n },\n },\n } as const,\n\n defaultVariants: {\n size: '$true',\n },\n})\n\nexport type SwitchThumbProps = GetProps<typeof SwitchThumbFrame>\n\nexport const SwitchThumb = SwitchThumbFrame.extractable(\n React.forwardRef<React.ElementRef<'span'>, SwitchThumbProps>(\n (props: ScopedProps<SwitchThumbProps, 'Switch'>, forwardedRef) => {\n const { __scopeSwitch, ...thumbProps } = props\n const { size, disabled, checked } = useSwitchContext(THUMB_NAME, __scopeSwitch)\n return (\n <SwitchThumbFrame\n size={size}\n data-state={getState(checked)}\n data-disabled={disabled ? '' : undefined}\n {...thumbProps}\n x={\n checked\n ? getVariableValue(getSwitchWidth(size)) -\n getVariableValue(getSwitchHeight(size))\n : 0\n }\n ref={forwardedRef}\n />\n )\n }\n )\n)\n\nSwitchThumb.displayName = THUMB_NAME\n\n/* -------------------------------------------------------------------------------------------------\n * Switch\n * -----------------------------------------------------------------------------------------------*/\n\nexport const SwitchFrame = styled(XStack, {\n name: 'Switch',\n tag: 'button',\n borderRadius: 1000,\n borderWidth: 2,\n borderColor: 'transparent',\n backgroundColor: '$background',\n\n focusStyle: {\n borderColor: '$borderColorFocus',\n },\n\n variants: {\n size: {\n '...size': (val) => {\n const height = getSwitchHeight(val) + 4\n const width = getSwitchWidth(val) + 4\n return {\n height,\n minHeight: height,\n width,\n }\n },\n },\n } as const,\n\n defaultVariants: {\n size: '$true',\n },\n})\n\ntype SwitchButtonProps = GetProps<typeof SwitchFrame>\n\nexport type SwitchProps = SwitchButtonProps & {\n labeledBy?: string\n name?: string\n value?: string\n checked?: boolean\n defaultChecked?: boolean\n required?: boolean\n onCheckedChange?(checked: boolean): void\n}\n\nexport const Switch = withStaticProperties(\n SwitchFrame.extractable(\n React.forwardRef<HTMLButtonElement | View, SwitchProps>(\n (props: ScopedProps<SwitchProps, 'Switch'>, forwardedRef) => {\n const {\n __scopeSwitch,\n labeledBy: ariaLabelledby,\n name,\n checked: checkedProp,\n defaultChecked,\n required,\n disabled,\n value = 'on',\n onCheckedChange,\n size = '$true',\n ...switchProps\n } = props\n const [button, setButton] = React.useState<HTMLButtonElement | null>(null)\n const composedRefs = useComposedRefs(forwardedRef, (node) =>\n setButton(node as any)\n )\n const labelId = useLabelContext(button)\n const labelledBy = ariaLabelledby || labelId\n const hasConsumerStoppedPropagationRef = React.useRef(false)\n // We set this to true by default so that events bubble to forms without JS (SSR)\n const isFormControl = isWeb\n ? button\n ? Boolean(button.closest('form'))\n : true\n : false\n const [checked = false, setChecked] = useControllableState({\n prop: checkedProp,\n defaultProp: defaultChecked || false,\n onChange: onCheckedChange,\n transition: true,\n })\n\n if (!isWeb) {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useEffect(() => {\n if (!props.id) return\n return registerFocusable(props.id, {\n focus: () => {\n setChecked((x) => !x)\n },\n })\n }, [props.id, setChecked])\n }\n\n return (\n <SwitchProvider\n scope={__scopeSwitch}\n checked={checked}\n disabled={disabled}\n size={size}\n >\n <SwitchFrame\n size={size}\n // @ts-ignore\n role=\"switch\"\n aria-checked={checked}\n aria-labelledby={labelledBy}\n aria-required={required}\n data-state={getState(checked)}\n data-disabled={disabled ? '' : undefined}\n disabled={disabled}\n theme={checked ? 'active' : null}\n themeShallow\n // @ts-ignore\n tabIndex={disabled ? undefined : 0}\n // @ts-ignore\n value={value}\n {...switchProps}\n ref={composedRefs}\n onPress={(event) => {\n props.onPress?.(event)\n setChecked((prevChecked) => !prevChecked)\n if (isWeb && isFormControl) {\n hasConsumerStoppedPropagationRef.current = event.isPropagationStopped()\n // if switch is in a form, stop propagation from the button so that we only propagate\n // one click event (from the input). We propagate changes from an input so that native\n // form validation works and form events reflect switch updates.\n if (!hasConsumerStoppedPropagationRef.current) event.stopPropagation()\n }\n }}\n />\n {isWeb && isFormControl && (\n <BubbleInput\n control={button}\n bubbles={!hasConsumerStoppedPropagationRef.current}\n name={name}\n value={value}\n checked={checked}\n required={required}\n disabled={disabled}\n // We transform because the input is absolutely positioned but we have\n // rendered it **after** the button. This pulls it back to sit on top\n // of the button.\n style={{ transform: 'translateX(-100%)' }}\n />\n )}\n </SwitchProvider>\n )\n }\n )\n ),\n {\n Thumb: SwitchThumb,\n }\n)\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype InputProps = any //Radix.ComponentPropsWithoutRef<'input'>\ninterface BubbleInputProps extends Omit<InputProps, 'checked'> {\n checked: boolean\n control: HTMLElement | null\n bubbles: boolean\n}\n\n// TODO make this native friendly\nconst BubbleInput = (props: BubbleInputProps) => {\n const { control, checked, bubbles = true, ...inputProps } = props\n const ref = React.useRef<HTMLInputElement>(null)\n const prevChecked = usePrevious(checked)\n // const controlSize = useSize(control)\n\n // Bubble checked change to parents (e.g form change event)\n React.useEffect(() => {\n const input = ref.current!\n const inputProto = window.HTMLInputElement.prototype\n const descriptor = Object.getOwnPropertyDescriptor(\n inputProto,\n 'checked'\n ) as PropertyDescriptor\n const setChecked = descriptor.set\n if (prevChecked !== checked && setChecked) {\n const event = new Event('click', { bubbles })\n setChecked.call(input, checked)\n input.dispatchEvent(event)\n }\n }, [prevChecked, checked, bubbles])\n\n return (\n <input\n type=\"checkbox\"\n aria-hidden\n defaultChecked={checked}\n {...inputProps}\n tabIndex={-1}\n ref={ref}\n style={{\n ...props.style,\n // ...controlSize,\n position: 'absolute',\n pointerEvents: 'none',\n opacity: 0,\n margin: 0,\n }}\n />\n )\n}\n\nfunction getState(checked: boolean) {\n return checked ? 'checked' : 'unchecked'\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/switch",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"sideEffects": [
|
|
5
5
|
"*.css"
|
|
6
6
|
],
|
|
@@ -24,13 +24,14 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@radix-ui/react-use-previous": "^0.1.1",
|
|
27
|
-
"@tamagui/compose-refs": "^1.0.
|
|
28
|
-
"@tamagui/core": "^1.0.
|
|
29
|
-
"@tamagui/create-context": "^1.0.
|
|
30
|
-
"@tamagui/focusable": "^1.0.
|
|
31
|
-
"@tamagui/
|
|
32
|
-
"@tamagui/
|
|
33
|
-
"@tamagui/
|
|
27
|
+
"@tamagui/compose-refs": "^1.0.4",
|
|
28
|
+
"@tamagui/core": "^1.0.4",
|
|
29
|
+
"@tamagui/create-context": "^1.0.4",
|
|
30
|
+
"@tamagui/focusable": "^1.0.4",
|
|
31
|
+
"@tamagui/get-size": "^1.0.4",
|
|
32
|
+
"@tamagui/label": "^1.0.4",
|
|
33
|
+
"@tamagui/stacks": "^1.0.4",
|
|
34
|
+
"@tamagui/use-controllable-state": "^1.0.4"
|
|
34
35
|
},
|
|
35
36
|
"peerDependencies": {
|
|
36
37
|
"react": "*",
|
|
@@ -38,7 +39,7 @@
|
|
|
38
39
|
"react-native": "*"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
|
-
"@tamagui/build": "^1.0.
|
|
42
|
+
"@tamagui/build": "^1.0.4",
|
|
42
43
|
"react": "^18.2.0",
|
|
43
44
|
"react-dom": "^18.2.0",
|
|
44
45
|
"react-native": "*"
|
package/src/Switch.tsx
CHANGED
|
@@ -6,7 +6,6 @@ import { useComposedRefs } from '@tamagui/compose-refs'
|
|
|
6
6
|
import {
|
|
7
7
|
GetProps,
|
|
8
8
|
SizeTokens,
|
|
9
|
-
getSize,
|
|
10
9
|
getVariableValue,
|
|
11
10
|
isWeb,
|
|
12
11
|
styled,
|
|
@@ -14,6 +13,7 @@ import {
|
|
|
14
13
|
} from '@tamagui/core'
|
|
15
14
|
import { ScopedProps, createContextScope } from '@tamagui/create-context'
|
|
16
15
|
import { registerFocusable } from '@tamagui/focusable'
|
|
16
|
+
import { getSize } from '@tamagui/get-size'
|
|
17
17
|
import { useLabelContext } from '@tamagui/label'
|
|
18
18
|
import { ThemeableStack, XStack } from '@tamagui/stacks'
|
|
19
19
|
import { useControllableState } from '@tamagui/use-controllable-state'
|
|
@@ -50,15 +50,18 @@ export const SwitchThumbFrame = styled(ThemeableStack, {
|
|
|
50
50
|
|
|
51
51
|
variants: {
|
|
52
52
|
size: {
|
|
53
|
-
'...size': (val) =>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
'...size': (val) => {
|
|
54
|
+
const size = getSwitchHeight(val)
|
|
55
|
+
return {
|
|
56
|
+
height: size,
|
|
57
|
+
width: size,
|
|
58
|
+
}
|
|
59
|
+
},
|
|
57
60
|
},
|
|
58
61
|
} as const,
|
|
59
62
|
|
|
60
63
|
defaultVariants: {
|
|
61
|
-
size: '$
|
|
64
|
+
size: '$true',
|
|
62
65
|
},
|
|
63
66
|
})
|
|
64
67
|
|
|
@@ -121,7 +124,7 @@ export const SwitchFrame = styled(XStack, {
|
|
|
121
124
|
} as const,
|
|
122
125
|
|
|
123
126
|
defaultVariants: {
|
|
124
|
-
size: '$
|
|
127
|
+
size: '$true',
|
|
125
128
|
},
|
|
126
129
|
})
|
|
127
130
|
|
|
@@ -151,7 +154,7 @@ export const Switch = withStaticProperties(
|
|
|
151
154
|
disabled,
|
|
152
155
|
value = 'on',
|
|
153
156
|
onCheckedChange,
|
|
154
|
-
size = '$
|
|
157
|
+
size = '$true',
|
|
155
158
|
...switchProps
|
|
156
159
|
} = props
|
|
157
160
|
const [button, setButton] = React.useState<HTMLButtonElement | null>(null)
|