@next-core/react-runtime 1.9.0 → 1.10.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/dist/cjs/index.js CHANGED
@@ -190,4 +190,26 @@ Object.keys(_useSystemInfo).forEach(function (key) {
190
190
  }
191
191
  });
192
192
  });
193
+ var _useCheckPermissions = require("./useCheckPermissions.js");
194
+ Object.keys(_useCheckPermissions).forEach(function (key) {
195
+ if (key === "default" || key === "__esModule") return;
196
+ if (key in exports && exports[key] === _useCheckPermissions[key]) return;
197
+ Object.defineProperty(exports, key, {
198
+ enumerable: true,
199
+ get: function () {
200
+ return _useCheckPermissions[key];
201
+ }
202
+ });
203
+ });
204
+ var _useControlledState = require("./useControlledState.js");
205
+ Object.keys(_useControlledState).forEach(function (key) {
206
+ if (key === "default" || key === "__esModule") return;
207
+ if (key in exports && exports[key] === _useControlledState[key]) return;
208
+ Object.defineProperty(exports, key, {
209
+ enumerable: true,
210
+ get: function () {
211
+ return _useControlledState[key];
212
+ }
213
+ });
214
+ });
193
215
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_ReactUseBrick","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_useCurrentTheme","_useCurrentApp","_useRecentApps","_useRouteRender","_useProvider","_asyncWrapBrick","_useNavConfig","_useLazyWrapBrick","_usePathParams","_useSearchParams","_useParams","_useHistory","_useAuth","_useLocation","_useFeatureFlags","_useSystemInfo"],"sources":["../../src/index.ts"],"sourcesContent":["export * from \"./ReactUseBrick.js\";\nexport * from \"./useCurrentTheme.js\";\nexport * from \"./useCurrentApp.js\";\nexport * from \"./useRecentApps.js\";\nexport * from \"./useRouteRender.js\";\nexport * from \"./useProvider/useProvider.js\";\nexport * from \"./asyncWrapBrick.js\";\nexport * from \"./useNavConfig.js\";\nexport * from \"./useLazyWrapBrick.js\";\nexport * from \"./usePathParams.js\";\nexport * from \"./useSearchParams.js\";\nexport * from \"./useParams.js\";\nexport * from \"./useHistory.js\";\nexport * from \"./useAuth.js\";\nexport * from \"./useLocation.js\";\nexport * from \"./useFeatureFlags.js\";\nexport * from \"./useSystemInfo.js\";\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["_ReactUseBrick","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_useCurrentTheme","_useCurrentApp","_useRecentApps","_useRouteRender","_useProvider","_asyncWrapBrick","_useNavConfig","_useLazyWrapBrick","_usePathParams","_useSearchParams","_useParams","_useHistory","_useAuth","_useLocation","_useFeatureFlags","_useSystemInfo","_useCheckPermissions","_useControlledState"],"sources":["../../src/index.ts"],"sourcesContent":["export * from \"./ReactUseBrick.js\";\nexport * from \"./useCurrentTheme.js\";\nexport * from \"./useCurrentApp.js\";\nexport * from \"./useRecentApps.js\";\nexport * from \"./useRouteRender.js\";\nexport * from \"./useProvider/useProvider.js\";\nexport * from \"./asyncWrapBrick.js\";\nexport * from \"./useNavConfig.js\";\nexport * from \"./useLazyWrapBrick.js\";\nexport * from \"./usePathParams.js\";\nexport * from \"./useSearchParams.js\";\nexport * from \"./useParams.js\";\nexport * from \"./useHistory.js\";\nexport * from \"./useAuth.js\";\nexport * from \"./useLocation.js\";\nexport * from \"./useFeatureFlags.js\";\nexport * from \"./useSystemInfo.js\";\nexport * from \"./useCheckPermissions.js\";\nexport * from \"./useControlledState.js\";\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useCheckPermissions = useCheckPermissions;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _easyopsRuntime = require("@next-core/easyops-runtime");
10
+ /**
11
+ * 检查用户权限的 React hooks。
12
+ *
13
+ * 此 hook 用于检查当前登录用户是否拥有指定的权限操作。
14
+ * 权限必须在 storyboard 配置的 `permissionsPreCheck` 中预先声明,
15
+ * 否则会返回 false 并在控制台输出错误。
16
+ *
17
+ * **工作原理:**
18
+ * - 权限会在路由渲染时自动预检查(通过 `preCheckPermissions`)
19
+ * - 此 hook 查询已缓存的权限结果(同步操作)
20
+ * - 管理员用户始终返回 true
21
+ * - 未登录用户始终返回 false
22
+ *
23
+ * **注意事项:**
24
+ * 1. 权限必须在 `permissionsPreCheck` 中声明
25
+ * 2. 所有传入的 actions 都必须有权限才返回 true
26
+ * 3. 权限检查结果会被缓存,避免重复计算
27
+ *
28
+ * @param actions - 需要检查的权限操作列表
29
+ * @returns 是否拥有所有指定的权限
30
+ *
31
+ * @example
32
+ *
33
+ * ```tsx
34
+ * // 检查单个权限
35
+ * function DeleteButton() {
36
+ * const canDelete = useCheckPermissions("my-app:user.delete");
37
+ *
38
+ * if (!canDelete) {
39
+ * return null;
40
+ * }
41
+ *
42
+ * return <button onClick={handleDelete}>Delete</button>;
43
+ * }
44
+ * ```
45
+ *
46
+ * @example
47
+ *
48
+ * ```tsx
49
+ * // 检查多个权限(需要全部拥有)
50
+ * function AdminPanel() {
51
+ * const hasAccess = useCheckPermissions(
52
+ * "my-app:admin.read",
53
+ * "my-app:admin.write"
54
+ * );
55
+ *
56
+ * if (!hasAccess) {
57
+ * return <div>Access Denied</div>;
58
+ * }
59
+ *
60
+ * return <div>Admin Panel Content</div>;
61
+ * }
62
+ * ```
63
+ *
64
+ * @example
65
+ *
66
+ * ```tsx
67
+ * // 在 storyboard 中配置权限预检查
68
+ * // routes.yaml
69
+ * routes:
70
+ * - path: /users
71
+ * permissionsPreCheck:
72
+ * - "my-app:user.read"
73
+ * - "my-app:user.delete"
74
+ * bricks:
75
+ * - brick: "my-brick"
76
+ * ```
77
+ */
78
+ function useCheckPermissions(...actions) {
79
+ // 使用 useMemo 缓存权限检查结果
80
+ // 因为权限在会话期间是稳定的,只依赖于 actions 列表
81
+ return _react.default.useMemo(() => _easyopsRuntime.checkPermissions.checkPermissions(...actions),
82
+ // 序列化 actions 作为依赖,避免数组引用变化导致重新计算
83
+ // eslint-disable-next-line react-hooks/exhaustive-deps
84
+ [JSON.stringify(actions)]);
85
+ }
86
+ //# sourceMappingURL=useCheckPermissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCheckPermissions.js","names":["_react","_interopRequireDefault","require","_easyopsRuntime","useCheckPermissions","actions","React","useMemo","checkPermissions","JSON","stringify"],"sources":["../../src/useCheckPermissions.ts"],"sourcesContent":["import React from \"react\";\nimport { checkPermissions } from \"@next-core/easyops-runtime\";\n\n/**\n * 检查用户权限的 React hooks。\n *\n * 此 hook 用于检查当前登录用户是否拥有指定的权限操作。\n * 权限必须在 storyboard 配置的 `permissionsPreCheck` 中预先声明,\n * 否则会返回 false 并在控制台输出错误。\n *\n * **工作原理:**\n * - 权限会在路由渲染时自动预检查(通过 `preCheckPermissions`)\n * - 此 hook 查询已缓存的权限结果(同步操作)\n * - 管理员用户始终返回 true\n * - 未登录用户始终返回 false\n *\n * **注意事项:**\n * 1. 权限必须在 `permissionsPreCheck` 中声明\n * 2. 所有传入的 actions 都必须有权限才返回 true\n * 3. 权限检查结果会被缓存,避免重复计算\n *\n * @param actions - 需要检查的权限操作列表\n * @returns 是否拥有所有指定的权限\n *\n * @example\n *\n * ```tsx\n * // 检查单个权限\n * function DeleteButton() {\n * const canDelete = useCheckPermissions(\"my-app:user.delete\");\n *\n * if (!canDelete) {\n * return null;\n * }\n *\n * return <button onClick={handleDelete}>Delete</button>;\n * }\n * ```\n *\n * @example\n *\n * ```tsx\n * // 检查多个权限(需要全部拥有)\n * function AdminPanel() {\n * const hasAccess = useCheckPermissions(\n * \"my-app:admin.read\",\n * \"my-app:admin.write\"\n * );\n *\n * if (!hasAccess) {\n * return <div>Access Denied</div>;\n * }\n *\n * return <div>Admin Panel Content</div>;\n * }\n * ```\n *\n * @example\n *\n * ```tsx\n * // 在 storyboard 中配置权限预检查\n * // routes.yaml\n * routes:\n * - path: /users\n * permissionsPreCheck:\n * - \"my-app:user.read\"\n * - \"my-app:user.delete\"\n * bricks:\n * - brick: \"my-brick\"\n * ```\n */\nexport function useCheckPermissions(...actions: string[]): boolean {\n // 使用 useMemo 缓存权限检查结果\n // 因为权限在会话期间是稳定的,只依赖于 actions 列表\n return React.useMemo(\n () => checkPermissions.checkPermissions(...actions),\n // 序列化 actions 作为依赖,避免数组引用变化导致重新计算\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(actions)]\n );\n}\n"],"mappings":";;;;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,eAAA,GAAAD,OAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASE,mBAAmBA,CAAC,GAAGC,OAAiB,EAAW;EACjE;EACA;EACA,OAAOC,cAAK,CAACC,OAAO,CAClB,MAAMC,gCAAgB,CAACA,gBAAgB,CAAC,GAAGH,OAAO,CAAC;EACnD;EACA;EACA,CAACI,IAAI,CAACC,SAAS,CAACL,OAAO,CAAC,CAC1B,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useControlledState = useControlledState;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _lodash = require("lodash");
10
+ /**
11
+ * 受控/非受控混合模式的通用 Hook。
12
+ *
13
+ * 此 hook 允许组件既支持受控模式(由父组件通过 props 控制状态),
14
+ * 也支持非受控模式(组件自己管理内部状态)。
15
+ *
16
+ * **工作原理:**
17
+ * - 当 `propValue !== undefined` 时,组件处于**受控模式**,状态跟随 prop 更新
18
+ * - 当 `propValue === undefined` 时,组件处于**非受控模式**,使用内部状态
19
+ * - 支持深度比较选项,避免复杂对象引用变化导致的不必要更新
20
+ *
21
+ * **使用场景:**
22
+ * 1. 表单组件需要支持受控和非受控两种模式
23
+ * 2. 组件状态可能由父组件控制,也可能自己管理
24
+ * 3. 复杂对象状态需要避免不必要的重新渲染
25
+ *
26
+ * @template T - 状态值的类型
27
+ * @param propValue - 来自 props 的值(undefined 表示非受控模式)
28
+ * @param defaultValue - 默认值(props 为 undefined 时使用)
29
+ * @param deepCompare - 是否使用深度比较(用于复杂对象,默认 false)
30
+ * @returns 返回 [当前值, 设置值的函数],类似 useState
31
+ *
32
+ * @example
33
+ *
34
+ * ```tsx
35
+ * // 简单值(字符串、数字)
36
+ * function MyComponent({ deployed }: { deployed?: string }) {
37
+ * const [value, setValue] = useControlledState(deployed, 'host');
38
+ *
39
+ * return (
40
+ * <select value={value} onChange={(e) => setValue(e.target.value)}>
41
+ * <option value="host">Host</option>
42
+ * <option value="container">Container</option>
43
+ * </select>
44
+ * );
45
+ * }
46
+ *
47
+ * // 使用方式 1:受控模式
48
+ * <MyComponent deployed="container" />
49
+ *
50
+ * // 使用方式 2:非受控模式
51
+ * <MyComponent />
52
+ * ```
53
+ *
54
+ * @example
55
+ *
56
+ * ```tsx
57
+ * // 复杂对象(启用深度比较)
58
+ * interface Config {
59
+ * host: string;
60
+ * port: number;
61
+ * }
62
+ *
63
+ * function ConfigEditor({ config }: { config?: Config }) {
64
+ * const [value, setValue] = useControlledState<Config | null>(
65
+ * config,
66
+ * null,
67
+ * true // 启用深度比较
68
+ * );
69
+ *
70
+ * return <div>{JSON.stringify(value)}</div>;
71
+ * }
72
+ * ```
73
+ *
74
+ * @example
75
+ *
76
+ * ```tsx
77
+ * // 与 onChange 回调结合
78
+ * function Input({
79
+ * value,
80
+ * defaultValue = '',
81
+ * onChange
82
+ * }: {
83
+ * value?: string;
84
+ * defaultValue?: string;
85
+ * onChange?: (val: string) => void;
86
+ * }) {
87
+ * const [internalValue, setInternalValue] = useControlledState(
88
+ * value,
89
+ * defaultValue
90
+ * );
91
+ *
92
+ * const handleChange = (newValue: string) => {
93
+ * setInternalValue(newValue);
94
+ * onChange?.(newValue);
95
+ * };
96
+ *
97
+ * return (
98
+ * <input
99
+ * value={internalValue}
100
+ * onChange={(e) => handleChange(e.target.value)}
101
+ * />
102
+ * );
103
+ * }
104
+ * ```
105
+ */
106
+ function useControlledState(propValue, defaultValue, deepCompare = false) {
107
+ // 初始化内部状态
108
+ // 如果 propValue 不是 undefined,使用 propValue;否则使用 defaultValue
109
+ const [internalValue, setInternalValue] = _react.default.useState(propValue !== undefined ? propValue : defaultValue);
110
+ const isControlled = propValue !== undefined;
111
+
112
+ // 在受控模式下同步 propValue 到 internalValue
113
+ _react.default.useEffect(() => {
114
+ if (isControlled) {
115
+ if (deepCompare) {
116
+ // 深度比较模式:只有值真正变化时才更新
117
+ setInternalValue(prev => (0, _lodash.isEqual)(prev, propValue) ? prev : propValue);
118
+ } else {
119
+ // 浅比较模式:直接更新(React 会自动优化相同值)
120
+ setInternalValue(propValue);
121
+ }
122
+ }
123
+ // 注意:当 propValue 变为 undefined 时,不更新 internalValue
124
+ // 这样可以保持最后一次的值,实现从受控切换到非受控的平滑过渡
125
+ }, [isControlled, propValue, deepCompare]);
126
+
127
+ // 计算最终返回的值
128
+ let value;
129
+ if (isControlled) {
130
+ if (deepCompare) {
131
+ // 深度比较模式:如果内容相同,返回 internalValue 保持引用稳定
132
+ // 否则返回 propValue
133
+ value = (0, _lodash.isEqual)(internalValue, propValue) ? internalValue : propValue;
134
+ } else {
135
+ // 浅比较模式:直接返回 propValue,确保受控模式下值始终同步
136
+ value = propValue;
137
+ }
138
+ } else {
139
+ // 非受控模式:返回 internalValue
140
+ value = internalValue;
141
+ }
142
+ return [value, setInternalValue];
143
+ }
144
+ //# sourceMappingURL=useControlledState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useControlledState.js","names":["_react","_interopRequireDefault","require","_lodash","useControlledState","propValue","defaultValue","deepCompare","internalValue","setInternalValue","React","useState","undefined","isControlled","useEffect","prev","isEqual","value"],"sources":["../../src/useControlledState.ts"],"sourcesContent":["import React from \"react\";\nimport { isEqual } from \"lodash\";\n\n/**\n * 受控/非受控混合模式的通用 Hook。\n *\n * 此 hook 允许组件既支持受控模式(由父组件通过 props 控制状态),\n * 也支持非受控模式(组件自己管理内部状态)。\n *\n * **工作原理:**\n * - 当 `propValue !== undefined` 时,组件处于**受控模式**,状态跟随 prop 更新\n * - 当 `propValue === undefined` 时,组件处于**非受控模式**,使用内部状态\n * - 支持深度比较选项,避免复杂对象引用变化导致的不必要更新\n *\n * **使用场景:**\n * 1. 表单组件需要支持受控和非受控两种模式\n * 2. 组件状态可能由父组件控制,也可能自己管理\n * 3. 复杂对象状态需要避免不必要的重新渲染\n *\n * @template T - 状态值的类型\n * @param propValue - 来自 props 的值(undefined 表示非受控模式)\n * @param defaultValue - 默认值(props 为 undefined 时使用)\n * @param deepCompare - 是否使用深度比较(用于复杂对象,默认 false)\n * @returns 返回 [当前值, 设置值的函数],类似 useState\n *\n * @example\n *\n * ```tsx\n * // 简单值(字符串、数字)\n * function MyComponent({ deployed }: { deployed?: string }) {\n * const [value, setValue] = useControlledState(deployed, 'host');\n *\n * return (\n * <select value={value} onChange={(e) => setValue(e.target.value)}>\n * <option value=\"host\">Host</option>\n * <option value=\"container\">Container</option>\n * </select>\n * );\n * }\n *\n * // 使用方式 1:受控模式\n * <MyComponent deployed=\"container\" />\n *\n * // 使用方式 2:非受控模式\n * <MyComponent />\n * ```\n *\n * @example\n *\n * ```tsx\n * // 复杂对象(启用深度比较)\n * interface Config {\n * host: string;\n * port: number;\n * }\n *\n * function ConfigEditor({ config }: { config?: Config }) {\n * const [value, setValue] = useControlledState<Config | null>(\n * config,\n * null,\n * true // 启用深度比较\n * );\n *\n * return <div>{JSON.stringify(value)}</div>;\n * }\n * ```\n *\n * @example\n *\n * ```tsx\n * // 与 onChange 回调结合\n * function Input({\n * value,\n * defaultValue = '',\n * onChange\n * }: {\n * value?: string;\n * defaultValue?: string;\n * onChange?: (val: string) => void;\n * }) {\n * const [internalValue, setInternalValue] = useControlledState(\n * value,\n * defaultValue\n * );\n *\n * const handleChange = (newValue: string) => {\n * setInternalValue(newValue);\n * onChange?.(newValue);\n * };\n *\n * return (\n * <input\n * value={internalValue}\n * onChange={(e) => handleChange(e.target.value)}\n * />\n * );\n * }\n * ```\n */\nexport function useControlledState<T>(\n propValue: T | undefined,\n defaultValue: T,\n deepCompare = false\n): [T, React.Dispatch<React.SetStateAction<T>>] {\n // 初始化内部状态\n // 如果 propValue 不是 undefined,使用 propValue;否则使用 defaultValue\n const [internalValue, setInternalValue] = React.useState<T>(\n propValue !== undefined ? propValue : defaultValue\n );\n\n const isControlled = propValue !== undefined;\n\n // 在受控模式下同步 propValue 到 internalValue\n React.useEffect(() => {\n if (isControlled) {\n if (deepCompare) {\n // 深度比较模式:只有值真正变化时才更新\n setInternalValue((prev) =>\n isEqual(prev, propValue) ? prev : propValue\n );\n } else {\n // 浅比较模式:直接更新(React 会自动优化相同值)\n setInternalValue(propValue);\n }\n }\n // 注意:当 propValue 变为 undefined 时,不更新 internalValue\n // 这样可以保持最后一次的值,实现从受控切换到非受控的平滑过渡\n }, [isControlled, propValue, deepCompare]);\n\n // 计算最终返回的值\n let value: T;\n if (isControlled) {\n if (deepCompare) {\n // 深度比较模式:如果内容相同,返回 internalValue 保持引用稳定\n // 否则返回 propValue\n value = isEqual(internalValue, propValue) ? internalValue : propValue;\n } else {\n // 浅比较模式:直接返回 propValue,确保受控模式下值始终同步\n value = propValue;\n }\n } else {\n // 非受控模式:返回 internalValue\n value = internalValue;\n }\n\n return [value, setInternalValue];\n}\n"],"mappings":";;;;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASE,kBAAkBA,CAChCC,SAAwB,EACxBC,YAAe,EACfC,WAAW,GAAG,KAAK,EAC2B;EAC9C;EACA;EACA,MAAM,CAACC,aAAa,EAAEC,gBAAgB,CAAC,GAAGC,cAAK,CAACC,QAAQ,CACtDN,SAAS,KAAKO,SAAS,GAAGP,SAAS,GAAGC,YACxC,CAAC;EAED,MAAMO,YAAY,GAAGR,SAAS,KAAKO,SAAS;;EAE5C;EACAF,cAAK,CAACI,SAAS,CAAC,MAAM;IACpB,IAAID,YAAY,EAAE;MAChB,IAAIN,WAAW,EAAE;QACf;QACAE,gBAAgB,CAAEM,IAAI,IACpB,IAAAC,eAAO,EAACD,IAAI,EAAEV,SAAS,CAAC,GAAGU,IAAI,GAAGV,SACpC,CAAC;MACH,CAAC,MAAM;QACL;QACAI,gBAAgB,CAACJ,SAAS,CAAC;MAC7B;IACF;IACA;IACA;EACF,CAAC,EAAE,CAACQ,YAAY,EAAER,SAAS,EAAEE,WAAW,CAAC,CAAC;;EAE1C;EACA,IAAIU,KAAQ;EACZ,IAAIJ,YAAY,EAAE;IAChB,IAAIN,WAAW,EAAE;MACf;MACA;MACAU,KAAK,GAAG,IAAAD,eAAO,EAACR,aAAa,EAAEH,SAAS,CAAC,GAAGG,aAAa,GAAGH,SAAS;IACvE,CAAC,MAAM;MACL;MACAY,KAAK,GAAGZ,SAAS;IACnB;EACF,CAAC,MAAM;IACL;IACAY,KAAK,GAAGT,aAAa;EACvB;EAEA,OAAO,CAACS,KAAK,EAAER,gBAAgB,CAAC;AAClC","ignoreList":[]}
package/dist/esm/index.js CHANGED
@@ -15,4 +15,6 @@ export * from "./useAuth.js";
15
15
  export * from "./useLocation.js";
