From d236a661d2490f28e868bfaf95c67821b58b4b2f Mon Sep 17 00:00:00 2001 From: Vidhi Kataria Date: Mon, 29 Jan 2024 11:37:32 +0530 Subject: [PATCH 01/12] feat: slider flow setup --- .../storybook/.ondevice/storybook.requires.js | 2 + example/storybook/babel.config.js | 4 + example/storybook/metro.config.js | 2 +- example/storybook/package.json | 2 +- .../Forms/RangeSlider/RangeSlider.png | Bin 0 -> 13209 bytes .../Forms/RangeSlider/RangeSlider.stories.tsx | 11 + .../Forms/RangeSlider/RangeSlider.tsx | 108 ++++++++++ .../components/Forms/Slider/index.stories.mdx | 1 - example/storybook/tsconfig.json | 3 + .../config/src/theme/RangeSliderLeftThumb.ts | 57 +++++ .../config/src/theme/RangeSliderRightThumb.ts | 57 +++++ packages/config/src/theme/index.ts | 2 + packages/themed/babel.config.js | 28 +++ packages/themed/package.json | 1 + .../src/components/RangeSlider/config.json | 4 + .../src/components/RangeSlider/index.tsx | 24 +++ .../styled-components/FilledTrack.tsx | 7 + .../styled-components/LeftThumb.tsx | 7 + .../styled-components/RightThumb.tsx | 7 + .../RangeSlider/styled-components/Root.tsx | 7 + .../styled-components/ThumbInteraction.tsx | 6 + .../RangeSlider/styled-components/Track.tsx | 7 + .../RangeSlider/styled-components/index.tsx | 6 + packages/themed/src/components/index.tsx | 1 + packages/themed/tsconfig.json | 6 +- packages/unstyled/range-slider/.npmignore | 20 ++ packages/unstyled/range-slider/CHANGELOG.md | 91 ++++++++ packages/unstyled/range-slider/README.md | 76 +++++++ .../unstyled/range-slider/babel.config.js | 21 ++ packages/unstyled/range-slider/package.json | 106 ++++++++++ packages/unstyled/range-slider/src/Context.ts | 3 + .../range-slider/src/RangeSlider-aria.tsx | 158 ++++++++++++++ .../unstyled/range-slider/src/RangeSlider.tsx | 158 ++++++++++++++ .../src/RangeSliderFilledTrack.tsx | 101 +++++++++ .../range-slider/src/RangeSliderLeftThumb.tsx | 197 ++++++++++++++++++ .../src/RangeSliderRightThumb.tsx | 182 ++++++++++++++++ .../src/RangeSliderTrack-aria.tsx | 52 +++++ .../range-slider/src/RangeSliderTrack.tsx | 56 +++++ packages/unstyled/range-slider/src/index.tsx | 53 +++++ packages/unstyled/range-slider/src/types.tsx | 96 +++++++++ packages/unstyled/range-slider/tsconfig.json | 32 +++ yarn.lock | 4 +- 42 files changed, 1759 insertions(+), 7 deletions(-) create mode 100644 example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.png create mode 100644 example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.stories.tsx create mode 100644 example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx create mode 100644 packages/config/src/theme/RangeSliderLeftThumb.ts create mode 100644 packages/config/src/theme/RangeSliderRightThumb.ts create mode 100644 packages/themed/babel.config.js create mode 100644 packages/themed/src/components/RangeSlider/config.json create mode 100644 packages/themed/src/components/RangeSlider/index.tsx create mode 100644 packages/themed/src/components/RangeSlider/styled-components/FilledTrack.tsx create mode 100644 packages/themed/src/components/RangeSlider/styled-components/LeftThumb.tsx create mode 100644 packages/themed/src/components/RangeSlider/styled-components/RightThumb.tsx create mode 100644 packages/themed/src/components/RangeSlider/styled-components/Root.tsx create mode 100644 packages/themed/src/components/RangeSlider/styled-components/ThumbInteraction.tsx create mode 100644 packages/themed/src/components/RangeSlider/styled-components/Track.tsx create mode 100644 packages/themed/src/components/RangeSlider/styled-components/index.tsx create mode 100644 packages/unstyled/range-slider/.npmignore create mode 100644 packages/unstyled/range-slider/CHANGELOG.md create mode 100644 packages/unstyled/range-slider/README.md create mode 100644 packages/unstyled/range-slider/babel.config.js create mode 100644 packages/unstyled/range-slider/package.json create mode 100644 packages/unstyled/range-slider/src/Context.ts create mode 100644 packages/unstyled/range-slider/src/RangeSlider-aria.tsx create mode 100644 packages/unstyled/range-slider/src/RangeSlider.tsx create mode 100644 packages/unstyled/range-slider/src/RangeSliderFilledTrack.tsx create mode 100644 packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx create mode 100644 packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx create mode 100644 packages/unstyled/range-slider/src/RangeSliderTrack-aria.tsx create mode 100644 packages/unstyled/range-slider/src/RangeSliderTrack.tsx create mode 100644 packages/unstyled/range-slider/src/index.tsx create mode 100644 packages/unstyled/range-slider/src/types.tsx create mode 100644 packages/unstyled/range-slider/tsconfig.json diff --git a/example/storybook/.ondevice/storybook.requires.js b/example/storybook/.ondevice/storybook.requires.js index d5c8a4345f..28a7d65406 100644 --- a/example/storybook/.ondevice/storybook.requires.js +++ b/example/storybook/.ondevice/storybook.requires.js @@ -84,6 +84,8 @@ const getStories = () => { // require('../src/components/Layout/VStack/VStack.stories.tsx'), // require('../src/components/Layout/LinearGradient/LinearGradient.stories.tsx'), // require('../src/components/Forms/Tabs/Tabs.stories.tsx'), + require('../src/ui/components/Forms/RangeSlider/RangeSlider.stories.tsx'), + require('../src/ui/components/Forms/Slider/Slider.stories.tsx'), // require('../src/components/MediaAndIcons/Image/Image.stories.tsx'), // require('../src/react-native-components/FlatList/FlatList.stories.tsx'), // require('../src/react-native-components/SectionList/SectionList.stories.tsx'), diff --git a/example/storybook/babel.config.js b/example/storybook/babel.config.js index 2005bb67fb..fbe0aa803c 100644 --- a/example/storybook/babel.config.js +++ b/example/storybook/babel.config.js @@ -45,6 +45,10 @@ module.exports = function (api) { __dirname, '../../packages/unstyled/avatar/src' ), + '@gluestack-ui/range-slider': path.join( + __dirname, + '../../packages/unstyled/range-slider/src' + ), '@gluestack-ui/button': path.join( __dirname, '../../packages/unstyled/button/src' diff --git a/example/storybook/metro.config.js b/example/storybook/metro.config.js index 75447906eb..e95320da78 100644 --- a/example/storybook/metro.config.js +++ b/example/storybook/metro.config.js @@ -32,4 +32,4 @@ config.transformer.getTransformOptions = async () => ({ config.watchFolders = [...config.watchFolders]; -module.exports = config; +module.exports = config; \ No newline at end of file diff --git a/example/storybook/package.json b/example/storybook/package.json index 1cbda254e8..6ff96bc3f9 100644 --- a/example/storybook/package.json +++ b/example/storybook/package.json @@ -56,7 +56,7 @@ "react": "^18.2.0", "react-aria": "^3.30.0", "react-dom": "^18.2.0", - "react-native": "0.72.4", + "react-native": "^0.73.2", "react-native-gesture-handler": "^2.12.1", "react-native-safe-area-context": "^4.4.1", "react-native-svg": "13.4.0", diff --git a/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.png b/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.png new file mode 100644 index 0000000000000000000000000000000000000000..cbf37081d79f9d3b0c30e58fd3aceb0289a36ee0 GIT binary patch literal 13209 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 Q9|^djrLS46Zu{te0KxsO*8l(j literal 0 HcmV?d00001 diff --git a/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.stories.tsx b/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.stories.tsx new file mode 100644 index 0000000000..59ee74a69e --- /dev/null +++ b/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.stories.tsx @@ -0,0 +1,11 @@ +import type { ComponentMeta } from '@storybook/react-native'; +import RangeSlide from './RangeSlider'; + +const SliderMeta: ComponentMeta = { + title: 'stories/FORMS/Range Slider', + component: RangeSlide, +}; + +export default SliderMeta; + +export { RangeSlide }; diff --git a/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx b/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx new file mode 100644 index 0000000000..46ae708992 --- /dev/null +++ b/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx @@ -0,0 +1,108 @@ +import React, { useState } from 'react'; +import { + Text, + Slider, + SliderTrack, + SliderFilledTrack, + SliderThumb, + VStack, + HStack, + Box, + Icon, + Heading, + Tooltip, + TooltipContent, + Button, + Center, + RangeSlider, + RangeSliderTrack, + RangeSliderFilledTrack, + RangeSliderLeftThumb, + RangeSliderRightThumb, + View, + ButtonText, +} from '@gluestack-ui/themed'; +// import { createRangeSlider } from '@gluestack-ui/range-slider'; +import { Volume, Volume2Icon, LightbulbIcon } from 'lucide-react-native'; + +const RangeSliderBasic = ({ value: valueProp, ...props }: any) => { + const [sliderValue, setSliderValue] = React.useState([30, 49]); + const [height, setHeight] = useState(30); + const handleChange = (values: any) => { + setSliderValue(values); + }; + return ( +
+ { + console.log(values, 'values '); + handleChange(values); + }} + orientation="vertical" + > + + + + {/* */} + + + {/* { + handleChange(values); + }} + > + + + + + + */} +
+ ); +}; + +RangeSliderBasic.description = + 'This is a basic RangeSlider component example. RangeSlider are used to select a value from a range of values.'; + +export default RangeSliderBasic; + +export { + RangeSlider, + RangeSliderTrack, + RangeSliderFilledTrack, + RangeSliderLeftThumb, + RangeSliderRightThumb, + VStack, + Volume, + HStack, + Volume2Icon, + Text, + Box, + LightbulbIcon, + Icon, + Heading, + Tooltip, + TooltipContent, + Button, + Center, +}; diff --git a/example/storybook/src/ui/components/Forms/Slider/index.stories.mdx b/example/storybook/src/ui/components/Forms/Slider/index.stories.mdx index c5d005beb6..9dd57610dd 100644 --- a/example/storybook/src/ui/components/Forms/Slider/index.stories.mdx +++ b/example/storybook/src/ui/components/Forms/Slider/index.stories.mdx @@ -889,7 +889,6 @@ export default () => ( ``` --> - ## Spec Doc Explore the comprehensive details of the Slider in this document, including its implementation details, checklist, and potential future additions. Dive into the thought process behind the component and gain insights into its development journey. diff --git a/example/storybook/tsconfig.json b/example/storybook/tsconfig.json index 50a1359be5..19ca5cc699 100644 --- a/example/storybook/tsconfig.json +++ b/example/storybook/tsconfig.json @@ -5,6 +5,9 @@ "paths": { "@gluestack-ui/themed": ["../../packages/themed/src"], "@gluestack-ui/config": ["../../packages/config/src/gluestack-ui.config"], + "@gluestack-ui/range-slider": [ + "../../packages/unstyled/range-slider/src" + ], "react-native": ["./node_modules/react-native-web"], "@gluestack-style/react": ["../../packages/styled/react/src"], "@gluestack-style/animation-resolver": [ diff --git a/packages/config/src/theme/RangeSliderLeftThumb.ts b/packages/config/src/theme/RangeSliderLeftThumb.ts new file mode 100644 index 0000000000..06a0869e08 --- /dev/null +++ b/packages/config/src/theme/RangeSliderLeftThumb.ts @@ -0,0 +1,57 @@ +import { createStyle } from '@gluestack-style/react'; + +export const RangeSliderLeftThumb = createStyle({ + 'bg': '$primary500', + '_dark': { + bg: '$primary400', + }, + 'position': 'absolute', + 'borderRadius': '$full', + ':focus': { + bg: '$primary600', + _dark: { + bg: '$primary300', + }, + }, + ':active': { + bg: '$primary600', + _dark: { + bg: '$primary300', + }, + }, + ':hover': { + bg: '$primary600', + _dark: { + bg: '$primary300', + }, + }, + ':disabled': { + bg: '$primary500', + _dark: { + bg: '$primary500', + }, + }, + '_web': { + //@ts-ignore + 'cursor': 'pointer', + ':active': { + outlineWidth: 4, + outlineStyle: 'solid', + outlineColor: '$primary400', + _dark: { + outlineColor: '$primary500', + }, + }, + ':focus': { + outlineWidth: 4, + outlineStyle: 'solid', + outlineColor: '$primary400', + _dark: { + outlineColor: '$primary500', + }, + }, + }, + 'defaultProps': { + hardShadow: '1', + }, +}); diff --git a/packages/config/src/theme/RangeSliderRightThumb.ts b/packages/config/src/theme/RangeSliderRightThumb.ts new file mode 100644 index 0000000000..da61a9751b --- /dev/null +++ b/packages/config/src/theme/RangeSliderRightThumb.ts @@ -0,0 +1,57 @@ +import { createStyle } from '@gluestack-style/react'; + +export const RangeSliderRightThumb = createStyle({ + 'bg': '$red500', + '_dark': { + bg: '$primary400', + }, + 'position': 'absolute', + 'borderRadius': '$full', + ':focus': { + bg: '$primary600', + _dark: { + bg: '$primary300', + }, + }, + ':active': { + bg: '$primary600', + _dark: { + bg: '$primary300', + }, + }, + ':hover': { + bg: '$primary600', + _dark: { + bg: '$primary300', + }, + }, + ':disabled': { + bg: '$primary500', + _dark: { + bg: '$primary500', + }, + }, + '_web': { + //@ts-ignore + 'cursor': 'pointer', + ':active': { + outlineWidth: 4, + outlineStyle: 'solid', + outlineColor: '$primary400', + _dark: { + outlineColor: '$primary500', + }, + }, + ':focus': { + outlineWidth: 4, + outlineStyle: 'solid', + outlineColor: '$primary400', + _dark: { + outlineColor: '$primary500', + }, + }, + }, + 'defaultProps': { + hardShadow: '1', + }, +}); diff --git a/packages/config/src/theme/index.ts b/packages/config/src/theme/index.ts index a9c555f87f..1fe2a1117c 100644 --- a/packages/config/src/theme/index.ts +++ b/packages/config/src/theme/index.ts @@ -147,3 +147,5 @@ export * from './TooltipContent'; export * from './TooltipText'; export * from './VStack'; export * from './View'; +export * from './RangeSliderLeftThumb'; +export * from './RangeSliderRightThumb'; diff --git a/packages/themed/babel.config.js b/packages/themed/babel.config.js new file mode 100644 index 0000000000..3924eab8cd --- /dev/null +++ b/packages/themed/babel.config.js @@ -0,0 +1,28 @@ +const path = require('path'); +module.exports = function (api) { + api.cache(true); + return { + presets: ['babel-preset-expo'], + plugins: [ + process.env.NODE_ENV !== 'production' + ? [ + 'module-resolver', + { + alias: { + '@gluestack-ui/range-slider': path.join( + __dirname, + '../unstyled/range-slider/src' + ), + }, + }, + ] + : [ + 'babel-plugin-react-docgen-typescript', + { + exclude: 'node_modules', + }, + ], + '@babel/plugin-transform-modules-commonjs', + ], + }; +}; diff --git a/packages/themed/package.json b/packages/themed/package.json index c52e4f64d3..32604280d0 100644 --- a/packages/themed/package.json +++ b/packages/themed/package.json @@ -55,6 +55,7 @@ "@gluestack-ui/progress": "0.1.12", "@gluestack-ui/provider": "0.1.10", "@gluestack-ui/radio": "0.1.23", + "@gluestack-ui/range-slider": "*", "@gluestack-ui/select": "0.1.21", "@gluestack-ui/slider": "0.1.19", "@gluestack-ui/spinner": "0.1.14", diff --git a/packages/themed/src/components/RangeSlider/config.json b/packages/themed/src/components/RangeSlider/config.json new file mode 100644 index 0000000000..7b0813defc --- /dev/null +++ b/packages/themed/src/components/RangeSlider/config.json @@ -0,0 +1,4 @@ +{ + "dependencies": { "@gluestack-ui/slider": "latest" }, + "keywords": ["components", "core"] +} diff --git a/packages/themed/src/components/RangeSlider/index.tsx b/packages/themed/src/components/RangeSlider/index.tsx new file mode 100644 index 0000000000..1430df22fa --- /dev/null +++ b/packages/themed/src/components/RangeSlider/index.tsx @@ -0,0 +1,24 @@ +import { createRangeSlider } from '@gluestack-ui/range-slider'; + +import { + Root, + LeftThumb, + RightThumb, + Track, + FilledTrack, + ThumbInteraction, +} from './styled-components'; + +export const RangeSlider = createRangeSlider({ + Root, + LeftThumb, + RightThumb, + Track, + FilledTrack, + ThumbInteraction, +}); + +export const RangeSliderLeftThumb = RangeSlider.LeftThumb; +export const RangeSliderRightThumb = RangeSlider.RightThumb; +export const RangeSliderTrack = RangeSlider.Track; +export const RangeSliderFilledTrack = RangeSlider.FilledTrack; diff --git a/packages/themed/src/components/RangeSlider/styled-components/FilledTrack.tsx b/packages/themed/src/components/RangeSlider/styled-components/FilledTrack.tsx new file mode 100644 index 0000000000..0350da835d --- /dev/null +++ b/packages/themed/src/components/RangeSlider/styled-components/FilledTrack.tsx @@ -0,0 +1,7 @@ +import { styled } from '@gluestack-style/react'; +import { View } from 'react-native'; + +export default styled(View, {}, { + componentName: 'SliderFilledTrack', + ancestorStyle: ['_filledTrack'], +} as const); diff --git a/packages/themed/src/components/RangeSlider/styled-components/LeftThumb.tsx b/packages/themed/src/components/RangeSlider/styled-components/LeftThumb.tsx new file mode 100644 index 0000000000..c6b0d826cf --- /dev/null +++ b/packages/themed/src/components/RangeSlider/styled-components/LeftThumb.tsx @@ -0,0 +1,7 @@ +import { styled } from '@gluestack-style/react'; +import { View } from 'react-native'; + +export default styled(View, {}, { + componentName: 'RangeSliderLeftThumb', + ancestorStyle: ['_thumb'], +} as const); diff --git a/packages/themed/src/components/RangeSlider/styled-components/RightThumb.tsx b/packages/themed/src/components/RangeSlider/styled-components/RightThumb.tsx new file mode 100644 index 0000000000..2687060d34 --- /dev/null +++ b/packages/themed/src/components/RangeSlider/styled-components/RightThumb.tsx @@ -0,0 +1,7 @@ +import { styled } from '@gluestack-style/react'; +import { View } from 'react-native'; + +export default styled(View, {}, { + componentName: 'RangeSliderRightThumb', + ancestorStyle: ['_thumb'], +} as const); diff --git a/packages/themed/src/components/RangeSlider/styled-components/Root.tsx b/packages/themed/src/components/RangeSlider/styled-components/Root.tsx new file mode 100644 index 0000000000..52116c5dba --- /dev/null +++ b/packages/themed/src/components/RangeSlider/styled-components/Root.tsx @@ -0,0 +1,7 @@ +// @ts-nocheck +import { styled } from '@gluestack-style/react'; +import { View } from 'react-native'; +export default styled(View, {}, { + componentName: 'Slider', + descendantStyle: ['_thumb', '_track', '_filledTrack'], +} as const); diff --git a/packages/themed/src/components/RangeSlider/styled-components/ThumbInteraction.tsx b/packages/themed/src/components/RangeSlider/styled-components/ThumbInteraction.tsx new file mode 100644 index 0000000000..2a90e25ed9 --- /dev/null +++ b/packages/themed/src/components/RangeSlider/styled-components/ThumbInteraction.tsx @@ -0,0 +1,6 @@ +import { styled } from '@gluestack-style/react'; +import { View } from 'react-native'; + +export default styled(View, {}, { + componentName: 'SliderThumbInteraction', +} as const); diff --git a/packages/themed/src/components/RangeSlider/styled-components/Track.tsx b/packages/themed/src/components/RangeSlider/styled-components/Track.tsx new file mode 100644 index 0000000000..57b1d79756 --- /dev/null +++ b/packages/themed/src/components/RangeSlider/styled-components/Track.tsx @@ -0,0 +1,7 @@ +import { styled } from '@gluestack-style/react'; +import { Pressable } from 'react-native'; + +export default styled(Pressable, {}, { + componentName: 'SliderTrack', + ancestorStyle: ['_track'], +} as const); diff --git a/packages/themed/src/components/RangeSlider/styled-components/index.tsx b/packages/themed/src/components/RangeSlider/styled-components/index.tsx new file mode 100644 index 0000000000..c33bf2bc25 --- /dev/null +++ b/packages/themed/src/components/RangeSlider/styled-components/index.tsx @@ -0,0 +1,6 @@ +export { default as Root } from './Root'; +export { default as LeftThumb } from './LeftThumb'; +export { default as RightThumb } from './RightThumb'; +export { default as Track } from './Track'; +export { default as FilledTrack } from './FilledTrack'; +export { default as ThumbInteraction } from './ThumbInteraction'; diff --git a/packages/themed/src/components/index.tsx b/packages/themed/src/components/index.tsx index 7b1005b6d9..32cb8be697 100644 --- a/packages/themed/src/components/index.tsx +++ b/packages/themed/src/components/index.tsx @@ -46,3 +46,4 @@ export * from './Icons/Icons'; export * from './VirtualizedList'; export * from './RefreshControl'; export * from './ImageBackground'; +export * from './RangeSlider'; diff --git a/packages/themed/tsconfig.json b/packages/themed/tsconfig.json index 4728950c79..b4674d8ec2 100644 --- a/packages/themed/tsconfig.json +++ b/packages/themed/tsconfig.json @@ -1,11 +1,13 @@ { "include": ["./src"], "exclude": ["node_modules", "example"], - "path": {}, "compilerOptions": { + "paths": { + "@gluestack-ui/range-slider": ["../unstyled/range-slider/src"] + }, "ignoreDeprecations": "5.0", "noEmit": false, - "declaration": true, + "declaration": false, "allowJs": true, "allowUnreachableCode": false, "allowUnusedLabels": true, diff --git a/packages/unstyled/range-slider/.npmignore b/packages/unstyled/range-slider/.npmignore new file mode 100644 index 0000000000..187790b632 --- /dev/null +++ b/packages/unstyled/range-slider/.npmignore @@ -0,0 +1,20 @@ +# Dotfiles +.babelrc +.eslintignore +.eslintrc.json +.gitattributes +_config.yml +.editorconfig + + +#Config files +babel.config.js + +# Documents +CONTRIBUTING.md +ISSUE_TEMPLATE.txt +img + +# Test cases +__tests__ +dist/__tests__ diff --git a/packages/unstyled/range-slider/CHANGELOG.md b/packages/unstyled/range-slider/CHANGELOG.md new file mode 100644 index 0000000000..cd903f472c --- /dev/null +++ b/packages/unstyled/range-slider/CHANGELOG.md @@ -0,0 +1,91 @@ +# @gluestack-ui/slider + +## 0.1.19 + +### Patch Changes + +- Updated dependencies + - @gluestack-ui/hooks@0.1.11 + +## 0.1.12 + +### Patch Changes + +- Reversed functionality fixed + +## 0.1.11 + +### Patch Changes + +- fix: figma refactor + +## 0.1.10 + +### Patch Changes + +- Changed component APIs from dot notation to normal +- Updated dependencies + - @gluestack-ui/form-control@0.1.10 + +## 0.1.9 + +### Patch Changes + +- Fixed slider with orientation and reversed and moved out style from styled files + +## 0.1.8 + +### Patch Changes + +- Added support for isReversed and orientation prop. + +## 0.1.7 + +### Patch Changes + +- component typings updated + +## 0.1.6 + +### Patch Changes + +- included path links in compilerOptions in tsconfig file +- Updated dependencies + - @gluestack-ui/form-control@0.1.8 + - @gluestack-ui/hooks@0.1.2 + - @gluestack-ui/utils@0.1.5 + +## 0.1.5 + +### Patch Changes + +- feat: migration of hook to react native aria +- Updated dependencies + - @gluestack-ui/form-control@0.1.7 + +## 0.1.4 + +### Patch Changes + +- package json and readme fixes +- Updated dependencies + - @gluestack-ui/hooks@0.1.1 + - @gluestack-ui/utils@0.1.4 + +## 0.1.3 + +### Patch Changes + +- fix forwardref warning issues + +## 0.1.2 + +### Patch Changes + +- added form control support + +## 0.1.1 + +### Patch Changes + +- added accessibility diff --git a/packages/unstyled/range-slider/README.md b/packages/unstyled/range-slider/README.md new file mode 100644 index 0000000000..d8bf6733e7 --- /dev/null +++ b/packages/unstyled/range-slider/README.md @@ -0,0 +1,76 @@ +# @gluestack-ui/slider + +## Installation + +To use `@gluestack-ui/slider`, all you need to do is install the +`@gluestack-ui/slider` package: + +```sh +$ yarn add @gluestack-ui/slider + +# or + +$ npm i @gluestack-ui/slider +``` + +## Usage + +The Slider component enables an intuitive selection of values within a designated range. Users can easily adjust their selection by sliding a visual indicator along the track. Here's an example how to use this package to create one: + +```jsx +import { + Root, + Thumb, + Track, + FilledTrack, + ThumbInteraction, +} from '../components/core/slider/styled-components'; +import { createSlider } from '@gluestack-ui/slider'; +const Slider = createSlider({ + Root, + Thumb, + Track, + FilledTrack, + ThumbInteraction, +}); +``` + +## Customizing the slider: + +Default styling of all these components can be found in the components/core/slider file. For reference, you can view the [source code](https://github.com/gluestack/gluestack-ui/blob/development/example/storybook/src/ui-components/Slider/index.tsx) of the styled `slider` components. + +```jsx +// import the styles +import { + Root, + Thumb, + Track, + FilledTrack, + ThumbInteraction, +} from '../components/core/slider/styled-components'; + +// import the createSlider function +import { createSlider } from '@gluestack-ui/slider'; + +// Understanding the API +const Slider = createSlider({ + Root, + Thumb, + Track, + FilledTrack, + ThumbInteraction, +}); + +// Using the Slider component +export default () => ( + + + + + + +); +``` + +More guides on how to get started are available +[here](https://ui.gluestack.io/docs/components/forms/slider). diff --git a/packages/unstyled/range-slider/babel.config.js b/packages/unstyled/range-slider/babel.config.js new file mode 100644 index 0000000000..8f87f2b1cf --- /dev/null +++ b/packages/unstyled/range-slider/babel.config.js @@ -0,0 +1,21 @@ +const path = require('path'); + +module.exports = function (api) { + api.cache(true); + return { + presets: ['babel-preset-expo'], + plugins: [ + process.env.NODE_ENV !== 'production' + ? [ + 'module-resolver', + { + alias: { + // ['@gluestack-ui/utils']: path.resolve(__dirname, '../utils/src'), + // For development, we want to alias the library to the source + }, + }, + ] + : ['babel-plugin-react-docgen-typescript', { exclude: 'node_modules' }], + ], + }; +}; diff --git a/packages/unstyled/range-slider/package.json b/packages/unstyled/range-slider/package.json new file mode 100644 index 0000000000..8e06f211a9 --- /dev/null +++ b/packages/unstyled/range-slider/package.json @@ -0,0 +1,106 @@ +{ + "name": "@gluestack-ui/range-slider", + "description": "A universal headless slider component for React Native, Next.js & React", + "version": "0.1.0", + "main": "lib/commonjs/index", + "module": "lib/module/index", + "types": "lib/typescript/index.d.ts", + "react-native": "src/index", + "source": "src/index", + "typings": "lib/typescript/index.d.ts", + "scripts": { + "prepare": "bob build", + "release": "release-it", + "build": "bob build", + "clean": "rm -rf lib", + "dev:web": "cd example/native && yarn web --clear", + "storybook": "cd example/native/storybook && yarn web" + }, + "devDependencies": { + "@types/react": "^18.0.22", + "@types/react-native": "^0.72.3", + "babel-plugin-transform-remove-console": "^6.9.4", + "react": "^18.1.0", + "react-dom": "^18.1.0", + "react-native": "^0.72.4", + "react-native-builder-bob": "^0.20.1", + "react-native-web": "^0.19.9", + "tsconfig": "7", + "typescript": "^4.9.4" + }, + "dependencies": { + "@gluestack-ui/form-control": "^0.1.14", + "@gluestack-ui/hooks": "0.1.11", + "@gluestack-ui/utils": "^0.1.12", + "@react-aria/visually-hidden": "^3.8.1", + "@react-native-aria/interactions": "^0.2.11", + "@react-native-aria/slider": "^0.2.10", + "@react-stately/slider": "^3.2.4" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + }, + "react-native-builder-bob": { + "source": "src", + "output": "lib", + "targets": [ + "commonjs", + [ + "module" + ], + "typescript" + ] + }, + "files": [ + "lib/", + "src/" + ], + "jest": { + "preset": "jest-expo", + "transform": { + "^.+\\.js$": "/node_modules/react-native/jest/preprocessor.js" + }, + "modulePathIgnorePatterns": [ + "/example/*", + "/lib/" + ], + "transformIgnorePatterns": [ + "node_modules/(?!(@react-native|react-native|expo-asset|expo-constants|@unimodules|react-native-unimodules|expo-font|react-native-svg|@expo/vector-icons|react-native-vector-icons|@react-native-aria/checkbox|@react-native-aria/interactions|@react-native-aria/button|@react-native-aria/switch|@react-native-aria/toggle|@react-native-aria/utils|@react-native-aria/*))" + ], + "setupFiles": [ + "/src/jest/mock.ts" + ] + }, + "release-it": { + "git": { + "commitMessage": "chore: release ${version}", + "tagName": "v${version}" + }, + "npm": { + "publish": true + }, + "github": { + "release": true + }, + "plugins": { + "@release-it/conventional-changelog": { + "preset": "angular" + } + } + }, + "keywords": [ + "react", + "native", + "react-native", + "slider", + "gluestack-ui", + "universal", + "headless", + "typescript", + "component", + "android", + "ios", + "nextjs" + ] +} diff --git a/packages/unstyled/range-slider/src/Context.ts b/packages/unstyled/range-slider/src/Context.ts new file mode 100644 index 0000000000..1e8acfcbe6 --- /dev/null +++ b/packages/unstyled/range-slider/src/Context.ts @@ -0,0 +1,3 @@ +import React from 'react'; + +export const RangeSliderContext = React.createContext({}); diff --git a/packages/unstyled/range-slider/src/RangeSlider-aria.tsx b/packages/unstyled/range-slider/src/RangeSlider-aria.tsx new file mode 100644 index 0000000000..3d648f6f70 --- /dev/null +++ b/packages/unstyled/range-slider/src/RangeSlider-aria.tsx @@ -0,0 +1,158 @@ +import React, { forwardRef } from 'react'; +import { useSliderState } from '@react-stately/slider'; +import { useLayout } from '@gluestack-ui/hooks'; +import type { IRangeSliderProps } from './types'; +import { RangeSliderContext } from './Context'; +import { useSlider } from '@react-aria/slider'; +import { useFormControlContext } from '@gluestack-ui/form-control'; + +function RangeSlider( + StyledRangeSlider: React.ComponentType +) { + return forwardRef( + ( + { + orientation = 'horizontal', + isReversed = false, + 'isHovered': isHoveredProp, + 'isDisabled': isDisabledProp, + 'isFocused': isFocusedProp, + 'isFocusVisible': isFocusVisibleProp, + 'isPressed': isPressedProp, + // @ts-ignore + 'aria-label': ariaLabel = 'Slider', + children, + ...props + }: StyledSliderProps & IRangeSliderProps, + ref?: any + ) => { + const formControlContext = useFormControlContext(); + + const { isDisabled, isReadOnly, ...newProps } = { + ...formControlContext, + ...props, + 'aria-label': ariaLabel, + } as any; + let trackRef = React.useRef(null); + // @ts-ignore + if (props.value && props?.value?.prop?.constructor === Array) { + //@ts-ignore - React Native Aria slider accepts array of values + newProps.value = props.value; + } + + if ( + props.defaultValue && + // @ts-ignore + props?.defaultValue?.prop?.constructor === Array + ) { + //@ts-ignore - React Native Aria slider accepts array of values + newProps.defaultValue = props.defaultValue; + } + props = newProps; + + const { onLayout, layout: trackLayout } = useLayout(); + const updatedProps: IRangeSliderProps = Object.assign({}, props); + + if (isReadOnly || isDisabled) { + updatedProps.isDisabled = true; + } + + const state = useSliderState({ + ...updatedProps, + //@ts-ignore + numberFormatter: { format: (e) => e }, + minValue: props.minValue, + maxValue: props.maxValue, + orientation: orientation ?? 'horizontal', + // orientation: 'vertical', + onChange: (val: any) => { + console.log(val, 'values >>>>>>'); + props.onChange && props.onChange(val); + }, + onChangeEnd: (val: any) => { + props.onChangeEnd && props.onChangeEnd(val); + }, + }); + const { groupProps, trackProps, outputProps } = useSlider( + props as unknown as any, + state, + trackRef + ); + const [isFocused, setIsFocused] = React.useState(false); + const [isFocusVisible, setIsFocusVisible] = React.useState(false); + const [isHovered, setIsHovered] = React.useState(false); + const [isPressed, setIsPressed] = React.useState(false); + const contextValue = React.useMemo(() => { + return { + trackLayout, + state, + orientation: orientation, + isDisabled: isDisabled, + isFocused: isFocused, + setIsFocused: setIsFocused, + isFocusVisible: isFocusVisible, + setIsFocusVisible: setIsFocusVisible, + outputProps, + isPressed: isPressed, + setIsPressed: setIsPressed, + isHovered: isHovered, + setIsHovered: setIsHovered, + isReversed: isReversed, + trackProps, + trackRef, + isReadOnly: isReadOnly, + onTrackLayout: onLayout, + isHoveredProp, + isDisabledProp, + isFocusedProp, + isFocusVisibleProp, + isPressedProp, + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + trackProps, + trackRef, + trackLayout, + state, + orientation, + isDisabled, + isReversed, + isReadOnly, + onLayout, + isFocused, + setIsFocused, + isFocusVisible, + setIsFocusVisible, + isPressed, + setIsPressed, + isHoveredProp, + isDisabledProp, + isFocusedProp, + isFocusVisibleProp, + isPressedProp, + ]); + // console.log(groupProps, 'GROUPPPP'); + return ( + + + {children} + + + ); + } + ); +} +export default RangeSlider; diff --git a/packages/unstyled/range-slider/src/RangeSlider.tsx b/packages/unstyled/range-slider/src/RangeSlider.tsx new file mode 100644 index 0000000000..123422da98 --- /dev/null +++ b/packages/unstyled/range-slider/src/RangeSlider.tsx @@ -0,0 +1,158 @@ +import React, { forwardRef } from 'react'; +import { useSliderState } from '@react-stately/slider'; +import { useLayout } from '@gluestack-ui/hooks'; +import type { IRangeSliderProps } from './types'; +import { RangeSliderContext } from './Context'; +import { useSlider } from '@react-native-aria/slider'; +import { useFormControlContext } from '@gluestack-ui/form-control'; + +function RangeSlider( + StyledRangeSlider: React.ComponentType +) { + return forwardRef( + ( + { + orientation = 'horizontal', + isReversed = false, + 'isHovered': isHoveredProp, + 'isDisabled': isDisabledProp, + 'isFocused': isFocusedProp, + 'isFocusVisible': isFocusVisibleProp, + 'isPressed': isPressedProp, + // @ts-ignore + 'aria-label': ariaLabel = 'Slider', + children, + ...props + }: StyledSliderProps & IRangeSliderProps, + ref?: any + ) => { + const formControlContext = useFormControlContext(); + + const { isDisabled, isReadOnly, ...newProps } = { + ...formControlContext, + ...props, + 'aria-label': ariaLabel, + } as any; + let trackRef = React.useRef(null); + // @ts-ignore + if (props.value && props?.value?.prop?.constructor === Array) { + //@ts-ignore - React Native Aria slider accepts array of values + newProps.value = props.value; + } + + if ( + props.defaultValue && + // @ts-ignore + props?.defaultValue?.prop?.constructor === Array + ) { + //@ts-ignore - React Native Aria slider accepts array of values + newProps.defaultValue = props.defaultValue; + } + props = newProps; + + const { onLayout, layout: trackLayout } = useLayout(); + const updatedProps: IRangeSliderProps = Object.assign({}, props); + + if (isReadOnly || isDisabled) { + updatedProps.isDisabled = true; + } + + const state = useSliderState({ + ...updatedProps, + //@ts-ignore + numberFormatter: { format: (e) => e }, + minValue: props.minValue, + maxValue: props.maxValue, + orientation: orientation ?? 'horizontal', + // orientation: 'vertical', + onChange: (val: any) => { + props.onChange && props.onChange(val); + }, + onChangeEnd: (val: any) => { + props.onChangeEnd && props.onChangeEnd(val); + }, + }); + + const { groupProps, trackProps, outputProps } = useSlider( + props as unknown as any, + state, + trackRef + ); + const [isFocused, setIsFocused] = React.useState(false); + const [isFocusVisible, setIsFocusVisible] = React.useState(false); + const [isHovered, setIsHovered] = React.useState(false); + // const [isPressed, setIsPressed] = React.useState(false); + const contextValue = React.useMemo(() => { + return { + trackLayout, + state, + orientation: orientation, + isDisabled: isDisabled, + isFocused: isFocused, + setIsFocused: setIsFocused, + isFocusVisible: isFocusVisible, + setIsFocusVisible: setIsFocusVisible, + outputProps, + // isPressed: isPressed, + // setIsPressed: setIsPressed, + isHovered: isHovered, + setIsHovered: setIsHovered, + isReversed: isReversed, + trackProps, + trackRef, + isReadOnly: isReadOnly, + onTrackLayout: onLayout, + isHoveredProp, + isDisabledProp, + isFocusedProp, + isFocusVisibleProp, + isPressedProp, + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + trackProps, + trackRef, + trackLayout, + state, + orientation, + isDisabled, + isReversed, + isReadOnly, + onLayout, + isFocused, + setIsFocused, + isFocusVisible, + setIsFocusVisible, + // isPressed, + // setIsPressed, + isHoveredProp, + isDisabledProp, + isFocusedProp, + isFocusVisibleProp, + isPressedProp, + ]); + + return ( + + + {children} + + + ); + } + ); +} +export default RangeSlider; diff --git a/packages/unstyled/range-slider/src/RangeSliderFilledTrack.tsx b/packages/unstyled/range-slider/src/RangeSliderFilledTrack.tsx new file mode 100644 index 0000000000..43fd37aef5 --- /dev/null +++ b/packages/unstyled/range-slider/src/RangeSliderFilledTrack.tsx @@ -0,0 +1,101 @@ +import React, { forwardRef } from 'react'; +import { RangeSliderContext } from './Context'; +import { Platform } from 'react-native'; +import { mergeRefs } from '@gluestack-ui/utils'; + +function RangeSliderFilledTrack( + StyledSliderFilledTrack: React.ComponentType +) { + return forwardRef( + ( + { + _experimentalSliderFilledTrack = false, + _experimentalSliderFilledTrackValue = 0, + style, + ...props + }: any, + ref?: any + ) => { + const _ref = React.useRef(null); + + const { + state, + trackLayout, + orientation, + isDisabled, + isFocused, + isHovered, + isPressed, + isFocusVisible, + isHoveredProp, + isDisabledProp, + isFocusedProp, + isFocusVisibleProp, + isPressedProp, + } = React.useContext(RangeSliderContext); + + const getSliderTrackPosition = () => { + if (orientation === 'vertical') { + return ( + trackLayout.height - + (trackLayout.height * state.getThumbPercent(0) + + (trackLayout.height - + trackLayout.height * state.getThumbPercent(1))) + ); + } else { + return ( + trackLayout.width - + (trackLayout.width * state.getThumbPercent(0) + + (trackLayout.width - + trackLayout.width * state.getThumbPercent(1))) + ); + + // return trackLayout.width * state.getThumbPercent(0); + } + }; + + const sliderTrackPosition = getSliderTrackPosition(); + + let positionProps = + orientation === 'vertical' + ? { + height: Math.abs(sliderTrackPosition), + bottom: trackLayout?.height * state.getThumbPercent(0), + position: 'absolute', + } + : { + width: sliderTrackPosition, + left: trackLayout?.width * state.getThumbPercent(0), + }; + // if (_experimentalSliderFilledTrack) { + // // @ts-ignore + // positionProps = + // orientation === 'vertical' + // ? { height: _experimentalSliderFilledTrackValue } + // : { width: _experimentalSliderFilledTrackValue }; + // } + return ( + + ); + } + ); +} +export default RangeSliderFilledTrack; diff --git a/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx b/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx new file mode 100644 index 0000000000..d528d2599b --- /dev/null +++ b/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx @@ -0,0 +1,197 @@ +import React, { forwardRef, useEffect } from 'react'; +import { Platform } from 'react-native'; +import { useSliderThumb } from '@react-native-aria/slider'; +import { VisuallyHidden } from '@react-aria/visually-hidden'; +import { RangeSliderContext } from './Context'; +import { useHover } from '@react-native-aria/interactions'; +import { mergeRefs } from '@gluestack-ui/utils'; +import type { IRangeSliderThumbProps } from './types'; +import { useFocusRing, useFocus } from '@react-native-aria/focus'; +import { composeEventHandlers } from '@gluestack-ui/utils'; + +const positionMap = new Map([ + ['horizontal true', 'right'], + ['horizontal false', 'left'], + ['vertical true', 'top'], + ['vertical false', 'bottom'], +]); +const LeftThumbIndex = 0; +function RangeSliderThumb< + StyledRangeSliderThumb, + StyledRangeSliderThumbInteraction +>( + StyledRangeSliderThumb: React.ComponentType, + StyledRangeSliderThumbInteraction: React.ComponentType +) { + return forwardRef( + ( + { + children, + scaleOnPressed = 1, + style, + ...props + }: StyledRangeSliderThumbInteraction & + StyledRangeSliderThumbInteraction & + IRangeSliderThumbProps & { children?: any; style?: any }, + ref?: any + ) => { + const [thumbSize, setThumbSize] = React.useState({ + height: 0, + width: 0, + }); + + const _ref = React.useRef(null); + const { isHovered } = useHover({}, _ref); + // const [isFocused, setIsFocused] = React.useState(false) + + // const [isFocusVisible, setIsFocusVisible] = React.useState(false); + // const [isHovered, setIsHovered] = React.useState(false); + const [isPressed, setIsPressed] = React.useState(false); + const { + state, + trackLayout, + orientation, + isDisabled, + isReversed, + // isPressed, + setIsHovered, + // setIsPressed, + setIsFocused, + setIsFocusVisible, + isHoveredProp, + isDisabledProp, + isFocusedProp, + isFocusVisibleProp, + isPressedProp, + trackRef, + } = React.useContext(RangeSliderContext); + const handleFocus = (focusState: boolean, callback: any) => { + setIsFocused(focusState); + callback(); + }; + const inputRef = React.useRef(null); + const { thumbProps, inputProps } = useSliderThumb( + { + index: LeftThumbIndex, + trackLayout, + inputRef, + orientation: orientation, + }, + state, + isReversed + ); + const { isFocusVisible, focusProps: focusRingProps }: any = + useFocusRing(); + const { isFocused, focusProps } = useFocus(); + + const thumbStyles: any = { + // transform: + // orientation === 'vertical' + // ? [ + // { + // translateY: isReversed + // ? -thumbSize?.height / 2 + // : thumbSize?.height / 2, + // }, + // ] + // : [ + // { + // translateX: isReversed + // ? thumbSize?.height / 2 + // : -thumbSize?.height / 2, + // }, + // ], + }; + + thumbStyles[`${positionMap.get(`${orientation} ${isReversed}`)}`] = `${ + state.getThumbPercent(LeftThumbIndex) * 100 + }%`; + console.log(state, '<< { + // setIsPressed(state.isThumbDragging(LeftThumbIndex)); + // }, [state, setIsPressed, isPressed]); + React.useEffect(() => { + setIsPressed(state.isThumbDragging(LeftThumbIndex)); + }, [state, setIsPressed, isPressed]); + + useEffect(() => { + setIsFocused(isFocused); + }, [isFocused, setIsFocused]); + + useEffect(() => { + setIsFocusVisible(isFocusVisible); + }, [isFocusVisible, setIsFocusVisible]); + + useEffect(() => { + setIsHovered(isHovered); + }, [isHovered, setIsHovered]); + + return ( + { + setThumbSize({ + height: layout?.nativeEvent?.layout?.height, + width: layout?.nativeEvent?.layout?.width, + }); + }} + states={{ + hover: isHovered || isHoveredProp, + disabled: isDisabled || isDisabledProp, + focus: isFocused || isFocusedProp, + focusVisible: isFocusVisible || isFocusVisibleProp, + active: isPressed || isPressedProp, + }} + disabled={isDisabled} + {...thumbProps} + style={{ + ...style, + ...thumbStyles, + }} + // style={{ + // // @ts-ignore + // }} + // @ts-ignore - web only + onFocus={composeEventHandlers( + composeEventHandlers(props?.onFocus, focusProps.onFocus), + focusRingProps.onFocus + )} + // @ts-ignore - web only + onBlur={composeEventHandlers( + composeEventHandlers(props?.onBlur, focusProps.onBlur), + focusRingProps.onBlur + )} + ref={mergeRefs([mergeRefs([_ref, ref]), trackRef])} + {...props} + > + {/* @ts-ignore */} + + {children} + {Platform.OS === 'web' && ( + + + + )} + + + ); + } + ); +} +export default RangeSliderThumb; diff --git a/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx b/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx new file mode 100644 index 0000000000..4878eaf367 --- /dev/null +++ b/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx @@ -0,0 +1,182 @@ +import React, { forwardRef, useEffect } from 'react'; +import { Platform } from 'react-native'; +import { useSliderThumb } from '@react-native-aria/slider'; +import { VisuallyHidden } from '@react-aria/visually-hidden'; +import { RangeSliderContext } from './Context'; +import { useHover } from '@react-native-aria/interactions'; +import { mergeRefs } from '@gluestack-ui/utils'; +import type { IRangeSliderThumbProps } from './types'; +import { useFocusRing, useFocus } from '@react-native-aria/focus'; +import { composeEventHandlers } from '@gluestack-ui/utils'; + +const positionMap = new Map([ + ['horizontal true', 'right'], + ['horizontal false', 'left'], + ['vertical true', 'top'], + ['vertical false', 'bottom'], +]); +const RightThumbIndex = 1; + +function RangeSliderThumb< + StyledRangeSliderThumb, + StyledRangeSliderThumbInteraction +>( + StyledRangeSliderThumb: React.ComponentType, + StyledRangeSliderThumbInteraction: React.ComponentType +) { + return forwardRef( + ( + { + children, + scaleOnPressed = 1, + style, + ...props + }: StyledRangeSliderThumbInteraction & + StyledRangeSliderThumbInteraction & + IRangeSliderThumbProps & { children?: any; style?: any }, + ref?: any + ) => { + const [thumbSize, setThumbSize] = React.useState({ + height: 0, + width: 0, + }); + + const _ref = React.useRef(null); + const { isHovered } = useHover({}, _ref); + const [isPressed, setIsPressed] = React.useState(false); + + const { + state, + trackLayout, + orientation, + isDisabled, + isReversed, + // isPressed, + setIsHovered, + // setIsPressed, + setIsFocused, + setIsFocusVisible, + isHoveredProp, + isDisabledProp, + isFocusedProp, + isFocusVisibleProp, + isPressedProp, + } = React.useContext(RangeSliderContext); + + const inputRef = React.useRef(null); + const { thumbProps, inputProps } = useSliderThumb( + { + index: RightThumbIndex, + trackLayout, + inputRef, + orientation: orientation, + }, + state, + isReversed + ); + const { isFocusVisible, focusProps: focusRingProps }: any = + useFocusRing(); + const { isFocused, focusProps } = useFocus(); + + const thumbStyles: any = { + // transform: + // orientation === 'vertical' + // ? [ + // { + // translateY: isReversed + // ? -thumbSize?.height / 2 + // : thumbSize?.height / 2, + // }, + // ] + // : [ + // { + // translateX: isReversed + // ? thumbSize?.height / 2 + // : -thumbSize?.height / 2, + // }, + // ], + }; + + thumbStyles[`${positionMap.get(`${orientation} ${isReversed}`)}`] = `${ + state.getThumbPercent(RightThumbIndex) * 100 + }%`; + thumbStyles?.transform?.push({ + transform: { + translateX: trackLayout.width ? -trackLayout.width / 2 : 0, + }, + // scale: state.isThumbDragging(0) ? scaleOnPressed : 1, + }); + + useEffect(() => { + setIsPressed(state.isThumbDragging(RightThumbIndex)); + }, [state]); + + useEffect(() => { + setIsFocused(isFocused); + }, [isFocused, setIsFocused]); + + useEffect(() => { + setIsFocusVisible(isFocusVisible); + }, [isFocusVisible, setIsFocusVisible]); + + useEffect(() => { + setIsHovered(isHovered); + }, [isHovered, setIsHovered]); + + return ( + { + setThumbSize({ + height: layout?.nativeEvent?.layout?.height, + width: layout?.nativeEvent?.layout?.width, + }); + }} + states={{ + hover: isHovered || isHoveredProp, + disabled: isDisabled || isDisabledProp, + focus: isFocused || isFocusedProp, + focusVisible: isFocusVisible || isFocusVisibleProp, + active: isPressed || isPressedProp, + }} + disabled={isDisabled} + {...thumbProps} + style={{ + ...style, + ...thumbStyles, + }} + // @ts-ignore - web only + onFocus={composeEventHandlers( + composeEventHandlers(props?.onFocus, focusProps.onFocus), + focusRingProps.onFocus + )} + // @ts-ignore - web only + onBlur={composeEventHandlers( + composeEventHandlers(props?.onBlur, focusProps.onBlur), + focusRingProps.onBlur + )} + ref={mergeRefs([_ref, ref])} + {...props} + > + {/* @ts-ignore */} + + {children} + {Platform.OS === 'web' && ( + + + + )} + + + ); + } + ); +} +export default RangeSliderThumb; diff --git a/packages/unstyled/range-slider/src/RangeSliderTrack-aria.tsx b/packages/unstyled/range-slider/src/RangeSliderTrack-aria.tsx new file mode 100644 index 0000000000..92bd4cbeb7 --- /dev/null +++ b/packages/unstyled/range-slider/src/RangeSliderTrack-aria.tsx @@ -0,0 +1,52 @@ +import React, { forwardRef } from 'react'; +import { RangeSliderContext } from './Context'; +import { mergeRefs } from '@gluestack-ui/utils'; +import { useHover } from '@react-native-aria/interactions'; + +function RangeSliderTrack( + StyledRangeSliderTrack: React.ComponentType +) { + return forwardRef(({ children, style, ...props }: any, ref?: any) => { + const _ref = React.useRef(null); + const { isHovered } = useHover({}, _ref); + const { + trackProps, + onTrackLayout, + isFocused, + isFocusVisible, + isDisabled, + isPressed, + isHoveredProp, + isDisabledProp, + isFocusedProp, + isFocusVisibleProp, + isPressedProp, + } = React.useContext(RangeSliderContext); + // const [isPressed, setIsPressed] = React.useState(false); + // console.log(trackProps, 'TTTTTTTT'); + const { onMouseDown } = trackProps; + + return ( + + {children} + + ); + }); +} +export default RangeSliderTrack; diff --git a/packages/unstyled/range-slider/src/RangeSliderTrack.tsx b/packages/unstyled/range-slider/src/RangeSliderTrack.tsx new file mode 100644 index 0000000000..ebb745d695 --- /dev/null +++ b/packages/unstyled/range-slider/src/RangeSliderTrack.tsx @@ -0,0 +1,56 @@ +import React, { forwardRef } from 'react'; +import { RangeSliderContext } from './Context'; +import { mergeRefs } from '@gluestack-ui/utils'; +import { useHover } from '@react-native-aria/interactions'; + +function RangeSliderTrack( + StyledRangeSliderTrack: React.ComponentType +) { + return forwardRef(({ children, style, ...props }: any, ref?: any) => { + const _ref = React.useRef(null); + const { isHovered } = useHover({}, _ref); + const { + trackProps, + onTrackLayout, + isFocused, + isFocusVisible, + isDisabled, + isPressed, + isHoveredProp, + isDisabledProp, + isFocusedProp, + isFocusVisibleProp, + isPressedProp, + } = React.useContext(RangeSliderContext); + // const [isPressed, setIsPressed] = React.useState(false); + console.log(trackProps, 'TTTTTTTT'); + // const { onMouseDown, onPointerDown, onTouchStart, onKeyDown } = trackProps; + return
hello
; + // return ( + // { + // console.log(e, '<<<<<'); + // onPointerDown(e); + // }} + // style={{ ...style }} + // {...props} + // isDisabled={isDisabled} + // tabIndex={-1} + // states={{ + // hover: isHovered || isHoveredProp, + // disabled: isDisabled || isDisabledProp, + // focus: isFocused || isFocusedProp, + // focusVisible: isFocusVisible || isFocusVisibleProp, + // active: isPressed || isPressedProp, + // }} + // disabled={isDisabled} + // > + // {children} + // + // ); + }); +} +export default RangeSliderTrack; diff --git a/packages/unstyled/range-slider/src/index.tsx b/packages/unstyled/range-slider/src/index.tsx new file mode 100644 index 0000000000..3ed5e92ad0 --- /dev/null +++ b/packages/unstyled/range-slider/src/index.tsx @@ -0,0 +1,53 @@ +import RangeSliderMain from './RangeSlider-aria'; +import RangeSliderLeftThumb from './RangeSliderLeftThumb'; +import RangeSliderRightThumb from './RangeSliderRightThumb'; +import RangeSliderTrack from './RangeSliderTrack-aria'; +import RangeSliderFilledTrack from './RangeSliderFilledTrack'; +import type { IRangeSliderComponentType } from './types'; + +export { RangeSliderContext } from './Context'; + +export type { IRangeSliderProps } from './types'; + +export function createRangeSlider< + RangeSliderProps, + RangeSliderThumbInteractionProps, + RangeSliderLeftThumbProps, + RangeSliderRightThumbProps, + RangeSliderTrackProps, + RangeSliderFilledTrackProps +>({ + Root, + ThumbInteraction, + LeftThumb, + RightThumb, + Track, + FilledTrack, +}: { + Root: React.ComponentType; + LeftThumb: React.ComponentType; + RightThumb: React.ComponentType; + ThumbInteraction: React.ComponentType; + Track: React.ComponentType; + FilledTrack: React.ComponentType; +}) { + const RangeSlider: any = RangeSliderMain(Root); + RangeSlider.LeftThumb = RangeSliderLeftThumb(LeftThumb, ThumbInteraction); + RangeSlider.RightThumb = RangeSliderRightThumb(RightThumb, ThumbInteraction); + RangeSlider.Track = RangeSliderTrack(Track); + RangeSlider.FilledTrack = RangeSliderFilledTrack(FilledTrack); + + RangeSlider.displayName = 'RangeSlider'; + RangeSlider.LeftThumb.displayName = 'RangeSlider.LeftThumb'; + RangeSlider.RightThumb.displayName = 'RangeSlider.RightThumb'; + RangeSlider.Track.displayName = 'RangeSlider.Track'; + RangeSlider.FilledTrack.displayName = 'RangeSlider.FilledTrack'; + + return RangeSlider as IRangeSliderComponentType< + RangeSliderProps, + RangeSliderLeftThumbProps, + RangeSliderRightThumbProps, + RangeSliderTrackProps, + RangeSliderFilledTrackProps + >; +} diff --git a/packages/unstyled/range-slider/src/types.tsx b/packages/unstyled/range-slider/src/types.tsx new file mode 100644 index 0000000000..39980d9e9b --- /dev/null +++ b/packages/unstyled/range-slider/src/types.tsx @@ -0,0 +1,96 @@ +export interface InterfaceRangeSliderProps { + /** The current value of the Slider */ + value?: number; + /** The default value (uncontrolled). */ + defaultValue?: number; + /** Handler that is called when the value changes. */ + onChange?: (value: number) => void; + children?: any; + /** + * If true, the value will be incremented or decremented in reverse. + */ + isReversed?: boolean; + /** + * The orientation of the Slider. + * @default 'horizontal' + */ + orientation?: 'horizontal' | 'vertical'; + /** Whether the whole Slider is disabled. */ + isDisabled?: boolean; + /** Fired when the slider stops moving, due to being let go. */ + onChangeEnd?: (value: number) => void; + /** + * The slider's minimum value. + * @default 0 + */ + minValue?: number; + /** + * The slider's maximum value. + * @default 100 + */ + maxValue?: number; + /** + * The slider's step value. + * @default 1 + */ + step?: number; + /** Whether the whole Slider is readonly. */ + isReadOnly?: boolean; + /** Prop applied to change slider track height */ + sliderTrackHeight?: (string & {}) | number; + /**Prop applied to change size of slider thumb */ + thumbSize?: (string & {}) | number; + isHovered?: boolean; + isFocused?: boolean; + isFocusVisible?: boolean; + isPressed?: boolean; +} + +export interface IRangeSliderTrackProps { + /** Whether the whole Slider is readonly. */ + isReadOnly?: boolean; + children?: any; +} + +export interface IRangeSliderTrackFilledProps { + /** Whether the whole Slider is readonly. */ + isReadOnly?: boolean; +} + +export interface IRangeSliderThumbProps { + /** + * The orientation of the Slider. + * @default 'horizontal' + */ + orientation?: 'horizontal' | 'vertical'; + /** Whether the Thumb is disabled. */ + isDisabled?: boolean; + /** Whether the whole Slider is readonly. */ + isReadOnly?: boolean; + onFocus?: (e: any) => void; + onBlur?: (e: any) => void; + scaleOnPressed?: any; +} + +export type IRangeSliderComponentType< + StyledRangeSlider, + StyledRangeSliderLeftThumb, + StyledRangeSliderRightThumb, + StyledRangeSliderTrack, + StyledRangeSliderFilledTrack +> = React.ForwardRefExoticComponent & { + LeftThumb: React.ForwardRefExoticComponent< + StyledRangeSliderLeftThumb & IRangeSliderThumbProps + >; + RightThumb: React.ForwardRefExoticComponent< + StyledRangeSliderRightThumb & IRangeSliderThumbProps + >; + Track: React.ForwardRefExoticComponent< + StyledRangeSliderTrack & IRangeSliderTrackProps + >; + FilledTrack: React.ForwardRefExoticComponent< + StyledRangeSliderFilledTrack & IRangeSliderTrackFilledProps + >; +}; + +export type IRangeSliderProps = InterfaceRangeSliderProps; diff --git a/packages/unstyled/range-slider/tsconfig.json b/packages/unstyled/range-slider/tsconfig.json new file mode 100644 index 0000000000..7ec1befca7 --- /dev/null +++ b/packages/unstyled/range-slider/tsconfig.json @@ -0,0 +1,32 @@ +{ + "include": ["src"], + "exclude": ["node_modules", "example"], + "paths": { + "@gluestack-ui/utils": ["../utils/src"], + "@gluestack-ui/form-control": ["../form-control/src"] + }, + "compilerOptions": { + "emitDeclarationOnly": true, + "noEmit": false, + "baseUrl": "", + "declaration": true, + "allowUnreachableCode": false, + "allowUnusedLabels": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "jsx": "react", + "lib": ["esnext", "dom"], + "module": "esnext", + "moduleResolution": "node", + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "noImplicitUseStrict": false, + "noStrictGenericChecks": false, + "noUnusedLocals": false, + "noUnusedParameters": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "esnext" + } +} diff --git a/yarn.lock b/yarn.lock index 2a7182a199..a967d78f30 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19815,9 +19815,9 @@ react-native-web@0.19.9, react-native-web@^0.18.1, react-native-web@^0.19.9: postcss-value-parser "^4.2.0" styleq "^0.1.3" -react-native@0.72.4, react-native@^0.70.3, react-native@^0.72.4, react-native@^0.72.5: +react-native@0.72.4, react-native@^0.70.3, react-native@^0.72.4, react-native@^0.72.5, react-native@^0.73.2: version "0.72.4" - resolved "https://registry.npmjs.org/react-native/-/react-native-0.72.4.tgz" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.72.4.tgz#97b57e22e4d7657eaf4d1f62a678511fcf9bdda7" integrity sha512-+vrObi0wZR+NeqL09KihAAdVlQ9IdplwznJWtYrjnQ4UbCW6rkzZJebRsugwUneSOKNFaHFEo1uKU89HsgtYBg== dependencies: "@jest/create-cache-key-function" "^29.2.1" From 333d737b5093a249dd8c18c822b9868994e7ced5 Mon Sep 17 00:00:00 2001 From: Vidhi Kataria Date: Thu, 14 Mar 2024 19:52:35 +0530 Subject: [PATCH 02/12] feat: dual slider --- .../Forms/RangeSlider/RangeSlider.tsx | 74 +------- .../config/src/theme/RangeSliderRightThumb.ts | 2 +- .../slider/src/useSlider.web.ts | 7 + .../src/components/RangeSlider/index.tsx | 2 +- .../unstyled/range-slider/babel.config.js | 5 +- .../range-slider/src/RangeSlider-aria.tsx | 158 ------------------ .../unstyled/range-slider/src/RangeSlider.tsx | 72 ++++---- .../range-slider/src/RangeSliderLeftThumb.tsx | 65 ++++--- .../src/RangeSliderRightThumb.tsx | 13 +- .../src/RangeSliderTrack-aria.tsx | 52 ------ .../range-slider/src/RangeSliderTrack.tsx | 53 +++--- packages/unstyled/range-slider/src/index.tsx | 4 +- packages/unstyled/range-slider/tsconfig.json | 3 +- packages/unstyled/slider/src/SliderTrack.tsx | 1 - 14 files changed, 131 insertions(+), 380 deletions(-) delete mode 100644 packages/unstyled/range-slider/src/RangeSlider-aria.tsx delete mode 100644 packages/unstyled/range-slider/src/RangeSliderTrack-aria.tsx diff --git a/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx b/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx index 46ae708992..8728b86005 100644 --- a/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx +++ b/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx @@ -1,82 +1,37 @@ -import React, { useState } from 'react'; +import React from 'react'; import { - Text, - Slider, - SliderTrack, - SliderFilledTrack, - SliderThumb, - VStack, - HStack, - Box, - Icon, - Heading, - Tooltip, - TooltipContent, - Button, Center, RangeSlider, RangeSliderTrack, RangeSliderFilledTrack, RangeSliderLeftThumb, RangeSliderRightThumb, - View, - ButtonText, } from '@gluestack-ui/themed'; -// import { createRangeSlider } from '@gluestack-ui/range-slider'; -import { Volume, Volume2Icon, LightbulbIcon } from 'lucide-react-native'; -const RangeSliderBasic = ({ value: valueProp, ...props }: any) => { +const RangeSliderBasic = ({ ...props }: any) => { const [sliderValue, setSliderValue] = React.useState([30, 49]); - const [height, setHeight] = useState(30); - const handleChange = (values: any) => { - setSliderValue(values); - }; + return (
{ - console.log(values, 'values '); - handleChange(values); - }} + onChange={setSliderValue} + label="Range" orientation="vertical" + // isDisabled + // isReadOnly > - {/* */} + - {/* { - handleChange(values); - }} - > - - - - - - */}
); }; @@ -92,17 +47,4 @@ export { RangeSliderFilledTrack, RangeSliderLeftThumb, RangeSliderRightThumb, - VStack, - Volume, - HStack, - Volume2Icon, - Text, - Box, - LightbulbIcon, - Icon, - Heading, - Tooltip, - TooltipContent, - Button, - Center, }; diff --git a/packages/config/src/theme/RangeSliderRightThumb.ts b/packages/config/src/theme/RangeSliderRightThumb.ts index da61a9751b..7112ff37d2 100644 --- a/packages/config/src/theme/RangeSliderRightThumb.ts +++ b/packages/config/src/theme/RangeSliderRightThumb.ts @@ -1,7 +1,7 @@ import { createStyle } from '@gluestack-style/react'; export const RangeSliderRightThumb = createStyle({ - 'bg': '$red500', + 'bg': '$primary500', '_dark': { bg: '$primary400', }, diff --git a/packages/react-native-aria/slider/src/useSlider.web.ts b/packages/react-native-aria/slider/src/useSlider.web.ts index 742971b6f0..224f80ebcc 100644 --- a/packages/react-native-aria/slider/src/useSlider.web.ts +++ b/packages/react-native-aria/slider/src/useSlider.web.ts @@ -118,6 +118,13 @@ function useSliderWeb( // Find the closest thumb const trackPosition = trackLayout[isVertical ? 'top' : 'left']; const clickPosition = isVertical ? clientY : clientX; + console.log( + trackPosition, + trackLayout, + clickPosition, + 'trackPosition, clickPosition', + trackLayout + ); const offset = clickPosition - trackPosition; let percent = offset / size; if (reverseX) { diff --git a/packages/themed/src/components/RangeSlider/index.tsx b/packages/themed/src/components/RangeSlider/index.tsx index 1430df22fa..8f74f58653 100644 --- a/packages/themed/src/components/RangeSlider/index.tsx +++ b/packages/themed/src/components/RangeSlider/index.tsx @@ -11,11 +11,11 @@ import { export const RangeSlider = createRangeSlider({ Root, + ThumbInteraction, LeftThumb, RightThumb, Track, FilledTrack, - ThumbInteraction, }); export const RangeSliderLeftThumb = RangeSlider.LeftThumb; diff --git a/packages/unstyled/range-slider/babel.config.js b/packages/unstyled/range-slider/babel.config.js index 8f87f2b1cf..c564c723f7 100644 --- a/packages/unstyled/range-slider/babel.config.js +++ b/packages/unstyled/range-slider/babel.config.js @@ -10,7 +10,10 @@ module.exports = function (api) { 'module-resolver', { alias: { - // ['@gluestack-ui/utils']: path.resolve(__dirname, '../utils/src'), + ['@react-native-aria/slider']: path.resolve( + __dirname, + '../../react-native-aria/slider/src' + ), // For development, we want to alias the library to the source }, }, diff --git a/packages/unstyled/range-slider/src/RangeSlider-aria.tsx b/packages/unstyled/range-slider/src/RangeSlider-aria.tsx deleted file mode 100644 index 3d648f6f70..0000000000 --- a/packages/unstyled/range-slider/src/RangeSlider-aria.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import React, { forwardRef } from 'react'; -import { useSliderState } from '@react-stately/slider'; -import { useLayout } from '@gluestack-ui/hooks'; -import type { IRangeSliderProps } from './types'; -import { RangeSliderContext } from './Context'; -import { useSlider } from '@react-aria/slider'; -import { useFormControlContext } from '@gluestack-ui/form-control'; - -function RangeSlider( - StyledRangeSlider: React.ComponentType -) { - return forwardRef( - ( - { - orientation = 'horizontal', - isReversed = false, - 'isHovered': isHoveredProp, - 'isDisabled': isDisabledProp, - 'isFocused': isFocusedProp, - 'isFocusVisible': isFocusVisibleProp, - 'isPressed': isPressedProp, - // @ts-ignore - 'aria-label': ariaLabel = 'Slider', - children, - ...props - }: StyledSliderProps & IRangeSliderProps, - ref?: any - ) => { - const formControlContext = useFormControlContext(); - - const { isDisabled, isReadOnly, ...newProps } = { - ...formControlContext, - ...props, - 'aria-label': ariaLabel, - } as any; - let trackRef = React.useRef(null); - // @ts-ignore - if (props.value && props?.value?.prop?.constructor === Array) { - //@ts-ignore - React Native Aria slider accepts array of values - newProps.value = props.value; - } - - if ( - props.defaultValue && - // @ts-ignore - props?.defaultValue?.prop?.constructor === Array - ) { - //@ts-ignore - React Native Aria slider accepts array of values - newProps.defaultValue = props.defaultValue; - } - props = newProps; - - const { onLayout, layout: trackLayout } = useLayout(); - const updatedProps: IRangeSliderProps = Object.assign({}, props); - - if (isReadOnly || isDisabled) { - updatedProps.isDisabled = true; - } - - const state = useSliderState({ - ...updatedProps, - //@ts-ignore - numberFormatter: { format: (e) => e }, - minValue: props.minValue, - maxValue: props.maxValue, - orientation: orientation ?? 'horizontal', - // orientation: 'vertical', - onChange: (val: any) => { - console.log(val, 'values >>>>>>'); - props.onChange && props.onChange(val); - }, - onChangeEnd: (val: any) => { - props.onChangeEnd && props.onChangeEnd(val); - }, - }); - const { groupProps, trackProps, outputProps } = useSlider( - props as unknown as any, - state, - trackRef - ); - const [isFocused, setIsFocused] = React.useState(false); - const [isFocusVisible, setIsFocusVisible] = React.useState(false); - const [isHovered, setIsHovered] = React.useState(false); - const [isPressed, setIsPressed] = React.useState(false); - const contextValue = React.useMemo(() => { - return { - trackLayout, - state, - orientation: orientation, - isDisabled: isDisabled, - isFocused: isFocused, - setIsFocused: setIsFocused, - isFocusVisible: isFocusVisible, - setIsFocusVisible: setIsFocusVisible, - outputProps, - isPressed: isPressed, - setIsPressed: setIsPressed, - isHovered: isHovered, - setIsHovered: setIsHovered, - isReversed: isReversed, - trackProps, - trackRef, - isReadOnly: isReadOnly, - onTrackLayout: onLayout, - isHoveredProp, - isDisabledProp, - isFocusedProp, - isFocusVisibleProp, - isPressedProp, - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - trackProps, - trackRef, - trackLayout, - state, - orientation, - isDisabled, - isReversed, - isReadOnly, - onLayout, - isFocused, - setIsFocused, - isFocusVisible, - setIsFocusVisible, - isPressed, - setIsPressed, - isHoveredProp, - isDisabledProp, - isFocusedProp, - isFocusVisibleProp, - isPressedProp, - ]); - // console.log(groupProps, 'GROUPPPP'); - return ( - - - {children} - - - ); - } - ); -} -export default RangeSlider; diff --git a/packages/unstyled/range-slider/src/RangeSlider.tsx b/packages/unstyled/range-slider/src/RangeSlider.tsx index 123422da98..a3dc00259e 100644 --- a/packages/unstyled/range-slider/src/RangeSlider.tsx +++ b/packages/unstyled/range-slider/src/RangeSlider.tsx @@ -12,13 +12,13 @@ function RangeSlider( return forwardRef( ( { - orientation = 'horizontal', + // isDisabled = false, isReversed = false, - 'isHovered': isHoveredProp, - 'isDisabled': isDisabledProp, - 'isFocused': isFocusedProp, - 'isFocusVisible': isFocusVisibleProp, - 'isPressed': isPressedProp, + // 'isHovered', + // 'isDisabled', + // 'isFocused', + // 'isFocusVisible', + // 'isPressed', // @ts-ignore 'aria-label': ariaLabel = 'Slider', children, @@ -27,7 +27,6 @@ function RangeSlider( ref?: any ) => { const formControlContext = useFormControlContext(); - const { isDisabled, isReadOnly, ...newProps } = { ...formControlContext, ...props, @@ -51,6 +50,7 @@ function RangeSlider( props = newProps; const { onLayout, layout: trackLayout } = useLayout(); + const updatedProps: IRangeSliderProps = Object.assign({}, props); if (isReadOnly || isDisabled) { @@ -63,8 +63,8 @@ function RangeSlider( numberFormatter: { format: (e) => e }, minValue: props.minValue, maxValue: props.maxValue, - orientation: orientation ?? 'horizontal', - // orientation: 'vertical', + orientation: props.orientation ?? 'horizontal', + onChange: (val: any) => { props.onChange && props.onChange(val); }, @@ -73,28 +73,30 @@ function RangeSlider( }, }); - const { groupProps, trackProps, outputProps } = useSlider( - props as unknown as any, + let { groupProps, trackProps, outputProps } = useSlider( + props as any, state, - trackRef + trackLayout + // trackRef ); + const [isFocused, setIsFocused] = React.useState(false); const [isFocusVisible, setIsFocusVisible] = React.useState(false); const [isHovered, setIsHovered] = React.useState(false); - // const [isPressed, setIsPressed] = React.useState(false); + const [isPressed, setIsPressed] = React.useState(false); const contextValue = React.useMemo(() => { return { trackLayout, state, - orientation: orientation, + orientation: props.orientation ? props.orientation : 'horizontal', isDisabled: isDisabled, isFocused: isFocused, setIsFocused: setIsFocused, isFocusVisible: isFocusVisible, setIsFocusVisible: setIsFocusVisible, outputProps, - // isPressed: isPressed, - // setIsPressed: setIsPressed, + isPressed: isPressed, + setIsPressed: setIsPressed, isHovered: isHovered, setIsHovered: setIsHovered, isReversed: isReversed, @@ -102,11 +104,11 @@ function RangeSlider( trackRef, isReadOnly: isReadOnly, onTrackLayout: onLayout, - isHoveredProp, - isDisabledProp, - isFocusedProp, - isFocusVisibleProp, - isPressedProp, + // isHoveredProp, + // isDisabledProp, + // isFocusedProp, + // isFocusVisibleProp, + // isPressedProp, }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [ @@ -114,7 +116,7 @@ function RangeSlider( trackRef, trackLayout, state, - orientation, + // orientation, isDisabled, isReversed, isReadOnly, @@ -123,13 +125,13 @@ function RangeSlider( setIsFocused, isFocusVisible, setIsFocusVisible, - // isPressed, - // setIsPressed, - isHoveredProp, - isDisabledProp, - isFocusedProp, - isFocusVisibleProp, - isPressedProp, + isPressed, + setIsPressed, + // isHoveredProp, + // isDisabledProp, + // isFocusedProp, + // isFocusVisibleProp, + // isPressedProp, ]); return ( @@ -138,13 +140,13 @@ function RangeSlider( {...(props as StyledSliderProps)} ref={ref} states={{ - hover: isHovered || isHoveredProp, - disabled: isDisabled || isDisabledProp, - focus: isFocused || isFocusedProp, - focusVisible: isFocusVisible || isFocusVisibleProp, - // active: isPressed || isPressedProp, + hover: isHovered, + disabled: isDisabled, + focus: isFocused, + focusVisible: isFocusVisible, + active: isPressed, }} - orientation={orientation ?? 'horizontal'} + orientation={props.orientation ?? 'horizontal'} isReversed={isReversed ?? false} {...groupProps} > diff --git a/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx b/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx index d528d2599b..3ac17eee0d 100644 --- a/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx +++ b/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx @@ -35,7 +35,7 @@ function RangeSliderThumb< IRangeSliderThumbProps & { children?: any; style?: any }, ref?: any ) => { - const [thumbSize, setThumbSize] = React.useState({ + const [setThumbSize] = React.useState({ height: 0, width: 0, }); @@ -46,39 +46,49 @@ function RangeSliderThumb< // const [isFocusVisible, setIsFocusVisible] = React.useState(false); // const [isHovered, setIsHovered] = React.useState(false); - const [isPressed, setIsPressed] = React.useState(false); + // const [isPressed, setIsPressed] = React.useState(false); const { state, trackLayout, orientation, isDisabled, isReversed, - // isPressed, + isPressed, setIsHovered, - // setIsPressed, + setIsPressed, setIsFocused, setIsFocusVisible, - isHoveredProp, - isDisabledProp, - isFocusedProp, - isFocusVisibleProp, - isPressedProp, + // isHoveredProp, + // isDisabledProp, + // isFocusedProp, + // isFocusVisibleProp, + // isPressedProp, trackRef, } = React.useContext(RangeSliderContext); - const handleFocus = (focusState: boolean, callback: any) => { - setIsFocused(focusState); - callback(); - }; + // const handleFocus = (focusState: boolean, callback: any) => { + // setIsFocused(focusState); + // callback(); + // }; const inputRef = React.useRef(null); - const { thumbProps, inputProps } = useSliderThumb( + // const { thumbProps, inputProps } = useSliderThumb( + // { + // index: LeftThumbIndex, + // trackLayout, + // inputRef, + // orientation: orientation, + // }, + // state, + // isReversed + // ); + + let { thumbProps, inputProps } = useSliderThumb( { index: LeftThumbIndex, trackLayout, + orientation, inputRef, - orientation: orientation, }, - state, - isReversed + state ); const { isFocusVisible, focusProps: focusRingProps }: any = useFocusRing(); @@ -106,7 +116,6 @@ function RangeSliderThumb< thumbStyles[`${positionMap.get(`${orientation} ${isReversed}`)}`] = `${ state.getThumbPercent(LeftThumbIndex) * 100 }%`; - console.log(state, '<< { - // setIsPressed(state.isThumbDragging(LeftThumbIndex)); - // }, [state, setIsPressed, isPressed]); + useEffect(() => { + setIsPressed(state.isThumbDragging(LeftThumbIndex)); + }, [state, setIsPressed, isPressed]); + React.useEffect(() => { setIsPressed(state.isThumbDragging(LeftThumbIndex)); }, [state, setIsPressed, isPressed]); @@ -144,11 +154,11 @@ function RangeSliderThumb< }); }} states={{ - hover: isHovered || isHoveredProp, - disabled: isDisabled || isDisabledProp, - focus: isFocused || isFocusedProp, - focusVisible: isFocusVisible || isFocusVisibleProp, - active: isPressed || isPressedProp, + hover: isHovered, + disabled: isDisabled, + focus: isFocused, + focusVisible: isFocusVisible, + active: isPressed, }} disabled={isDisabled} {...thumbProps} @@ -181,11 +191,12 @@ function RangeSliderThumb< disabled: isDisabled, active: isPressed, }} + className={`thumb ${isFocusVisible ? 'focus' : ''} `} > {children} {Platform.OS === 'web' && ( - + )}
diff --git a/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx b/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx index 4878eaf367..eb6601a7c6 100644 --- a/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx +++ b/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx @@ -28,7 +28,8 @@ function RangeSliderThumb< ( { children, - scaleOnPressed = 1, + // FIX: Commenting to fix linting error + // scaleOnPressed = 1, style, ...props }: StyledRangeSliderThumbInteraction & @@ -36,14 +37,13 @@ function RangeSliderThumb< IRangeSliderThumbProps & { children?: any; style?: any }, ref?: any ) => { - const [thumbSize, setThumbSize] = React.useState({ + const [setThumbSize] = React.useState({ height: 0, width: 0, }); const _ref = React.useRef(null); const { isHovered } = useHover({}, _ref); - const [isPressed, setIsPressed] = React.useState(false); const { state, @@ -51,9 +51,9 @@ function RangeSliderThumb< orientation, isDisabled, isReversed, - // isPressed, + isPressed, setIsHovered, - // setIsPressed, + setIsPressed, setIsFocused, setIsFocusVisible, isHoveredProp, @@ -96,7 +96,6 @@ function RangeSliderThumb< // }, // ], }; - thumbStyles[`${positionMap.get(`${orientation} ${isReversed}`)}`] = `${ state.getThumbPercent(RightThumbIndex) * 100 }%`; @@ -109,7 +108,7 @@ function RangeSliderThumb< useEffect(() => { setIsPressed(state.isThumbDragging(RightThumbIndex)); - }, [state]); + }, [state, setIsPressed]); useEffect(() => { setIsFocused(isFocused); diff --git a/packages/unstyled/range-slider/src/RangeSliderTrack-aria.tsx b/packages/unstyled/range-slider/src/RangeSliderTrack-aria.tsx deleted file mode 100644 index 92bd4cbeb7..0000000000 --- a/packages/unstyled/range-slider/src/RangeSliderTrack-aria.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React, { forwardRef } from 'react'; -import { RangeSliderContext } from './Context'; -import { mergeRefs } from '@gluestack-ui/utils'; -import { useHover } from '@react-native-aria/interactions'; - -function RangeSliderTrack( - StyledRangeSliderTrack: React.ComponentType -) { - return forwardRef(({ children, style, ...props }: any, ref?: any) => { - const _ref = React.useRef(null); - const { isHovered } = useHover({}, _ref); - const { - trackProps, - onTrackLayout, - isFocused, - isFocusVisible, - isDisabled, - isPressed, - isHoveredProp, - isDisabledProp, - isFocusedProp, - isFocusVisibleProp, - isPressedProp, - } = React.useContext(RangeSliderContext); - // const [isPressed, setIsPressed] = React.useState(false); - // console.log(trackProps, 'TTTTTTTT'); - const { onMouseDown } = trackProps; - - return ( - - {children} - - ); - }); -} -export default RangeSliderTrack; diff --git a/packages/unstyled/range-slider/src/RangeSliderTrack.tsx b/packages/unstyled/range-slider/src/RangeSliderTrack.tsx index ebb745d695..dba58f1139 100644 --- a/packages/unstyled/range-slider/src/RangeSliderTrack.tsx +++ b/packages/unstyled/range-slider/src/RangeSliderTrack.tsx @@ -21,36 +21,33 @@ function RangeSliderTrack( isFocusedProp, isFocusVisibleProp, isPressedProp, + // state, } = React.useContext(RangeSliderContext); // const [isPressed, setIsPressed] = React.useState(false); - console.log(trackProps, 'TTTTTTTT'); - // const { onMouseDown, onPointerDown, onTouchStart, onKeyDown } = trackProps; - return
hello
; - // return ( - // { - // console.log(e, '<<<<<'); - // onPointerDown(e); - // }} - // style={{ ...style }} - // {...props} - // isDisabled={isDisabled} - // tabIndex={-1} - // states={{ - // hover: isHovered || isHoveredProp, - // disabled: isDisabled || isDisabledProp, - // focus: isFocused || isFocusedProp, - // focusVisible: isFocusVisible || isFocusVisibleProp, - // active: isPressed || isPressedProp, - // }} - // disabled={isDisabled} - // > - // {children} - // - // ); + + // const { onPointerDown } = trackProps; + + return ( + + {children} + + ); }); } export default RangeSliderTrack; diff --git a/packages/unstyled/range-slider/src/index.tsx b/packages/unstyled/range-slider/src/index.tsx index 3ed5e92ad0..72c9ac529d 100644 --- a/packages/unstyled/range-slider/src/index.tsx +++ b/packages/unstyled/range-slider/src/index.tsx @@ -1,7 +1,7 @@ -import RangeSliderMain from './RangeSlider-aria'; +import RangeSliderMain from './RangeSlider'; import RangeSliderLeftThumb from './RangeSliderLeftThumb'; import RangeSliderRightThumb from './RangeSliderRightThumb'; -import RangeSliderTrack from './RangeSliderTrack-aria'; +import RangeSliderTrack from './RangeSliderTrack'; import RangeSliderFilledTrack from './RangeSliderFilledTrack'; import type { IRangeSliderComponentType } from './types'; diff --git a/packages/unstyled/range-slider/tsconfig.json b/packages/unstyled/range-slider/tsconfig.json index 7ec1befca7..3eed3361a6 100644 --- a/packages/unstyled/range-slider/tsconfig.json +++ b/packages/unstyled/range-slider/tsconfig.json @@ -3,7 +3,8 @@ "exclude": ["node_modules", "example"], "paths": { "@gluestack-ui/utils": ["../utils/src"], - "@gluestack-ui/form-control": ["../form-control/src"] + "@gluestack-ui/form-control": ["../form-control/src"], + "'@react-native-aria/slider'": ["../../react-native-aria/slider/src"] }, "compilerOptions": { "emitDeclarationOnly": true, diff --git a/packages/unstyled/slider/src/SliderTrack.tsx b/packages/unstyled/slider/src/SliderTrack.tsx index e70a6300a2..c6ad2857bf 100644 --- a/packages/unstyled/slider/src/SliderTrack.tsx +++ b/packages/unstyled/slider/src/SliderTrack.tsx @@ -22,7 +22,6 @@ function SliderTrack( isFocusVisibleProp, isPressedProp, } = React.useContext(SliderContext); - return ( Date: Mon, 18 Mar 2024 13:32:51 +0530 Subject: [PATCH 03/12] feat: range slider docs --- .../Forms/RangeSlider/RangeSlider.tsx | 57 +- .../Forms/RangeSlider/index.stories.mdx | 861 ++++++++++++++++++ packages/config/src/theme/RangeSlider.ts | 192 ++++ packages/config/src/theme/index.ts | 1 + .../RangeSlider/styled-components/Root.tsx | 2 +- .../unstyled/range-slider/src/RangeSlider.tsx | 12 +- .../range-slider/src/RangeSliderLeftThumb.tsx | 7 +- .../src/RangeSliderRightThumb.tsx | 6 +- 8 files changed, 1115 insertions(+), 23 deletions(-) create mode 100644 example/storybook/src/ui/components/Forms/RangeSlider/index.stories.mdx create mode 100644 packages/config/src/theme/RangeSlider.ts diff --git a/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx b/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx index 8728b86005..46a3d961a0 100644 --- a/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx +++ b/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx @@ -6,31 +6,55 @@ import { RangeSliderFilledTrack, RangeSliderLeftThumb, RangeSliderRightThumb, + Text, + VStack, + HStack, + Box, + Icon, + Heading, + Tooltip, + TooltipContent, + Button, } from '@gluestack-ui/themed'; const RangeSliderBasic = ({ ...props }: any) => { - const [sliderValue, setSliderValue] = React.useState([30, 49]); + const [sliderValue, setSliderValue] = React.useState([20, 49]); return ( -
+
- - - - - + + + + + + + + + + + +
); @@ -42,9 +66,20 @@ RangeSliderBasic.description = export default RangeSliderBasic; export { + Center, RangeSlider, RangeSliderTrack, RangeSliderFilledTrack, RangeSliderLeftThumb, RangeSliderRightThumb, + Text, + VStack, + HStack, + Box, + Icon, + Heading, + Tooltip, + TooltipContent, + Button, }; +export { Volume, Volume2Icon, LightbulbIcon } from 'lucide-react-native'; diff --git a/example/storybook/src/ui/components/Forms/RangeSlider/index.stories.mdx b/example/storybook/src/ui/components/Forms/RangeSlider/index.stories.mdx new file mode 100644 index 0000000000..6249a5c795 --- /dev/null +++ b/example/storybook/src/ui/components/Forms/RangeSlider/index.stories.mdx @@ -0,0 +1,861 @@ +--- +title: Range Slider | gluestack-ui | Installation, Usage, and API + +description: The Range Slider component enables an intuitive selection of values within a designated range. Users can easily adjust their selection by sliding a visual indicator along the track. + +pageTitle: Range Slider + +pageDescription: The Range Slider component enables an intuitive selection of values within a designated range. Users can easily adjust their selection by sliding a visual indicator along the track. + +showHeader: true + +tag: beta +--- + +import { Meta } from '@storybook/addon-docs'; +import { useRef, useEffect, useState } from 'react'; + + + +import { + RangeSlider, + RangeSliderTrack, + RangeSliderFilledTrack, + RangeSliderLeftThumb, + RangeSliderRightThumb, + VStack, + Volume, + Text, +} from './RangeSlider'; +import { + Slider, + SliderTrack, + SliderFilledTrack, + SliderThumb, +} from "@gluestack-ui/themed" +import { HStack, Volume2Icon, Box, Center } from './RangeSlider'; +import { + LightbulbIcon, + Icon, + Heading, + Tooltip, + TooltipContent, + Button, +} from './RangeSlider'; +import { transformedCode } from '../../../utils'; +import { + AppProvider, + CodePreview, + InlineCode, + Table, + TableContainer, +} from '@gluestack/design-system'; + +import Wrapper from '../../Wrapper'; + +This is an illustration of a **Themed Range Slider** component with default configuration. + + + + + + + + + + + +
+ `, + transformCode: (code) => { + return transformedCode(code); + }, + scope: { + Wrapper, + RangeSlider, + RangeSliderTrack, + RangeSliderFilledTrack, + RangeSliderLeftThumb, + RangeSliderRightThumb, + Center, + }, + argsType: { + size: { + control: 'select', + options: ['sm', 'md', 'lg'], + default: 'md', + }, + orientation: { + control: 'select', + options: ['vertical', 'horizontal'], + default: 'horizontal', + }, + isDisabled: { + control: 'boolean', + }, + }, + }} + /> + + +
+ +## API Reference + +### Import + +To use this component in your project, include the following import statement in your file. + +```bash +import { RangeSlider } from '@gluestack-ui/themed'; +``` + +### Anatomy + +The structure provided below can help you identify and understand a Range Slider component's various parts. + +```jsx +export default () => ( + + + + + + + +); +``` + +### Component Props + +This section provides a comprehensive reference list for the component props, detailing descriptions, properties, types, and default behavior for easy project integration. + +#### Range Slider + +It inherits all the properties of React Native's [View](https://reactnative.dev/docs/view) component. + + + + + + + + Prop + + + Type + + + Default + + + Description + + + + + + + + onChange + + + + {'(value: number) => void'} + + + - + + + + Function called when the state of the Range Slider changes. + + + + + + + isDisabled + + + + bool + + + false + + + When true, this will disable Range Slider + + + + + + isReadOnly + + + + boolean + + + false + + + + To manually set read-only to the checkbox. + + + + + + + sliderTrackHeight + + + + number + + + 8 + + + To change the range slider track height . + + + + + + defaultValue + + + + number + + + - + + + To change the range slider value . + + + + + + minValue + + + + number + + + - + + + The range slider's minimum value + + + + + + maxValue + + + + number + + + - + + + The range slider's maximum value. + + + + + + value + + + + number + + + - + + + The range slider's current value. + + + + + + step + + + + number + + + - + + + The range slider's step value. + + + +
+
+
+ +**Descendants Styling Props** +Props to style child components. + + + + + + + + Sx Prop + + + Description + + + + + + + + _thumb + + + + {`Prop to style RangSliderThumb Component`} + + + + + + _track + + + + {`Prop to style RangSliderTrack Component`} + + + + + + _filledTrack + + + + {`Prop to style RangeSliderFilledTrack Component`} + + + +
+
+
+ +#### RangeSliderTrack + +It inherits all the properties of React Native's [Pressable](https://reactnative.dev/docs/Pressable) component. + +#### RangeSliderFilledTrack + +It inherits all the properties of React Native's [View](https://reactnative.dev/docs/view) component. + +#### RangeSliderLeftThumb + +It inherits all the properties of React Native's [View](https://reactnative.dev/docs/view) component. + +#### RangeSliderRightThumb + +It inherits all the properties of React Native's [View](https://reactnative.dev/docs/view) component. + +### Features + +- Keyboard support for actions. +- Support for hover, focus and active states. + +### Accessibility + +We have outlined the various features that ensure the Range Slider component is accessible to all users, including those with disabilities. These features help ensure that your application is inclusive and meets accessibility standards.Adheres to the [WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/slider/). + +#### Keyboard + +- `Tab`: Moves focus to the next focusable element. +- `Right Arrow`: Increase the value of the range slider by one step. +- `Up Arrow`: Increase the value of the range slider by one step. +- `Left Arrow`: Decrease the value of the range slider by one step. +- `Down Arrow`: Decrease the value of the range slider by one step. + +### Screen Reader + +- VoiceOver: When the range slider is focused, the screen reader will announce the range slider's value. + +## Themed + +The themed version of the component is a pre-styled version of the component, which allows you to quickly integrate the component into your project. The component's design and functionality are fully defined, allowing you to focus on the more important aspects of your project. To know more about Themed Library please visit this [link](https://gluestack.io/ui/docs/core-concepts/themed-library). + +### Props + +Range Slider component is created using View component from react-native. It extends all the props supported by [React Native View](https://reactnative.dev/docs/view#props), [utility props](/ui/docs/styling/utility-and-sx-props) and the props mentioned below. + +#### Range Slider + + + + + + + + Name + + + Value + + + Default + + + + + + + + orientation + + + + horizontal | vertical + + + horizontal + + + + + + size + + + + sm | md | lg + + + md + + + +
+
+
+ +> Note: These props are exclusively applicable when utilizing the default configuration of gluestack-ui/config. If you are using a custom theme, these props may not be available. + +### Examples + +The Examples section provides visual representations of the different variants of the component, allowing you to quickly and easily determine which one best fits your needs. Simply copy the code and integrate it into your project. + +#### Range Slider with Orientation + +An example of the Range Slider component being used with the Range Slider with Orientation feature to customize the orientation of the range slider, providing flexibility in the direction of sliding and input for numerical or adjustable values within a user interface. + + + { + setSliderValue(value); + }; + return ( +
+ + + + + + + +
+ ); +} +`, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Box, + RangeSlider, + RangeSliderTrack, + RangeSliderFilledTrack, + RangeSliderLeftThumb, + RangeSliderRightThumb, + Center, + Wrapper, + }, + argsType: {}, + }} + /> +
+ +#### Color scheme + +A Range Slider component with a color scheme adds visual styling and customization options, allowing the range slider track and handle to be displayed in different colors, enhancing the aesthetic appeal and visual coherence of the range slider within a user interface. + + + +
+ + + + + + + +
+
+ + + + + + + +
+
+ + + + + + + +
+
+ + + + + + + +
+ + ); +} +`, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Center, + RangeSlider, + RangeSliderTrack, + RangeSliderFilledTrack, + RangeSliderLeftThumb, + RangeSliderRightThumb, + VStack, + Wrapper, + }, + argsType: {}, + }} + /> +
+ +#### With tooltip + +A Range Slider component with a tooltip displays a visual indicator or text overlay that provides real-time feedback on the selected value as users interact with the range slider, improving usability and precision in inputting or adjusting numeric or continuous data within a user interface. + + + { + setSliderValue(value); + }; + return ( + + $0 + { + return ( +
+ + + + + + + +
+ ) + }} + > + + {"$" + sliderValue} + +
+ $60 +
+); +} +`, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Wrapper, + RangeSlider, + RangeSliderTrack, + RangeSliderFilledTrack, + RangeSliderLeftThumb, + RangeSliderRightThumb, + Center, + Volume, + VStack, + HStack, + Volume2Icon, + Text, + Box, + Tooltip, + TooltipContent, + Button, + }, + argsType: {}, + }} + /> +
+ +#### Form Controlled + +A Range Slider component with form-controlled behavior allows for seamless integration with a form's state management, enabling the range slider value to be controlled and updated through a parent component's form state, providing a consistent and synchronized user experience for capturing and manipulating numeric or continuous data within a form. + + + { + setSliderValue(value); + }; + return ( + + Select the quantity +
+ { + handleChange(value); + }}> + + + + + + +
+ Slide the knob to select the number of products +
+ ); +} +`, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Wrapper, + Center, + RangeSlider, + RangeSliderTrack, + RangeSliderFilledTrack, + RangeSliderLeftThumb, + RangeSliderRightThumb, + Center, + LightbulbIcon, + Icon, + Text, + VStack, + Heading, + }, + argsType: {}, + }} + /> +
+ +#### Custom + +A custom Range Slider component with an icon incorporates a personalized design by combining a graphical symbol or icon with the slider interface, adding a unique visual element and enhancing the user experience when interacting with numeric or continuous data input in a user interface. + + + { + setSliderValue(value); + }; + return ( + + Brightness +
+ { + handleChange(value); + }}> + + + + + + + + + + +
+
+ ); +} +`, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Wrapper, + Center, + RangeSlider, + RangeSliderTrack, + RangeSliderFilledTrack, + RangeSliderLeftThumb, + RangeSliderRightThumb, + LightbulbIcon, + Icon, + Text, + VStack, + }, + argsType: {}, + }} + /> +
+ +#### Volume + +A Range Slider component used as a volume control allows users to adjust the audio volume by sliding the handle along the track, providing an intuitive and interactive way to control the sound output within a user interface. + + + { + setSliderValue(value); + }; + return ( + + + current sliderValue - {sliderValue} + onChangeEndValue - {onChangeEndValue} + + + +
+ + + + + + + +
+ +
+
+ ); +} +`, + transformCode: (code) => { + return transformedCode(code, 'function', 'App'); + }, + scope: { + Wrapper, + Center, + RangeSlider, + RangeSliderTrack, + RangeSliderFilledTrack, + RangeSliderLeftThumb, + RangeSliderRightThumb, + Center, + Volume, + VStack, + HStack, + Volume2Icon, + Text, + Box, + }, + argsType: {}, + }} + /> +
+ +## Unstyled + +All the components in `gluestack-ui` are unstyled by default. To customize your UI using the extendedTheme, please refer to this [link](https://gluestack.io/ui/docs/theme-configuration/customizing-theme). The import names of components serve as keys to customize each component. \ No newline at end of file diff --git a/packages/config/src/theme/RangeSlider.ts b/packages/config/src/theme/RangeSlider.ts new file mode 100644 index 0000000000..2cb61730f5 --- /dev/null +++ b/packages/config/src/theme/RangeSlider.ts @@ -0,0 +1,192 @@ +import { createStyle } from '@gluestack-style/react'; + +export const RangeSlider = createStyle({ + justifyContent: 'center', + alignItems: 'center', + variants: { + orientation: { + horizontal: { + w: '$full', + _track: { + width: '$full', + }, + _filledTrack: { + height: '$full', + }, + }, + vertical: { + h: '$full', + _track: { + height: '$full', + }, + _filledTrack: { + width: '$full', + }, + }, + }, + isReversed: { + true: {}, + false: {}, + }, + size: { + sm: { + _thumb: { + h: '$4', + w: '$4', + }, + }, + md: { + _thumb: { + h: '$5', + w: '$5', + }, + }, + lg: { + _thumb: { + h: '$6', + w: '$6', + }, + }, + }, + }, + compoundVariants: [ + { + orientation: 'horizontal', + size: 'sm', + value: { + _track: { + height: '$1', + flexDirection: 'row', + }, + }, + }, + { + orientation: 'horizontal', + size: 'sm', + isReversed: true, + value: { + _track: { + height: '$1', + flexDirection: 'row-reverse', + }, + }, + }, + { + orientation: 'horizontal', + size: 'md', + value: { + _track: { + height: 5, + flexDirection: 'row', + }, + }, + }, + { + orientation: 'horizontal', + size: 'md', + isReversed: true, + value: { + _track: { + height: 5, + flexDirection: 'row-reverse', + }, + }, + }, + { + orientation: 'horizontal', + size: 'lg', + value: { + _track: { + height: '$1.5', + flexDirection: 'row', + }, + }, + }, + { + orientation: 'horizontal', + size: 'lg', + isReversed: true, + value: { + _track: { + height: '$1.5', + flexDirection: 'row-reverse', + }, + }, + }, + { + orientation: 'vertical', + size: 'sm', + value: { + _track: { + w: '$1', + flexDirection: 'column-reverse', + }, + }, + }, + { + orientation: 'vertical', + size: 'sm', + isReversed: true, + value: { + _track: { + width: '$1', + flexDirection: 'column', + }, + }, + }, + { + orientation: 'vertical', + size: 'md', + value: { + _track: { + width: 5, + flexDirection: 'column-reverse', + }, + }, + }, + { + orientation: 'vertical', + size: 'md', + isReversed: true, + value: { + _track: { + width: 5, + flexDirection: 'column', + }, + }, + }, + { + orientation: 'vertical', + size: 'lg', + value: { + _track: { + width: '$1.5', + flexDirection: 'column-reverse', + }, + }, + }, + { + orientation: 'vertical', + size: 'lg', + isReversed: true, + value: { + _track: { + width: '$1.5', + flexDirection: 'column', + }, + }, + }, + ], + _web: { + ':disabled': { + // @ts-ignore + pointerEvents: 'all !important', + cursor: 'not-allowed', + opacity: 0.4, + }, + }, + defaultProps: { + size: 'md', + orientation: 'horizontal', + }, +}); diff --git a/packages/config/src/theme/index.ts b/packages/config/src/theme/index.ts index 31c0b448fc..3862da6034 100644 --- a/packages/config/src/theme/index.ts +++ b/packages/config/src/theme/index.ts @@ -148,6 +148,7 @@ export * from './TooltipContent'; export * from './TooltipText'; export * from './VStack'; export * from './View'; +export * from './RangeSlider'; export * from './RangeSliderLeftThumb'; export * from './RangeSliderRightThumb'; export * from './ImageBackground'; diff --git a/packages/themed/src/components/RangeSlider/styled-components/Root.tsx b/packages/themed/src/components/RangeSlider/styled-components/Root.tsx index 52116c5dba..288e85caaa 100644 --- a/packages/themed/src/components/RangeSlider/styled-components/Root.tsx +++ b/packages/themed/src/components/RangeSlider/styled-components/Root.tsx @@ -2,6 +2,6 @@ import { styled } from '@gluestack-style/react'; import { View } from 'react-native'; export default styled(View, {}, { - componentName: 'Slider', + componentName: 'RangeSlider', descendantStyle: ['_thumb', '_track', '_filledTrack'], } as const); diff --git a/packages/unstyled/range-slider/src/RangeSlider.tsx b/packages/unstyled/range-slider/src/RangeSlider.tsx index a3dc00259e..ee458c11ff 100644 --- a/packages/unstyled/range-slider/src/RangeSlider.tsx +++ b/packages/unstyled/range-slider/src/RangeSlider.tsx @@ -83,7 +83,7 @@ function RangeSlider( const [isFocused, setIsFocused] = React.useState(false); const [isFocusVisible, setIsFocusVisible] = React.useState(false); const [isHovered, setIsHovered] = React.useState(false); - const [isPressed, setIsPressed] = React.useState(false); + // const [isPressed, setIsPressed] = React.useState(false); const contextValue = React.useMemo(() => { return { trackLayout, @@ -95,8 +95,8 @@ function RangeSlider( isFocusVisible: isFocusVisible, setIsFocusVisible: setIsFocusVisible, outputProps, - isPressed: isPressed, - setIsPressed: setIsPressed, + // isPressed: isPressed, + // setIsPressed: setIsPressed, isHovered: isHovered, setIsHovered: setIsHovered, isReversed: isReversed, @@ -125,8 +125,8 @@ function RangeSlider( setIsFocused, isFocusVisible, setIsFocusVisible, - isPressed, - setIsPressed, + // isPressed, + // setIsPressed, // isHoveredProp, // isDisabledProp, // isFocusedProp, @@ -144,7 +144,7 @@ function RangeSlider( disabled: isDisabled, focus: isFocused, focusVisible: isFocusVisible, - active: isPressed, + // active: isPressed, }} orientation={props.orientation ?? 'horizontal'} isReversed={isReversed ?? false} diff --git a/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx b/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx index 3ac17eee0d..46c60029e3 100644 --- a/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx +++ b/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx @@ -43,7 +43,7 @@ function RangeSliderThumb< const _ref = React.useRef(null); const { isHovered } = useHover({}, _ref); // const [isFocused, setIsFocused] = React.useState(false) - + const [isPressed, setIsPressed] = React.useState(false); // const [isFocusVisible, setIsFocusVisible] = React.useState(false); // const [isHovered, setIsHovered] = React.useState(false); // const [isPressed, setIsPressed] = React.useState(false); @@ -53,9 +53,9 @@ function RangeSliderThumb< orientation, isDisabled, isReversed, - isPressed, + // isPressed, setIsHovered, - setIsPressed, + // setIsPressed, setIsFocused, setIsFocusVisible, // isHoveredProp, @@ -148,6 +148,7 @@ function RangeSliderThumb< return ( { + // @ts-ignore setThumbSize({ height: layout?.nativeEvent?.layout?.height, width: layout?.nativeEvent?.layout?.width, diff --git a/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx b/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx index eb6601a7c6..cbe7b83369 100644 --- a/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx +++ b/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx @@ -44,6 +44,7 @@ function RangeSliderThumb< const _ref = React.useRef(null); const { isHovered } = useHover({}, _ref); + const [isPressed, setIsPressed] = React.useState(false); const { state, @@ -51,9 +52,9 @@ function RangeSliderThumb< orientation, isDisabled, isReversed, - isPressed, + // isPressed, setIsHovered, - setIsPressed, + // setIsPressed, setIsFocused, setIsFocusVisible, isHoveredProp, @@ -125,6 +126,7 @@ function RangeSliderThumb< return ( { + // @ts-ignore setThumbSize({ height: layout?.nativeEvent?.layout?.height, width: layout?.nativeEvent?.layout?.width, From 06290685635e9a5f3a19ac85b69c307405b68993 Mon Sep 17 00:00:00 2001 From: Vidhi Kataria Date: Mon, 18 Mar 2024 13:46:08 +0530 Subject: [PATCH 04/12] v1.1.18 --- packages/config/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/config/package.json b/packages/config/package.json index 1c9ab18822..dad44e57cc 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-ui/config", - "version": "1.1.17", + "version": "1.1.18", "main": "build/gluestack-ui.config.js", "types": "build/gluestack-ui.config.d.ts", "module": "build/gluestack-ui.config", From 1404adb7496ff8a07805e74589d151f414d6a526 Mon Sep 17 00:00:00 2001 From: Vidhi Kataria Date: Mon, 18 Mar 2024 13:47:28 +0530 Subject: [PATCH 05/12] v1.1.13 --- packages/themed/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/themed/package.json b/packages/themed/package.json index 681be09f9f..d23fd22071 100644 --- a/packages/themed/package.json +++ b/packages/themed/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-ui/themed", - "version": "1.1.11", + "version": "1.1.13", "main": "build/index.js", "types": "build/index.d.ts", "module": "build/index", From c74526356be1e95b44f60f57a1b32df13af70d63 Mon Sep 17 00:00:00 2001 From: Vidhi Kataria Date: Mon, 18 Mar 2024 15:00:51 +0530 Subject: [PATCH 06/12] feat: range slider docs --- example/storybook/.storybook/preview.js | 1 + packages/unstyled/range-slider/package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/example/storybook/.storybook/preview.js b/example/storybook/.storybook/preview.js index eba42f09af..15139f1bfb 100644 --- a/example/storybook/.storybook/preview.js +++ b/example/storybook/.storybook/preview.js @@ -73,6 +73,7 @@ export const parameters = { 'Radio', 'Select', 'Slider', + 'Range Slider', 'Switch', 'Tabs', 'Textarea', diff --git a/packages/unstyled/range-slider/package.json b/packages/unstyled/range-slider/package.json index 8e06f211a9..cb2d37bfbf 100644 --- a/packages/unstyled/range-slider/package.json +++ b/packages/unstyled/range-slider/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-ui/range-slider", - "description": "A universal headless slider component for React Native, Next.js & React", + "description": "A universal headless range slider component for React Native, Next.js & React", "version": "0.1.0", "main": "lib/commonjs/index", "module": "lib/module/index", From cb99ac9b7ddaf1f66623665c00731d5ce72c34eb Mon Sep 17 00:00:00 2001 From: Vidhi Kataria Date: Mon, 18 Mar 2024 16:53:28 +0530 Subject: [PATCH 07/12] v1.1.15 --- packages/themed/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/themed/package.json b/packages/themed/package.json index d23fd22071..45be379830 100644 --- a/packages/themed/package.json +++ b/packages/themed/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-ui/themed", - "version": "1.1.13", + "version": "1.1.15", "main": "build/index.js", "types": "build/index.d.ts", "module": "build/index", From f3476969ccc60d32ecf8d85e069c8d219483fc2a Mon Sep 17 00:00:00 2001 From: Vidhi Kataria Date: Mon, 18 Mar 2024 18:06:49 +0530 Subject: [PATCH 08/12] v1.1.15-alpha.0 --- packages/themed/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/themed/package.json b/packages/themed/package.json index 45be379830..188811f225 100644 --- a/packages/themed/package.json +++ b/packages/themed/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-ui/themed", - "version": "1.1.15", + "version": "1.1.15-alpha.0", "main": "build/index.js", "types": "build/index.d.ts", "module": "build/index", From 2c42a0c96170fd5ea18489ed7fc0876f52fe4940 Mon Sep 17 00:00:00 2001 From: Vidhi Kataria Date: Mon, 18 Mar 2024 18:17:48 +0530 Subject: [PATCH 09/12] v0.1.1 --- packages/unstyled/range-slider/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/unstyled/range-slider/package.json b/packages/unstyled/range-slider/package.json index cb2d37bfbf..b961bc6beb 100644 --- a/packages/unstyled/range-slider/package.json +++ b/packages/unstyled/range-slider/package.json @@ -1,7 +1,7 @@ { "name": "@gluestack-ui/range-slider", "description": "A universal headless range slider component for React Native, Next.js & React", - "version": "0.1.0", + "version": "0.1.1", "main": "lib/commonjs/index", "module": "lib/module/index", "types": "lib/typescript/index.d.ts", From 1d4f249121d026db58250b869f750ee68f48d8b7 Mon Sep 17 00:00:00 2001 From: Vidhi Kataria Date: Mon, 18 Mar 2024 18:24:42 +0530 Subject: [PATCH 10/12] v1.1.16 --- packages/themed/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/themed/package.json b/packages/themed/package.json index 188811f225..262622f5d6 100644 --- a/packages/themed/package.json +++ b/packages/themed/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-ui/themed", - "version": "1.1.15-alpha.0", + "version": "1.1.16", "main": "build/index.js", "types": "build/index.d.ts", "module": "build/index", From 2c7a64ac6702e806b1e40e304d4d590f83e61b71 Mon Sep 17 00:00:00 2001 From: Vidhi Kataria Date: Mon, 18 Mar 2024 18:25:29 +0530 Subject: [PATCH 11/12] v1.1.17 --- packages/themed/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/themed/package.json b/packages/themed/package.json index 262622f5d6..67b4d9efd3 100644 --- a/packages/themed/package.json +++ b/packages/themed/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-ui/themed", - "version": "1.1.16", + "version": "1.1.17", "main": "build/index.js", "types": "build/index.d.ts", "module": "build/index", @@ -59,7 +59,7 @@ "@gluestack-ui/progress": "0.1.13", "@gluestack-ui/provider": "0.1.10", "@gluestack-ui/radio": "0.1.25", - "@gluestack-ui/range-slider": "*", + "@gluestack-ui/range-slider": "0.1.1", "@gluestack-ui/select": "0.1.24", "@gluestack-ui/slider": "0.1.21", "@gluestack-ui/spinner": "0.1.14", From a343d585f72c582ba57cfd09d6253fb08564d608 Mon Sep 17 00:00:00 2001 From: Vidhi Kataria Date: Wed, 20 Mar 2024 14:09:38 +0530 Subject: [PATCH 12/12] fix: slider fixes --- .../storybook/.ondevice/storybook.requires.js | 2 +- .../Forms/RangeSlider/RangeSlider.tsx | 21 +--------- packages/themed/tsconfig.json | 6 +-- .../range-slider/src/RangeSliderLeftThumb.tsx | 22 +++++----- .../src/RangeSliderRightThumb.tsx | 22 +++++----- yarn.lock | 40 +++++++++++++++++++ 6 files changed, 66 insertions(+), 47 deletions(-) diff --git a/example/storybook/.ondevice/storybook.requires.js b/example/storybook/.ondevice/storybook.requires.js index 1cf471268d..1539780502 100644 --- a/example/storybook/.ondevice/storybook.requires.js +++ b/example/storybook/.ondevice/storybook.requires.js @@ -78,7 +78,7 @@ const getStories = () => { // require('../src/ui/components/Feedback/Progress/Progress.stories.tsx'), // require('../src/ui/components/Forms/Radio/Radio.stories.tsx'), // require('../src/ui/components/Forms/Select/Select.stories.tsx'), - // require('../src/ui/components/Forms/Slider/Slider.stories.tsx'), + require('../src/ui/components/Forms/Slider/Slider.stories.tsx'), // require('../src/ui/components/Feedback/Spinner/Spinner.stories.tsx'), // require('../src/ui/components/Forms/Switch/Switch.stories.tsx'), // require('../src/ui/components/Forms/Textarea/Textarea.stories.tsx'), diff --git a/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx b/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx index 46a3d961a0..a228810d7e 100644 --- a/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx +++ b/example/storybook/src/ui/components/Forms/RangeSlider/RangeSlider.tsx @@ -21,12 +21,10 @@ const RangeSliderBasic = ({ ...props }: any) => { const [sliderValue, setSliderValue] = React.useState([20, 49]); return ( -
+
{ - - - - - - -
); }; diff --git a/packages/themed/tsconfig.json b/packages/themed/tsconfig.json index b4674d8ec2..4728950c79 100644 --- a/packages/themed/tsconfig.json +++ b/packages/themed/tsconfig.json @@ -1,13 +1,11 @@ { "include": ["./src"], "exclude": ["node_modules", "example"], + "path": {}, "compilerOptions": { - "paths": { - "@gluestack-ui/range-slider": ["../unstyled/range-slider/src"] - }, "ignoreDeprecations": "5.0", "noEmit": false, - "declaration": false, + "declaration": true, "allowJs": true, "allowUnreachableCode": false, "allowUnusedLabels": true, diff --git a/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx b/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx index 46c60029e3..afdc253b37 100644 --- a/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx +++ b/packages/unstyled/range-slider/src/RangeSliderLeftThumb.tsx @@ -35,10 +35,10 @@ function RangeSliderThumb< IRangeSliderThumbProps & { children?: any; style?: any }, ref?: any ) => { - const [setThumbSize] = React.useState({ - height: 0, - width: 0, - }); + // const [setThumbSize] = React.useState({ + // height: 0, + // width: 0, + // }); const _ref = React.useRef(null); const { isHovered } = useHover({}, _ref); @@ -147,13 +147,13 @@ function RangeSliderThumb< return ( { - // @ts-ignore - setThumbSize({ - height: layout?.nativeEvent?.layout?.height, - width: layout?.nativeEvent?.layout?.width, - }); - }} + // onLayout={(layout: any) => { + // // @ts-ignore + // // setThumbSize({ + // // height: layout?.nativeEvent?.layout?.height, + // // width: layout?.nativeEvent?.layout?.width, + // // }); + // }} states={{ hover: isHovered, disabled: isDisabled, diff --git a/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx b/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx index cbe7b83369..62373e8b66 100644 --- a/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx +++ b/packages/unstyled/range-slider/src/RangeSliderRightThumb.tsx @@ -37,10 +37,10 @@ function RangeSliderThumb< IRangeSliderThumbProps & { children?: any; style?: any }, ref?: any ) => { - const [setThumbSize] = React.useState({ - height: 0, - width: 0, - }); + // const [setThumbSize] = React.useState({ + // height: 0, + // width: 0, + // }); const _ref = React.useRef(null); const { isHovered } = useHover({}, _ref); @@ -125,13 +125,13 @@ function RangeSliderThumb< return ( { - // @ts-ignore - setThumbSize({ - height: layout?.nativeEvent?.layout?.height, - width: layout?.nativeEvent?.layout?.width, - }); - }} + // onLayout={(layout: any) => { + // // @ts-ignore + // setThumbSize({ + // height: layout?.nativeEvent?.layout?.height, + // width: layout?.nativeEvent?.layout?.width, + // }); + // }} states={{ hover: isHovered || isHoveredProp, disabled: isDisabled || isDisabledProp, diff --git a/yarn.lock b/yarn.lock index b56a95ef5e..d9ce85015c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3297,6 +3297,46 @@ "@react-native-aria/focus" "^0.2.9" "@react-native-aria/interactions" "^0.2.11" +"@gluestack-ui/themed@1.1.11": + version "1.1.11" + resolved "https://registry.yarnpkg.com/@gluestack-ui/themed/-/themed-1.1.11.tgz#556efbdb41e4b7d1a8630dc04b9080e178032d88" + integrity sha512-win1zOmiCxez07eAR2Rb1fhPGIC6a1Oi5JHnnRZMbsvX1+DHMCUN0/8m3uVv1hc5JiaamP0MudFJwgzbbAGS0g== + dependencies: + "@expo/html-elements" latest + "@gluestack-style/animation-resolver" "1.0.4" + "@gluestack-style/legend-motion-animation-driver" "1.0.3" + "@gluestack-ui/accordion" "1.0.1" + "@gluestack-ui/actionsheet" "0.2.37" + "@gluestack-ui/alert" "0.1.12" + "@gluestack-ui/alert-dialog" "0.1.25" + "@gluestack-ui/avatar" "0.1.15" + "@gluestack-ui/button" "1.0.1" + "@gluestack-ui/checkbox" "0.1.24" + "@gluestack-ui/divider" "0.1.8" + "@gluestack-ui/fab" "0.1.18" + "@gluestack-ui/form-control" "0.1.16" + "@gluestack-ui/icon" "0.1.20" + "@gluestack-ui/image" "0.1.7" + "@gluestack-ui/input" "0.1.24" + "@gluestack-ui/link" "0.1.17" + "@gluestack-ui/menu" "0.2.30" + "@gluestack-ui/modal" "0.1.29" + "@gluestack-ui/overlay" "0.1.12" + "@gluestack-ui/popover" "0.1.32" + "@gluestack-ui/pressable" "0.1.14" + "@gluestack-ui/progress" "0.1.13" + "@gluestack-ui/provider" "0.1.10" + "@gluestack-ui/radio" "0.1.25" + "@gluestack-ui/select" "0.1.24" + "@gluestack-ui/slider" "0.1.21" + "@gluestack-ui/spinner" "0.1.14" + "@gluestack-ui/switch" "0.1.19" + "@gluestack-ui/tabs" "0.1.14" + "@gluestack-ui/textarea" "0.1.20" + "@gluestack-ui/toast" "1.0.4" + "@gluestack-ui/tooltip" "0.1.26" + "@legendapp/motion" latest + "@gluestack-ui/toast@^0.1.7": version "0.1.20" resolved "https://registry.yarnpkg.com/@gluestack-ui/toast/-/toast-0.1.20.tgz#863453f75d2e941000204a9524161bfd2500e320"