@effijs/templates 0.0.0-stage → 1.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +27 -0
- package/LICENSE +22 -0
- package/README.md +32 -2
- package/ai/SETUP.md +5 -0
- package/docs/catalog.md +85 -0
- package/forge.manifest.js +75 -0
- package/lib/compat.js +40 -0
- package/lib/docs/build.js +146 -0
- package/lib/install.js +51 -0
- package/lib/journal.js +40 -0
- package/lib/jsonConfig.js +33 -0
- package/lib/migration.js +35 -0
- package/lib/names.js +42 -0
- package/lib/patch.js +62 -0
- package/lib/paths.js +12 -0
- package/lib/project.js +48 -0
- package/lib/registry.js +99 -0
- package/package.json +46 -4
- package/platforms/react-native/CATALOG.md +391 -0
- package/platforms/react-native/ORIGIN.md +42 -0
- package/platforms/react-native/README.md +78 -0
- package/platforms/react-native/ai/AGENTS.md.hbs +36 -0
- package/platforms/react-native/ai/SETUP.md +89 -0
- package/platforms/react-native/compat/matrix.js +150 -0
- package/platforms/react-native/configs/babel.js +63 -0
- package/platforms/react-native/configs/forgeConfig.js +35 -0
- package/platforms/react-native/configs/jsConfigs.js +96 -0
- package/platforms/react-native/configs/metro.js +86 -0
- package/platforms/react-native/generators/add/generator.js +12 -0
- package/platforms/react-native/generators/add/run.js +64 -0
- package/platforms/react-native/generators/component/generator.js +75 -0
- package/platforms/react-native/generators/component/render.js +69 -0
- package/platforms/react-native/generators/component/templates/Common.tsx.hbs +13 -0
- package/platforms/react-native/generators/component/templates/index.ts.hbs +13 -0
- package/platforms/react-native/generators/component/templates/pm.ts.hbs +7 -0
- package/platforms/react-native/generators/component/templates/types.ts.hbs +3 -0
- package/platforms/react-native/generators/demo/files/api/app.http +8 -0
- package/platforms/react-native/generators/demo/files/api/environment/http-client.env.json +5 -0
- package/platforms/react-native/generators/demo/files/entity/category/category.api.ts +18 -0
- package/platforms/react-native/generators/demo/files/entity/category/category.dto.ts +15 -0
- package/platforms/react-native/generators/demo/files/entity/category/category.service.ts +42 -0
- package/platforms/react-native/generators/demo/files/entity/category/category.store.ts +26 -0
- package/platforms/react-native/generators/demo/files/entity/category/index.ts +2 -0
- package/platforms/react-native/generators/demo/files/entity/product/index.ts +2 -0
- package/platforms/react-native/generators/demo/files/entity/product/product.api.ts +49 -0
- package/platforms/react-native/generators/demo/files/entity/product/product.dto.ts +120 -0
- package/platforms/react-native/generators/demo/files/entity/product/product.service.ts +139 -0
- package/platforms/react-native/generators/demo/files/entity/product/product.store.ts +37 -0
- package/platforms/react-native/generators/demo/files/feature/product/components/Product.CategorySelect.tsx +36 -0
- package/platforms/react-native/generators/demo/files/feature/product/detail/Product.Detail.Screen.tsx +100 -0
- package/platforms/react-native/generators/demo/files/feature/product/detail/product.detail.service.ts +33 -0
- package/platforms/react-native/generators/demo/files/feature/product/filter/Product.Filter.Screen.tsx +59 -0
- package/platforms/react-native/generators/demo/files/feature/product/filter/product.filter.service.ts +78 -0
- package/platforms/react-native/generators/demo/files/feature/product/form/Product.Form.Screen.tsx +71 -0
- package/platforms/react-native/generators/demo/files/feature/product/form/product.form.service.ts +142 -0
- package/platforms/react-native/generators/demo/files/feature/product/index.ts +7 -0
- package/platforms/react-native/generators/demo/files/feature/product/list/Product.List.Item.tsx +34 -0
- package/platforms/react-native/generators/demo/files/feature/product/list/Product.List.Screen.tsx +106 -0
- package/platforms/react-native/generators/demo/files/feature/product/list/product.list.service.ts +47 -0
- package/platforms/react-native/generators/demo/files/feature/product/product.feature.ts +29 -0
- package/platforms/react-native/generators/demo/files/feature/product/product.hooks.ts +7 -0
- package/platforms/react-native/generators/demo/files/feature/product/search/Product.Search.Screen.tsx +82 -0
- package/platforms/react-native/generators/demo/files/feature/product/search/product.search.service.ts +97 -0
- package/platforms/react-native/generators/demo/files/navigation/navigation.product.ts +46 -0
- package/platforms/react-native/generators/demo/generator.js +93 -0
- package/platforms/react-native/generators/entity/generator.js +68 -0
- package/platforms/react-native/generators/feature/generator.js +224 -0
- package/platforms/react-native/generators/feature/render.js +163 -0
- package/platforms/react-native/generators/feature/templates/detail.screen.tsx.hbs +25 -0
- package/platforms/react-native/generators/feature/templates/detail.service.ts.hbs +14 -0
- package/platforms/react-native/generators/feature/templates/feature.ts.hbs +18 -0
- package/platforms/react-native/generators/feature/templates/filter.screen.tsx.hbs +17 -0
- package/platforms/react-native/generators/feature/templates/filter.service.ts.hbs +14 -0
- package/platforms/react-native/generators/feature/templates/form.screen.tsx.hbs +21 -0
- package/platforms/react-native/generators/feature/templates/form.service.ts.hbs +37 -0
- package/platforms/react-native/generators/feature/templates/hooks.ts.hbs +7 -0
- package/platforms/react-native/generators/feature/templates/index.ts.hbs +2 -0
- package/platforms/react-native/generators/feature/templates/list.item.tsx.hbs +16 -0
- package/platforms/react-native/generators/feature/templates/list.screen.tsx.hbs +34 -0
- package/platforms/react-native/generators/feature/templates/list.service.ts.hbs +15 -0
- package/platforms/react-native/generators/feature/templates/navigation.ts.hbs +12 -0
- package/platforms/react-native/generators/feature/templates/search.screen.tsx.hbs +24 -0
- package/platforms/react-native/generators/feature/templates/search.service.ts.hbs +13 -0
- package/platforms/react-native/generators/feature/templates/tab.tsx.hbs +8 -0
- package/platforms/react-native/generators/init/files/app/app.controller.ts +41 -0
- package/platforms/react-native/generators/init/files/app/app.error.ts +1 -0
- package/platforms/react-native/generators/init/files/app/app.store.ts +12 -0
- package/platforms/react-native/generators/init/files/app/index.ts +19 -0
- package/platforms/react-native/generators/init/files/app/splash/Onboarding.Screen.tsx +31 -0
- package/platforms/react-native/generators/init/files/app/splash/Splash.Screen.tsx +14 -0
- package/platforms/react-native/generators/init/files/app/tabs/home/Home.tab.tsx +24 -0
- package/platforms/react-native/generators/init/files/app/tabs/profile/Profile.tab.tsx +1 -0
- package/platforms/react-native/generators/init/files/configs/dev.ts.hbs +5 -0
- package/platforms/react-native/generators/init/files/configs/index.ts +4 -0
- package/platforms/react-native/generators/init/files/configs/prod.ts.hbs +5 -0
- package/platforms/react-native/generators/init/files/entity/auth/auth.api.ts +36 -0
- package/platforms/react-native/generators/init/files/entity/auth/auth.dto.ts +26 -0
- package/platforms/react-native/generators/init/files/entity/auth/auth.service.ts +94 -0
- package/platforms/react-native/generators/init/files/entity/auth/auth.session.store.ts +14 -0
- package/platforms/react-native/generators/init/files/entity/auth/auth.store.ts +20 -0
- package/platforms/react-native/generators/init/files/entity/auth/index.ts +2 -0
- package/platforms/react-native/generators/init/files/entity/index.ts +2 -0
- package/platforms/react-native/generators/init/files/feature/auth/auth.feature.ts +10 -0
- package/platforms/react-native/generators/init/files/feature/auth/auth.hooks.ts +7 -0
- package/platforms/react-native/generators/init/files/feature/auth/index.ts +1 -0
- package/platforms/react-native/generators/init/files/feature/auth/sign-in/SignIn.Screen.tsx +39 -0
- package/platforms/react-native/generators/init/files/feature/auth/sign-in/signIn.service.ts +54 -0
- package/platforms/react-native/generators/init/files/feature/auth/sign-up/SignUp.Screen.tsx +64 -0
- package/platforms/react-native/generators/init/files/feature/auth/sign-up/signUp.service.ts +73 -0
- package/platforms/react-native/generators/init/files/feature/feature.hooks.ts +15 -0
- package/platforms/react-native/generators/init/files/feature/index.ts +3 -0
- package/platforms/react-native/generators/init/files/feature/profile/Profile.Screen.tsx +52 -0
- package/platforms/react-native/generators/init/files/feature/profile/index.ts +1 -0
- package/platforms/react-native/generators/init/files/feature/profile/profile.feature.ts +18 -0
- package/platforms/react-native/generators/init/files/feature/profile/profile.hooks.ts +7 -0
- package/platforms/react-native/generators/init/files/index.ts +16 -0
- package/platforms/react-native/generators/init/files/navigation/index.ts +18 -0
- package/platforms/react-native/generators/init/files/navigation/navigation.app.ts +58 -0
- package/platforms/react-native/generators/init/files/navigation/navigation.features.ts +9 -0
- package/platforms/react-native/generators/init/files/navigation/navigation.hooks.ts +5 -0
- package/platforms/react-native/generators/init/files/navigation/navigation.tabs.ts +55 -0
- package/platforms/react-native/generators/init/files/navigation/navigation.widgets.ts +23 -0
- package/platforms/react-native/generators/init/files/services/http/http.base.ts +69 -0
- package/platforms/react-native/generators/init/files/services/http/http.error.ts +10 -0
- package/platforms/react-native/generators/init/files/services/http/http.service.ts +24 -0
- package/platforms/react-native/generators/init/files/services/http/middleware/index.ts +12 -0
- package/platforms/react-native/generators/init/files/services/http/middleware/middleware.error.ts +36 -0
- package/platforms/react-native/generators/init/files/services/http/middleware/middleware.registry.ts +3 -0
- package/platforms/react-native/generators/init/files/services/http/middleware/middleware.token.ts +97 -0
- package/platforms/react-native/generators/init/files/services/index.ts +15 -0
- package/platforms/react-native/generators/init/files/ui/components/Box/Common.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Box/box.pm.ts +111 -0
- package/platforms/react-native/generators/init/files/ui/components/Box/box.types.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/components/Box/index.ts +13 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/Common.tsx +50 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/Touchable.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/button.pm.ts +197 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/button.types.ts +22 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/button.utils.ts +16 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/index.ts +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/Colours.tsx +50 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/Common.tsx +38 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/ErrorText.tsx +11 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/Input.tsx +115 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/InputArea.tsx +70 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/Label.tsx +18 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/Select.tsx +86 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/components/SecureTextEntry.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/form.error.ts +18 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/form.pm.ts +134 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/form.types.ts +59 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/index.ts +67 -0
- package/platforms/react-native/generators/init/files/ui/components/Grid/Common.tsx +11 -0
- package/platforms/react-native/generators/init/files/ui/components/Grid/grid.pm.ts +93 -0
- package/platforms/react-native/generators/init/files/ui/components/Grid/grid.types.ts +79 -0
- package/platforms/react-native/generators/init/files/ui/components/Grid/index.ts +13 -0
- package/platforms/react-native/generators/init/files/ui/components/Icon/Common.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Icon/icons.pm.ts +74 -0
- package/platforms/react-native/generators/init/files/ui/components/Icon/icons.types.ts +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Icon/index.ts +3 -0
- package/platforms/react-native/generators/init/files/ui/components/Loading/Loading.tsx +10 -0
- package/platforms/react-native/generators/init/files/ui/components/Loading/loading.hook.ts +5 -0
- package/platforms/react-native/generators/init/files/ui/components/Loading/loading.service.ts +22 -0
- package/platforms/react-native/generators/init/files/ui/components/Loading/loading.store.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/Common.tsx +87 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/Content.tsx +77 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/Header.tsx +80 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/HeaderTab.tsx +17 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/SafeAreaHOC.tsx +9 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/index.ts +22 -0
- package/platforms/react-native/generators/init/files/ui/components/Text/Common.tsx +20 -0
- package/platforms/react-native/generators/init/files/ui/components/Text/index.ts +13 -0
- package/platforms/react-native/generators/init/files/ui/components/Text/text.pm.ts +55 -0
- package/platforms/react-native/generators/init/files/ui/components/Text/text.types.ts +27 -0
- package/platforms/react-native/generators/init/files/ui/components/TextInput/Common.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/components/TextInput/index.ts +15 -0
- package/platforms/react-native/generators/init/files/ui/components/TextInput/textInput.pm.ts +65 -0
- package/platforms/react-native/generators/init/files/ui/components/TextInput/textInput.types.ts +16 -0
- package/platforms/react-native/generators/init/files/ui/components/ThemePicker/ThemePicker.tsx +92 -0
- package/platforms/react-native/generators/init/files/ui/components/ThemePicker/index.ts +1 -0
- package/platforms/react-native/generators/init/files/ui/components/index.ts +27 -0
- package/platforms/react-native/generators/init/files/ui/components/utils/color.ts +19 -0
- package/platforms/react-native/generators/init/files/ui/components/utils/index.ts +3 -0
- package/platforms/react-native/generators/init/files/ui/components/utils/useLoading.hook.spec.tsx +202 -0
- package/platforms/react-native/generators/init/files/ui/components/utils/useLoading.hook.ts +172 -0
- package/platforms/react-native/generators/init/files/ui/components/utils/useStore.ts +34 -0
- package/platforms/react-native/generators/init/files/ui/fonts/font-icons.ttf +0 -0
- package/platforms/react-native/generators/init/files/ui/icons/font-icons.json +53 -0
- package/platforms/react-native/generators/init/files/ui/icons/logo.png +0 -0
- package/platforms/react-native/generators/init/files/ui/icons/logo.svg +304 -0
- package/platforms/react-native/generators/init/files/ui/icons/tabs/icon-1.png +0 -0
- package/platforms/react-native/generators/init/files/ui/icons/tabs/icon-2.png +0 -0
- package/platforms/react-native/generators/init/files/ui/theme/black/black.color.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/theme/black/index.ts +10 -0
- package/platforms/react-native/generators/init/files/ui/theme/blue/blue.color.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/theme/blue/index.ts +10 -0
- package/platforms/react-native/generators/init/files/ui/theme/green/green.color.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/theme/green/index.ts +10 -0
- package/platforms/react-native/generators/init/files/ui/theme/index.ts +11 -0
- package/platforms/react-native/generators/init/files/ui/theme/pink/index.ts +10 -0
- package/platforms/react-native/generators/init/files/ui/theme/pink/pink.color.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/index.ts +23 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/theme.scheme.color.ts +139 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/theme.scheme.radius.ts +21 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/theme.scheme.spacing.ts +24 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/theme.scheme.ts +25 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/theme.scheme.typography.ts +98 -0
- package/platforms/react-native/generators/init/files/ui/theme/shared/index.ts +4 -0
- package/platforms/react-native/generators/init/files/ui/theme/shared/shared.color.base.ts +79 -0
- package/platforms/react-native/generators/init/files/ui/theme/shared/shared.radius.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/theme/shared/shared.spacing.ts +9 -0
- package/platforms/react-native/generators/init/files/ui/theme/shared/shared.typography.ts +105 -0
- package/platforms/react-native/generators/init/files/ui/theme/theme.hooks.ts +7 -0
- package/platforms/react-native/generators/init/files/ui/theme/theme.meta.ts +10 -0
- package/platforms/react-native/generators/init/files/ui/theme/theme.provider.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/theme/theme.service.ts +36 -0
- package/platforms/react-native/generators/init/files/ui/theme/theme.ts +27 -0
- package/platforms/react-native/generators/init/files/ui/widgets/index.ts +1 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/Toast.Item.tsx +175 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/Toast.Overlay.tsx +46 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/Toast.Stack.tsx +75 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/index.ts +7 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/toast.hooks.ts +18 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/toast.service.ts +39 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/toast.store.ts +59 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/toast.types.ts +18 -0
- package/platforms/react-native/generators/init/files/ui/widgets/widgets.feature.ts +14 -0
- package/platforms/react-native/generators/init/files/utils/date.ts +11 -0
- package/platforms/react-native/generators/init/files/utils/index.ts +12 -0
- package/platforms/react-native/generators/init/files/utils/store.persistent.ts +103 -0
- package/platforms/react-native/generators/init/files/utils/store.registry.ts +14 -0
- package/platforms/react-native/generators/init/files/utils/string.ts +100 -0
- package/platforms/react-native/generators/init/generator.js +86 -0
- package/platforms/react-native/generators/init/kit.js +23 -0
- package/platforms/react-native/generators/init/navigators/expo-router/index.ts +18 -0
- package/platforms/react-native/generators/init/navigators/expo-router/navigation.app.ts +8 -0
- package/platforms/react-native/generators/init/navigators/expo-router/navigation.features.ts +9 -0
- package/platforms/react-native/generators/init/navigators/expo-router/navigation.hooks.ts +5 -0
- package/platforms/react-native/generators/init/navigators/expo-router/navigation.tabs.ts +7 -0
- package/platforms/react-native/generators/init/navigators/expo-router/navigation.widgets.ts +5 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/index.ts +18 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/navigation.app.ts +8 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/navigation.features.ts +9 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/navigation.hooks.ts +5 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/navigation.tabs.ts +7 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/navigation.widgets.ts +5 -0
- package/platforms/react-native/generators/setup/generator.js +225 -0
- package/platforms/react-native/generators/util/generator.js +12 -0
- package/platforms/react-native/platform.js +32 -0
- package/platforms/react-native/runtime.js +57 -0
- package/platforms/react-native/solutions/components/BottomSheet/README.md +29 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/Common.tsx +120 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/Content.tsx +57 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/Context.tsx +22 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/FlatList.tsx +50 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/Header.tsx +57 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/Search.tsx +24 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/bottomSheet.constants.ts +13 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/bottomSheet.types.ts +31 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/index.ts +33 -0
- package/platforms/react-native/solutions/components/BottomSheet/solution.js +38 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/README.md +29 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/files/SelectPicker.tsx +47 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/files/bottomSheet/Content.BottomSheet.tsx +22 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/files/bottomSheet/DateTimePicker.BottomSheet.tsx +74 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/files/bottomSheet/List.BottomSheet.tsx +62 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/solution.js +49 -0
- package/platforms/react-native/solutions/components/Calendar/README.md +29 -0
- package/platforms/react-native/solutions/components/Calendar/files/Common.tsx +16 -0
- package/platforms/react-native/solutions/components/Calendar/files/Context.tsx +466 -0
- package/platforms/react-native/solutions/components/Calendar/files/DayCell.tsx +89 -0
- package/platforms/react-native/solutions/components/Calendar/files/MonthView.tsx +41 -0
- package/platforms/react-native/solutions/components/Calendar/files/MonthYearOverlay.tsx +51 -0
- package/platforms/react-native/solutions/components/Calendar/files/SwipeablePeriod.tsx +44 -0
- package/platforms/react-native/solutions/components/Calendar/files/WeekDayTitles.tsx +31 -0
- package/platforms/react-native/solutions/components/Calendar/files/WeekView.tsx +40 -0
- package/platforms/react-native/solutions/components/Calendar/files/calendar.styles.ts +142 -0
- package/platforms/react-native/solutions/components/Calendar/files/calendar.types.ts +126 -0
- package/platforms/react-native/solutions/components/Calendar/files/calendar.utils.ts +143 -0
- package/platforms/react-native/solutions/components/Calendar/files/index.ts +40 -0
- package/platforms/react-native/solutions/components/Calendar/solution.js +38 -0
- package/platforms/react-native/solutions/components/Chart/README.md +29 -0
- package/platforms/react-native/solutions/components/Chart/files/Cilcular.tsx +140 -0
- package/platforms/react-native/solutions/components/Chart/files/index.ts +3 -0
- package/platforms/react-native/solutions/components/Chart/solution.js +38 -0
- package/platforms/react-native/solutions/components/CheckBox/README.md +29 -0
- package/platforms/react-native/solutions/components/CheckBox/files/Common.tsx +55 -0
- package/platforms/react-native/solutions/components/CheckBox/files/checkbox.pm.ts +71 -0
- package/platforms/react-native/solutions/components/CheckBox/files/index.ts +9 -0
- package/platforms/react-native/solutions/components/CheckBox/form/Checkbox.tsx +22 -0
- package/platforms/react-native/solutions/components/CheckBox/solution.js +57 -0
- package/platforms/react-native/solutions/components/DateTimePicker/README.md +29 -0
- package/platforms/react-native/solutions/components/DateTimePicker/files/DateTimePicker.tsx +44 -0
- package/platforms/react-native/solutions/components/DateTimePicker/solution.js +45 -0
- package/platforms/react-native/solutions/components/Image/README.md +29 -0
- package/platforms/react-native/solutions/components/Image/files/SVG.tsx +74 -0
- package/platforms/react-native/solutions/components/Image/files/image.pm.ts +25 -0
- package/platforms/react-native/solutions/components/Image/files/image.utils.ts +35 -0
- package/platforms/react-native/solutions/components/Image/files/index.ts +5 -0
- package/platforms/react-native/solutions/components/Image/solution.js +40 -0
- package/platforms/react-native/solutions/components/InputSecurity/README.md +29 -0
- package/platforms/react-native/solutions/components/InputSecurity/files/InputSecurity.ts +142 -0
- package/platforms/react-native/solutions/components/InputSecurity/solution.js +28 -0
- package/platforms/react-native/solutions/components/OTP/README.md +29 -0
- package/platforms/react-native/solutions/components/OTP/files/Item.tsx +16 -0
- package/platforms/react-native/solutions/components/OTP/files/Items.tsx +33 -0
- package/platforms/react-native/solutions/components/OTP/files/index.tsx +120 -0
- package/platforms/react-native/solutions/components/OTP/files/otp.pm.ts +30 -0
- package/platforms/react-native/solutions/components/OTP/solution.js +38 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/README.md +29 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/files/Circular.tsx +154 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/files/Linear.tsx +133 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/files/circular.pm.ts +34 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/files/index.ts +16 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/solution.js +39 -0
- package/platforms/react-native/solutions/components/Ruler/README.md +29 -0
- package/platforms/react-native/solutions/components/Ruler/files/Common.tsx +44 -0
- package/platforms/react-native/solutions/components/Ruler/files/Context.tsx +210 -0
- package/platforms/react-native/solutions/components/Ruler/files/Track.tsx +686 -0
- package/platforms/react-native/solutions/components/Ruler/files/Value.tsx +60 -0
- package/platforms/react-native/solutions/components/Ruler/files/index.ts +23 -0
- package/platforms/react-native/solutions/components/Ruler/files/ruler.constants.ts +70 -0
- package/platforms/react-native/solutions/components/Ruler/files/ruler.types.ts +98 -0
- package/platforms/react-native/solutions/components/Ruler/files/ruler.utils.ts +332 -0
- package/platforms/react-native/solutions/components/Ruler/solution.js +38 -0
- package/platforms/react-native/solutions/components/Section/README.md +29 -0
- package/platforms/react-native/solutions/components/Section/files/Common.tsx +144 -0
- package/platforms/react-native/solutions/components/Section/solution.js +37 -0
- package/platforms/react-native/solutions/components/Slider/README.md +29 -0
- package/platforms/react-native/solutions/components/Slider/files/Container.tsx +5 -0
- package/platforms/react-native/solutions/components/Slider/files/Content.tsx +44 -0
- package/platforms/react-native/solutions/components/Slider/files/Context.tsx +30 -0
- package/platforms/react-native/solutions/components/Slider/files/Pagination.Dot.tsx +61 -0
- package/platforms/react-native/solutions/components/Slider/files/index.ts +22 -0
- package/platforms/react-native/solutions/components/Slider/solution.js +38 -0
- package/platforms/react-native/solutions/components/Switch/README.md +29 -0
- package/platforms/react-native/solutions/components/Switch/files/Common.tsx +38 -0
- package/platforms/react-native/solutions/components/Switch/files/index.ts +9 -0
- package/platforms/react-native/solutions/components/Switch/files/switch.pm.ts +53 -0
- package/platforms/react-native/solutions/components/Switch/solution.js +38 -0
- package/platforms/react-native/solutions/install.js +97 -0
- package/platforms/react-native/solutions/services/firebase-core/README.md +31 -0
- package/platforms/react-native/solutions/services/firebase-core/files/index.ts +5 -0
- package/platforms/react-native/solutions/services/firebase-core/solution.js +39 -0
- package/platforms/react-native/solutions/services/firebase-messaging/README.md +31 -0
- package/platforms/react-native/solutions/services/firebase-messaging/files/index.ts +20 -0
- package/platforms/react-native/solutions/services/firebase-messaging/solution.js +42 -0
- package/platforms/react-native/solutions/utils/permissions/README.md +29 -0
- package/platforms/react-native/solutions/utils/permissions/files/permissions.ts +10 -0
- package/platforms/react-native/solutions/utils/permissions/solution.js +32 -0
- package/presets/react-native-fsd/index.js +25 -0
- package/shared/generators/entity/render.js +88 -0
- package/shared/generators/entity/templates/crud/api.ts.hbs +36 -0
- package/shared/generators/entity/templates/crud/dto.ts.hbs +36 -0
- package/shared/generators/entity/templates/crud/service.ts.hbs +73 -0
- package/shared/generators/entity/templates/crud/store.ts.hbs +27 -0
- package/shared/generators/entity/templates/index.ts.hbs +2 -0
- package/shared/generators/entity/templates/simple/api.ts.hbs +16 -0
- package/shared/generators/entity/templates/simple/dto.ts.hbs +5 -0
- package/shared/generators/entity/templates/simple/service.ts.hbs +26 -0
- package/shared/generators/entity/templates/simple/store.ts.hbs +18 -0
- package/shared/solutions/utils/date/README.md +29 -0
- package/shared/solutions/utils/date/files/date.ts +11 -0
- package/shared/solutions/utils/date/solution.js +27 -0
- package/shared/solutions/utils/string/README.md +29 -0
- package/shared/solutions/utils/string/files/string.ts +100 -0
- package/shared/solutions/utils/string/solution.js +27 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Canvas,
|
|
3
|
+
Group,
|
|
4
|
+
Path,
|
|
5
|
+
Skia,
|
|
6
|
+
// BlurMask, SweepGradient, vec
|
|
7
|
+
} from '@shopify/react-native-skia';
|
|
8
|
+
import React, { useEffect, useMemo } from 'react';
|
|
9
|
+
import Animated, {
|
|
10
|
+
Easing,
|
|
11
|
+
FadeIn,
|
|
12
|
+
FadeOut,
|
|
13
|
+
interpolate,
|
|
14
|
+
useAnimatedStyle,
|
|
15
|
+
useDerivedValue,
|
|
16
|
+
useSharedValue,
|
|
17
|
+
withRepeat,
|
|
18
|
+
withTiming,
|
|
19
|
+
} from 'react-native-reanimated';
|
|
20
|
+
|
|
21
|
+
import Grid from '../Grid';
|
|
22
|
+
|
|
23
|
+
export type TCircularIndicatorProps = {
|
|
24
|
+
size?: number;
|
|
25
|
+
progress?: number;
|
|
26
|
+
color?: string;
|
|
27
|
+
backgroundColor?: string;
|
|
28
|
+
strokeWidth?: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const CircularIndicator: React.FC<TCircularIndicatorProps> = ({
|
|
32
|
+
size = 24,
|
|
33
|
+
progress: externalProgress,
|
|
34
|
+
color = '#ff000050',
|
|
35
|
+
backgroundColor = '#ff000010',
|
|
36
|
+
strokeWidth = 4,
|
|
37
|
+
}) => {
|
|
38
|
+
const radius = (size - strokeWidth) / 2;
|
|
39
|
+
const canvasSize = size;
|
|
40
|
+
|
|
41
|
+
const circle = useMemo(() => {
|
|
42
|
+
return Skia.Path.Circle(canvasSize / 2, canvasSize / 2, radius);
|
|
43
|
+
}, [canvasSize, radius]);
|
|
44
|
+
|
|
45
|
+
const spinAnimation = useSharedValue(0);
|
|
46
|
+
|
|
47
|
+
const isDeterminate = externalProgress !== undefined;
|
|
48
|
+
|
|
49
|
+
const progressValue = useSharedValue(isDeterminate ? externalProgress! : 0);
|
|
50
|
+
|
|
51
|
+
useEffect(() => () => circle.dispose(), [circle]);
|
|
52
|
+
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (!isDeterminate) {
|
|
55
|
+
spinAnimation.value = withRepeat(
|
|
56
|
+
withTiming(1, { duration: 2000, easing: Easing.linear }),
|
|
57
|
+
-1, // infinite repeat
|
|
58
|
+
false,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}, [isDeterminate, spinAnimation]);
|
|
62
|
+
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (isDeterminate && externalProgress !== undefined) {
|
|
65
|
+
progressValue.value = withTiming(externalProgress, {
|
|
66
|
+
duration: 300,
|
|
67
|
+
easing: Easing.inOut(Easing.quad),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}, [isDeterminate, externalProgress, progressValue]);
|
|
71
|
+
|
|
72
|
+
const rContainerStyle = useAnimatedStyle(() => {
|
|
73
|
+
return {
|
|
74
|
+
transform: !isDeterminate ? [{ rotateZ: `${4 * Math.PI * spinAnimation.value}rad` }] : [],
|
|
75
|
+
};
|
|
76
|
+
}, [isDeterminate]);
|
|
77
|
+
|
|
78
|
+
const startPath = useDerivedValue(() => {
|
|
79
|
+
if (isDeterminate) {
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
return interpolate(spinAnimation.value, [0, 0.6, 1], [0.8, 0.3, 0.8]);
|
|
83
|
+
}, [isDeterminate]);
|
|
84
|
+
|
|
85
|
+
const endPath = useDerivedValue(() => {
|
|
86
|
+
if (isDeterminate) {
|
|
87
|
+
return progressValue.value;
|
|
88
|
+
}
|
|
89
|
+
return interpolate(spinAnimation.value, [0, 0.6, 1], [1.0, 0.9, 1.0]);
|
|
90
|
+
}, [isDeterminate, progressValue]);
|
|
91
|
+
|
|
92
|
+
const startPath2 = useDerivedValue(() => {
|
|
93
|
+
if (isDeterminate) return 0;
|
|
94
|
+
return interpolate(spinAnimation.value, [0, 0.6, 1], [0.35, 0.25, 0.35]);
|
|
95
|
+
}, [isDeterminate]);
|
|
96
|
+
|
|
97
|
+
const endPath2 = useDerivedValue(() => {
|
|
98
|
+
if (isDeterminate) return 1;
|
|
99
|
+
return interpolate(spinAnimation.value, [0, 0.6, 1], [0.95, 0.45, 0.95]);
|
|
100
|
+
}, [isDeterminate]);
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<Grid center>
|
|
104
|
+
<Animated.View entering={FadeIn.duration(500)} exiting={FadeOut.duration(100)} style={rContainerStyle}>
|
|
105
|
+
<Canvas
|
|
106
|
+
style={{
|
|
107
|
+
width: canvasSize,
|
|
108
|
+
height: canvasSize,
|
|
109
|
+
}}>
|
|
110
|
+
<Group
|
|
111
|
+
transform={[
|
|
112
|
+
{ translateX: canvasSize / 2 },
|
|
113
|
+
{ translateY: canvasSize / 2 },
|
|
114
|
+
{ rotate: -Math.PI / 2 },
|
|
115
|
+
{ rotateX: Math.PI },
|
|
116
|
+
{ translateX: -canvasSize / 2 },
|
|
117
|
+
{ translateY: -canvasSize / 2 },
|
|
118
|
+
]}>
|
|
119
|
+
<Path
|
|
120
|
+
path={circle}
|
|
121
|
+
color={color}
|
|
122
|
+
style="stroke"
|
|
123
|
+
strokeWidth={strokeWidth}
|
|
124
|
+
start={startPath}
|
|
125
|
+
end={endPath}
|
|
126
|
+
strokeCap={'round'}>
|
|
127
|
+
{/*<SweepGradient c={vec(canvasSize / 2, canvasSize / 2)} colors={['cyan', 'magenta', 'yellow', 'cyan']} />*/}
|
|
128
|
+
{/*<BlurMask blur={5} style="solid" />*/}
|
|
129
|
+
</Path>
|
|
130
|
+
|
|
131
|
+
{!isDeterminate && (
|
|
132
|
+
<Path
|
|
133
|
+
path={circle}
|
|
134
|
+
color={backgroundColor}
|
|
135
|
+
style="stroke"
|
|
136
|
+
strokeWidth={strokeWidth}
|
|
137
|
+
start={startPath2}
|
|
138
|
+
end={endPath2}
|
|
139
|
+
transform={[
|
|
140
|
+
{ translateX: canvasSize / 2 },
|
|
141
|
+
{ translateY: canvasSize / 2 },
|
|
142
|
+
{ rotate: -Math.PI / 2 },
|
|
143
|
+
{ translateX: -canvasSize / 2 },
|
|
144
|
+
{ translateY: -canvasSize / 2 },
|
|
145
|
+
]}
|
|
146
|
+
strokeCap={'round'}
|
|
147
|
+
/>
|
|
148
|
+
)}
|
|
149
|
+
</Group>
|
|
150
|
+
</Canvas>
|
|
151
|
+
</Animated.View>
|
|
152
|
+
</Grid>
|
|
153
|
+
);
|
|
154
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { Canvas, Path, Skia, RoundedRect } from '@shopify/react-native-skia';
|
|
2
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import { type LayoutChangeEvent } from 'react-native';
|
|
4
|
+
import Animated, {
|
|
5
|
+
Easing,
|
|
6
|
+
FadeIn,
|
|
7
|
+
FadeOut,
|
|
8
|
+
interpolate,
|
|
9
|
+
useDerivedValue,
|
|
10
|
+
useSharedValue,
|
|
11
|
+
withRepeat,
|
|
12
|
+
withTiming,
|
|
13
|
+
} from 'react-native-reanimated';
|
|
14
|
+
|
|
15
|
+
import Grid from '@components/Grid';
|
|
16
|
+
|
|
17
|
+
export type TLinearIndicatorProps = {
|
|
18
|
+
width?: number;
|
|
19
|
+
height?: number;
|
|
20
|
+
progress?: number;
|
|
21
|
+
color?: string;
|
|
22
|
+
backgroundColor?: string;
|
|
23
|
+
borderRadius?: number;
|
|
24
|
+
duration?: number;
|
|
25
|
+
onDurationDone?: () => void;
|
|
26
|
+
reverse?: boolean;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const LinearIndicator: React.FC<TLinearIndicatorProps> = ({
|
|
30
|
+
height = 8,
|
|
31
|
+
progress: externalProgress,
|
|
32
|
+
color = '#ff000050',
|
|
33
|
+
backgroundColor = '#ff000010',
|
|
34
|
+
borderRadius,
|
|
35
|
+
duration,
|
|
36
|
+
onDurationDone,
|
|
37
|
+
reverse = false,
|
|
38
|
+
}) => {
|
|
39
|
+
const [canvasWidth, setCanvasWidth] = useState(0);
|
|
40
|
+
const canvasHeight = height;
|
|
41
|
+
const radius = borderRadius ?? height / 2;
|
|
42
|
+
|
|
43
|
+
const backgroundPath = useMemo(() => {
|
|
44
|
+
const path = Skia.Path.Make();
|
|
45
|
+
path.addRRect({
|
|
46
|
+
rect: { x: 0, y: 0, width: canvasWidth, height: canvasHeight },
|
|
47
|
+
rx: radius,
|
|
48
|
+
ry: radius,
|
|
49
|
+
});
|
|
50
|
+
return path;
|
|
51
|
+
}, [canvasWidth, canvasHeight, radius]);
|
|
52
|
+
|
|
53
|
+
useEffect(() => () => backgroundPath.dispose(), [backgroundPath]);
|
|
54
|
+
|
|
55
|
+
const isDeterminate = externalProgress !== undefined || duration !== undefined;
|
|
56
|
+
|
|
57
|
+
const initialProgress = useMemo(() => {
|
|
58
|
+
if (!isDeterminate) return 0;
|
|
59
|
+
if (externalProgress !== undefined) {
|
|
60
|
+
return reverse ? 1 - externalProgress : externalProgress;
|
|
61
|
+
}
|
|
62
|
+
return reverse ? 1 : 0;
|
|
63
|
+
}, [isDeterminate, externalProgress, reverse]);
|
|
64
|
+
|
|
65
|
+
const progressValue = useSharedValue(initialProgress);
|
|
66
|
+
const animationProgress = useSharedValue(0);
|
|
67
|
+
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (!isDeterminate) {
|
|
70
|
+
animationProgress.value = withRepeat(withTiming(1, { duration: 2000, easing: Easing.linear }), -1, false);
|
|
71
|
+
}
|
|
72
|
+
}, [isDeterminate, animationProgress]);
|
|
73
|
+
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (isDeterminate && externalProgress !== undefined) {
|
|
76
|
+
const target = reverse ? 1 - externalProgress : externalProgress;
|
|
77
|
+
progressValue.value = withTiming(target, {
|
|
78
|
+
duration: 300,
|
|
79
|
+
easing: Easing.inOut(Easing.quad),
|
|
80
|
+
});
|
|
81
|
+
} else if (isDeterminate && duration !== undefined) {
|
|
82
|
+
const toValue = reverse ? 0 : 1;
|
|
83
|
+
progressValue.value = withTiming(toValue, { duration, easing: Easing.inOut(Easing.quad) }, onDurationDone);
|
|
84
|
+
}
|
|
85
|
+
}, [externalProgress, duration, isDeterminate, reverse, onDurationDone, progressValue]);
|
|
86
|
+
|
|
87
|
+
const indeterminateWidth = useDerivedValue(() => {
|
|
88
|
+
if (isDeterminate) return progressValue.value * canvasWidth;
|
|
89
|
+
return interpolate(
|
|
90
|
+
animationProgress.value,
|
|
91
|
+
[0, 0.6, 1],
|
|
92
|
+
[canvasWidth * 0.01, canvasWidth * 0.7, canvasWidth * 0.01],
|
|
93
|
+
);
|
|
94
|
+
}, [isDeterminate, animationProgress, canvasWidth]);
|
|
95
|
+
|
|
96
|
+
const indeterminatePosition = useDerivedValue(() => {
|
|
97
|
+
if (isDeterminate) return 0;
|
|
98
|
+
return interpolate(animationProgress.value, [0, 0.6, 1], [0, 0, canvasWidth]);
|
|
99
|
+
}, [isDeterminate, animationProgress, canvasWidth]);
|
|
100
|
+
|
|
101
|
+
const progressWidth = useDerivedValue(() => {
|
|
102
|
+
if (!isDeterminate) return 0;
|
|
103
|
+
return progressValue.value * canvasWidth;
|
|
104
|
+
}, [isDeterminate, progressValue, canvasWidth]);
|
|
105
|
+
|
|
106
|
+
const onLayout = useCallback(({ nativeEvent: { layout } }: LayoutChangeEvent) => {
|
|
107
|
+
setCanvasWidth(layout.width);
|
|
108
|
+
}, []);
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<Grid row flex={1} onLayout={onLayout}>
|
|
112
|
+
<Animated.View entering={FadeIn.duration(500)} exiting={FadeOut.duration(100)}>
|
|
113
|
+
<Canvas style={{ width: canvasWidth, height: canvasHeight }}>
|
|
114
|
+
<Path path={backgroundPath} color={backgroundColor} />
|
|
115
|
+
{isDeterminate && (
|
|
116
|
+
<RoundedRect x={0} y={0} width={progressWidth} height={canvasHeight} r={radius} color={color} />
|
|
117
|
+
)}
|
|
118
|
+
|
|
119
|
+
{!isDeterminate && (
|
|
120
|
+
<RoundedRect
|
|
121
|
+
x={indeterminatePosition}
|
|
122
|
+
y={0}
|
|
123
|
+
width={indeterminateWidth}
|
|
124
|
+
height={canvasHeight}
|
|
125
|
+
r={radius}
|
|
126
|
+
color={color}
|
|
127
|
+
/>
|
|
128
|
+
)}
|
|
129
|
+
</Canvas>
|
|
130
|
+
</Animated.View>
|
|
131
|
+
</Grid>
|
|
132
|
+
);
|
|
133
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Prop, PropertyManager, Node } from '@effijs/props-manager';
|
|
2
|
+
|
|
3
|
+
export const CircularIndicatorPM = PropertyManager.create('CircularIndicator').node(
|
|
4
|
+
Node('container').keys(
|
|
5
|
+
Prop(
|
|
6
|
+
'color',
|
|
7
|
+
({ color }, { theme }) => ({
|
|
8
|
+
color: theme.color.hasKey(color) ? theme.color[color] : color,
|
|
9
|
+
backgroundColor: colorOpacity(theme.color.hasKey(color) ? theme.color[color] : color, 0.3),
|
|
10
|
+
}),
|
|
11
|
+
{ providers: ['theme'] },
|
|
12
|
+
),
|
|
13
|
+
),
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
function opacityToHex(opacity: number | undefined) {
|
|
17
|
+
if (opacity === undefined) return '';
|
|
18
|
+
|
|
19
|
+
let value = opacity;
|
|
20
|
+
if (opacity < 0) value = 0;
|
|
21
|
+
if (opacity > 1) value = 1;
|
|
22
|
+
|
|
23
|
+
return Math.round(value * 255)
|
|
24
|
+
.toString(16)
|
|
25
|
+
.padStart(2, '0');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function colorOpacity(color: string, opacity: number | undefined) {
|
|
29
|
+
if (opacity !== undefined && color.startsWith('#')) {
|
|
30
|
+
return `${color}${opacityToHex(opacity)}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return color;
|
|
34
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { CircularIndicator, type TCircularIndicatorProps } from './Circular';
|
|
4
|
+
import { CircularIndicatorPM } from './circular.pm';
|
|
5
|
+
import { LinearIndicator as Linear } from './Linear';
|
|
6
|
+
|
|
7
|
+
type TCircularIndicator = React.FC<TCircularIndicatorProps>;
|
|
8
|
+
|
|
9
|
+
interface ICircularIndicator extends TCircularIndicator {
|
|
10
|
+
PM: typeof CircularIndicatorPM;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const Circular = CircularIndicator as ICircularIndicator;
|
|
14
|
+
Circular.PM = CircularIndicatorPM;
|
|
15
|
+
|
|
16
|
+
export default { Circular, Linear };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
"id": "component:ProgressIndicator",
|
|
3
|
+
"type": "component",
|
|
4
|
+
"platforms": [
|
|
5
|
+
"react-native"
|
|
6
|
+
],
|
|
7
|
+
"title": "ProgressIndicator",
|
|
8
|
+
"description": "Linear and circular progress drawn with Skia.",
|
|
9
|
+
"status": "stable",
|
|
10
|
+
"since": "1.0.0",
|
|
11
|
+
"tags": [
|
|
12
|
+
"ui"
|
|
13
|
+
],
|
|
14
|
+
"requires": [],
|
|
15
|
+
"dependencies": [
|
|
16
|
+
"skia"
|
|
17
|
+
],
|
|
18
|
+
"files": [
|
|
19
|
+
{
|
|
20
|
+
"from": "files",
|
|
21
|
+
"to": "ui/components/ProgressIndicator"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"register": [
|
|
25
|
+
{
|
|
26
|
+
"file": "ui/components/index.ts",
|
|
27
|
+
"marker": "components-import",
|
|
28
|
+
"code": "import ProgressIndicator from './ProgressIndicator';\n"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"file": "ui/components/index.ts",
|
|
32
|
+
"marker": "components-export",
|
|
33
|
+
"code": " ProgressIndicator,\n"
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"manual": [],
|
|
37
|
+
"api": "ProgressIndicator.Circular and ProgressIndicator.Linear.",
|
|
38
|
+
"example": "<ProgressIndicator.Circular size={16} />"
|
|
39
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Ruler
|
|
2
|
+
|
|
3
|
+
Ruler from the previous template kit. Treat the API as experimental until it is wired into a screen.
|
|
4
|
+
|
|
5
|
+
## API
|
|
6
|
+
|
|
7
|
+
Default export from ui/components/Ruler.
|
|
8
|
+
|
|
9
|
+
## Example
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import Ruler from '@components/Ruler';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Dependencies
|
|
16
|
+
|
|
17
|
+
None beyond the setup baseline.
|
|
18
|
+
|
|
19
|
+
No other solutions are required.
|
|
20
|
+
|
|
21
|
+
## Manual steps
|
|
22
|
+
|
|
23
|
+
None.
|
|
24
|
+
|
|
25
|
+
## Added in
|
|
26
|
+
|
|
27
|
+
1.0.0 (`experimental`).
|
|
28
|
+
|
|
29
|
+
Install with `forge g add --id component:Ruler`.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import { RulerProvider } from './Context';
|
|
4
|
+
import { DEFAULT_FRACTION_DIGITS, DEFAULT_RULER_STEP } from './ruler.constants';
|
|
5
|
+
import type { IRulerProps } from './ruler.types';
|
|
6
|
+
import { clamp, validateRulerProps } from './ruler.utils';
|
|
7
|
+
|
|
8
|
+
export default function RulerCommon({
|
|
9
|
+
min,
|
|
10
|
+
max,
|
|
11
|
+
step = DEFAULT_RULER_STEP,
|
|
12
|
+
fractionDigits = DEFAULT_FRACTION_DIGITS,
|
|
13
|
+
value,
|
|
14
|
+
defaultValue,
|
|
15
|
+
onChange,
|
|
16
|
+
onChangeEnd,
|
|
17
|
+
children,
|
|
18
|
+
}: IRulerProps) {
|
|
19
|
+
validateRulerProps(min, max, step);
|
|
20
|
+
|
|
21
|
+
const _value = value === undefined || value === null ? value : clamp(value, min, max);
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (_value !== undefined && _value !== null && _value !== value) {
|
|
25
|
+
onChange?.(_value);
|
|
26
|
+
}
|
|
27
|
+
// Only notify the consumer when their controlled value falls outside [min, max].
|
|
28
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
29
|
+
}, [_value, value]);
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<RulerProvider
|
|
33
|
+
min={min}
|
|
34
|
+
max={max}
|
|
35
|
+
step={step}
|
|
36
|
+
fractionDigits={fractionDigits}
|
|
37
|
+
value={_value}
|
|
38
|
+
defaultValue={defaultValue}
|
|
39
|
+
onValueChange={onChange}
|
|
40
|
+
onValueChangeEnd={onChangeEnd}>
|
|
41
|
+
{children}
|
|
42
|
+
</RulerProvider>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { runOnJS, useAnimatedReaction, useDerivedValue, useSharedValue, withTiming } from 'react-native-reanimated';
|
|
3
|
+
|
|
4
|
+
import { DEFAULT_TRACK_VISUAL, RULER_CONTROLLED_TIMING_CONFIG } from './ruler.constants';
|
|
5
|
+
import type { IRulerContextValue, IRulerTrackVisualConfig } from './ruler.types';
|
|
6
|
+
import {
|
|
7
|
+
formatRulerValue,
|
|
8
|
+
getMaxOffset,
|
|
9
|
+
getStepCount,
|
|
10
|
+
getStepSize,
|
|
11
|
+
offsetToValue,
|
|
12
|
+
rescaleOffsetToStepSize,
|
|
13
|
+
valueToOffset,
|
|
14
|
+
} from './ruler.utils';
|
|
15
|
+
|
|
16
|
+
const RulerContext = createContext<IRulerContextValue | null>(null);
|
|
17
|
+
|
|
18
|
+
interface IRulerProviderProps {
|
|
19
|
+
min: number;
|
|
20
|
+
max: number;
|
|
21
|
+
step: number;
|
|
22
|
+
fractionDigits: number;
|
|
23
|
+
value?: number;
|
|
24
|
+
defaultValue?: number;
|
|
25
|
+
onValueChange?: (value: number) => void;
|
|
26
|
+
onValueChangeEnd?: (value: number) => void;
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function RulerProvider({
|
|
31
|
+
min,
|
|
32
|
+
max,
|
|
33
|
+
step,
|
|
34
|
+
fractionDigits,
|
|
35
|
+
value: controlledValue,
|
|
36
|
+
defaultValue,
|
|
37
|
+
onValueChange,
|
|
38
|
+
onValueChangeEnd,
|
|
39
|
+
children,
|
|
40
|
+
}: IRulerProviderProps) {
|
|
41
|
+
const stepCount = useMemo(() => getStepCount(min, max, step), [min, max, step]);
|
|
42
|
+
const [trackVisual, setTrackVisual] = useState<IRulerTrackVisualConfig>(DEFAULT_TRACK_VISUAL);
|
|
43
|
+
|
|
44
|
+
const initialStepSize = getStepSize(trackVisual.stepWidth, trackVisual.gapBetweenSteps);
|
|
45
|
+
const initialOffset = valueToOffset(controlledValue ?? defaultValue ?? min, {
|
|
46
|
+
min,
|
|
47
|
+
max,
|
|
48
|
+
step,
|
|
49
|
+
stepSize: initialStepSize,
|
|
50
|
+
stepCount,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const offset = useSharedValue(initialOffset);
|
|
54
|
+
const stepSize = useSharedValue(initialStepSize);
|
|
55
|
+
const maxOffset = useSharedValue(getMaxOffset(stepCount, initialStepSize));
|
|
56
|
+
const isDragging = useSharedValue(false);
|
|
57
|
+
const viewportWidth = useSharedValue(0);
|
|
58
|
+
const viewportHeight = useSharedValue(0);
|
|
59
|
+
const controlledValueSV = useSharedValue(controlledValue ?? defaultValue ?? min);
|
|
60
|
+
|
|
61
|
+
const onValueChangeRef = useRef(onValueChange);
|
|
62
|
+
const onValueChangeEndRef = useRef(onValueChangeEnd);
|
|
63
|
+
const isDraggingRef = useRef(false);
|
|
64
|
+
|
|
65
|
+
onValueChangeRef.current = onValueChange;
|
|
66
|
+
onValueChangeEndRef.current = onValueChangeEnd;
|
|
67
|
+
|
|
68
|
+
const mathConfig = useMemo(() => ({ min, max, step, stepCount }), [min, max, step, stepCount]);
|
|
69
|
+
|
|
70
|
+
const updateTrackVisual = useCallback(
|
|
71
|
+
(config: Partial<IRulerTrackVisualConfig>) => {
|
|
72
|
+
setTrackVisual(current => {
|
|
73
|
+
const next = { ...current, ...config };
|
|
74
|
+
const previousStepSize = stepSize.value;
|
|
75
|
+
const nextStepSize = getStepSize(next.stepWidth, next.gapBetweenSteps);
|
|
76
|
+
|
|
77
|
+
stepSize.value = nextStepSize;
|
|
78
|
+
maxOffset.value = getMaxOffset(stepCount, nextStepSize);
|
|
79
|
+
offset.value = rescaleOffsetToStepSize(offset.value, previousStepSize, nextStepSize, stepCount);
|
|
80
|
+
|
|
81
|
+
return next;
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
[mathConfig, maxOffset, offset, stepCount, stepSize],
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (controlledValue !== undefined) {
|
|
89
|
+
controlledValueSV.value = controlledValue;
|
|
90
|
+
}
|
|
91
|
+
}, [controlledValue, controlledValueSV]);
|
|
92
|
+
|
|
93
|
+
const value = useDerivedValue(() => {
|
|
94
|
+
return offsetToValue(offset.value, {
|
|
95
|
+
...mathConfig,
|
|
96
|
+
stepSize: stepSize.value,
|
|
97
|
+
});
|
|
98
|
+
}, [mathConfig, offset, stepSize]);
|
|
99
|
+
|
|
100
|
+
const formattedValue = useDerivedValue(() => {
|
|
101
|
+
return formatRulerValue(value.value, fractionDigits);
|
|
102
|
+
}, [fractionDigits, value]);
|
|
103
|
+
|
|
104
|
+
const emitValueChange = useCallback((nextValue: number) => {
|
|
105
|
+
onValueChangeRef.current?.(nextValue);
|
|
106
|
+
}, []);
|
|
107
|
+
|
|
108
|
+
const emitValueChangeEnd = useCallback((nextValue: number) => {
|
|
109
|
+
onValueChangeEndRef.current?.(nextValue);
|
|
110
|
+
}, []);
|
|
111
|
+
|
|
112
|
+
const setDragging = useCallback((dragging: boolean) => {
|
|
113
|
+
isDraggingRef.current = dragging;
|
|
114
|
+
}, []);
|
|
115
|
+
|
|
116
|
+
useAnimatedReaction(
|
|
117
|
+
() => value.value,
|
|
118
|
+
(current, previous) => {
|
|
119
|
+
if (current === previous || previous === null) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
runOnJS(emitValueChange)(current);
|
|
124
|
+
},
|
|
125
|
+
[emitValueChange],
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
useAnimatedReaction(
|
|
129
|
+
() => controlledValueSV.value,
|
|
130
|
+
(current, previous) => {
|
|
131
|
+
if (current === previous || isDragging.value) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
offset.value = withTiming(
|
|
136
|
+
valueToOffset(current, {
|
|
137
|
+
...mathConfig,
|
|
138
|
+
stepSize: stepSize.value,
|
|
139
|
+
}),
|
|
140
|
+
RULER_CONTROLLED_TIMING_CONFIG,
|
|
141
|
+
);
|
|
142
|
+
},
|
|
143
|
+
[controlledValueSV, isDragging, mathConfig, offset, stepSize],
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
useAnimatedReaction(
|
|
147
|
+
() => isDragging.value,
|
|
148
|
+
(current, previous) => {
|
|
149
|
+
if (current === previous) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
runOnJS(setDragging)(current);
|
|
154
|
+
|
|
155
|
+
if (!current && previous) {
|
|
156
|
+
runOnJS(emitValueChangeEnd)(value.value);
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
[emitValueChangeEnd, isDragging, setDragging, value],
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const contextValue = useMemo<IRulerContextValue>(
|
|
163
|
+
() => ({
|
|
164
|
+
value,
|
|
165
|
+
formattedValue,
|
|
166
|
+
offset,
|
|
167
|
+
isDragging,
|
|
168
|
+
min,
|
|
169
|
+
max,
|
|
170
|
+
step,
|
|
171
|
+
fractionDigits,
|
|
172
|
+
stepCount,
|
|
173
|
+
stepSize,
|
|
174
|
+
maxOffset,
|
|
175
|
+
trackVisual,
|
|
176
|
+
viewportWidth,
|
|
177
|
+
viewportHeight,
|
|
178
|
+
updateTrackVisual,
|
|
179
|
+
}),
|
|
180
|
+
[
|
|
181
|
+
value,
|
|
182
|
+
formattedValue,
|
|
183
|
+
offset,
|
|
184
|
+
isDragging,
|
|
185
|
+
min,
|
|
186
|
+
max,
|
|
187
|
+
step,
|
|
188
|
+
fractionDigits,
|
|
189
|
+
stepCount,
|
|
190
|
+
stepSize,
|
|
191
|
+
maxOffset,
|
|
192
|
+
trackVisual,
|
|
193
|
+
viewportWidth,
|
|
194
|
+
viewportHeight,
|
|
195
|
+
updateTrackVisual,
|
|
196
|
+
],
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
return <RulerContext.Provider value={contextValue}>{children}</RulerContext.Provider>;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function useRuler(): IRulerContextValue {
|
|
203
|
+
const context = useContext(RulerContext);
|
|
204
|
+
|
|
205
|
+
if (!context) {
|
|
206
|
+
throw new Error('useRuler must be used within a <Ruler> component.');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return context;
|
|
210
|
+
}
|