16
16
  export * from "./useFeatureFlags.js";
17
17
  export * from "./useSystemInfo.js";
18
+ export * from "./useCheckPermissions.js";
19
+ export * from "./useControlledState.js";
18
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/index.ts"],"sourcesContent":["export * from \"./ReactUseBrick.js\";\nexport * from \"./useCurrentTheme.js\";\nexport * from \"./useCurrentApp.js\";\nexport * from \"./useRecentApps.js\";\nexport * from \"./useRouteRender.js\";\nexport * from \"./useProvider/useProvider.js\";\nexport * from \"./asyncWrapBrick.js\";\nexport * from \"./useNavConfig.js\";\nexport * from \"./useLazyWrapBrick.js\";\nexport * from \"./usePathParams.js\";\nexport * from \"./useSearchParams.js\";\nexport * from \"./useParams.js\";\nexport * from \"./useHistory.js\";\nexport * from \"./useAuth.js\";\nexport * from \"./useLocation.js\";\nexport * from \"./useFeatureFlags.js\";\nexport * from \"./useSystemInfo.js\";\n"],"mappings":"AAAA,cAAc,oBAAoB;AAClC,cAAc,sBAAsB;AACpC,cAAc,oBAAoB;AAClC,cAAc,oBAAoB;AAClC,cAAc,qBAAqB;AACnC,cAAc,8BAA8B;AAC5C,cAAc,qBAAqB;AACnC,cAAc,mBAAmB;AACjC,cAAc,uBAAuB;AACrC,cAAc,oBAAoB;AAClC,cAAc,sBAAsB;AACpC,cAAc,gBAAgB;AAC9B,cAAc,iBAAiB;AAC/B,cAAc,cAAc;AAC5B,cAAc,kBAAkB;AAChC,cAAc,sBAAsB;AACpC,cAAc,oBAAoB","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/index.ts"],"sourcesContent":["export * from \"./ReactUseBrick.js\";\nexport * from \"./useCurrentTheme.js\";\nexport * from \"./useCurrentApp.js\";\nexport * from \"./useRecentApps.js\";\nexport * from \"./useRouteRender.js\";\nexport * from \"./useProvider/useProvider.js\";\nexport * from \"./asyncWrapBrick.js\";\nexport * from \"./useNavConfig.js\";\nexport * from \"./useLazyWrapBrick.js\";\nexport * from \"./usePathParams.js\";\nexport * from \"./useSearchParams.js\";\nexport * from \"./useParams.js\";\nexport * from \"./useHistory.js\";\nexport * from \"./useAuth.js\";\nexport * from \"./useLocation.js\";\nexport * from \"./useFeatureFlags.js\";\nexport * from \"./useSystemInfo.js\";\nexport * from \"./useCheckPermissions.js\";\nexport * from \"./useControlledState.js\";\n"],"mappings":"AAAA,cAAc,oBAAoB;AAClC,cAAc,sBAAsB;AACpC,cAAc,oBAAoB;AAClC,cAAc,oBAAoB;AAClC,cAAc,qBAAqB;AACnC,cAAc,8BAA8B;AAC5C,cAAc,qBAAqB;AACnC,cAAc,mBAAmB;AACjC,cAAc,uBAAuB;AACrC,cAAc,oBAAoB;AAClC,cAAc,sBAAsB;AACpC,cAAc,gBAAgB;AAC9B,cAAc,iBAAiB;AAC/B,cAAc,cAAc;AAC5B,cAAc,kBAAkB;AAChC,cAAc,sBAAsB;AACpC,cAAc,oBAAoB;AAClC,cAAc,0BAA0B;AACxC,cAAc,yBAAyB","ignoreList":[]}
@@ -0,0 +1,83 @@
1
+ import React from "react";
2
+ import { checkPermissions } from "@next-core/easyops-runtime";
3
+
4
+ /**
5
+ * 检查用户权限的 React hooks。
6
+ *
7
+ * 此 hook 用于检查当前登录用户是否拥有指定的权限操作。
8
+ * 权限必须在 storyboard 配置的 `permissionsPreCheck` 中预先声明,
9
+ * 否则会返回 false 并在控制台输出错误。
10
+ *
11
+ * **工作原理:**
12
+ * - 权限会在路由渲染时自动预检查(通过 `preCheckPermissions`)
13
+ * - 此 hook 查询已缓存的权限结果(同步操作)
14
+ * - 管理员用户始终返回 true
15
+ * - 未登录用户始终返回 false
16
+ *
17
+ * **注意事项:**
18
+ * 1. 权限必须在 `permissionsPreCheck` 中声明
19
+ * 2. 所有传入的 actions 都必须有权限才返回 true
20
+ * 3. 权限检查结果会被缓存,避免重复计算
21
+ *
22
+ * @param actions - 需要检查的权限操作列表
23
+ * @returns 是否拥有所有指定的权限
24
+ *
25
+ * @example
26
+ *
27
+ * ```tsx
28
+ * // 检查单个权限
29
+ * function DeleteButton() {
30
+ * const canDelete = useCheckPermissions("my-app:user.delete");
31
+ *
32
+ * if (!canDelete) {
33
+ * return null;
34
+ * }
35
+ *
36
+ * return <button onClick={handleDelete}>Delete</button>;
37
+ * }
38
+ * ```
39
+ *
40
+ * @example
41
+ *
42
+ * ```tsx
43
+ * // 检查多个权限(需要全部拥有)
44
+ * function AdminPanel() {
45
+ * const hasAccess = useCheckPermissions(
46
+ * "my-app:admin.read",
47
+ * "my-app:admin.write"
48
+ * );
49
+ *
50
+ * if (!hasAccess) {
51
+ * return <div>Access Denied</div>;
52
+ * }
53
+ *
54
+ * return <div>Admin Panel Content</div>;
55
+ * }
56
+ * ```
57
+ *
58
+ * @example
59
+ *
60
+ * ```tsx
61
+ * // 在 storyboard 中配置权限预检查
62
+ * // routes.yaml
63
+ * routes:
64
+ * - path: /users
65
+ * permissionsPreCheck:
66
+ * - "my-app:user.read"
67
+ * - "my-app:user.delete"
68
+ * bricks:
69
+ * - brick: "my-brick"
70
+ * ```
71
+ */
72
+ export function useCheckPermissions() {
73
+ for (var _len = arguments.length, actions = new Array(_len), _key = 0; _key < _len; _key++) {
74
+ actions[_key] = arguments[_key];
75
+ }
76
+ // 使用 useMemo 缓存权限检查结果
77
+ // 因为权限在会话期间是稳定的,只依赖于 actions 列表
78
+ return React.useMemo(() => checkPermissions.checkPermissions(...actions),
79
+ // 序列化 actions 作为依赖,避免数组引用变化导致重新计算
80
+ // eslint-disable-next-line react-hooks/exhaustive-deps
81
+ [JSON.stringify(actions)]);
82
+ }
83
+ //# sourceMappingURL=useCheckPermissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCheckPermissions.js","names":["React","checkPermissions","useCheckPermissions","_len","arguments","length","actions","Array","_key","useMemo","JSON","stringify"],"sources":["../../src/useCheckPermissions.ts"],"sourcesContent":["import React from \"react\";\nimport { checkPermissions } from \"@next-core/easyops-runtime\";\n\n/**\n * 检查用户权限的 React hooks。\n *\n * 此 hook 用于检查当前登录用户是否拥有指定的权限操作。\n * 权限必须在 storyboard 配置的 `permissionsPreCheck` 中预先声明,\n * 否则会返回 false 并在控制台输出错误。\n *\n * **工作原理:**\n * - 权限会在路由渲染时自动预检查(通过 `preCheckPermissions`)\n * - 此 hook 查询已缓存的权限结果(同步操作)\n * - 管理员用户始终返回 true\n * - 未登录用户始终返回 false\n *\n * **注意事项:**\n * 1. 权限必须在 `permissionsPreCheck` 中声明\n * 2. 所有传入的 actions 都必须有权限才返回 true\n * 3. 权限检查结果会被缓存,避免重复计算\n *\n * @param actions - 需要检查的权限操作列表\n * @returns 是否拥有所有指定的权限\n *\n * @example\n *\n * ```tsx\n * // 检查单个权限\n * function DeleteButton() {\n * const canDelete = useCheckPermissions(\"my-app:user.delete\");\n *\n * if (!canDelete) {\n * return null;\n * }\n *\n * return <button onClick={handleDelete}>Delete</button>;\n * }\n * ```\n *\n * @example\n *\n * ```tsx\n * // 检查多个权限(需要全部拥有)\n * function AdminPanel() {\n * const hasAccess = useCheckPermissions(\n * \"my-app:admin.read\",\n * \"my-app:admin.write\"\n * );\n *\n * if (!hasAccess) {\n * return <div>Access Denied</div>;\n * }\n *\n * return <div>Admin Panel Content</div>;\n * }\n * ```\n *\n * @example\n *\n * ```tsx\n * // 在 storyboard 中配置权限预检查\n * // routes.yaml\n * routes:\n * - path: /users\n * permissionsPreCheck:\n * - \"my-app:user.read\"\n * - \"my-app:user.delete\"\n * bricks:\n * - brick: \"my-brick\"\n * ```\n */\nexport function useCheckPermissions(...actions: string[]): boolean {\n // 使用 useMemo 缓存权限检查结果\n // 因为权限在会话期间是稳定的,只依赖于 actions 列表\n return React.useMemo(\n () => checkPermissions.checkPermissions(...actions),\n // 序列化 actions 作为依赖,避免数组引用变化导致重新计算\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(actions)]\n );\n}\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,gBAAgB,QAAQ,4BAA4B;;AAE7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,mBAAmBA,CAAA,EAAgC;EAAA,SAAAC,IAAA,GAAAC,SAAA,CAAAC,MAAA,EAA5BC,OAAO,OAAAC,KAAA,CAAAJ,IAAA,GAAAK,IAAA,MAAAA,IAAA,GAAAL,IAAA,EAAAK,IAAA;IAAPF,OAAO,CAAAE,IAAA,IAAAJ,SAAA,CAAAI,IAAA;EAAA;EAC5C;EACA;EACA,OAAOR,KAAK,CAACS,OAAO,CAClB,MAAMR,gBAAgB,CAACA,gBAAgB,CAAC,GAAGK,OAAO,CAAC;EACnD;EACA;EACA,CAACI,IAAI,CAACC,SAAS,CAACL,OAAO,CAAC,CAC1B,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,139 @@
1
+ import React from "react";
2
+ import { isEqual } from "lodash";
3
+
4
+ /**
5
+ * 受控/非受控混合模式的通用 Hook。
6
+ *
7
+ * 此 hook 允许组件既支持受控模式(由父组件通过 props 控制状态),
8
+ * 也支持非受控模式(组件自己管理内部状态)。
9
+ *
10
+ * **工作原理:**
11
+ * - 当 `propValue !== undefined` 时,组件处于**受控模式**,状态跟随 prop 更新
12
+ * - 当 `propValue === undefined` 时,组件处于**非受控模式**,使用内部状态
13
+ * - 支持深度比较选项,避免复杂对象引用变化导致的不必要更新
14
+ *
15
+ * **使用场景:**
16
+ * 1. 表单组件需要支持受控和非受控两种模式
17
+ * 2. 组件状态可能由父组件控制,也可能自己管理
18
+ * 3. 复杂对象状态需要避免不必要的重新渲染
19
+ *
20
+ * @template T - 状态值的类型
21
+ * @param propValue - 来自 props 的值(undefined 表示非受控模式)
22
+ * @param defaultValue - 默认值(props 为 undefined 时使用)
23
+ * @param deepCompare - 是否使用深度比较(用于复杂对象,默认 false)
24
+ * @returns 返回 [当前值, 设置值的函数],类似 useState
25
+ *
26
+ * @example
27
+ *
28
+ * ```tsx
29
+ * // 简单值(字符串、数字)
30
+ * function MyComponent({ deployed }: { deployed?: string }) {
31
+ * const [value, setValue] = useControlledState(deployed, 'host');
32
+ *
33
+ * return (
34
+ * <select value={value} onChange={(e) => setValue(e.target.value)}>
35
+ * <option value="host">Host</option>
36
+ * <option value="container">Container</option>
37
+ * </select>
38
+ * );
39
+ * }
40
+ *
41
+ * // 使用方式 1:受控模式
42
+ * <MyComponent deployed="container" />
43
+ *
44
+ * // 使用方式 2:非受控模式
45
+ * <MyComponent />
46
+ * ```
47
+ *
48
+ * @example
49
+ *
50
+ * ```tsx
51
+ * // 复杂对象(启用深度比较)
52
+ * interface Config {
53
+ * host: string;
54
+ * port: number;
55
+ * }
56
+ *
57
+ * function ConfigEditor({ config }: { config?: Config }) {
58
+ * const [value, setValue] = useControlledState<Config | null>(
59
+ * config,
60
+ * null,
61
+ * true // 启用深度比较
62
+ * );
63
+ *
64
+ * return <div>{JSON.stringify(value)}</div>;
65
+ * }
66
+ * ```
67
+ *
68
+ * @example
69
+ *
70
+ * ```tsx
71
+ * // 与 onChange 回调结合
72
+ * function Input({
73
+ * value,
74
+ * defaultValue = '',
75
+ * onChange
76
+ * }: {
77
+ * value?: string;
78
+ * defaultValue?: string;
79
+ * onChange?: (val: string) => void;
80
+ * }) {
81
+ * const [internalValue, setInternalValue] = useControlledState(
82
+ * value,
83
+ * defaultValue
84
+ * );
85
+ *
86
+ * const handleChange = (newValue: string) => {
87
+ * setInternalValue(newValue);
88
+ * onChange?.(newValue);
89
+ * };
90
+ *
91
+ * return (
92
+ * <input
93
+ * value={internalValue}
94
+ * onChange={(e) => handleChange(e.target.value)}
95
+ * />
96
+ * );
97
+ * }
98
+ * ```
99
+ */
100
+ export function useControlledState(propValue, defaultValue) {
101
+ let deepCompare = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
102
+ // 初始化内部状态
103
+ // 如果 propValue 不是 undefined,使用 propValue;否则使用 defaultValue
104
+ const [internalValue, setInternalValue] = React.useState(propValue !== undefined ? propValue : defaultValue);
105
+ const isControlled = propValue !== undefined;
106
+
107
+ // 在受控模式下同步 propValue 到 internalValue
108
+ React.useEffect(() => {
109
+ if (isControlled) {
110
+ if (deepCompare) {
111
+ // 深度比较模式:只有值真正变化时才更新
112
+ setInternalValue(prev => isEqual(prev, propValue) ? prev : propValue);
113
+ } else {
114
+ // 浅比较模式:直接更新(React 会自动优化相同值)
115
+ setInternalValue(propValue);
116
+ }
117
+ }
118
+ // 注意:当 propValue 变为 undefined 时,不更新 internalValue
119
+ // 这样可以保持最后一次的值,实现从受控切换到非受控的平滑过渡
120
+ }, [isControlled, propValue, deepCompare]);
121
+
122
+ // 计算最终返回的值
123
+ let value;
124
+ if (isControlled) {
125
+ if (deepCompare) {
126
+ // 深度比较模式:如果内容相同,返回 internalValue 保持引用稳定
127
+ // 否则返回 propValue
128
+ value = isEqual(internalValue, propValue) ? internalValue : propValue;
129
+ } else {
130
+ // 浅比较模式:直接返回 propValue,确保受控模式下值始终同步
131
+ value = propValue;
132
+ }
133
+ } else {
134
+ // 非受控模式:返回 internalValue
135
+ value = internalValue;
136
+ }
137
+ return [value, setInternalValue];
138
+ }
139
+ //# sourceMappingURL=useControlledState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useControlledState.js","names":["React","isEqual","useControlledState","propValue","defaultValue","deepCompare","arguments","length","undefined","internalValue","setInternalValue","useState","isControlled","useEffect","prev","value"],"sources":["../../src/useControlledState.ts"],"sourcesContent":["import React from \"react\";\nimport { isEqual } from \"lodash\";\n\n/**\n * 受控/非受控混合模式的通用 Hook。\n *\n * 此 hook 允许组件既支持受控模式(由父组件通过 props 控制状态),\n * 也支持非受控模式(组件自己管理内部状态)。\n *\n * **工作原理:**\n * - 当 `propValue !== undefined` 时,组件处于**受控模式**,状态跟随 prop 更新\n * - 当 `propValue === undefined` 时,组件处于**非受控模式**,使用内部状态\n * - 支持深度比较选项,避免复杂对象引用变化导致的不必要更新\n *\n * **使用场景:**\n * 1. 表单组件需要支持受控和非受控两种模式\n * 2. 组件状态可能由父组件控制,也可能自己管理\n * 3. 复杂对象状态需要避免不必要的重新渲染\n *\n * @template T - 状态值的类型\n * @param propValue - 来自 props 的值(undefined 表示非受控模式)\n * @param defaultValue - 默认值(props 为 undefined 时使用)\n * @param deepCompare - 是否使用深度比较(用于复杂对象,默认 false)\n * @returns 返回 [当前值, 设置值的函数],类似 useState\n *\n * @example\n *\n * ```tsx\n * // 简单值(字符串、数字)\n * function MyComponent({ deployed }: { deployed?: string }) {\n * const [value, setValue] = useControlledState(deployed, 'host');\n *\n * return (\n * <select value={value} onChange={(e) => setValue(e.target.value)}>\n * <option value=\"host\">Host</option>\n * <option value=\"container\">Container</option>\n * </select>\n * );\n * }\n *\n * // 使用方式 1:受控模式\n * <MyComponent deployed=\"container\" />\n *\n * // 使用方式 2:非受控模式\n * <MyComponent />\n * ```\n *\n * @example\n *\n * ```tsx\n * // 复杂对象(启用深度比较)\n * interface Config {\n * host: string;\n * port: number;\n * }\n *\n * function ConfigEditor({ config }: { config?: Config }) {\n * const [value, setValue] = useControlledState<Config | null>(\n * config,\n * null,\n * true // 启用深度比较\n * );\n *\n * return <div>{JSON.stringify(value)}</div>;\n * }\n * ```\n *\n * @example\n *\n * ```tsx\n * // 与 onChange 回调结合\n * function Input({\n * value,\n * defaultValue = '',\n * onChange\n * }: {\n * value?: string;\n * defaultValue?: string;\n * onChange?: (val: string) => void;\n * }) {\n * const [internalValue, setInternalValue] = useControlledState(\n * value,\n * defaultValue\n * );\n *\n * const handleChange = (newValue: string) => {\n * setInternalValue(newValue);\n * onChange?.(newValue);\n * };\n *\n * return (\n * <input\n * value={internalValue}\n * onChange={(e) => handleChange(e.target.value)}\n * />\n * );\n * }\n * ```\n */\nexport function useControlledState<T>(\n propValue: T | undefined,\n defaultValue: T,\n deepCompare = false\n): [T, React.Dispatch<React.SetStateAction<T>>] {\n // 初始化内部状态\n // 如果 propValue 不是 undefined,使用 propValue;否则使用 defaultValue\n const [internalValue, setInternalValue] = React.useState<T>(\n propValue !== undefined ? propValue : defaultValue\n );\n\n const isControlled = propValue !== undefined;\n\n // 在受控模式下同步 propValue 到 internalValue\n React.useEffect(() => {\n if (isControlled) {\n if (deepCompare) {\n // 深度比较模式:只有值真正变化时才更新\n setInternalValue((prev) =>\n isEqual(prev, propValue) ? prev : propValue\n );\n } else {\n // 浅比较模式:直接更新(React 会自动优化相同值)\n setInternalValue(propValue);\n }\n }\n // 注意:当 propValue 变为 undefined 时,不更新 internalValue\n // 这样可以保持最后一次的值,实现从受控切换到非受控的平滑过渡\n }, [isControlled, propValue, deepCompare]);\n\n // 计算最终返回的值\n let value: T;\n if (isControlled) {\n if (deepCompare) {\n // 深度比较模式:如果内容相同,返回 internalValue 保持引用稳定\n // 否则返回 propValue\n value = isEqual(internalValue, propValue) ? internalValue : propValue;\n } else {\n // 浅比较模式:直接返回 propValue,确保受控模式下值始终同步\n value = propValue;\n }\n } else {\n // 非受控模式:返回 internalValue\n value = internalValue;\n }\n\n return [value, setInternalValue];\n}\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,OAAO,QAAQ,QAAQ;;AAEhC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,kBAAkBA,CAChCC,SAAwB,EACxBC,YAAe,EAE+B;EAAA,IAD9CC,WAAW,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,KAAK;EAEnB;EACA;EACA,MAAM,CAACG,aAAa,EAAEC,gBAAgB,CAAC,GAAGV,KAAK,CAACW,QAAQ,CACtDR,SAAS,KAAKK,SAAS,GAAGL,SAAS,GAAGC,YACxC,CAAC;EAED,MAAMQ,YAAY,GAAGT,SAAS,KAAKK,SAAS;;EAE5C;EACAR,KAAK,CAACa,SAAS,CAAC,MAAM;IACpB,IAAID,YAAY,EAAE;MAChB,IAAIP,WAAW,EAAE;QACf;QACAK,gBAAgB,CAAEI,IAAI,IACpBb,OAAO,CAACa,IAAI,EAAEX,SAAS,CAAC,GAAGW,IAAI,GAAGX,SACpC,CAAC;MACH,CAAC,MAAM;QACL;QACAO,gBAAgB,CAACP,SAAS,CAAC;MAC7B;IACF;IACA;IACA;EACF,CAAC,EAAE,CAACS,YAAY,EAAET,SAAS,EAAEE,WAAW,CAAC,CAAC;;EAE1C;EACA,IAAIU,KAAQ;EACZ,IAAIH,YAAY,EAAE;IAChB,IAAIP,WAAW,EAAE;MACf;MACA;MACAU,KAAK,GAAGd,OAAO,CAACQ,aAAa,EAAEN,SAAS,CAAC,GAAGM,aAAa,GAAGN,SAAS;IACvE,CAAC,MAAM;MACL;MACAY,KAAK,GAAGZ,SAAS;IACnB;EACF,CAAC,MAAM;IACL;IACAY,KAAK,GAAGN,aAAa;EACvB;EAEA,OAAO,CAACM,KAAK,EAAEL,gBAAgB,CAAC;AAClC","ignoreList":[]}
@@ -15,3 +15,5 @@ export * from "./useAuth.js";
15
15
  export * from "./useLocation.js";
