@skyroc/scripts 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +508 -0
- package/dist/cli.mjs +78 -0
- package/dist/config-BKkdncJS.mjs +987 -0
- package/dist/index.mjs +14 -0
- package/package.json +83 -0
- package/templates/admin/.env +62 -0
- package/templates/admin/.env.prod +7 -0
- package/templates/admin/.env.test +7 -0
- package/templates/admin/.oxlintrc.json +6 -0
- package/templates/admin/README.md +508 -0
- package/templates/admin/index.html +14 -0
- package/templates/admin/package.json +105 -0
- package/templates/admin/public/favicon.svg +3 -0
- package/templates/admin/src/App.tsx +71 -0
- package/templates/admin/src/assets/audio/wechat-style-notification.wav +0 -0
- package/templates/admin/src/assets/imgs/skyroc.jpg +0 -0
- package/templates/admin/src/assets/svg-icon/activity.svg +1 -0
- package/templates/admin/src/assets/svg-icon/at-sign.svg +1 -0
- package/templates/admin/src/assets/svg-icon/avatar.svg +1 -0
- package/templates/admin/src/assets/svg-icon/banner.svg +1 -0
- package/templates/admin/src/assets/svg-icon/cast.svg +1 -0
- package/templates/admin/src/assets/svg-icon/chrome.svg +1 -0
- package/templates/admin/src/assets/svg-icon/copy.svg +1 -0
- package/templates/admin/src/assets/svg-icon/custom-icon.svg +1 -0
- package/templates/admin/src/assets/svg-icon/empty-data.svg +1 -0
- package/templates/admin/src/assets/svg-icon/error.svg +1 -0
- package/templates/admin/src/assets/svg-icon/expectation.svg +1 -0
- package/templates/admin/src/assets/svg-icon/heart.svg +1 -0
- package/templates/admin/src/assets/svg-icon/logo.svg +15 -0
- package/templates/admin/src/assets/svg-icon/network-error.svg +1 -0
- package/templates/admin/src/assets/svg-icon/no-icon.svg +1 -0
- package/templates/admin/src/assets/svg-icon/no-permission.svg +1 -0
- package/templates/admin/src/assets/svg-icon/not-found.svg +1 -0
- package/templates/admin/src/assets/svg-icon/service-error.svg +1 -0
- package/templates/admin/src/bootstrap.tsx +60 -0
- package/templates/admin/src/components/SkyrocAvatar.tsx +13 -0
- package/templates/admin/src/components/SystemLogo.tsx +7 -0
- package/templates/admin/src/config.ts +125 -0
- package/templates/admin/src/features/antd/AntdProvider.tsx +21 -0
- package/templates/admin/src/features/auth/components/UserAvatar.tsx +76 -0
- package/templates/admin/src/features/auth/use-auth-form-rules.ts +83 -0
- package/templates/admin/src/features/auth/use-auth.ts +96 -0
- package/templates/admin/src/features/auth/use-login.ts +72 -0
- package/templates/admin/src/features/effects/GlobalEffect.tsx +15 -0
- package/templates/admin/src/features/menus/dynamic-routes.ts +10 -0
- package/templates/admin/src/features/menus/extras.ts +3 -0
- package/templates/admin/src/features/menus/menu-category.ts +14 -0
- package/templates/admin/src/features/menus/menu-config.ts +5 -0
- package/templates/admin/src/features/router/RouterProvider.tsx +18 -0
- package/templates/admin/src/features/router/guard.ts +97 -0
- package/templates/admin/src/features/router/index.ts +52 -0
- package/templates/admin/src/features/router/routeTree.gen.ts +237 -0
- package/templates/admin/src/features/router/router-ref.ts +24 -0
- package/templates/admin/src/locales/antd.ts +8 -0
- package/templates/admin/src/locales/index.ts +22 -0
- package/templates/admin/src/locales/sync.ts +14 -0
- package/templates/admin/src/main.tsx +9 -0
- package/templates/admin/src/pages/(admin)/home/index.tsx +46 -0
- package/templates/admin/src/pages/(admin)/layout.tsx +44 -0
- package/templates/admin/src/pages/(auth)/login/index.tsx +102 -0
- package/templates/admin/src/pages/(auth)/login/layout.tsx +71 -0
- package/templates/admin/src/pages/(auth)/login-out.tsx +27 -0
- package/templates/admin/src/pages/(errors)/403.tsx +16 -0
- package/templates/admin/src/pages/(errors)/404.tsx +16 -0
- package/templates/admin/src/pages/(errors)/500.tsx +16 -0
- package/templates/admin/src/pages/__root.tsx +54 -0
- package/templates/admin/src/pages/error.tsx +19 -0
- package/templates/admin/src/pages/index.tsx +14 -0
- package/templates/admin/src/pages/loading.tsx +45 -0
- package/templates/admin/src/pages/not-found.tsx +9 -0
- package/templates/admin/src/plugins/app.tsx +47 -0
- package/templates/admin/src/plugins/assets.ts +4 -0
- package/templates/admin/src/plugins/index.ts +32 -0
- package/templates/admin/src/service/adapter.ts +63 -0
- package/templates/admin/src/service/api/auth/api.ts +31 -0
- package/templates/admin/src/service/api/auth/hooks.ts +28 -0
- package/templates/admin/src/service/api/auth/index.ts +10 -0
- package/templates/admin/src/service/api/auth/keys.ts +7 -0
- package/templates/admin/src/service/api/auth/urls.ts +7 -0
- package/templates/admin/src/service/api/index.ts +2 -0
- package/templates/admin/src/service/api/route/api.ts +7 -0
- package/templates/admin/src/service/api/route/hooks.ts +21 -0
- package/templates/admin/src/service/api/route/index.ts +10 -0
- package/templates/admin/src/service/api/route/keys.ts +3 -0
- package/templates/admin/src/service/api/route/urls.ts +5 -0
- package/templates/admin/src/service/queryClient.ts +13 -0
- package/templates/admin/src/service/request/index.ts +62 -0
- package/templates/admin/src/styles/scss/global.scss +1 -0
- package/templates/admin/src/styles/scss/scrollbar.scss +28 -0
- package/templates/admin/src/types/auto-imports.d.ts +186 -0
- package/templates/admin/src/types/global.d.ts +16 -0
- package/templates/admin/src/types/router.d.ts +14 -0
- package/templates/admin/src/types/storage.d.ts +17 -0
- package/templates/admin/src/types/vite-env.d.ts +117 -0
- package/templates/admin/src/utils/common.tsx +38 -0
- package/templates/admin/src/utils/icon.ts +9 -0
- package/templates/admin/src/utils/service.ts +75 -0
- package/templates/admin/src/utils/storage.ts +7 -0
- package/templates/admin/tsconfig.json +22 -0
- package/templates/admin/uno.config.ts +18 -0
- package/templates/admin/vite.config.ts +13 -0
- package/templates/admin-shell/i18n/atoms/lang.ts +20 -0
- package/templates/admin-shell/i18n/config/default.ts +11 -0
- package/templates/admin-shell/i18n/features/lang/LangEffect.tsx +25 -0
- package/templates/admin-shell/i18n/features/lang/LangSwitch.tsx +49 -0
- package/templates/admin-shell/i18n/hooks/use-lang.ts +47 -0
- package/templates/admin-shell/i18n/i18n.ts +116 -0
- package/templates/admin-shell/i18n/index.ts +23 -0
- package/templates/admin-shell/i18n/langs/en-us/common.json +49 -0
- package/templates/admin-shell/i18n/langs/en-us/datatable.json +8 -0
- package/templates/admin-shell/i18n/langs/en-us/dropdown.json +9 -0
- package/templates/admin-shell/i18n/langs/en-us/form.json +27 -0
- package/templates/admin-shell/i18n/langs/en-us/icon.json +13 -0
- package/templates/admin-shell/i18n/langs/en-us/notification.json +20 -0
- package/templates/admin-shell/i18n/langs/en-us/page.json +442 -0
- package/templates/admin-shell/i18n/langs/en-us/request.json +8 -0
- package/templates/admin-shell/i18n/langs/en-us/route.json +84 -0
- package/templates/admin-shell/i18n/langs/en-us/system.json +9 -0
- package/templates/admin-shell/i18n/langs/en-us/theme.json +173 -0
- package/templates/admin-shell/i18n/langs/index.ts +63 -0
- package/templates/admin-shell/i18n/langs/zh-cn/common.json +49 -0
- package/templates/admin-shell/i18n/langs/zh-cn/datatable.json +8 -0
- package/templates/admin-shell/i18n/langs/zh-cn/dropdown.json +9 -0
- package/templates/admin-shell/i18n/langs/zh-cn/form.json +27 -0
- package/templates/admin-shell/i18n/langs/zh-cn/icon.json +13 -0
- package/templates/admin-shell/i18n/langs/zh-cn/notification.json +20 -0
- package/templates/admin-shell/i18n/langs/zh-cn/page.json +442 -0
- package/templates/admin-shell/i18n/langs/zh-cn/request.json +8 -0
- package/templates/admin-shell/i18n/langs/zh-cn/route.json +84 -0
- package/templates/admin-shell/i18n/langs/zh-cn/system.json +9 -0
- package/templates/admin-shell/i18n/langs/zh-cn/theme.json +173 -0
- package/templates/admin-shell/i18n/types/i18n.ts +29 -0
- package/templates/admin-shell/i18n/types.ts +53 -0
- package/templates/admin-shell/i18n/utils/helpers.ts +18 -0
- package/templates/admin-shell/layouts/AdminLayout.tsx +161 -0
- package/templates/admin-shell/layouts/constant.ts +56 -0
- package/templates/admin-shell/layouts/context.tsx +101 -0
- package/templates/admin-shell/layouts/features/menus/MenuBadge.tsx +76 -0
- package/templates/admin-shell/layouts/features/menus/dynamic-routes.ts +146 -0
- package/templates/admin-shell/layouts/features/menus/menu-generator.tsx +444 -0
- package/templates/admin-shell/layouts/features/menus/menu-renderer.tsx +149 -0
- package/templates/admin-shell/layouts/features/menus/permissions.ts +28 -0
- package/templates/admin-shell/layouts/features/menus/use-menus.ts +98 -0
- package/templates/admin-shell/layouts/features/use-route.ts +30 -0
- package/templates/admin-shell/layouts/index.ts +44 -0
- package/templates/admin-shell/layouts/materials/index.ts +6 -0
- package/templates/admin-shell/layouts/materials/libs/admin-layout/index.module.css +63 -0
- package/templates/admin-shell/layouts/materials/libs/admin-layout/index.module.css.d.ts +18 -0
- package/templates/admin-shell/layouts/materials/libs/admin-layout/index.tsx +238 -0
- package/templates/admin-shell/layouts/materials/libs/admin-layout/shared.ts +67 -0
- package/templates/admin-shell/layouts/materials/libs/page-tab/ButtonTab.tsx +44 -0
- package/templates/admin-shell/layouts/materials/libs/page-tab/ChromeTab.tsx +54 -0
- package/templates/admin-shell/layouts/materials/libs/page-tab/ChromeTabBg.tsx +30 -0
- package/templates/admin-shell/layouts/materials/libs/page-tab/SliderTab.tsx +44 -0
- package/templates/admin-shell/layouts/materials/libs/page-tab/SvgClose.tsx +51 -0
- package/templates/admin-shell/layouts/materials/libs/page-tab/hook.ts +34 -0
- package/templates/admin-shell/layouts/materials/libs/page-tab/index.module.css +120 -0
- package/templates/admin-shell/layouts/materials/libs/page-tab/index.module.css.d.ts +18 -0
- package/templates/admin-shell/layouts/materials/libs/page-tab/index.tsx +76 -0
- package/templates/admin-shell/layouts/materials/libs/page-tab/shared.ts +32 -0
- package/templates/admin-shell/layouts/materials/types/index.ts +322 -0
- package/templates/admin-shell/layouts/modules/AdminContent.tsx +285 -0
- package/templates/admin-shell/layouts/modules/AdminFooter.tsx +13 -0
- package/templates/admin-shell/layouts/modules/AdminLogo.tsx +28 -0
- package/templates/admin-shell/layouts/modules/AdminSider.tsx +50 -0
- package/templates/admin-shell/layouts/modules/admin-header/AdminHeader.tsx +132 -0
- package/templates/admin-shell/layouts/modules/admin-header/components/Breadcrumb.tsx +62 -0
- package/templates/admin-shell/layouts/modules/admin-header/components/ThemeButton.tsx +24 -0
- package/templates/admin-shell/layouts/modules/admin-menu/AdminMenu.tsx +37 -0
- package/templates/admin-shell/layouts/modules/admin-menu/components/FirstLevelMenu.tsx +156 -0
- package/templates/admin-shell/layouts/modules/admin-menu/components/HorizontalMenu.tsx +88 -0
- package/templates/admin-shell/layouts/modules/admin-menu/components/MenuPortal.tsx +28 -0
- package/templates/admin-shell/layouts/modules/admin-menu/components/VerticalMenu.tsx +123 -0
- package/templates/admin-shell/layouts/modules/admin-menu/enum.ts +47 -0
- package/templates/admin-shell/layouts/modules/admin-menu/modules/Horizontal.tsx +22 -0
- package/templates/admin-shell/layouts/modules/admin-menu/modules/TopHybridHeaderFirst.tsx +15 -0
- package/templates/admin-shell/layouts/modules/admin-menu/modules/TopHybridSidebarFirst.tsx +18 -0
- package/templates/admin-shell/layouts/modules/admin-menu/modules/Vertical.tsx +14 -0
- package/templates/admin-shell/layouts/modules/admin-menu/modules/VerticalHybridHeaderFirst.tsx +18 -0
- package/templates/admin-shell/layouts/modules/admin-menu/modules/VerticalMix.tsx +132 -0
- package/templates/admin-shell/layouts/modules/admin-search/AdminSearch.tsx +36 -0
- package/templates/admin-shell/layouts/modules/admin-search/components/SearchFooter.tsx +38 -0
- package/templates/admin-shell/layouts/modules/admin-search/components/SearchModal.tsx +171 -0
- package/templates/admin-shell/layouts/modules/admin-search/components/SearchResult.tsx +43 -0
- package/templates/admin-shell/layouts/modules/admin-tab/AdminTab.tsx +125 -0
- package/templates/admin-shell/layouts/modules/admin-tab/components/TabContextMenu.tsx +107 -0
- package/templates/admin-shell/layouts/modules/admin-tab/hooks/useTabScroll.ts +86 -0
- package/templates/admin-shell/layouts/modules/shared/logo.ts +42 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/ThemeDrawer.tsx +68 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/components/AnimatedCollapse.tsx +36 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/components/AnimatedItem.tsx +35 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/components/LayoutModeCard.tsx +110 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/components/SettingItem.tsx +31 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/ConfigOperation.tsx +53 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/appearance/CustomPicker.tsx +105 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/appearance/ThemeColor.tsx +58 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/appearance/ThemeSchema.tsx +42 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/appearance/ThemeToken.tsx +44 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/appearance/index.tsx +23 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/general/GlobalSettings.tsx +57 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/general/ThemeGeneral.tsx +20 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/general/WatermarkSettings.tsx +103 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/layout/ContentSettings.tsx +100 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/layout/FooterSettings.tsx +71 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/layout/HeaderSettings.tsx +63 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/layout/LayoutMode.tsx +73 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/layout/SiderSettings.tsx +124 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/layout/TabSettings.tsx +95 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/layout/ThemeLayout.tsx +32 -0
- package/templates/admin-shell/layouts/modules/theme-drawer/modules/preset/ThemePreset.tsx +132 -0
- package/templates/admin-shell/layouts/options.tsx +79 -0
- package/templates/admin-shell/layouts/setup.ts +102 -0
- package/templates/admin-shell/layouts/state/AdminEffect.tsx +56 -0
- package/templates/admin-shell/layouts/state/AdminTabEffect.tsx +28 -0
- package/templates/admin-shell/layouts/state/index.ts +3 -0
- package/templates/admin-shell/layouts/state/menus/MenuToggler.tsx +53 -0
- package/templates/admin-shell/layouts/state/menus/use-admin-menu-badges.ts +46 -0
- package/templates/admin-shell/layouts/state/menus/use-admin-menus.tsx +164 -0
- package/templates/admin-shell/layouts/state/tabs/index.ts +1 -0
- package/templates/admin-shell/layouts/state/tabs/shared.tsx +148 -0
- package/templates/admin-shell/layouts/state/tabs/use-admin-tab.ts +377 -0
- package/templates/admin-shell/layouts/state/use-admin-state.ts +118 -0
- package/templates/admin-shell/layouts/types/router.d.ts +10 -0
- package/templates/admin-shell/layouts/types/storage.ts +18 -0
- package/templates/admin-shell/notification/NotificationButton.tsx +91 -0
- package/templates/admin-shell/notification/NotificationContext.ts +8 -0
- package/templates/admin-shell/notification/NotificationPanel.tsx +194 -0
- package/templates/admin-shell/notification/NotificationProvider.tsx +59 -0
- package/templates/admin-shell/notification/index.ts +12 -0
- package/templates/admin-shell/notification/mock.ts +59 -0
- package/templates/admin-shell/notification/notification-store.ts +438 -0
- package/templates/admin-shell/notification/notification.css +60 -0
- package/templates/admin-shell/notification/types.ts +104 -0
- package/templates/admin-shell/notification/use-notification.ts +51 -0
- package/templates/admin-shell/notification/useNotificationContext.ts +14 -0
- package/templates/admin-shell/runtime/app-update.ts +156 -0
- package/templates/admin-shell/runtime/dayjs.ts +20 -0
- package/templates/admin-shell/runtime/iconify.ts +17 -0
- package/templates/admin-shell/runtime/index.ts +10 -0
- package/templates/admin-shell/runtime/nprogress.ts +25 -0
- package/templates/admin-shell/runtime/plugins.ts +62 -0
- package/templates/admin-shell/styles/global.css +54 -0
- package/templates/admin-shell/styles/nprogress.css +85 -0
- package/templates/admin-shell/styles/reset.css +378 -0
- package/templates/admin-shell/theme/antd/AntdProvider.tsx +106 -0
- package/templates/admin-shell/theme/antd/index.ts +23 -0
- package/templates/admin-shell/theme/antd/shared.ts +80 -0
- package/templates/admin-shell/theme/antd/ui.ts +250 -0
- package/templates/admin-shell/theme/antd-algorithm/algorithm/dark/colors.ts +99 -0
- package/templates/admin-shell/theme/antd-algorithm/algorithm/dark/index.ts +87 -0
- package/templates/admin-shell/theme/antd-algorithm/algorithm/default/colors.ts +91 -0
- package/templates/admin-shell/theme/antd-algorithm/algorithm/default/index.ts +77 -0
- package/templates/admin-shell/theme/antd-algorithm/index.ts +80 -0
- package/templates/admin-shell/theme/antd-algorithm/seed/index.ts +41 -0
- package/templates/admin-shell/theme/antd-algorithm/shared/colorAlgorithm.ts +10 -0
- package/templates/admin-shell/theme/antd-algorithm/shared/genColorMapToken.ts +165 -0
- package/templates/admin-shell/theme/antd-algorithm/shared/genCommonMapToken.ts +23 -0
- package/templates/admin-shell/theme/antd-algorithm/shared/genControlHeight.ts +14 -0
- package/templates/admin-shell/theme/antd-algorithm/shared/genFontMapToken.ts +274 -0
- package/templates/admin-shell/theme/antd-algorithm/shared/genRadiusMapToken.ts +139 -0
- package/templates/admin-shell/theme/antd-algorithm/shared/genSizeMapToken.ts +114 -0
- package/templates/admin-shell/theme/antd-algorithm/types/index.ts +20 -0
- package/templates/admin-shell/theme/components/ThemeEffect.tsx +55 -0
- package/templates/admin-shell/theme/components/ThemeSchemaSegmented.tsx +27 -0
- package/templates/admin-shell/theme/components/ThemeSchemaSwitch.tsx +77 -0
- package/templates/admin-shell/theme/components/shared.ts +5 -0
- package/templates/admin-shell/theme/config/default.ts +108 -0
- package/templates/admin-shell/theme/config/index.ts +1 -0
- package/templates/admin-shell/theme/hooks/index.ts +2 -0
- package/templates/admin-shell/theme/hooks/use-theme.ts +244 -0
- package/templates/admin-shell/theme/index.ts +78 -0
- package/templates/admin-shell/theme/presets/azir.json +39 -0
- package/templates/admin-shell/theme/presets/compact.json +38 -0
- package/templates/admin-shell/theme/presets/dark.json +93 -0
- package/templates/admin-shell/theme/presets/default.json +95 -0
- package/templates/admin-shell/theme/presets/index.ts +29 -0
- package/templates/admin-shell/theme/presets/shadcn.json +99 -0
- package/templates/admin-shell/theme/setup.ts +115 -0
- package/templates/admin-shell/theme/types/index.ts +27 -0
- package/templates/admin-shell/theme/types/theme.d.ts +316 -0
- package/templates/admin-shell/theme/utils/dark-mode.ts +46 -0
- package/templates/admin-shell/theme/utils/filters.ts +20 -0
- package/templates/admin-shell/theme/utils/index.ts +3 -0
- package/templates/admin-shell/theme/utils/settings.ts +43 -0
- package/templates/admin-shell/types/api/auth.d.ts +148 -0
- package/templates/admin-shell/types/api/common.d.ts +54 -0
- package/templates/admin-shell/types/api/route.d.ts +104 -0
- package/templates/admin-shell/types/api/service.d.ts +51 -0
- package/templates/admin-shell/types/api/system-manage.d.ts +160 -0
- package/templates/admin-shell/types/app/common.d.ts +31 -0
- package/templates/admin-shell/types/app/global.d.ts +71 -0
- package/templates/admin-shell/types/app/menu.d.ts +57 -0
- package/templates/admin-shell/types/app/router.d.ts +201 -0
- package/templates/admin-shell/types/app/storage.d.ts +10 -0
- package/templates/admin-shell/types/app/union-key.d.ts +156 -0
- package/templates/admin-shell/types/locales/i18n.d.ts +135 -0
- package/templates/admin-shell/ui/antd/components/AppTree.tsx +62 -0
- package/templates/admin-shell/ui/antd/components/BeyondHiding.tsx +42 -0
- package/templates/admin-shell/ui/antd/components/ButtonIcon.tsx +123 -0
- package/templates/admin-shell/ui/antd/components/ButtonLink.tsx +30 -0
- package/templates/admin-shell/ui/antd/components/ErrorBoundary.tsx +45 -0
- package/templates/admin-shell/ui/antd/components/ExceptionBase.tsx +69 -0
- package/templates/admin-shell/ui/antd/components/FullScreen.tsx +33 -0
- package/templates/admin-shell/ui/antd/components/PinToggler.tsx +35 -0
- package/templates/admin-shell/ui/antd/components/ReloadButton.tsx +20 -0
- package/templates/admin-shell/ui/antd/components/index.ts +12 -0
- package/templates/admin-shell/ui/antd/components/styles/button-icon-animations.css +246 -0
- package/templates/admin-shell/ui/antd/index.ts +1 -0
- package/templates/admin-shell/ui/antd/styles.d.ts +1 -0
- package/templates/admin-shell/ui/compose/animate-feature.ts +5 -0
- package/templates/admin-shell/ui/compose/components/BetterScroll.tsx +51 -0
- package/templates/admin-shell/ui/compose/components/DarkModeContainer.tsx +22 -0
- package/templates/admin-shell/ui/compose/components/FlipText.tsx +41 -0
- package/templates/admin-shell/ui/compose/components/I18nLabel.tsx +18 -0
- package/templates/admin-shell/ui/compose/components/LazyAnimate.tsx +10 -0
- package/templates/admin-shell/ui/compose/components/LookForward.tsx +24 -0
- package/templates/admin-shell/ui/compose/components/NumberTicker.tsx +105 -0
- package/templates/admin-shell/ui/compose/components/Portal.tsx +74 -0
- package/templates/admin-shell/ui/compose/components/SvgIcon.tsx +39 -0
- package/templates/admin-shell/ui/compose/components/TypingAnimation.tsx +83 -0
- package/templates/admin-shell/ui/compose/components/WaveBg.tsx +56 -0
- package/templates/admin-shell/ui/compose/components/index.ts +11 -0
- package/templates/admin-shell/ui/compose/index.ts +2 -0
- package/templates/admin-shell/ui/compose/table/DragContent.tsx +239 -0
- package/templates/admin-shell/ui/compose/table/TableHeaderOperation.tsx +210 -0
- package/templates/admin-shell/ui/compose/table/hooks.ts +196 -0
- package/templates/admin-shell/ui/compose/table/index.ts +16 -0
- package/templates/admin-shell/ui/compose/table/types.ts +244 -0
- package/templates/admin-shell/ui/compose/table/use-table-operate.ts +136 -0
- package/templates/admin-shell/ui/compose/table/use-table-scroll.ts +49 -0
- package/templates/admin-shell/ui/compose/table/use-table.ts +303 -0
- package/templates/admin.meta.json +756 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { SvgIcon } from '@shell/ui/compose';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import ButtonIcon from './ButtonIcon';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
/** Button class */
|
|
8
|
+
className: string;
|
|
9
|
+
/** Click handler */
|
|
10
|
+
onClick?: React.ComponentProps<'button'>['onClick'];
|
|
11
|
+
/** Whether the item is pinned */
|
|
12
|
+
pin?: boolean;
|
|
13
|
+
/** Tooltip text when pinned (default: 'Unpin') */
|
|
14
|
+
pinnedTooltip?: string;
|
|
15
|
+
/** Tooltip text when unpinned (default: 'Pin') */
|
|
16
|
+
unpinnedTooltip?: string;
|
|
17
|
+
}
|
|
18
|
+
const PinToggler = (props: Props) => {
|
|
19
|
+
const { className, onClick, pin, pinnedTooltip = 'Unpin', unpinnedTooltip = 'Pin' } = props;
|
|
20
|
+
|
|
21
|
+
const icon = pin ? 'mdi-pin-off' : 'mdi-pin';
|
|
22
|
+
return (
|
|
23
|
+
<ButtonIcon
|
|
24
|
+
triggerParent
|
|
25
|
+
className={className}
|
|
26
|
+
tooltipContent={pin ? pinnedTooltip : unpinnedTooltip}
|
|
27
|
+
tooltipPlacement="bottomLeft"
|
|
28
|
+
onClick={onClick}
|
|
29
|
+
>
|
|
30
|
+
<SvgIcon icon={icon} />
|
|
31
|
+
</ButtonIcon>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default PinToggler;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Icon } from '@iconify/react';
|
|
2
|
+
|
|
3
|
+
import type { ButtonIconProps } from './ButtonIcon';
|
|
4
|
+
import ButtonIcon from './ButtonIcon';
|
|
5
|
+
|
|
6
|
+
type Props = ButtonIconProps & {
|
|
7
|
+
isReload: boolean;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const ReloadButton = (props: Props) => {
|
|
11
|
+
const { isReload, ...rest } = props;
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<ButtonIcon {...rest}>
|
|
15
|
+
<Icon className={isReload ? '' : 'animate-spin animate-duration-750'} icon="ant-design:reload-outlined" />
|
|
16
|
+
</ButtonIcon>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default ReloadButton;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { default as AppTree } from './AppTree';
|
|
2
|
+
export type { AppTreeProps } from './AppTree';
|
|
3
|
+
export { default as BeyondHiding } from './BeyondHiding';
|
|
4
|
+
export { default as ButtonIcon } from './ButtonIcon';
|
|
5
|
+
export type { ButtonIconProps, IconHoverAnimation } from './ButtonIcon';
|
|
6
|
+
export { default as ButtonLink } from './ButtonLink';
|
|
7
|
+
export type { ButtonLinkComponentProps } from './ButtonLink';
|
|
8
|
+
export { default as ErrorBoundary } from './ErrorBoundary';
|
|
9
|
+
export { default as ExceptionBase } from './ExceptionBase';
|
|
10
|
+
export { default as FullScreen } from './FullScreen';
|
|
11
|
+
export { default as PinToggler } from './PinToggler';
|
|
12
|
+
export { default as ReloadButton } from './ReloadButton';
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/* ==================== ButtonIcon Hover Animations ==================== */
|
|
2
|
+
|
|
3
|
+
/* 基础过渡效果 */
|
|
4
|
+
.btn-icon-hover-scale,
|
|
5
|
+
.btn-icon-hover-rotate,
|
|
6
|
+
.btn-icon-hover-shake,
|
|
7
|
+
.btn-icon-hover-bounce,
|
|
8
|
+
.btn-icon-hover-pulse,
|
|
9
|
+
.btn-icon-hover-spin,
|
|
10
|
+
.btn-icon-hover-swing,
|
|
11
|
+
.btn-icon-hover-flip,
|
|
12
|
+
.btn-icon-hover-wiggle,
|
|
13
|
+
.btn-icon-hover-tada {
|
|
14
|
+
display: inline-flex;
|
|
15
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* 1. Scale - 缩放放大效果 (经典的交互反馈) */
|
|
19
|
+
.btn-icon-hover-scale {
|
|
20
|
+
transition: transform 0.3s ease;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.btn-icon-hover-scale:hover {
|
|
24
|
+
transform: scale(1.2);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* 2. Rotate - 旋转效果 (适合刷新、设置图标) */
|
|
28
|
+
.btn-icon-hover-rotate {
|
|
29
|
+
transition: transform 0.4s ease;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.btn-icon-hover-rotate:hover {
|
|
33
|
+
transform: rotate(180deg);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* 3. Shake - 左右抖动效果 (吸引注意力) */
|
|
37
|
+
.btn-icon-hover-shake:hover {
|
|
38
|
+
animation: btn-icon-shake 0.5s ease-in-out;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@keyframes btn-icon-shake {
|
|
42
|
+
0%,
|
|
43
|
+
100% {
|
|
44
|
+
transform: translateX(0);
|
|
45
|
+
}
|
|
46
|
+
10%,
|
|
47
|
+
30%,
|
|
48
|
+
50%,
|
|
49
|
+
70%,
|
|
50
|
+
90% {
|
|
51
|
+
transform: translateX(-4px);
|
|
52
|
+
}
|
|
53
|
+
20%,
|
|
54
|
+
40%,
|
|
55
|
+
60%,
|
|
56
|
+
80% {
|
|
57
|
+
transform: translateX(4px);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* 4. Bounce - 弹跳效果 (活泼有趣) */
|
|
62
|
+
.btn-icon-hover-bounce:hover {
|
|
63
|
+
animation: btn-icon-bounce 0.6s ease;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@keyframes btn-icon-bounce {
|
|
67
|
+
0%,
|
|
68
|
+
100% {
|
|
69
|
+
transform: translateY(0);
|
|
70
|
+
}
|
|
71
|
+
10%,
|
|
72
|
+
30% {
|
|
73
|
+
transform: translateY(-8px);
|
|
74
|
+
}
|
|
75
|
+
20% {
|
|
76
|
+
transform: translateY(-12px);
|
|
77
|
+
}
|
|
78
|
+
40%,
|
|
79
|
+
60% {
|
|
80
|
+
transform: translateY(-4px);
|
|
81
|
+
}
|
|
82
|
+
50% {
|
|
83
|
+
transform: translateY(-6px);
|
|
84
|
+
}
|
|
85
|
+
70%,
|
|
86
|
+
90% {
|
|
87
|
+
transform: translateY(-2px);
|
|
88
|
+
}
|
|
89
|
+
80% {
|
|
90
|
+
transform: translateY(-3px);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* 5. Pulse - 脉冲缩放效果 (呼吸效果) */
|
|
95
|
+
.btn-icon-hover-pulse:hover {
|
|
96
|
+
animation: btn-icon-pulse 1s ease-in-out infinite;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@keyframes btn-icon-pulse {
|
|
100
|
+
0%,
|
|
101
|
+
100% {
|
|
102
|
+
transform: scale(1);
|
|
103
|
+
opacity: 1;
|
|
104
|
+
}
|
|
105
|
+
50% {
|
|
106
|
+
transform: scale(1.15);
|
|
107
|
+
opacity: 0.85;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* 6. Spin - 持续旋转效果 (适合加载、刷新) */
|
|
112
|
+
.btn-icon-hover-spin:hover {
|
|
113
|
+
animation: btn-icon-spin 0.8s linear infinite;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@keyframes btn-icon-spin {
|
|
117
|
+
from {
|
|
118
|
+
transform: rotate(0deg);
|
|
119
|
+
}
|
|
120
|
+
to {
|
|
121
|
+
transform: rotate(360deg);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* 7. Swing - 摇摆效果 (类似钟摆) */
|
|
126
|
+
.btn-icon-hover-swing:hover {
|
|
127
|
+
animation: btn-icon-swing 0.6s ease-in-out;
|
|
128
|
+
transform-origin: center top;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@keyframes btn-icon-swing {
|
|
132
|
+
0%,
|
|
133
|
+
100% {
|
|
134
|
+
transform: rotate(0deg);
|
|
135
|
+
}
|
|
136
|
+
15% {
|
|
137
|
+
transform: rotate(15deg);
|
|
138
|
+
}
|
|
139
|
+
30% {
|
|
140
|
+
transform: rotate(-10deg);
|
|
141
|
+
}
|
|
142
|
+
45% {
|
|
143
|
+
transform: rotate(8deg);
|
|
144
|
+
}
|
|
145
|
+
60% {
|
|
146
|
+
transform: rotate(-6deg);
|
|
147
|
+
}
|
|
148
|
+
75% {
|
|
149
|
+
transform: rotate(4deg);
|
|
150
|
+
}
|
|
151
|
+
90% {
|
|
152
|
+
transform: rotate(-2deg);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* 8. Flip - 3D翻转效果 (酷炫效果) */
|
|
157
|
+
.btn-icon-hover-flip {
|
|
158
|
+
transition: transform 0.6s ease;
|
|
159
|
+
transform-style: preserve-3d;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.btn-icon-hover-flip:hover {
|
|
163
|
+
transform: rotateY(180deg);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* 9. Wiggle - 扭动效果 (俏皮可爱) */
|
|
167
|
+
.btn-icon-hover-wiggle:hover {
|
|
168
|
+
animation: btn-icon-wiggle 0.5s ease-in-out;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@keyframes btn-icon-wiggle {
|
|
172
|
+
0%,
|
|
173
|
+
100% {
|
|
174
|
+
transform: rotate(0deg);
|
|
175
|
+
}
|
|
176
|
+
10%,
|
|
177
|
+
30%,
|
|
178
|
+
50%,
|
|
179
|
+
70%,
|
|
180
|
+
90% {
|
|
181
|
+
transform: rotate(-3deg);
|
|
182
|
+
}
|
|
183
|
+
20%,
|
|
184
|
+
40%,
|
|
185
|
+
60%,
|
|
186
|
+
80% {
|
|
187
|
+
transform: rotate(3deg);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* 10. Tada - 惊喜效果 (多维度组合动画) */
|
|
192
|
+
.btn-icon-hover-tada:hover {
|
|
193
|
+
animation: btn-icon-tada 0.8s ease;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@keyframes btn-icon-tada {
|
|
197
|
+
0% {
|
|
198
|
+
transform: scale(1) rotate(0deg);
|
|
199
|
+
}
|
|
200
|
+
10%,
|
|
201
|
+
20% {
|
|
202
|
+
transform: scale(0.95) rotate(-3deg);
|
|
203
|
+
}
|
|
204
|
+
30%,
|
|
205
|
+
50%,
|
|
206
|
+
70%,
|
|
207
|
+
90% {
|
|
208
|
+
transform: scale(1.1) rotate(3deg);
|
|
209
|
+
}
|
|
210
|
+
40%,
|
|
211
|
+
60%,
|
|
212
|
+
80% {
|
|
213
|
+
transform: scale(1.1) rotate(-3deg);
|
|
214
|
+
}
|
|
215
|
+
100% {
|
|
216
|
+
transform: scale(1) rotate(0deg);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* 性能优化:使用 GPU 加速 */
|
|
221
|
+
.btn-icon-hover-scale,
|
|
222
|
+
.btn-icon-hover-rotate,
|
|
223
|
+
.btn-icon-hover-shake,
|
|
224
|
+
.btn-icon-hover-bounce,
|
|
225
|
+
.btn-icon-hover-pulse,
|
|
226
|
+
.btn-icon-hover-spin,
|
|
227
|
+
.btn-icon-hover-swing,
|
|
228
|
+
.btn-icon-hover-flip,
|
|
229
|
+
.btn-icon-hover-wiggle,
|
|
230
|
+
.btn-icon-hover-tada {
|
|
231
|
+
will-change: transform;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* 添加平滑的光标指针 */
|
|
235
|
+
.btn-icon-hover-scale:hover,
|
|
236
|
+
.btn-icon-hover-rotate:hover,
|
|
237
|
+
.btn-icon-hover-shake:hover,
|
|
238
|
+
.btn-icon-hover-bounce:hover,
|
|
239
|
+
.btn-icon-hover-pulse:hover,
|
|
240
|
+
.btn-icon-hover-spin:hover,
|
|
241
|
+
.btn-icon-hover-swing:hover,
|
|
242
|
+
.btn-icon-hover-flip:hover,
|
|
243
|
+
.btn-icon-hover-wiggle:hover,
|
|
244
|
+
.btn-icon-hover-tada:hover {
|
|
245
|
+
cursor: pointer;
|
|
246
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './components';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module '*.css';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Options } from '@better-scroll/core';
|
|
2
|
+
import BScroll from '@better-scroll/core';
|
|
3
|
+
import { useMount, useSize, useUpdateEffect } from 'ahooks';
|
|
4
|
+
import { clsx } from 'clsx';
|
|
5
|
+
import type { ComponentPropsWithoutRef, FC, Ref } from 'react';
|
|
6
|
+
import { useImperativeHandle, useRef } from 'react';
|
|
7
|
+
|
|
8
|
+
interface Props extends ComponentPropsWithoutRef<'div'> {
|
|
9
|
+
/**
|
|
10
|
+
* BetterScroll options
|
|
11
|
+
*
|
|
12
|
+
* @link https://better-scroll.github.io/docs/zh-CN/guide/base-scroll-options.html
|
|
13
|
+
*/
|
|
14
|
+
options: Options;
|
|
15
|
+
ref: Ref<BScroll>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const BetterScroll: FC<Props> = ({ children, className, options, ref, ...rest }) => {
|
|
19
|
+
const bsWrapper = useRef<HTMLDivElement>(null);
|
|
20
|
+
const bsContent = useRef<HTMLDivElement>(null);
|
|
21
|
+
const bsWrapperSize = useSize(bsWrapper);
|
|
22
|
+
const bsContentSize = useSize(bsContent);
|
|
23
|
+
const instance = useRef<BScroll | null>(null);
|
|
24
|
+
|
|
25
|
+
const isScrollY = Boolean(options.scrollY);
|
|
26
|
+
|
|
27
|
+
function initBetterScroll() {
|
|
28
|
+
if (!bsWrapper.current) return;
|
|
29
|
+
instance.current = new BScroll(bsWrapper.current, options);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
useImperativeHandle(ref, () => instance.current as BScroll);
|
|
33
|
+
|
|
34
|
+
useUpdateEffect(() => {
|
|
35
|
+
instance.current?.refresh();
|
|
36
|
+
}, [bsWrapperSize?.width, bsContentSize?.width]);
|
|
37
|
+
|
|
38
|
+
useMount(() => {
|
|
39
|
+
initBetterScroll();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div ref={bsWrapper} {...rest} className={clsx('h-full text-left', className)}>
|
|
44
|
+
<div className={clsx('inline-block', { 'h-full': !isScrollY })} ref={bsContent}>
|
|
45
|
+
{children}
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export default BetterScroll;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
|
|
3
|
+
interface Props extends React.ComponentProps<'div'> {
|
|
4
|
+
inverted?: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const DarkModeContainer = ({ children, className, inverted, ...rest }: Props) => {
|
|
8
|
+
return (
|
|
9
|
+
<div
|
|
10
|
+
className={clsx(
|
|
11
|
+
'bg-container text-base-text transition-300',
|
|
12
|
+
{ 'bg-inverted text-#1f1f1f': inverted },
|
|
13
|
+
className
|
|
14
|
+
)}
|
|
15
|
+
{...rest}
|
|
16
|
+
>
|
|
17
|
+
{children}
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default DarkModeContainer;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import type { Variants } from 'motion/react';
|
|
3
|
+
import { AnimatePresence, motion } from 'motion/react';
|
|
4
|
+
|
|
5
|
+
interface FlipTextProps {
|
|
6
|
+
readonly className?: string;
|
|
7
|
+
readonly delayMultiple?: number;
|
|
8
|
+
readonly duration?: number;
|
|
9
|
+
readonly framerProps?: Variants;
|
|
10
|
+
readonly word: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const FlipText = ({
|
|
14
|
+
className,
|
|
15
|
+
delayMultiple = 0.08,
|
|
16
|
+
duration = 0.5,
|
|
17
|
+
framerProps = {
|
|
18
|
+
hidden: { opacity: 0, rotateX: -90 },
|
|
19
|
+
visible: { opacity: 1, rotateX: 0 }
|
|
20
|
+
},
|
|
21
|
+
word
|
|
22
|
+
}: FlipTextProps) => {
|
|
23
|
+
return (
|
|
24
|
+
<AnimatePresence mode="sync">
|
|
25
|
+
{word.split('').map((char, i) => (
|
|
26
|
+
<motion.span
|
|
27
|
+
animate="visible"
|
|
28
|
+
className={clsx('drop-shadow-sm', className)}
|
|
29
|
+
initial="hidden"
|
|
30
|
+
key={i}
|
|
31
|
+
transition={{ delay: i * delayMultiple, duration }}
|
|
32
|
+
variants={framerProps}
|
|
33
|
+
>
|
|
34
|
+
{char}
|
|
35
|
+
</motion.span>
|
|
36
|
+
))}
|
|
37
|
+
</AnimatePresence>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default FlipText;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { i18n } from 'i18next';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import { Translation } from 'react-i18next';
|
|
4
|
+
|
|
5
|
+
interface I18nLabelProps {
|
|
6
|
+
/** Fallback content when i18nKey is not provided */
|
|
7
|
+
fallback?: ReactNode;
|
|
8
|
+
/** I18n instance (optional, uses default if not provided) */
|
|
9
|
+
i18n?: i18n;
|
|
10
|
+
/** I18n translation key */
|
|
11
|
+
i18nKey?: string | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const I18nLabel = ({ fallback, i18n: i18nInstance, i18nKey }: I18nLabelProps) => {
|
|
15
|
+
return <Translation i18n={i18nInstance}>{t => (i18nKey ? t(i18nKey) : fallback)}</Translation>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default I18nLabel;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { LazyMotion } from 'motion/react';
|
|
2
|
+
import type { PropsWithChildren } from 'react';
|
|
3
|
+
|
|
4
|
+
const loadFeatures = () => import('../animate-feature').then(res => res.default);
|
|
5
|
+
|
|
6
|
+
const LazyAnimate = ({ children }: PropsWithChildren) => {
|
|
7
|
+
return <LazyMotion features={loadFeatures}>{children}</LazyMotion>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default LazyAnimate;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PropsWithChildren } from 'react';
|
|
2
|
+
|
|
3
|
+
import SvgIcon from './SvgIcon';
|
|
4
|
+
|
|
5
|
+
interface LookForwardProps extends PropsWithChildren {
|
|
6
|
+
/** Fallback title text when no children provided (default: 'Coming Soon') */
|
|
7
|
+
title?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const LookForward = (props: LookForwardProps) => {
|
|
11
|
+
const { children, title = 'Coming Soon' } = props;
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div className="size-full min-h-520px flex-col-center gap-24px overflow-hidden">
|
|
15
|
+
<div className="flex text-400px text-primary">
|
|
16
|
+
<SvgIcon localIcon="expectation" />
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
{children || <h3 className="text-28px text-primary font-500">{title}</h3>}
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default LookForward;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import type { AnimationPlaybackControls } from 'motion/react';
|
|
3
|
+
import { animate, useInView, useMotionValue, useSpring } from 'motion/react';
|
|
4
|
+
import type { ComponentPropsWithoutRef } from 'react';
|
|
5
|
+
import { useEffect, useRef } from 'react';
|
|
6
|
+
|
|
7
|
+
interface NumberTickerProps extends ComponentPropsWithoutRef<'span'> {
|
|
8
|
+
/** - 小数位数 */
|
|
9
|
+
decimalPlaces?: number;
|
|
10
|
+
/** - 延时时间 单位:秒 */
|
|
11
|
+
delay?: number;
|
|
12
|
+
/** - 动画方向 */
|
|
13
|
+
direction?: 'down' | 'up';
|
|
14
|
+
/** - 动画时长 单位:秒 如果不指定 则使用spring动画 更为自然地过渡 */
|
|
15
|
+
duration?: number;
|
|
16
|
+
/** - 前缀 */
|
|
17
|
+
prefix?: string;
|
|
18
|
+
/** - 起始值 */
|
|
19
|
+
startValue?: number;
|
|
20
|
+
/** - 后缀 */
|
|
21
|
+
suffix?: string;
|
|
22
|
+
/** - 目标值 */
|
|
23
|
+
value: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const NumberTicker = ({
|
|
27
|
+
className,
|
|
28
|
+
decimalPlaces = 0,
|
|
29
|
+
delay = 0,
|
|
30
|
+
direction = 'up',
|
|
31
|
+
duration,
|
|
32
|
+
prefix = '',
|
|
33
|
+
startValue = 0,
|
|
34
|
+
suffix = '',
|
|
35
|
+
value,
|
|
36
|
+
...props
|
|
37
|
+
}: NumberTickerProps) => {
|
|
38
|
+
const ref = useRef<HTMLSpanElement>(null);
|
|
39
|
+
|
|
40
|
+
const endValue = direction === 'down' ? 0 : value;
|
|
41
|
+
|
|
42
|
+
const motionValue = useMotionValue(direction === 'down' ? value : 0);
|
|
43
|
+
|
|
44
|
+
const isInView = useInView(ref, { margin: '0px', once: true });
|
|
45
|
+
|
|
46
|
+
const springValue = useSpring(motionValue, {
|
|
47
|
+
damping: 60,
|
|
48
|
+
stiffness: 100
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
function updateTextContent(latest: number) {
|
|
52
|
+
if (!ref.current) return;
|
|
53
|
+
|
|
54
|
+
const formattedNumber = Intl.NumberFormat('en-US', {
|
|
55
|
+
maximumFractionDigits: decimalPlaces,
|
|
56
|
+
minimumFractionDigits: decimalPlaces
|
|
57
|
+
}).format(Number(latest.toFixed(decimalPlaces)));
|
|
58
|
+
ref.current.textContent = `${prefix} ${formattedNumber} ${suffix}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
63
|
+
isInView &&
|
|
64
|
+
setTimeout(() => {
|
|
65
|
+
motionValue.set(endValue);
|
|
66
|
+
}, delay * 1000);
|
|
67
|
+
}, [motionValue, isInView, delay, endValue]);
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
let animation: AnimationPlaybackControls;
|
|
71
|
+
if (duration) {
|
|
72
|
+
animation = animate(
|
|
73
|
+
motionValue.get(), // 起始值
|
|
74
|
+
endValue, // 目标值
|
|
75
|
+
{
|
|
76
|
+
duration, // 动画时长(秒)
|
|
77
|
+
onUpdate: latest => {
|
|
78
|
+
// 更新 motionValue(可选:如果后续还有依赖该值的逻辑)
|
|
79
|
+
motionValue.set(latest);
|
|
80
|
+
|
|
81
|
+
updateTextContent(latest);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
} else {
|
|
86
|
+
springValue.on('change', latest => {
|
|
87
|
+
updateTextContent(latest);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return () => animation?.cancel();
|
|
91
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
92
|
+
}, [motionValue, springValue, endValue, duration]);
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<span
|
|
96
|
+
className={clsx('inline-block text-white tracking-wider tabular-nums dark:text-dark', className)}
|
|
97
|
+
ref={ref}
|
|
98
|
+
{...props}
|
|
99
|
+
>
|
|
100
|
+
{prefix} {startValue} {suffix}
|
|
101
|
+
</span>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export default NumberTicker;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
2
|
+
import { type ReactNode, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { createPortal } from 'react-dom';
|
|
4
|
+
|
|
5
|
+
interface PortalProps {
|
|
6
|
+
/** 是否在容器不存在时自动创建 */
|
|
7
|
+
autoCreate?: boolean;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
/** 容器 ID 或 CSS 选择器 */
|
|
10
|
+
container: string | HTMLElement;
|
|
11
|
+
|
|
12
|
+
/** 容器不存在时的回退内容 */
|
|
13
|
+
fallback?: ReactNode;
|
|
14
|
+
/** 自动创建时的标签名 */
|
|
15
|
+
tagName?: keyof HTMLElementTagNameMap;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Portal = (props: PortalProps) => {
|
|
19
|
+
const { autoCreate = false, children, container, fallback = null, tagName = 'div' } = props;
|
|
20
|
+
|
|
21
|
+
const [targetElement, setTargetElement] = useState<HTMLElement | null>(null);
|
|
22
|
+
|
|
23
|
+
const createdElementRef = useRef<HTMLElement | null>(null);
|
|
24
|
+
|
|
25
|
+
function findTargetElement() {
|
|
26
|
+
let element: HTMLElement | null = null;
|
|
27
|
+
|
|
28
|
+
// 支持直接传入 HTMLElement
|
|
29
|
+
if (container instanceof HTMLElement) {
|
|
30
|
+
element = container;
|
|
31
|
+
}
|
|
32
|
+
// 支持 ID(#id)
|
|
33
|
+
else if (typeof container === 'string') {
|
|
34
|
+
if (container.startsWith('#')) {
|
|
35
|
+
element = document.getElementById(container.slice(1));
|
|
36
|
+
}
|
|
37
|
+
// 支持 CSS 选择器
|
|
38
|
+
else {
|
|
39
|
+
element = document.querySelector<HTMLElement>(container);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 自动创建容器
|
|
44
|
+
if (!element && autoCreate && typeof container === 'string') {
|
|
45
|
+
element = document.createElement(tagName);
|
|
46
|
+
element.id = container.startsWith('#') ? container.slice(1) : container;
|
|
47
|
+
document.body.appendChild(element);
|
|
48
|
+
createdElementRef.current = element;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
setTargetElement(element);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
findTargetElement();
|
|
56
|
+
|
|
57
|
+
// 清理:移除自动创建的元素
|
|
58
|
+
return () => {
|
|
59
|
+
if (createdElementRef.current) {
|
|
60
|
+
document.body.removeChild(createdElementRef.current);
|
|
61
|
+
createdElementRef.current = null;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}, []);
|
|
65
|
+
|
|
66
|
+
// 容器不存在时渲染回退内容
|
|
67
|
+
if (!targetElement) {
|
|
68
|
+
return fallback;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return createPortal(children, targetElement);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export default Portal;
|