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

@qfei-design/make-app-actions

v0.3.1

Published

Headless Make record-action model, reusable React action bar and batch-edit modal, Ant Design adapter, and CanvasTable selection adapter.

Readme

@qfei-design/make-app-actions

Make App 列表记录操作包,提供选择态操作模型、行级权限校验、批量编辑字段规则、通用 React 操作栏与批量编辑弹窗、Ant Design 适配器,以及 CanvasTable 选择快照适配。

安装

pnpm add @qfei-design/make-app-actions

Ant Design 宿主还需要安装 peer dependencies:

pnpm add react react-dom antd @ant-design/icons

宿主入口引入一次样式:

import "@qfei-design/make-app-actions/styles.css";

包与宿主边界

包负责:

  • 单条选择显示编辑、删除,多条选择显示批量操作。
  • 无可用操作时默认显示“暂无可用的操作”。
  • 部分记录无权限时保留操作入口,并返回无权限行 key。
  • 批量可编辑字段过滤、清空值归一化,以及供无原生批量接口宿主选用的串行执行辅助能力。
  • 标准操作栏、可注入宿主设计系统的通用批量编辑 Modal、AntD 适配器和 CanvasTable 选择快照适配。

宿主负责:

  • 在应用初始化、身份或租户变化、显式刷新时从 /api/make/app/principal/permission 加载并缓存权限。
  • data.record.update/delete/bulkUpdate 决定 action 的 visible
  • meta.field.update 生成批量可编辑字段 key。
  • 渲染具体字段控件、加载候选项、构造 Make mutation payload。
  • 点击操作时先冻结不可变的完整操作快照,再通过 apps/service 对该快照执行一次行级写权限预检。
  • 批量修改时调用一次 apps/service 批量接口,并负责删除确认、吐司、异常行高亮和列表刷新。

Core

import {
  RECORD_SELECTION_ACTION_BULK_EDIT,
  RECORD_SELECTION_ACTION_DELETE,
  RECORD_SELECTION_ACTION_EDIT,
  isRecordSelectionIntentResolved,
  resolveRecordOperationPermission,
  resolveRecordSelectionActionState,
  validateRecordBatchEditSelectionLimit,
  validateRecordSelectionAction,
} from "@qfei-design/make-app-actions";

const actions = [
  {
    key: RECORD_SELECTION_ACTION_EDIT,
    label: "编辑",
    permissionKey: "data.record.update",
    scope: "single",
    visible: canUpdate,
    canOperateRecord: (record) =>
      resolveRecordOperationPermission(record, "data.record.update"),
  },
  {
    key: RECORD_SELECTION_ACTION_DELETE,
    label: "删除",
    permissionKey: "data.record.delete",
    scope: "single",
    visible: canDelete,
    canOperateRecord: (record) =>
      resolveRecordOperationPermission(record, "data.record.delete"),
  },
  {
    key: RECORD_SELECTION_ACTION_BULK_EDIT,
    label: "批量编辑",
    permissionKey: "data.record.bulkUpdate",
    scope: "multiple",
    visible: canBulkUpdate && batchEditableFields.length > 0,
    canOperateRecord: (record) =>
      resolveRecordOperationPermission(record, "data.record.bulkUpdate"),
  },
] as const;

const state = resolveRecordSelectionActionState({
  actions: [...actions],
  selectedRecords,
  selectedCount,
  totalCount,
});

const validation = validateRecordSelectionAction(action, selectedRecords);
if (!validation.ok) {
  setAlertRowKeys(validation.unauthorizedRowKeys);
  toast.error("勾选范围中存在无权限数据,请检查勾选范围");
}

isRecordSelectionFullyResolved 只用于判断已加载记录是否足够执行本地逐行权限判断,不能用它阻止服务端可解析的跨页选择。宿主应使用 Canvas adapter 返回的 selectionIntentisRecordSelectionIntentResolved 判断提交目标是否完整:include 保留全部明确选中的 ID,exclude 保留全选后取消的 ID,并通过总数校验选择快照。

批量编辑前使用 validateRecordBatchEditSelectionLimit 校验数量。默认只限制 include 模式最多 200 条;恰好 200 条允许,exclude 模式不应用该限制。超限后的吐司和选择态保留仍由宿主负责。

Make 宿主标准编排

  1. data.record.updatedata.record.deletedata.record.bulkUpdate 是相互独立的权限点;宿主从当前缓存的 principal 权限分别计算按钮可见性。
  2. 使用 selectionIntent 区分明确选择的 include 模式和点击表头全选产生的 exclude 模式,不能根据 selectedCount === totalCount 推断全选。
  3. 用户点击操作时先冻结不可变的操作快照,包含完整 selectionIntent、数量和最近一次成功查询的 filter/groupFilter;后续列表状态变化不得改写该快照。
  4. 打开单条编辑或批量编辑界面前,将同一份操作快照交给 Service,Service 对 Make 行级写权限执行一次预检。预检拒绝时直接阻止打开界面;不要拆成逐 ID 诊断请求。
  5. 提交批量修改时复用同一份操作快照,只调用一次 Service 批量接口。Service 再向 Make 发起一次批量写请求,不循环调用单条更新接口。
  6. 权限预检只是用户操作前的反馈层,最终写接口仍必须执行权威鉴权。