16
16
  export * from "./useFeatureFlags.js";
17
17
  export * from "./useSystemInfo.js";
18
+ export * from "./useCheckPermissions.js";
19
+ export * from "./useControlledState.js";
@@ -0,0 +1,69 @@
1
+ /**
2
+ * 检查用户权限的 React hooks。
3
+ *
4
+ * 此 hook 用于检查当前登录用户是否拥有指定的权限操作。
5
+ * 权限必须在 storyboard 配置的 `permissionsPreCheck` 中预先声明,
6
+ * 否则会返回 false 并在控制台输出错误。
7
+ *
8
+ * **工作原理:**
9
+ * - 权限会在路由渲染时自动预检查(通过 `preCheckPermissions`)
10
+ * - 此 hook 查询已缓存的权限结果(同步操作)
11
+ * - 管理员用户始终返回 true
12
+ * - 未登录用户始终返回 false
13
+ *
14
+ * **注意事项:**
15
+ * 1. 权限必须在 `permissionsPreCheck` 中声明
16
+ * 2. 所有传入的 actions 都必须有权限才返回 true
17
+ * 3. 权限检查结果会被缓存,避免重复计算
18
+ *
19
+ * @param actions - 需要检查的权限操作列表
20
+ * @returns 是否拥有所有指定的权限
21
+ *
22
+ * @example
23
+ *
24
+ * ```tsx
25
+ * // 检查单个权限
26
+ * function DeleteButton() {
27
+ * const canDelete = useCheckPermissions("my-app:user.delete");
28
+ *
29
+ * if (!canDelete) {
30
+ * return null;
31
+ * }
32
+ *
33
+ * return <button onClick={handleDelete}>Delete</button>;
34
+ * }
35
+ * ```
36
+ *
37
+ * @example
38
+ *
39
+ * ```tsx
40
+ * // 检查多个权限(需要全部拥有)
41
+ * function AdminPanel() {
42
+ * const hasAccess = useCheckPermissions(
43
+ * "my-app:admin.read",
44
+ * "my-app:admin.write"
45
+ * );
46
+ *
47
+ * if (!hasAccess) {
48
+ * return <div>Access Denied</div>;
49
+ * }
50
+ *
51
+ * return <div>Admin Panel Content</div>;
52
+ * }
53
+ * ```
54
+ *
55
+ * @example
56
+ *
57
+ * ```tsx
58
+ * // 在 storyboard 中配置权限预检查
59
+ * // routes.yaml
60
+ * routes:
61
+ * - path: /users
62
+ * permissionsPreCheck:
63
+ * - "my-app:user.read"
64
+ * - "my-app:user.delete"
65
+ * bricks:
66
+ * - brick: "my-brick"
67
+ * ```
68
+ */
69
+ export declare function useCheckPermissions(...actions: string[]): boolean;
@@ -0,0 +1,98 @@
1
+ import React from "react";
2
+ /**
3
+ * 受控/非受控混合模式的通用 Hook。
4
+ *
5
+ * 此 hook 允许组件既支持受控模式(由父组件通过 props 控制状态),
6
+ * 也支持非受控模式(组件自己管理内部状态)。
7
+ *
8
+ * **工作原理:**
9
+ * - 当 `propValue !== undefined` 时,组件处于**受控模式**,状态跟随 prop 更新
10
+ * - 当 `propValue === undefined` 时,组件处于**非受控模式**,使用内部状态
11
+ * - 支持深度比较选项,避免复杂对象引用变化导致的不必要更新
12
+ *
13
+ * **使用场景:**
14
+ * 1. 表单组件需要支持受控和非受控两种模式
15
+ * 2. 组件状态可能由父组件控制,也可能自己管理
16
+ * 3. 复杂对象状态需要避免不必要的重新渲染
17
+ *
18
+ * @template T - 状态值的类型
19
+ * @param propValue - 来自 props 的值(undefined 表示非受控模式)
20
+ * @param defaultValue - 默认值(props 为 undefined 时使用)
21
+ * @param deepCompare - 是否使用深度比较(用于复杂对象,默认 false)
22
+ * @returns 返回 [当前值, 设置值的函数],类似 useState
23
+ *
24
+ * @example
25
+ *
26
+ * ```tsx
27
+ * // 简单值(字符串、数字)
28
+ * function MyComponent({ deployed }: { deployed?: string }) {
29
+ * const [value, setValue] = useControlledState(deployed, 'host');
30
+ *
31
+ * return (
32
+ * <select value={value} onChange={(e) => setValue(e.target.value)}>
33
+ * <option value="host">Host</option>
34
+ * <option value="container">Container</option>
35
+ * </select>
36
+ * );
37
+ * }
38
+ *
39
+ * // 使用方式 1:受控模式
40
+ * <MyComponent deployed="container" />
41
+ *
42
+ * // 使用方式 2:非受控模式
43
+ * <MyComponent />
44
+ * ```
45
+ *
46
+ * @example
47
+ *
48
+ * ```tsx
49
+ * // 复杂对象(启用深度比较)
50
+ * interface Config {
51
+ * host: string;
52
+ * port: number;
53
+ * }
54
+ *
55
+ * function ConfigEditor({ config }: { config?: Config }) {
56
+ * const [value, setValue] = useControlledState<Config | null>(
57
+ * config,
58
+ * null,
59
+ * true // 启用深度比较
60
+ * );
61
+ *
62
+ * return <div>{JSON.stringify(value)}</div>;
63
+ * }
64
+ * ```
65
+ *
66
+ * @example
67
+ *
68
+ * ```tsx
69
+ * // 与 onChange 回调结合
70
+ * function Input({
71
+ * value,
72
+ * defaultValue = '',
73
+ * onChange
74
+ * }: {
75
+ * value?: string;
76
+ * defaultValue?: string;
77
+ * onChange?: (val: string) => void;
78
+ * }) {
79
+ * const [internalValue, setInternalValue] = useControlledState(
80
+ * value,
81
+ * defaultValue
82
+ * );
83
+ *
84
+ * const handleChange = (newValue: string) => {
85
+ * setInternalValue(newValue);
86
+ * onChange?.(newValue);
87
+ * };
88
+ *
89
+ * return (
90
+ * <input
91
+ * value={internalValue}
92
+ * onChange={(e) => handleChange(e.target.value)}
93
+ * />
94
+ * );
95
+ * }
96
+ * ```
97
+ */
98
+ export declare function useControlledState<T>(propValue: T | undefined, defaultValue: T, deepCompare?: boolean): [T, React.Dispatch<React.SetStateAction<T>>];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next-core/react-runtime",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "homepage": "https://github.com/easyops-cn/next-core/tree/v3/packages/react-runtime",
5
5
  "license": "GPL-3.0",
6
6
  "repository": {
@@ -49,5 +49,5 @@
49
49
  "@next-core/test-next": "^2.0.1",
50
50
  "jest-fetch-mock": "^3.0.3"
51
51
  },
52
- "gitHead": "381ef5fdaae5f5134bae63da98fee74186eddb56"
52
+ "gitHead": "8147d007b09c62b6f52349bc3d3daf98173a01f8"
53
53
  }