npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

hd-attribute-set

v0.1.6

Published

属性集组件库,基于 React + antd

Readme

hd-attribute-set

基于 TypeScript + React 的属性集 / 业务工具库,使用 Vite 库模式构建,通过 CNB 云原生构建 自动发布到 npm。

  • 产物:ESM(.js)+ CJS(.cjs)+ .d.ts 类型声明
  • 入口:包根路径、hd-attribute-set/utils、hd-attribute-set/hooks
  • 依赖:react / react-dom / antd 为 peer 依赖,不打包进产物

安装

npm i hd-attribute-set
# 或
yarn add hd-attribute-set

引入方式

// 1. 包根路径:等价于同时引入 utils + hooks
import { isEmail, debounce, usePermission, version } from 'hd-attribute-set';

// 2. utils 子路径:只引工具方法
import { isPhone, listToTree, base64ToString } from 'hd-attribute-set/utils';

// 3. hooks 子路径:只引 hooks
import { usePermission, useBtnDeal, useSseConnect } from 'hd-attribute-set/hooks';

CommonJS:

const { version } = require('hd-attribute-set');
const { isPhone } = require('hd-attribute-set/utils');
const { usePermission } = require('hd-attribute-set/hooks');

目录结构

├── .cnb.yml                # CNB 云原生构建流水线配置
├── .npmrc                  # npm 发布凭据(提交在仓库内,发布时使用)
├── index.html              # 本地调试入口(playground)
├── src
│   ├── index.ts            # 包主入口
│   ├── App.tsx / main.tsx  # 调试页面
│   ├── utils               # 公共工具方法
│   │   ├── index.ts        # 统一出口(barrel)
│   │   ├── validate.ts     # 校验类:isEmpty / isPhone / isIdCard / isEmail
│   │   ├── object.ts       # 对象与树:deepClone / uniqueBy / listToTree
│   │   ├── fn.ts           # 通用函数:debounce / throttle / sleep / isBase64 / base64ToString / isJson
│   │   └── universal.ts    # 预留
│   └── hooks               # 业务 Hook(均已与 redux / ahooks 解耦)
│       ├── index.ts
│       ├── use-memoized-fn.ts
│       ├── use-permission.ts
│       ├── use-btn-deal.ts
│       └── use-sse-connect.ts
├── vite.config.ts          # Vite 配置(lib 模式,多入口)
└── tsconfig.json

utils API

| 文件 | 方法 | 说明 | |---|---|---| | validate.ts | isEmpty(value) | 空值判断(undefined / null / '' / 空数组 / 空 Map·Set / 空对象) | | | isPhone(value) | 手机号校验 | | | isIdCard(value) | 身份证校验 | | | isEmail(value) | 邮箱校验 | | object.ts | deepClone(source) | 深拷贝 | | | uniqueBy(list, key?) | 按字段(不传则按值)去重 | | | listToTree(list, { idKey, parentKey, childrenKey }) | 列表转树,默认 id / parentId / children | | fn.ts | debounce(fn, wait?) | 防抖,返回值带 cancel() | | | throttle(fn, wait?) | 节流 | | | sleep(ms) | 延时 | | | isBase64(str) | 是否合法 Base64(空串视为合法) | | | base64ToString(str) | Base64(UTF-8)转字符串,非 Base64 原样返回 | | | isJson(str) | 是否合法 JSON 字符串 |

hooks API

usePermission

const { hasPermission, shouldShowButton, shouldShowMenu, isNoPermissionShow } = usePermission(source?)

source 支持三种传法:

  1. 直接传权限配置对象(如 redux 里的 accessConfig);
  2. 传 getter:() => config,每次调用取最新值,适配 redux / context;
  3. 不传:视为拥有全部权限(DEFAULT_PERMISSION_CONFIG)。

PermissionConfig:{ noPermissionShow?: boolean; list?: (number | string)[]; selectAll?: boolean }。

useBtnDeal

