@lark-apaas/client-toolkit 1.2.17-alpha.1 → 1.2.17-alpha.2

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.
Files changed (71) hide show
  1. package/lib/antd-table.d.ts +2 -2
  2. package/lib/apis/aily-chat.d.ts +2 -0
  3. package/lib/apis/aily-chat.js +2 -0
  4. package/lib/apis/components/ActiveLink.d.ts +26 -0
  5. package/lib/apis/components/ActiveLink.js +66 -0
  6. package/lib/apis/hooks/useScrollReveal.d.ts +1 -0
  7. package/lib/apis/hooks/useScrollReveal.js +1 -0
  8. package/lib/apis/utils/getEnv.d.ts +1 -0
  9. package/lib/apis/utils/getEnv.js +2 -0
  10. package/lib/apis/utils/scopedStorage.d.ts +1 -0
  11. package/lib/apis/utils/scopedStorage.js +2 -0
  12. package/lib/auth.d.ts +1 -0
  13. package/lib/auth.js +2 -0
  14. package/lib/components/AppContainer/IframeBridge.d.ts +0 -1
  15. package/lib/components/AppContainer/IframeBridge.js +1 -20
  16. package/lib/components/AppContainer/api-proxy/core.js +2 -1
  17. package/lib/components/AppContainer/index.d.ts +9 -2
  18. package/lib/components/AppContainer/index.js +14 -70
  19. package/lib/components/AppContainer/utils/childApi.js +1 -0
  20. package/lib/components/AppContainer/utils/tea.js +1 -1
  21. package/lib/components/ErrorRender/index.js +5 -11
  22. package/lib/components/User/UserSelect.js +1 -13
  23. package/lib/components/theme/index.d.ts +0 -1
  24. package/lib/components/theme/index.js +0 -1
  25. package/lib/components/theme/util.d.ts +0 -2
  26. package/lib/components/theme/util.js +0 -108
  27. package/lib/components/ui/toast.d.ts +2 -0
  28. package/lib/components/ui/toast.js +53 -0
  29. package/lib/hooks/index.d.ts +1 -0
  30. package/lib/hooks/index.js +1 -0
  31. package/lib/hooks/useScrollReveal.d.ts +61 -0
  32. package/lib/hooks/useScrollReveal.js +37 -0
  33. package/lib/index.js +5 -1
  34. package/lib/integrations/dataloom.js +4 -2
  35. package/lib/integrations/services/types.d.ts +1 -0
  36. package/lib/logger/batch-logger.js +3 -2
  37. package/lib/logger/intercept-global-error.js +16 -14
  38. package/lib/logger/log-types.d.ts +4 -4
  39. package/lib/logger/log-types.js +1 -1
  40. package/lib/logger/selected-logs.js +1 -2
  41. package/lib/runtime/axios.d.ts +5 -0
  42. package/lib/runtime/axios.js +2 -0
  43. package/lib/runtime/dayjs.d.ts +5 -0
  44. package/lib/runtime/dayjs.js +2 -0
  45. package/lib/runtime/iframe-bridge.d.ts +11 -0
  46. package/lib/runtime/iframe-bridge.js +29 -0
  47. package/lib/runtime/index.d.ts +24 -0
  48. package/lib/runtime/index.js +17 -0
  49. package/lib/runtime/observable.d.ts +5 -0
  50. package/lib/runtime/observable.js +2 -0
  51. package/lib/runtime/react-devtools-hook.d.ts +19 -0
  52. package/lib/runtime/react-devtools-hook.js +20 -0
  53. package/lib/runtime/server-log.d.ts +5 -0
  54. package/lib/runtime/server-log.js +41 -0
  55. package/lib/runtime/styles.d.ts +5 -0
  56. package/lib/runtime/styles.js +1 -0
  57. package/lib/theme-layer.css +2 -1
  58. package/lib/utils/axiosConfig.js +25 -3
  59. package/lib/utils/getParentOrigin.js +12 -2
  60. package/lib/utils/hmr-api.d.ts +39 -0
  61. package/lib/utils/hmr-api.js +36 -0
  62. package/lib/utils/module-hot.d.ts +9 -5
  63. package/lib/utils/module-hot.js +9 -10
  64. package/lib/utils/requestManager.js +1 -3
  65. package/lib/utils/scopedStorage.d.ts +5 -0
  66. package/lib/utils/scopedStorage.js +46 -0
  67. package/package.json +2 -2
  68. package/lib/components/AppContainer/utils/listenHot.d.ts +0 -1
  69. package/lib/components/AppContainer/utils/listenHot.js +0 -57
  70. package/lib/components/theme/ui-config.d.ts +0 -1
  71. package/lib/components/theme/ui-config.js +0 -2