principal 权限只在应用初始化、身份或租户变化、显式刷新时重新加载。按钮点击和提交使用当前缓存,不为每次操作重复请求 principal 权限。

CanvasTable

import {
  resolveCanvasSelectedRecordSnapshot,
} from "@qfei-design/make-app-actions/adapters/canvas-table";

const snapshot = resolveCanvasSelectedRecordSnapshot(
  table.getSelectionInfo(),
  loadedRecords,
  totalCount,
);

if (
  !isRecordSelectionIntentResolved({
    selectionIntent: snapshot.selectionIntent,
    selectedCount: snapshot.selectedCount,
    totalCount: snapshot.totalCount,
  })
) {
  throw new Error("CanvasTable 选择快照不完整");
}

adapter 返回的兼容字段包括 rowKeysrecordsselectedCounttotalCount,并新增:

  • selectAll:保留用户是否点击表头全选的原始意图;手动选满全部记录时仍为 false
  • selectionIntent.mode = "include"recordIDs 是全部明确选中的 ID,不受已加载记录缓存限制。
  • selectionIntent.mode = "exclude"excludedRecordIDs 是表头全选后取消勾选的 ID。

CanvasTable 宿主仍负责:

  • selectable: { enabled: true, type: "multiple" }
  • 使用 table.tableId 监听 selection:change
  • 关闭操作栏时调用 clearSelection()
  • 用公开的 setRowColorsrowStyleOptions 标记无权限行。
  • 取消某行选择时移除该行异常态;关闭操作栏时清空全部异常态。
  • 不使用 selectedCount === totalCount 或表头视觉状态推断全选模式。

CanvasTable adapter 不导入 @qfei-design/canvas-table,避免把浏览器端表格运行时带进 core 或 SSR 构建。

React 操作栏

非 AntD 宿主使用通用组件:

import { RecordSelectionActionBar } from "@qfei-design/make-app-actions/react";

<RecordSelectionActionBar
  components={hostComponents}
  state={state}
  onAction={handleAction}
  onClose={clearSelection}
/>;

AntD 宿主可直接使用:

import {
  AntdRecordSelectionActionBar,
} from "@qfei-design/make-app-actions/adapters/antd";

<AntdRecordSelectionActionBar
  state={state}
  onAction={handleAction}
  onClose={clearSelection}
/>;

操作栏使用绝对定位,宿主表格容器需要 position: relative

批量编辑弹窗

非 AntD 宿主通过 MakeAppBatchEditComponents 注入 Modal、字段选择器和修改模式控件:

import {
  RecordBatchEditModal,
  type MakeAppBatchEditComponents,
} from "@qfei-design/make-app-actions/react";

const batchEditComponents: MakeAppBatchEditComponents = {
  Modal: HostDialog,
  FieldSelect: HostSelect,
  ModeControl: HostRadioGroup,
};

<RecordBatchEditModal
  components={batchEditComponents}
  open={batchEditOpen}
  fields={batchEditableFields}
  selectedCount={selectedCount}
  saving={saving}
  onClose={closeBatchEdit}
  onSubmit={handleBatchEditSubmit}
  renderValueControl={(field, control) =>
    renderHostFieldEditor(field, control)
  }
/>;

通用弹窗拥有字段、模式、当前值、校验、异步错误和防重复提交状态。注入的 Modal 只负责视觉壳与确认/取消按钮;FieldSelectModeControl 只把宿主控件的值变化回传给包。宿主仍通过 renderValueControl(field, { value, onChange, disabled, invalid, ariaDescribedBy }) 渲染实际 Make 字段控件,并把无障碍属性转交给真实输入控件。

AntD 宿主可直接使用适配器:

import {
  AntdRecordBatchEditModal,
} from "@qfei-design/make-app-actions/adapters/antd";

<AntdRecordBatchEditModal
  open={batchEditOpen}
  fields={batchEditableFields}
  selectedCount={selectedCount}
  saving={saving}
  onClose={closeBatchEdit}
  onSubmit={handleBatchEditSubmit}
  renderValueControl={(field, control) =>
    renderHostFieldEditor(field, { disabled: control.disabled })
  }
/>;

弹窗负责字段选择、“新值 / 清空内容”模式、校验、计数文案和布局。宿主通过 renderValueControl 按 Make 字段类型提供 Select、Input、DatePicker、Identity Picker 等控件,并把第二个参数中的 disabled 转交给实际控件;提交期间适配器也会对顶层 AntD 控件强制设置 disabled,兼容原有的一参数回调。包不把复杂字段降级为普通 Input,也不包含自动化流程选项。通用 React 与 AntD 入口共享 BatchEditValueModeBatchEditSubmitRecordBatchEditModalLabels 类型。

提交时:

  1. 检查当前缓存中的 data.record.bulkUpdate
  2. 检查目标字段 meta.field.update
  3. clear 模式使用 resolveBatchEditClearValue(field)
  4. 宿主基于预检前冻结的同一份操作快照构造 payload,并调用一次 Service 批量修改接口。
  5. 成功后关闭弹窗、刷新列表并清理本次选择;清理时不得覆盖用户在请求期间产生的更新选择态。

runRecordBatchMutation 是供非 Make 或没有原生批量接口的宿主选用的串行 fallback,不是 Make 宿主批量修改的默认执行路径。

完整导出见 PUBLIC_API.md