hd-attribute-set 0.1.0 → 0.1.3
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/hd-attribute-set.cjs +1 -0
- package/dist/hd-attribute-set.js +19 -33
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/use-memoized-fn.d.ts +9 -0
- package/dist/hooks/use-permission.d.ts +49 -0
- package/dist/hooks.cjs +1 -0
- package/dist/hooks.d.ts +2 -0
- package/dist/hooks.js +8 -0
- package/dist/index.d.ts +7 -1
- package/dist/use-permission-CbbVGG4p.cjs +1 -0
- package/dist/use-permission-DHvtS-2I.js +47 -0
- package/dist/utils/fn.d.ts +9 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/object.d.ts +13 -0
- package/dist/utils/validate.d.ts +8 -0
- package/dist/utils.cjs +1 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +68 -0
- package/package.json +89 -69
- package/readme.md +113 -0
- package/README.md +0 -62
- package/dist/components/attribute-set/index.d.ts +0 -7
- package/dist/components/attribute-set/types.d.ts +0 -27
- package/dist/hd-attribute-set.css +0 -1
- package/dist/hd-attribute-set.umd.cjs +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./utils.cjs"),i=require("./use-permission-CbbVGG4p.cjs"),s="0.1.3";exports.debounce=e.debounce;exports.deepClone=e.deepClone;exports.isEmail=e.isEmail;exports.isEmpty=e.isEmpty;exports.isIdCard=e.isIdCard;exports.isPhone=e.isPhone;exports.listToTree=e.listToTree;exports.sleep=e.sleep;exports.throttle=e.throttle;exports.uniqueBy=e.uniqueBy;exports.DEFAULT_PERMISSION_CONFIG=i.DEFAULT_PERMISSION_CONFIG;exports.normalizePermissionId=i.normalizePermissionId;exports.resolvePermissionConfig=i.resolvePermissionConfig;exports.useMemoizedFn=i.useMemoizedFn;exports.usePermission=i.usePermission;exports.version=s;
|
package/dist/hd-attribute-set.js
CHANGED
|
@@ -1,35 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
return !a || a.length === 0 ? /* @__PURE__ */ s("div", { className: "hd-attribute-set", children: [
|
|
5
|
-
t && /* @__PURE__ */ s(i, { children: [
|
|
6
|
-
/* @__PURE__ */ r("div", { className: "hd-attribute-set__title", children: t }),
|
|
7
|
-
/* @__PURE__ */ r(n, { style: { margin: "8px 0 16px" } })
|
|
8
|
-
] }),
|
|
9
|
-
/* @__PURE__ */ r(l, { image: l.PRESENTED_IMAGE_SIMPLE, description: p })
|
|
10
|
-
] }) : /* @__PURE__ */ s("div", { className: "hd-attribute-set", children: [
|
|
11
|
-
t && /* @__PURE__ */ s(i, { children: [
|
|
12
|
-
/* @__PURE__ */ r("div", { className: "hd-attribute-set__title", children: t }),
|
|
13
|
-
/* @__PURE__ */ r(n, { style: { margin: "8px 0 16px" } })
|
|
14
|
-
] }),
|
|
15
|
-
/* @__PURE__ */ r(
|
|
16
|
-
h,
|
|
17
|
-
{
|
|
18
|
-
size: "small",
|
|
19
|
-
column: d,
|
|
20
|
-
bordered: c,
|
|
21
|
-
items: a.map((e) => ({
|
|
22
|
-
key: e.key,
|
|
23
|
-
label: e.label,
|
|
24
|
-
children: e.render ? e.render(e.value) : e.value ?? "-",
|
|
25
|
-
span: e.span
|
|
26
|
-
}))
|
|
27
|
-
}
|
|
28
|
-
)
|
|
29
|
-
] });
|
|
30
|
-
}
|
|
31
|
-
const v = "0.1.0";
|
|
1
|
+
import { debounce as i, deepClone as r, isEmail as n, isEmpty as a, isIdCard as m, isPhone as t, listToTree as l, sleep as d, throttle as p, uniqueBy as u } from "./utils.js";
|
|
2
|
+
import { D as P, n as C, r as E, u as f, a as x } from "./use-permission-DHvtS-2I.js";
|
|
3
|
+
const e = "0.1.3";
|
|
32
4
|
export {
|
|
33
|
-
|
|
34
|
-
|
|
5
|
+
P as DEFAULT_PERMISSION_CONFIG,
|
|
6
|
+
i as debounce,
|
|
7
|
+
r as deepClone,
|
|
8
|
+
n as isEmail,
|
|
9
|
+
a as isEmpty,
|
|
10
|
+
m as isIdCard,
|
|
11
|
+
t as isPhone,
|
|
12
|
+
l as listToTree,
|
|
13
|
+
C as normalizePermissionId,
|
|
14
|
+
E as resolvePermissionConfig,
|
|
15
|
+
d as sleep,
|
|
16
|
+
p as throttle,
|
|
17
|
+
u as uniqueBy,
|
|
18
|
+
f as useMemoizedFn,
|
|
19
|
+
x as usePermission,
|
|
20
|
+
e as version
|
|
35
21
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 返回引用稳定的函数:外层引用永远不变,内部始终执行最新的实现。
|
|
3
|
+
* 用于替代 ahooks 的 useMemoizedFn,避免组件库引入额外运行时依赖。
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const handleClick = useMemoizedFn((id: string) => { ... });
|
|
7
|
+
*/
|
|
8
|
+
export declare function useMemoizedFn<T extends (...args: any[]) => any>(fn: T): T;
|
|
9
|
+
export default useMemoizedFn;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 权限判断 hook(与 redux / ahooks 解耦版)
|
|
3
|
+
* 权限配置由调用方通过参数传入,可以是 redux 中的 accessConfig,也可以是任意数据源。
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* // 直接传 redux 中的数据
|
|
7
|
+
* const accessConfig = useAppSelector(selectAccessConfig);
|
|
8
|
+
* const { shouldShowButton, isNoPermissionShow } = usePermission(accessConfig);
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // 传 getter:每次调用时取最新值,避免闭包拿到旧数据
|
|
12
|
+
* const { hasPermission } = usePermission(() => store.getState().auth.userInfo?.accessConfig);
|
|
13
|
+
*/
|
|
14
|
+
/** 权限配置(一般来自 redux 的 accessConfig) */
|
|
15
|
+
export interface PermissionConfig {
|
|
16
|
+
/** 无权限时是否在页面上展示(由消费方决定提示 / 禁用) */
|
|
17
|
+
noPermissionShow?: boolean;
|
|
18
|
+
/** 当前用户拥有的权限编号列表 */
|
|
19
|
+
list?: (number | string)[];
|
|
20
|
+
/** 是否拥有全部权限 */
|
|
21
|
+
selectAll?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** 权限配置来源:直接传对象,或传 getter(每次调用读取最新值,适配 redux / context 等外部数据源) */
|
|
24
|
+
export type PermissionConfigSource = PermissionConfig | (() => PermissionConfig | null | undefined);
|
|
25
|
+
export interface UsePermissionReturn {
|
|
26
|
+
/** 检查是否有权限 */
|
|
27
|
+
hasPermission: (permissionId?: number | string) => boolean;
|
|
28
|
+
/** 检查按钮是否应该显示 */
|
|
29
|
+
shouldShowButton: (permissionId?: number | string) => boolean;
|
|
30
|
+
/** 检查菜单是否应该显示 */
|
|
31
|
+
shouldShowMenu: (permissionId?: number | string) => {
|
|
32
|
+
noPermissionShow: boolean;
|
|
33
|
+
hasPerm: boolean;
|
|
34
|
+
};
|
|
35
|
+
/** 检查没权限时是否需要在页面上提示 / 禁用 */
|
|
36
|
+
isNoPermissionShow: (permissionId?: number | string) => boolean;
|
|
37
|
+
}
|
|
38
|
+
/** 没有权限配置时的兜底:视为拥有全部权限 */
|
|
39
|
+
export declare const DEFAULT_PERMISSION_CONFIG: PermissionConfig;
|
|
40
|
+
/**
|
|
41
|
+
* 权限编号归一化:平台权限编号是「定长分层编号」(导航 60000 → 二级菜单 62000 → 三级菜单 62100 → 按钮 62101),
|
|
42
|
+
* 而菜单配置里的三级菜单编号可能多补一位 0(如 621000),导致精确比较匹配不上、有权限的菜单显示不出来。
|
|
43
|
+
* 这里去掉编号末尾的补位 0(621000 与 62100 都归一化为 621)后再比较一次。
|
|
44
|
+
*/
|
|
45
|
+
export declare const normalizePermissionId: (permissionId: number | string) => string;
|
|
46
|
+
/** 解析权限配置(支持 getter,保证拿到外部数据源的最新值) */
|
|
47
|
+
export declare const resolvePermissionConfig: (source?: PermissionConfigSource) => PermissionConfig;
|
|
48
|
+
export declare function usePermission(source?: PermissionConfigSource): UsePermissionReturn;
|
|
49
|
+
export default usePermission;
|
package/dist/hooks.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./use-permission-CbbVGG4p.cjs");exports.DEFAULT_PERMISSION_CONFIG=e.DEFAULT_PERMISSION_CONFIG;exports.normalizePermissionId=e.normalizePermissionId;exports.resolvePermissionConfig=e.resolvePermissionConfig;exports.useMemoizedFn=e.useMemoizedFn;exports.usePermission=e.usePermission;
|
package/dist/hooks.d.ts
ADDED
package/dist/hooks.js
ADDED
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const f=require("react");function r(n){const e=f.useRef(n);e.current=n;const s=f.useRef(null);return s.current||(s.current=(...u)=>{var i;return(i=e.current)==null?void 0:i.call(e,...u)}),s.current}const P={noPermissionShow:!0,list:[],selectAll:!0},m=n=>String(n).replace(/0+$/,""),c=n=>(typeof n=="function"?n():n)||P;function g(n){const e=r(o=>{if(!o)return!0;const t=c(n);if(t.selectAll)return!0;const l=t.list||[];if(l.includes(Number(o)))return!0;const S=m(o);return l.some(h=>m(h)===S)}),s=r(o=>e(o)),u=r(o=>({noPermissionShow:!!c(n).noPermissionShow,hasPerm:e(o)})),i=r(o=>!!c(n).noPermissionShow&&!e(o));return{hasPermission:e,shouldShowButton:s,shouldShowMenu:u,isNoPermissionShow:i}}exports.DEFAULT_PERMISSION_CONFIG=P;exports.normalizePermissionId=m;exports.resolvePermissionConfig=c;exports.useMemoizedFn=r;exports.usePermission=g;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useRef as l } from "react";
|
|
2
|
+
function i(n) {
|
|
3
|
+
const o = l(n);
|
|
4
|
+
o.current = n;
|
|
5
|
+
const r = l(null);
|
|
6
|
+
return r.current || (r.current = (...c) => {
|
|
7
|
+
var s;
|
|
8
|
+
return (s = o.current) == null ? void 0 : s.call(o, ...c);
|
|
9
|
+
}), r.current;
|
|
10
|
+
}
|
|
11
|
+
const P = {
|
|
12
|
+
noPermissionShow: !0,
|
|
13
|
+
list: [],
|
|
14
|
+
selectAll: !0
|
|
15
|
+
}, f = (n) => String(n).replace(/0+$/, ""), u = (n) => (typeof n == "function" ? n() : n) || P;
|
|
16
|
+
function g(n) {
|
|
17
|
+
const o = i((e) => {
|
|
18
|
+
if (!e)
|
|
19
|
+
return !0;
|
|
20
|
+
const t = u(n);
|
|
21
|
+
if (t.selectAll)
|
|
22
|
+
return !0;
|
|
23
|
+
const m = t.list || [];
|
|
24
|
+
if (m.includes(Number(e)))
|
|
25
|
+
return !0;
|
|
26
|
+
const a = f(e);
|
|
27
|
+
return m.some((h) => f(h) === a);
|
|
28
|
+
}), r = i(
|
|
29
|
+
(e) => o(e)
|
|
30
|
+
), c = i((e) => ({
|
|
31
|
+
noPermissionShow: !!u(n).noPermissionShow,
|
|
32
|
+
hasPerm: o(e)
|
|
33
|
+
})), s = i((e) => !!u(n).noPermissionShow && !o(e));
|
|
34
|
+
return {
|
|
35
|
+
hasPermission: o,
|
|
36
|
+
shouldShowButton: r,
|
|
37
|
+
shouldShowMenu: c,
|
|
38
|
+
isNoPermissionShow: s
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
P as D,
|
|
43
|
+
g as a,
|
|
44
|
+
f as n,
|
|
45
|
+
u as r,
|
|
46
|
+
i as u
|
|
47
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** 防抖 */
|
|
2
|
+
export declare function debounce<T extends (...args: never[]) => void>(fn: T, wait?: number): {
|
|
3
|
+
(...args: Parameters<T>): void;
|
|
4
|
+
cancel(): void;
|
|
5
|
+
};
|
|
6
|
+
/** 节流 */
|
|
7
|
+
export declare function throttle<T extends (...args: never[]) => void>(fn: T, wait?: number): (...args: Parameters<T>) => void;
|
|
8
|
+
/** 睡眠 */
|
|
9
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** 深拷贝:优先 structuredClone,失败降级 JSON */
|
|
2
|
+
export declare function deepClone<T>(source: T): T;
|
|
3
|
+
/** 数组去重(按 key 或值) */
|
|
4
|
+
export declare function uniqueBy<T>(list: T[], key?: keyof T): T[];
|
|
5
|
+
/** 数组转树(扁平结构构建树形结构) */
|
|
6
|
+
export interface TreeNode<T> extends Record<string, unknown> {
|
|
7
|
+
children?: TreeNode<T>[];
|
|
8
|
+
}
|
|
9
|
+
export declare function listToTree<T extends Record<string, unknown>>(list: T[], { idKey, parentKey, childrenKey }?: {
|
|
10
|
+
idKey?: string | undefined;
|
|
11
|
+
parentKey?: string | undefined;
|
|
12
|
+
childrenKey?: string | undefined;
|
|
13
|
+
}): TreeNode<T>[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** 判断空值:undefined / null / 空字符串 / 空数组 / 空 MapSet / 空对象 */
|
|
2
|
+
export declare function isEmpty(value: unknown): boolean;
|
|
3
|
+
/** 手机号校验(中国大陆) */
|
|
4
|
+
export declare function isPhone(value: string): boolean;
|
|
5
|
+
/** 身份证校验(18 位) */
|
|
6
|
+
export declare function isIdCard(value: string): boolean;
|
|
7
|
+
/** 邮箱校验 */
|
|
8
|
+
export declare function isEmail(value: string): boolean;
|
package/dist/utils.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function f(t){return t==null||t===""?!0:Array.isArray(t)?t.length===0:t instanceof Map||t instanceof Set?t.size===0:typeof t=="object"?Object.keys(t).length===0:!1}function d(t){return/^1[3-9]\d{9}$/.test(t)}function a(t){return/^\d{17}[\dXx]$/.test(t)}function l(t){return/^[\w.+-]+@[\w-]+(\.[\w-]+)+$/.test(t)}function p(t){if(typeof structuredClone=="function")try{return structuredClone(t)}catch{}return JSON.parse(JSON.stringify(t))}function h(t,n){if(!n)return Array.from(new Set(t));const e=new Set;return t.filter(o=>{const r=o[n];return e.has(r)?!1:(e.add(r),!0)})}function m(t,{idKey:n="id",parentKey:e="parentId",childrenKey:o="children"}={}){const r=new Map,s=[];return t.forEach(i=>{r.set(i[n],{...i,[o]:[]})}),t.forEach(i=>{const u=r.get(i[n]),c=r.get(i[e]);c?c[o].push(u):s.push(u)}),s}function y(t,n=300){let e;const o=(...r)=>{e&&clearTimeout(e),e=setTimeout(()=>t(...r),n)};return o.cancel=()=>{e&&clearTimeout(e),e=void 0},o}function w(t,n=300){let e=0;return(...o)=>{const r=Date.now();r-e>=n&&(e=r,t(...o))}}function T(t){return new Promise(n=>setTimeout(n,t))}exports.debounce=y;exports.deepClone=p;exports.isEmail=l;exports.isEmpty=f;exports.isIdCard=a;exports.isPhone=d;exports.listToTree=m;exports.sleep=T;exports.throttle=w;exports.uniqueBy=h;
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function f(t) {
|
|
2
|
+
return t == null || t === "" ? !0 : Array.isArray(t) ? t.length === 0 : t instanceof Map || t instanceof Set ? t.size === 0 : typeof t == "object" ? Object.keys(t).length === 0 : !1;
|
|
3
|
+
}
|
|
4
|
+
function d(t) {
|
|
5
|
+
return /^1[3-9]\d{9}$/.test(t);
|
|
6
|
+
}
|
|
7
|
+
function a(t) {
|
|
8
|
+
return /^\d{17}[\dXx]$/.test(t);
|
|
9
|
+
}
|
|
10
|
+
function p(t) {
|
|
11
|
+
return /^[\w.+-]+@[\w-]+(\.[\w-]+)+$/.test(t);
|
|
12
|
+
}
|
|
13
|
+
function h(t) {
|
|
14
|
+
if (typeof structuredClone == "function")
|
|
15
|
+
try {
|
|
16
|
+
return structuredClone(t);
|
|
17
|
+
} catch {
|
|
18
|
+
}
|
|
19
|
+
return JSON.parse(JSON.stringify(t));
|
|
20
|
+
}
|
|
21
|
+
function l(t, e) {
|
|
22
|
+
if (!e) return Array.from(new Set(t));
|
|
23
|
+
const n = /* @__PURE__ */ new Set();
|
|
24
|
+
return t.filter((o) => {
|
|
25
|
+
const r = o[e];
|
|
26
|
+
return n.has(r) ? !1 : (n.add(r), !0);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function w(t, { idKey: e = "id", parentKey: n = "parentId", childrenKey: o = "children" } = {}) {
|
|
30
|
+
const r = /* @__PURE__ */ new Map(), s = [];
|
|
31
|
+
return t.forEach((i) => {
|
|
32
|
+
r.set(i[e], { ...i, [o]: [] });
|
|
33
|
+
}), t.forEach((i) => {
|
|
34
|
+
const u = r.get(i[e]), c = r.get(i[n]);
|
|
35
|
+
c ? c[o].push(u) : s.push(u);
|
|
36
|
+
}), s;
|
|
37
|
+
}
|
|
38
|
+
function m(t, e = 300) {
|
|
39
|
+
let n;
|
|
40
|
+
const o = (...r) => {
|
|
41
|
+
n && clearTimeout(n), n = setTimeout(() => t(...r), e);
|
|
42
|
+
};
|
|
43
|
+
return o.cancel = () => {
|
|
44
|
+
n && clearTimeout(n), n = void 0;
|
|
45
|
+
}, o;
|
|
46
|
+
}
|
|
47
|
+
function y(t, e = 300) {
|
|
48
|
+
let n = 0;
|
|
49
|
+
return (...o) => {
|
|
50
|
+
const r = Date.now();
|
|
51
|
+
r - n >= e && (n = r, t(...o));
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function T(t) {
|
|
55
|
+
return new Promise((e) => setTimeout(e, t));
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
m as debounce,
|
|
59
|
+
h as deepClone,
|
|
60
|
+
p as isEmail,
|
|
61
|
+
f as isEmpty,
|
|
62
|
+
a as isIdCard,
|
|
63
|
+
d as isPhone,
|
|
64
|
+
w as listToTree,
|
|
65
|
+
T as sleep,
|
|
66
|
+
y as throttle,
|
|
67
|
+
l as uniqueBy
|
|
68
|
+
};
|
package/package.json
CHANGED
|
@@ -1,69 +1,89 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "hd-attribute-set",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "属性集组件库,基于 React + antd",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"react",
|
|
7
|
-
"component",
|
|
8
|
-
"antd",
|
|
9
|
-
"attribute-set"
|
|
10
|
-
],
|
|
11
|
-
"license": "MIT",
|
|
12
|
-
"author": "szldjd",
|
|
13
|
-
"repository": {
|
|
14
|
-
"type": "git",
|
|
15
|
-
"url": "https://cnb.cool/szldjd/fee/hd-attribute-set"
|
|
16
|
-
},
|
|
17
|
-
"bugs": {
|
|
18
|
-
"url": "https://cnb.cool/szldjd/fee/hd-attribute-set/-/issues"
|
|
19
|
-
},
|
|
20
|
-
"homepage": "https://cnb.cool/szldjd/fee/hd-attribute-set",
|
|
21
|
-
"publishConfig": {
|
|
22
|
-
"access": "public",
|
|
23
|
-
"registry": "https://registry.npmjs.org/"
|
|
24
|
-
},
|
|
25
|
-
"type": "module",
|
|
26
|
-
"sideEffects": [
|
|
27
|
-
"**/*.css",
|
|
28
|
-
"**/*.less"
|
|
29
|
-
],
|
|
30
|
-
"files": [
|
|
31
|
-
"dist",
|
|
32
|
-
"README.md"
|
|
33
|
-
],
|
|
34
|
-
"main": "dist/hd-attribute-set.
|
|
35
|
-
"module": "dist/hd-attribute-set.js",
|
|
36
|
-
"types": "dist/index.d.ts",
|
|
37
|
-
"exports": {
|
|
38
|
-
".": {
|
|
39
|
-
"types": "./dist/index.d.ts",
|
|
40
|
-
"import": "./dist/hd-attribute-set.js",
|
|
41
|
-
"require": "./dist/hd-attribute-set.
|
|
42
|
-
},
|
|
43
|
-
"./
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "hd-attribute-set",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "属性集组件库,基于 React + antd",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"component",
|
|
8
|
+
"antd",
|
|
9
|
+
"attribute-set"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "szldjd",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://cnb.cool/szldjd/fee/hd-attribute-set"
|
|
16
|
+
},
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://cnb.cool/szldjd/fee/hd-attribute-set/-/issues"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://cnb.cool/szldjd/fee/hd-attribute-set",
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public",
|
|
23
|
+
"registry": "https://registry.npmjs.org/"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"sideEffects": [
|
|
27
|
+
"**/*.css",
|
|
28
|
+
"**/*.less"
|
|
29
|
+
],
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"main": "dist/hd-attribute-set.cjs",
|
|
35
|
+
"module": "dist/hd-attribute-set.js",
|
|
36
|
+
"types": "dist/index.d.ts",
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"import": "./dist/hd-attribute-set.js",
|
|
41
|
+
"require": "./dist/hd-attribute-set.cjs"
|
|
42
|
+
},
|
|
43
|
+
"./utils": {
|
|
44
|
+
"types": "./dist/utils.d.ts",
|
|
45
|
+
"import": "./dist/utils.js",
|
|
46
|
+
"require": "./dist/utils.cjs"
|
|
47
|
+
},
|
|
48
|
+
"./hooks": {
|
|
49
|
+
"types": "./dist/hooks.d.ts",
|
|
50
|
+
"import": "./dist/hooks.js",
|
|
51
|
+
"require": "./dist/hooks.cjs"
|
|
52
|
+
},
|
|
53
|
+
"./dist/*": "./dist/*"
|
|
54
|
+
},
|
|
55
|
+
"typesVersions": {
|
|
56
|
+
"*": {
|
|
57
|
+
"utils": [
|
|
58
|
+
"./dist/utils.d.ts"
|
|
59
|
+
],
|
|
60
|
+
"hooks": [
|
|
61
|
+
"./dist/hooks.d.ts"
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"dev": "vite",
|
|
67
|
+
"build": "tsc --noEmit && vite build",
|
|
68
|
+
"preview": "vite preview",
|
|
69
|
+
"prepublishOnly": "npm run build"
|
|
70
|
+
},
|
|
71
|
+
"peerDependencies": {
|
|
72
|
+
"antd": ">=5.0.0",
|
|
73
|
+
"react": ">=17.0.0",
|
|
74
|
+
"react-dom": ">=17.0.0"
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@types/react": "^18.3.0",
|
|
78
|
+
"@types/react-dom": "^18.3.0",
|
|
79
|
+
"@types/node": "^20.14.0",
|
|
80
|
+
"@vitejs/plugin-react": "^4.3.0",
|
|
81
|
+
"antd": "^5.21.0",
|
|
82
|
+
"less": "^4.2.0",
|
|
83
|
+
"react": "^18.3.0",
|
|
84
|
+
"react-dom": "^18.3.0",
|
|
85
|
+
"typescript": "^5.5.0",
|
|
86
|
+
"vite": "^5.4.0",
|
|
87
|
+
"vite-plugin-dts": "^4.2.0"
|
|
88
|
+
}
|
|
89
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# hd-attribute-set
|
|
2
|
+
|
|
3
|
+
基于 **TypeScript** 的工具/组件库,使用 Vite 库模式构建,通过 [CNB 云原生构建](https://docs.cnb.cool/) 自动发布到 npm。
|
|
4
|
+
|
|
5
|
+
## 目录结构
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
├── .cnb.yml # CNB 云原生构建流水线配置
|
|
9
|
+
├── index.html # 本地调试入口(playground)
|
|
10
|
+
├── src
|
|
11
|
+
│ ├── index.ts # 包主入口(构建产物入口)
|
|
12
|
+
│ ├── App.tsx / main.tsx # 调试页面
|
|
13
|
+
│ ├── utils # 公共工具方法(多文件)
|
|
14
|
+
│ │ ├── index.ts # 统一出口(barrel)
|
|
15
|
+
│ │ ├── format.ts
|
|
16
|
+
│ │ ├── validate.ts
|
|
17
|
+
│ │ ├── object.ts
|
|
18
|
+
│ │ └── fn.ts
|
|
19
|
+
│ └── hooks # 业务 Hook(解耦后版本)
|
|
20
|
+
│ ├── index.ts
|
|
21
|
+
│ ├── use-btn-deal.ts
|
|
22
|
+
│ ├── use-permission.ts
|
|
23
|
+
│ ├── use-row-selection.ts
|
|
24
|
+
│ └── use-memoized-fn.ts
|
|
25
|
+
├── vite.config.ts # Vite 配置(lib 模式,多入口)
|
|
26
|
+
└── tsconfig.json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 本地开发
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install
|
|
33
|
+
npm run dev # 启动 playground 调试
|
|
34
|
+
npm run build # 构建产物到 dist/
|
|
35
|
+
npm pack --dry-run # 查看将要发布到 npm 的文件清单
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 新增工具方法
|
|
39
|
+
|
|
40
|
+
1. 在 `src/utils/` 下新建文件(如 `string.ts`)并 `export` 方法;
|
|
41
|
+
2. 在 `src/utils/index.ts` 加一行 `export * from './string';`;
|
|
42
|
+
3. `npm run build`,新方法即自动出现在包根路径与 `hd-attribute-set/utils` 两个入口。
|
|
43
|
+
|
|
44
|
+
## 在其他项目中使用
|
|
45
|
+
|
|
46
|
+
安装:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm i hd-attribute-set
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
引入方式(三个入口,按需选择):
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// 1. 根路径:通用工具
|
|
56
|
+
import { formatMoney, version } from 'hd-attribute-set';
|
|
57
|
+
|
|
58
|
+
// 2. utils 子路径
|
|
59
|
+
import { isEmail, listToTree } from 'hd-attribute-set/utils';
|
|
60
|
+
|
|
61
|
+
// 3. hooks 子路径(已对权限/按钮/表格做解耦,可与任意数据源配合)
|
|
62
|
+
import { useBtnDeal, usePermission, useRowSelection } from 'hd-attribute-set/hooks';
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
CommonJS 环境:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
const { formatMoney } = require('hd-attribute-set');
|
|
69
|
+
const { isPhone } = require('hd-attribute-set/utils');
|
|
70
|
+
const { useBtnDeal } = require('hd-attribute-set/hooks');
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### hooks 用法示例
|
|
74
|
+
|
|
75
|
+
> 所有 hooks 都已与 Redux/ahooks 解耦,权限数据通过 `getAccessConfig` 注入。
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { useSelector } from 'react-redux';
|
|
79
|
+
import { useBtnDeal, usePermission } from 'hd-attribute-set/hooks';
|
|
80
|
+
|
|
81
|
+
// 接 Redux
|
|
82
|
+
const access = useSelector(s => s.auth.accessConfig);
|
|
83
|
+
const { controlShowStatus } = useBtnDeal(() => access);
|
|
84
|
+
// 或接任意数据源
|
|
85
|
+
const { hasPermission } = usePermission(() => ({ noPermissionShow: true, list: [], selectAll: true }));
|
|
86
|
+
|
|
87
|
+
const [editVisible, editBtn] = controlShowStatus({
|
|
88
|
+
type: 'edit',
|
|
89
|
+
detail: rowData,
|
|
90
|
+
configBtns: btnConfigs, // 来自后端/配置的按钮列表
|
|
91
|
+
});
|
|
92
|
+
{editVisible && <Button {...editBtn}>编辑</Button>}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 发布到 npm(云原生构建)
|
|
96
|
+
|
|
97
|
+
1. 在 npmjs.com 生成 Access Token(Classic Token 选 **Automation**,或 Granular Token 勾选 **Read and write**)。
|
|
98
|
+
2. 在 CNB 仓库设置中配置环境变量 `NPM_TOKEN`(或放入密钥仓库,并在 `.cnb.yml` 的 `tag_push` 中增加 `imports` 指向密钥仓库)。
|
|
99
|
+
3. push 到 `main` 分支会自动执行安装 + 构建校验;发布正式版时推送 tag:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm version patch # 0.1.0 -> 0.1.1,自动提交 tag
|
|
103
|
+
git push origin main --tags
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
流水线将自动构建并执行 `npm publish`(`prepublishOnly` 也会兜底执行构建)。
|
|
107
|
+
|
|
108
|
+
## 发布前检查清单
|
|
109
|
+
|
|
110
|
+
- [ ] `package.json` 的 `version` 已升版(与 tag 一致)。
|
|
111
|
+
- [ ] `npm run build` 通过,`dist` 含 `hd-attribute-set.js/.cjs`、`utils.js/.cjs` 及对应 `.d.ts`。
|
|
112
|
+
- [ ] `npm pack --dry-run` 中仅包含 `dist` 与 `README.md`,无源码泄露。
|
|
113
|
+
- [ ] 如使用了组件,需确认使用方已安装 `antd`(peer 依赖,不打包进产物)。
|
package/README.md
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# hd-attribute-set
|
|
2
|
-
|
|
3
|
-
基于 **React + TypeScript + antd** 的属性集组件库,使用 Vite 库模式构建,通过 [CNB 云原生构建](https://docs.cnb.cool/) 自动发布到 npm。
|
|
4
|
-
|
|
5
|
-
## 目录结构
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
├── .cnb.yml # CNB 云原生构建流水线配置
|
|
9
|
-
├── index.html # 本地调试入口(playground)
|
|
10
|
-
├── src
|
|
11
|
-
│ ├── index.ts # 组件库入口(构建产物入口)
|
|
12
|
-
│ ├── App.tsx # 调试页面
|
|
13
|
-
│ ├── main.tsx # 调试页面挂载入口
|
|
14
|
-
│ └── components
|
|
15
|
-
│ └── attribute-set # 属性集组件(antd)
|
|
16
|
-
├── vite.config.ts # Vite 配置(lib 模式)
|
|
17
|
-
└── tsconfig.json
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## 本地开发
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
npm install
|
|
24
|
-
npm run dev # 启动 playground 调试组件
|
|
25
|
-
npm run build # 构建产物到 dist/(ESM + UMD + CSS + 类型声明)
|
|
26
|
-
npm pack --dry-run # 查看将要发布到 npm 的文件清单
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## 使用示例
|
|
30
|
-
|
|
31
|
-
```tsx
|
|
32
|
-
import { AttributeSet } from 'hd-attribute-set';
|
|
33
|
-
import 'hd-attribute-set/dist/hd-attribute-set.css';
|
|
34
|
-
|
|
35
|
-
<AttributeSet
|
|
36
|
-
title="基础属性"
|
|
37
|
-
items={[
|
|
38
|
-
{ key: 'cpu', label: 'CPU', value: '8 核' },
|
|
39
|
-
{ key: 'memory', label: '内存', value: '16 GB' },
|
|
40
|
-
]}
|
|
41
|
-
/>
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## 发布到 npm(云原生构建)
|
|
45
|
-
|
|
46
|
-
1. 在 npmjs.com 生成 Access Token。
|
|
47
|
-
2. 在 CNB 仓库设置中配置环境变量 `NPM_TOKEN`(或放入密钥仓库,并在 `.cnb.yml` 的 `tag_push` 中增加 `imports` 指向密钥仓库)。
|
|
48
|
-
3. push 到 `main` 分支会自动执行安装 + 构建校验;发布正式版时推送 tag:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
npm version patch # 0.1.0 -> 0.1.1,自动提交 tag
|
|
52
|
-
git push origin main --tags
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
流水线将自动构建并执行 `npm publish`(`prepublishOnly` 也会兜底执行构建)。
|
|
56
|
-
|
|
57
|
-
## 发布前检查清单
|
|
58
|
-
|
|
59
|
-
- [ ] `package.json` 的 `version` 已升版(与 tag 一致)。
|
|
60
|
-
- [ ] `npm run build` 通过,`dist` 含 `hd-attribute-set.js`、`hd-attribute-set.umd.cjs`、`hd-attribute-set.css`、`index.d.ts`。
|
|
61
|
-
- [ ] `npm pack --dry-run` 中仅包含 `dist` 与 `README.md`,无源码泄露。
|
|
62
|
-
- [ ] 使用方已安装 `antd`(peer 依赖,不在包内打包)。
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { AttributeItem, AttributeSetProps } from './types';
|
|
2
|
-
export type { AttributeItem, AttributeSetProps };
|
|
3
|
-
/**
|
|
4
|
-
* 属性集组件:以 antd Descriptions 展示一组键值属性
|
|
5
|
-
*/
|
|
6
|
-
export declare function AttributeSet({ items, title, column, bordered, emptyText }: AttributeSetProps): import("react").JSX.Element;
|
|
7
|
-
export default AttributeSet;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
/** 单个属性项 */
|
|
3
|
-
export interface AttributeItem {
|
|
4
|
-
/** 唯一标识 */
|
|
5
|
-
key: string;
|
|
6
|
-
/** 属性名 */
|
|
7
|
-
label: ReactNode;
|
|
8
|
-
/** 属性值 */
|
|
9
|
-
value?: ReactNode;
|
|
10
|
-
/** 自定义渲染 */
|
|
11
|
-
render?: (value?: ReactNode) => ReactNode;
|
|
12
|
-
/** Descriptions 的栅格跨度 */
|
|
13
|
-
span?: number;
|
|
14
|
-
}
|
|
15
|
-
/** AttributeSet 组件属性 */
|
|
16
|
-
export interface AttributeSetProps {
|
|
17
|
-
/** 属性集标题 */
|
|
18
|
-
title?: ReactNode;
|
|
19
|
-
/** 属性项列表 */
|
|
20
|
-
items: AttributeItem[];
|
|
21
|
-
/** 每行列数,默认 2 */
|
|
22
|
-
column?: number;
|
|
23
|
-
/** 是否显示边框,默认 true */
|
|
24
|
-
bordered?: boolean;
|
|
25
|
-
/** 空数据提示文案 */
|
|
26
|
-
emptyText?: string;
|
|
27
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.hd-attribute-set__title{font-size:16px;font-weight:600}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(r,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("react/jsx-runtime"),require("antd")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","antd"],e):(r=typeof globalThis<"u"?globalThis:r||self,e(r.HdAttributeSet={},r.jsxRuntime,r.antd))})(this,function(r,e,s){"use strict";function n({items:d,title:i,column:l=2,bordered:c=!0,emptyText:p="暂无属性"}){return!d||d.length===0?e.jsxs("div",{className:"hd-attribute-set",children:[i&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"hd-attribute-set__title",children:i}),e.jsx(s.Divider,{style:{margin:"8px 0 16px"}})]}),e.jsx(s.Empty,{image:s.Empty.PRESENTED_IMAGE_SIMPLE,description:p})]}):e.jsxs("div",{className:"hd-attribute-set",children:[i&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"hd-attribute-set__title",children:i}),e.jsx(s.Divider,{style:{margin:"8px 0 16px"}})]}),e.jsx(s.Descriptions,{size:"small",column:l,bordered:c,items:d.map(t=>({key:t.key,label:t.label,children:t.render?t.render(t.value):t.value??"-",span:t.span}))})]})}const a="0.1.0";r.AttributeSet=n,r.version=a,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})});
|