@@ -1,4 +1,4 @@
1
1
  import { Table } from 'antd';
2
- import type { TableProps } from 'antd';
2
+ import type { TableProps, TableColumnType, TableColumnsType } from 'antd';
3
3
  export { Table };
4
- export type { TableProps };
4
+ export type { TableProps, TableColumnType, TableColumnsType };
@@ -0,0 +1,2 @@
1
+ export type { ChatPanel, IframeEventMessage, IframeMessage, IframeMessageType, IframeRequestMessage, IframeResponseMessage, WebSDKCommonConfig, WebSDKConfig, WebSDKConversionConfig, WebSDKEditorConfig, WebSDKEvents, WebSDKSkillInfo, } from '@lark-apaas/aily-web-sdk';
2
+ export { DEFAULT_ANONYMOUS_CHANNEL_TYPE, DEFAULT_CHANNEL_TYPE, getIframeBaseURL, IFRAME_BASE_URL, initAilyChat, MESSAGE_TIMEOUT, } from '@lark-apaas/aily-web-sdk';
@@ -0,0 +1,2 @@
1
+ import { DEFAULT_ANONYMOUS_CHANNEL_TYPE, DEFAULT_CHANNEL_TYPE, IFRAME_BASE_URL, MESSAGE_TIMEOUT, getIframeBaseURL, initAilyChat } from "@lark-apaas/aily-web-sdk";
2
+ export { DEFAULT_ANONYMOUS_CHANNEL_TYPE, DEFAULT_CHANNEL_TYPE, IFRAME_BASE_URL, MESSAGE_TIMEOUT, getIframeBaseURL, initAilyChat };
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import { type NavLinkProps } from 'react-router-dom';
3
+ export interface ActiveLinkProps extends Omit<NavLinkProps, 'to'> {
4
+ to: string;
5
+ }
6
+ /**
7
+ * ActiveLink 组件
8
+ *
9
+ * 替换 react-router-dom 的 NavLink,扩展支持 hash 路由跳转和激活态功能
10
+ *
11
+ * @example
12
+ * // 普通路由跳转
13
+ * <ActiveLink to="/dashboard">Dashboard</ActiveLink>
14
+ *
15
+ * // hash 路由跳转
16
+ * <ActiveLink to="#section1">Section 1</ActiveLink>
17
+ *
18
+ * // 使用函数式 className 显示激活态
19
+ * <ActiveLink
20
+ * to="#features"
21
+ * className={({isActive}) => isActive ? 'active' : ''}
22
+ * >
23
+ * Features
24
+ * </ActiveLink>
25
+ */
26
+ export declare const ActiveLink: React.ForwardRefExoticComponent<ActiveLinkProps & React.RefAttributes<HTMLAnchorElement>>;
@@ -0,0 +1,66 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useState } from "react";
3
+ import { NavLink } from "react-router-dom";
4
+ const ActiveLink = /*#__PURE__*/ forwardRef(({ to, onClick, className, style, children, ...rest }, ref)=>{
5
+ const [currentHash, setCurrentHash] = useState(()=>'undefined' != typeof window ? window.location.hash : '');
6
+ const isHashRoute = 'string' == typeof to && to.startsWith('#');
7
+ useEffect(()=>{
8
+ if (!isHashRoute) return;
9
+ const handleHashChange = ()=>{
10
+ setCurrentHash(window.location.hash);
11
+ };
12
+ window.addEventListener('hashchange', handleHashChange);
13
+ return ()=>window.removeEventListener('hashchange', handleHashChange);
14
+ }, [
15
+ isHashRoute
16
+ ]);
17
+ const isActive = isHashRoute && currentHash === to;
18
+ if (!isHashRoute) return /*#__PURE__*/ jsx(NavLink, {
19
+ ref: ref,
20
+ to: to,
21
+ onClick: onClick,
22
+ className: className,
23
+ style: style,
24
+ ...rest,
25
+ children: children
26
+ });
27
+ const handleHashClick = (e)=>{
28
+ onClick?.(e);
29
+ if (e.defaultPrevented) return;
30
+ e.preventDefault();
31
+ const targetId = to.slice(1);
32
+ const targetElement = document.getElementById(targetId);
33
+ history.pushState(null, '', to);
34
+ setCurrentHash(to);
35
+ window.dispatchEvent(new Event('hashchange'));
36
+ if (targetElement && 'function' == typeof targetElement.scrollIntoView) targetElement.scrollIntoView({
37
+ behavior: 'smooth'
38
+ });
39
+ };
40
+ const computedClassName = 'function' == typeof className ? className({
41
+ isActive,
42
+ isPending: false,
43
+ isTransitioning: false
44
+ }) : className;
45
+ const computedStyle = 'function' == typeof style ? style({
46
+ isActive,
47
+ isPending: false,
48
+ isTransitioning: false
49
+ }) : style;
50
+ const computedChildren = 'function' == typeof children ? children({
51
+ isActive,
52
+ isPending: false,
53
+ isTransitioning: false
54
+ }) : children;
55
+ return /*#__PURE__*/ jsx("a", {
56
+ ref: ref,
57
+ href: to,
58
+ onClick: handleHashClick,
59
+ className: computedClassName,
60
+ style: computedStyle,
61
+ ...rest,
62
+ children: computedChildren
63
+ });
64
+ });
65
+ ActiveLink.displayName = 'ActiveLink';
66
+ export { ActiveLink };
@@ -0,0 +1 @@
1
+ export * from '../../hooks/useScrollReveal';
@@ -0,0 +1 @@
1
+ export * from "../../hooks/useScrollReveal.js";
@@ -0,0 +1 @@
1
+ export { getEnv } from '../../utils/getParentOrigin';
@@ -0,0 +1,2 @@
1
+ import { getEnv } from "../../utils/getParentOrigin.js";
2
+ export { getEnv };
@@ -0,0 +1 @@
1
+ export { scopedStorage } from '../../utils/scopedStorage';
@@ -0,0 +1,2 @@
1
+ import { scopedStorage } from "../../utils/scopedStorage.js";
2
+ export { scopedStorage };
package/lib/auth.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { CanRole, AbilityContext, ROLE_SUBJECT } from '@lark-apaas/auth-sdk';
package/lib/auth.js ADDED
@@ -0,0 +1,2 @@
1
+ import { AbilityContext, CanRole, ROLE_SUBJECT } from "@lark-apaas/auth-sdk";
2
+ export { AbilityContext, CanRole, ROLE_SUBJECT };
@@ -1,3 +1,2 @@
1
1
  import React from 'react';