const { controlShowStatus } = useBtnDeal(source?)
const [isShow, btn] = controlShowStatus({ type, detail, configBtns })
  • 按 type 从 configBtns 中找按钮配置;
  • 用 btn-tag 校验权限(内部复用 usePermission);
  • 支持 show-match-key / show-match-value 单个或数组条件匹配,invert-show-match 反转;
  • 返回 [是否显示, 命中的按钮配置]。

useMemoizedFn

const memoized = useMemoizedFn(fn)

返回引用稳定的函数(内部经 useRef 保存最新实现),可安全放入依赖数组,行为与 ahooks 的同名 hook 一致。

useSseConnect

const { fullUrl, sseUser, closeSSE, reInitSSE, getConnectStatus } = useSseConnect({
  sseUrl,                                // { sse_test_url, sse_prod_url }
  env: import.meta.env.VITE_BUILD_ENV,   // test / dev 走测试地址
  event,                                 // 事件总线,收到带 datatype 的消息会 emit
  onSseUserChange: user => dispatch(updateSseUser(user)),
  onError: msg => message.error(msg?.msg),
  autoConnect: false,                    // 默认 true;false 时由外部调用 reInitSSE
});

其他参数:getToken / tokenStorageKey(默认读 sessionStorage 的 token)、handleDealMsg、onConnectSuccessCb、reconnectInterval(默认 3000ms)、maxReconnectTimes(默认 5)、debug。

token 取不到时不会建立连接。如果项目的 token 存在其他 key(例如 HD_TOKEN),必须传 getToken:

useSseConnect({ sseUrl, env, getToken: () => sessionStorage.getItem(TOKEN) });

接 redux 的完整示例

import { useBtnDeal, usePermission } from 'hd-attribute-set';
import { useAppSelector } from '@/store/hooks';
import { selectAccessConfig } from '@/store/slices/authSlice';

const accessConfig = useAppSelector(selectAccessConfig);
const { shouldShowButton, isNoPermissionShow } = usePermission(accessConfig);
const { controlShowStatus } = useBtnDeal(accessConfig);

const [editVisible, editBtn] = controlShowStatus({
  type: 'edit',
  detail: rowData,
  configBtns: btnConfigs, // 来自后端 / 配置的按钮列表
});

组件库不依赖 redux,所有业务数据(权限配置、SSE 地址、token、事件总线等)都由调用方传入。

本地开发

npm install
npm run dev            # 启动 playground 调试(index.html)
npm run build          # tsc --noEmit + vite build,产物输出到 dist/
npm pack --dry-run     # 查看将要发布到 npm 的文件清单

新增工具方法 / Hook

  1. 在 src/utils/ 或 src/hooks/ 下新建文件并 export;
  2. 在对应的 index.ts(barrel)加一行 export * from './xxx';;
  3. npm run build,新内容自动出现在包根路径与对应的子路径入口。

发布到 npm(CNB 云原生构建)

流水线规则见 .cnb.yml:

| 触发 | 执行内容 | |---|---| | push 到 main | 安装依赖 → 构建(仅校验,不发布) | | push 到 main 且 package.json 有变更 | 安装依赖 → 构建 → npm whoami → npm publish |

也就是说:改完 version 合并到 main 即自动发版。

发布凭据来自仓库根目录的 .npmrc(内含 npm Automation Token),流水线里不再依赖 NPM_TOKEN 环境变量。

发版步骤:

git checkout main && git pull
npm version patch        # 升版本号,如 0.1.5 -> 0.1.6
git push origin main --follow-tags

发布前检查清单

  • [ ] package.json 的 version 已升版(且该版本 npm 上不存在)。
  • [ ] npm run build 通过,dist 含 hd-attribute-set.js/.cjs、utils.js/.cjs、hooks.js/.cjs 及对应 .d.ts。
  • [ ] npm pack --dry-run 中仅包含 dist 与 README.md,无源码泄露(.npmrc 不会被发进包)。
  • [ ] 使用方已安装 react / react-dom / antd(peer 依赖)。
  • [ ] 新增的 hook / 方法已从 src/hooks/index.ts 或 src/utils/index.ts 导出。