2
- import './utils/listenHot';
3
2
  export default function IframeBridge(): React.JSX.Element;
@@ -1,11 +1,8 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useRef } from "react";
3
3
  import { useLocation, useNavigate } from "react-router-dom";
4
- import { connectToParent } from "penpal";
5
4
  import { useUpdatingRef } from "../../hooks/useUpdatingRef.js";
6
- import { resolveParentOrigin, submitPostMessage } from "../../utils/postMessage.js";
7
- import { childApi } from "./utils/childApi.js";
8
- import "./utils/listenHot.js";
5
+ import { submitPostMessage } from "../../utils/postMessage.js";
9
6
  var IframeBridge_RouteMessageType = /*#__PURE__*/ function(RouteMessageType) {
10
7
  RouteMessageType["RouteChange"] = "RouteChange";
11
8
  RouteMessageType["RouteBack"] = "RouteBack";
@@ -15,22 +12,6 @@ var IframeBridge_RouteMessageType = /*#__PURE__*/ function(RouteMessageType) {
15
12
  function isRouteMessageType(type) {
16
13
  return Object.values(IframeBridge_RouteMessageType).includes(type);
17
14
  }
18
- async function connectParent() {
19
- submitPostMessage({
20
- type: 'PreviewReady',
21
- data: {}
22
- });
23
- const parentOrigin = resolveParentOrigin();
24
- if (!parentOrigin) return;
25
- const connection = connectToParent({
26
- parentOrigin,
27
- methods: {
28
- ...childApi
29
- }
30
- });
31
- await connection.promise;
32
- }
33
- 'production' !== process.env.NODE_ENV && connectParent();
34
15
  function IframeBridge() {
35
16
  const location = useLocation();
36
17
  const navigate = useNavigate();
@@ -139,7 +139,8 @@ class ApiProxy {
139
139
  ...config,
140
140
  headers: {
141
141
  ...this.defaultConfig.headers,
142
- ...config.headers
142
+ ...config.headers,
143
+ 'X-Page-Route': 'undefined' != typeof window ? window.location?.pathname || '/' : '/'
143
144
  }
144
145
  };
145
146
  const requestKey = this.generateRequestKey(mergedConfig);
@@ -1,7 +1,14 @@
1
1
  import React from 'react';
2
2
  import { IBaseThemeProviderProps } from '../theme';
3
- import '../../index.css';
3
+ import '../../runtime';
4
+ interface IBaseAuthProviderProps {
5
+ enableAuth?: boolean;
6
+ }
7
+ interface IToasterProps {
8
+ /** 禁用内建 Toaster 组件,默认 false */
9
+ disableToaster?: boolean;
10
+ }
4
11
  declare const AppContainer: React.FC<{
5
12
  children: React.ReactNode;
6
- } & IBaseThemeProviderProps>;
13
+ } & IBaseThemeProviderProps & IBaseAuthProviderProps & IToasterProps>;
7
14
  export default AppContainer;
@@ -1,27 +1,19 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { useEffect, useRef, useState } from "react";
2
+ import { useEffect, useState } from "react";
3
3
  import { ConfigProvider } from "antd";
4
4
  import { MiaodaInspector } from "@lark-apaas/miaoda-inspector";
5
5
  import zh_CN from "antd/locale/zh_CN";
6
6
  import IframeBridge from "./IframeBridge.js";
7
- import { defaultUIConfig } from "../theme/ui-config.js";
8
7
  import { Toaster } from "./sonner.js";
9
8
  import { PageHoc } from "./PageHoc.js";
10
- import { findValueByPixel, generateTailwindRadiusToken, themeColorTokenMap, themeMetaOptions } from "../theme/index.js";
11
- import { registerDayjsPlugins } from "./dayjsPlugins.js";
12
- import "../../index.css";
13
- import { initAxiosConfig } from "../../utils/axiosConfig.js";
14
9
  import { reportTeaEvent } from "./utils/tea.js";
15
10
  import { useAppInfo } from "../../hooks/index.js";
16
11
  import { TrackKey } from "../../types/tea.js";
17
12
  import safety from "./safety.js";
18
13
  import { getAppId } from "../../utils/getAppId.js";
19
- import { ServerLogSSEClient } from "../../server-log/index.js";
20
14
  import QueryProvider from "../QueryProvider/index.js";
21
- import { initObservable } from "./utils/observable.js";
22
- registerDayjsPlugins();
23
- initAxiosConfig();
24
- initObservable();
15
+ import { AuthProvider } from "@lark-apaas/auth-sdk";
16
+ import "../../runtime/index.js";
25
17
  const isMiaodaPreview = window.IS_MIAODA_PREVIEW;
26
18
  const readCssVarColor = (varName, fallback)=>{
27
19
  try {
@@ -32,55 +24,10 @@ const readCssVarColor = (varName, fallback)=>{
32
24
  return fallback;
33
25
  }
34
26
  };
27
+ const appFlags = process.env.APP_FLAGS || {};
35
28
  const App = (props)=>{
36
- const { themeMeta = {} } = props;
29
+ const { enableAuth, disableToaster = false } = props;
37
30
  useAppInfo();
38
- const serverLogClientRef = useRef(null);
39
- const { rem } = findValueByPixel(themeMetaOptions.themeRadius, themeMeta.borderRadius) || {
40
- rem: '0.625'
41
- };
42
- const radiusToken = generateTailwindRadiusToken(Number(rem));
43
- const themeToken = {
44
- ...defaultUIConfig,
45
- common: {
46
- ...defaultUIConfig.common,
47
- borderRadius: radiusToken
48
- }
49
- };
50
- useEffect(()=>{
51
- if ('production' !== process.env.NODE_ENV && window.parent !== window) {
52
- try {
53
- const backendUrl = window.location.origin;
54
- serverLogClientRef.current = new ServerLogSSEClient({
55
- serverUrl: backendUrl,
56
- sseEndpoint: '/dev/logs/server-logs/stream',
57
- debug: true
58
- });
59
- serverLogClientRef.current.start();
60
- console.log('[AppContainer] Server log SSE client started');
61
- } catch (error) {
62
- console.error('[AppContainer] Failed to start server log SSE client:', error);
63
- }
64
- const handleVisibilityChange = ()=>{
65
- if (!serverLogClientRef.current) return;
66
- if (document.hidden) {
67
- serverLogClientRef.current.pause();
68
- console.log('[AppContainer] Tab hidden, SSE paused');
69
- } else {
70
- serverLogClientRef.current.resume();
71
- console.log('[AppContainer] Tab visible, SSE resumed');
72
- }
73
- };
74
- document.addEventListener('visibilitychange', handleVisibilityChange);
75
- return ()=>{
76
- document.removeEventListener('visibilitychange', handleVisibilityChange);
77
- if (serverLogClientRef.current) {
78
- serverLogClientRef.current.stop();
79
- console.log('[AppContainer] Server log SSE client stopped');
80
- }
81
- };
82
- }
83
- }, []);
84
31
  useEffect(()=>{
85
32
  if (isMiaodaPreview) fetch(`${location.origin}/ai/api/feida_preview/csrf`).then(()=>{
86
33
  setTimeout(()=>{
@@ -99,17 +46,13 @@ const App = (props)=>{
99
46
  }
100
47
  });
101
48
  }, []);
102
- return /*#__PURE__*/ jsxs(Fragment, {
49
+ return /*#__PURE__*/ jsxs(AuthProvider, {
50
+ config: {
51
+ enable: enableAuth
52
+ },
103
53
  children: [
104
- /*#__PURE__*/ jsx(Toaster, {}),
105
- 'production' !== process.env.NODE_ENV && /*#__PURE__*/ jsx(MiaodaInspector, {
106
- theme: {
107
- themeMetaOptions: themeMetaOptions,
108
- themeColorTokenMap: themeColorTokenMap,
109
- themeToken
110
- },
111
- cwd: process.env.CWD || ''
112
- }),
54
+ !disableToaster && true !== appFlags.customToaster && /*#__PURE__*/ jsx(Toaster, {}),
55
+ 'production' !== process.env.NODE_ENV && /*#__PURE__*/ jsx(MiaodaInspector, {}),
113
56
  'production' !== process.env.NODE_ENV && /*#__PURE__*/ jsx(IframeBridge, {}),
114
57
  /*#__PURE__*/ jsx(PageHoc, {
115
58
  children: props.children
@@ -118,7 +61,7 @@ const App = (props)=>{
118
61
  });
119
62
  };
120
63
  const AppContainer_AppContainer = (props)=>{
121
- const { children, ...rest } = props;
64
+ const { children } = props;
122
65
  const [cssColors, setCssColors] = useState(()=>({
123
66
  background: readCssVarColor('--background'),
124
67
  destructive: readCssVarColor('--destructive'),
@@ -246,7 +189,8 @@ const AppContainer_AppContainer = (props)=>{
246
189
  }
247
190
  },
248
191
  children: /*#__PURE__*/ jsx(App, {
249
- themeMeta: props.themeMeta,
192
+ enableAuth: props.enableAuth,
193
+ disableToaster: props.disableToaster,
250
194
  children: children
251
195
  })
252
196
  })
@@ -16,6 +16,7 @@ async function getRoutes() {
16
16
  return routes;
17
17
  }
18
18
  async function getSourceMap() {
19
+ if ('vite' === process.env.BUILD_TOOL) return '';
19
20
  let sourceMapContent = '';
20
21
  try {
21
22
  const basePath = normalizeBasePath(process.env.CLIENT_BASE_PATH);
@@ -16,7 +16,7 @@ async function createTracker() {
16
16
  const userIDEncrypt = userID && '0' !== userID ? encryptTea(userID) : void 0;
17
17
  const tenantIDEncrypt = tenantID && '0' !== tenantID ? encryptTea(tenantID) : void 0;
18
18
  window.collectEvent('init', {
19
- app_id: 672575,
19
+ app_id: 788827,
20
20
  channel: 'cn',
21
21
  disable_auto_pv: false,
22
22
  enable_ab_test: false,
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useEffect } from "react";
3
3
  import { logger } from "../../logger/index.js";
4
- import { createApplyHandle, getModuleHot } from "../../utils/module-hot.js";
4
+ import { getHmrApi } from "../../utils/hmr-api.js";
5
5
  import { submitPostMessage } from "../../utils/postMessage.js";
6
6
  const RenderError = (props)=>{
7
7
  const { error, resetErrorBoundary } = props;
@@ -27,16 +27,10 @@ const RenderError = (props)=>{
27
27
  ]);
28
28
  useEffect(()=>{
29
29
  if (!resetErrorBoundary) return;
30
- const hot = getModuleHot();
31
- if (hot) {
32
- const handler = createApplyHandle((success)=>{
33
- if (success) resetErrorBoundary();
34
- });
35
- hot.addStatusHandler(handler);
36
- return ()=>{
37
- hot.removeStatusHandler(handler);
38
- };
39
- }
30
+ const hmr = getHmrApi();
31
+ if (hmr) return hmr.onSuccess(()=>{
32
+ resetErrorBoundary();
33
+ });
40
34
  }, [
41
35
  resetErrorBoundary
42
36
  ]);
@@ -67,20 +67,8 @@ const UserSelect = ({ mode = 'single', defaultValue, value, onChange, placeholde
67
67
  if (!normalizedIds.length) return void setUiValue(void 0);
68
68
  const fetchProfiles = async ()=>{
69
69
  try {
70
- const ids = normalizedIds.map((id)=>Number(id)).filter((id)=>Number.isFinite(id));
71
- if (!ids.length) {
72
- const profiles = normalizedIds.map((id)=>inputProfilesMap.get(id) ?? {
73
- user_id: id,
74
- name: '',
75
- avatar: '',
76
- email: '',
77
- status: 1
78
- });
79
- setUiValue('single' === mode ? profiles[0] : profiles);
80
- return;
81
- }
82
70
  const dataloom = await getDataloom();
83
- const response = await dataloom.service.user.getByIds(ids);
71
+ const response = await dataloom.service.user.getByIds(normalizedIds);
84
72
  const fetchedList = Array.isArray(response?.data) ? response?.data : Array.isArray(response?.data?.user_list) ? response?.data?.user_list : [];
85
73
  const fetchedMap = new Map();
86
74
  fetchedList.forEach((profile)=>{
@@ -1,3 +1,2 @@
1
1
  export * from './constants';
2
2
  export * from './util';
3
- export * from './ui-config';
@@ -1,3 +1,2 @@
1
1
  export * from "./constants.js";
2
2
  export * from "./util.js";
3
- export * from "./ui-config.js";
@@ -1,5 +1,4 @@
1
1
  import { ITheme } from "../../types";
2
- import { UIComponentConfig } from "./ui-config";
3
2
  export interface IBaseThemeProviderProps {
4
3
  defaultTheme?: ITheme;
5
4
  themeMeta?: Partial<IThemeTokenMeta>;
@@ -18,4 +17,3 @@ export interface IThemeTokenMeta {
18
17
  */
19
18
  spacing: number;
20
19
  }
21
- export declare const generateTailwindRadiusToken: (radiusRemValue: number) => UIComponentConfig;
@@ -1,108 +0,0 @@
1
- const generateTailwindRadiusToken = (radiusRemValue)=>{
2
- try {
3
- const rootFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize);
4
- const radiusPx = radiusRemValue * rootFontSize;
5
- const tempElement = document.createElement('div');
6
- tempElement.style.position = 'absolute';
7
- tempElement.style.visibility = 'hidden';
8
- document.body.appendChild(tempElement);
9
- tempElement.style.borderRadius = `${radiusPx}px`;
10
- const computed = getComputedStyle(tempElement).borderRadius;
11
- document.body.removeChild(tempElement);
12
- if (computed && 'auto' !== computed && 'initial' !== computed) return {
13
- type: 'select',
14
- options: [
15
- {
16
- value: 'rounded-none',
17
- label: 'none(0px)',
18
- rawValue: '0'
19
- },
20
- {
21
- value: 'rounded-sm',
22
- label: `sm (${Math.max(0, radiusPx - 4)}px)`,
23
- rawValue: `${Math.max(0, radiusPx - 4)}`
24
- },
25
- {
26
- value: 'rounded',
27
- label: 's (4px)',
28
- rawValue: '4'
29
- },
30
- {
31
- value: 'rounded-md',
32
- label: `m (${Math.max(0, radiusPx - 2)}px)`,
33
- rawValue: `${Math.max(0, radiusPx - 2)}`
34
- },
35
- {
36
- value: 'rounded-lg',
37
- label: `l (${radiusPx}px)`,
38
- rawValue: `${radiusPx}`
39
- },
40
- {
41
- value: 'rounded-xl',
42
- label: `xl (${radiusPx + 4}px)`,
43
- rawValue: `${radiusPx + 4}`
44
- },
45
- {
46
- value: 'rounded-2xl',
47
- label: '2xl (16px)',
48
- rawValue: '16'
49
- },
50
- {
51
- value: 'rounded-full',
52
- label: 'Full',
53
- rawValue: '9999'
54
- }
55
- ]
56
- };
57
- throw new Error('Browser calculation validation failed');
58
- } catch (error) {
59
- console.warn('Failed to get computed values from browser, falling back to default calculation:', error);
60
- const radiusPx = 16 * radiusRemValue;
61
- return {
62
- type: 'select',
63
- options: [
64
- {
65
- value: 'rounded-none',
66
- label: 'none(0px)',
67
- rawValue: '0'
68
- },
69
- {
70
- value: 'rounded-sm',
71
- label: `sm (${Math.max(0, radiusPx - 4)}px)`,
72
- rawValue: `${Math.max(0, radiusPx - 4)}`
73
- },
74
- {
75
- value: 'rounded',
76
- label: 's (4px)',
77
- rawValue: '4'
78
- },
79
- {
80
- value: 'rounded-md',
81
- label: `m (${Math.max(0, radiusPx - 2)}px)`,
82
- rawValue: `${Math.max(0, radiusPx - 2)}`
83
- },
84
- {
85
- value: 'rounded-lg',
86
- label: `l (${radiusPx}px)`,
87
- rawValue: `${radiusPx}`
88
- },
89
- {
90
- value: 'rounded-xl',
91
- label: `xl (${radiusPx + 4}px)`,
92
- rawValue: `${radiusPx + 4}`
93
- },
94
- {
95
- value: 'rounded-2xl',
96
- label: '2xl (16px)',
97
- rawValue: '16'
98
- },
99
- {
100
- value: 'rounded-full',
101
- label: 'Full',
102
- rawValue: '9999'
103
- }
104
- ]
105
- };
106
- }
107
- };
108
- export { generateTailwindRadiusToken };
@@ -0,0 +1,2 @@
1
+ /** 显示 toast 提示(兼容 PC/移动端) */
2
+ export declare function showToast(message: string, duration?: number): Promise<void>;
@@ -0,0 +1,53 @@
1
+ function showToast(message, duration = 3000) {
2
+ return new Promise((resolve)=>{
3
+ const toast = document.createElement('div');
4
+ const iconSvg = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
5
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M8 1.333a6.667 6.667 0 1 1 0 13.334A6.667 6.667 0 0 1 8 1.333ZM8 10a.667.667 0 1 0 0 1.333A.667.667 0 0 0 8 10Zm0-5.333a.667.667 0 0 0-.667.666v3.334a.667.667 0 0 0 1.334 0V5.333A.667.667 0 0 0 8 4.667Z" fill="#ff811a"/>
6
+ </svg>`;
7
+ const iconWrapper = document.createElement('span');
8
+ iconWrapper.innerHTML = iconSvg;
9
+ Object.assign(iconWrapper.style, {
10
+ display: 'flex',
11
+ alignItems: 'center',
12
+ marginRight: '8px',
13
+ flexShrink: '0'
14
+ });
15
+ const textWrapper = document.createElement('span');
16
+ textWrapper.textContent = message;
17
+ toast.appendChild(iconWrapper);
18
+ toast.appendChild(textWrapper);
19
+ Object.assign(toast.style, {
20
+ position: 'fixed',
21
+ top: '32px',
22
+ left: '50%',
23
+ transform: 'translate(-50%, -50%)',
24
+ display: 'flex',
25
+ alignItems: 'center',
26
+ padding: '12px 16px',
27
+ backgroundColor: '#fff',
28
+ color: '#1f2329',
29
+ border: '1px solid #dee0e3',
30
+ borderRadius: '6px',
31
+ fontSize: '14px',
32
+ lineHeight: '1.5',
33
+ zIndex: '99999',
34
+ maxWidth: '80vw',
35
+ wordBreak: 'break-word',
36
+ boxShadow: '0 4px 8px rgba(0, 0, 0, 0.03), 0 3px 6px rgba(0, 0, 0, 0.05), 0 6px 18px rgba(0, 0, 0, 0.03)',
37
+ opacity: '0',
38
+ transition: 'opacity 0.3s ease'
39
+ });
40
+ document.body.appendChild(toast);
41
+ requestAnimationFrame(()=>{
42
+ toast.style.opacity = '1';
43
+ });
44
+ setTimeout(()=>{
45
+ toast.style.opacity = '0';
46
+ setTimeout(()=>{
47
+ document.body.removeChild(toast);
48
+ resolve();
49
+ }, 300);
50
+ }, duration);
51
+ });
52
+ }
53
+ export { showToast };
@@ -2,3 +2,4 @@ export * from './useAppInfo';
2
2
  export * from './useCurrentUserProfile';
3
3
  export * from './useIsMobile';
4
4
  export * from './useLogout';
5
+ export * from './useScrollReveal';
@@ -2,3 +2,4 @@ export * from "./useAppInfo.js";
2
2
  export * from "./useCurrentUserProfile.js";
3
3
  export * from "./useIsMobile.js";
4
4
  export * from "./useLogout.js";
5
+ export * from "./useScrollReveal.js";