@manohub/app-kit 0.1.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.
Files changed (103) hide show
  1. package/CONTRACT.md +592 -0
  2. package/README.md +27 -0
  3. package/dist/atoms/app-button.d.ts +90 -0
  4. package/dist/atoms/app-button.js +74 -0
  5. package/dist/atoms/app-checkbox.d.ts +86 -0
  6. package/dist/atoms/app-checkbox.js +78 -0
  7. package/dist/atoms/app-icon-button.d.ts +79 -0
  8. package/dist/atoms/app-icon-button.js +54 -0
  9. package/dist/atoms/app-input.d.ts +118 -0
  10. package/dist/atoms/app-input.js +83 -0
  11. package/dist/atoms/app-layout.d.ts +348 -0
  12. package/dist/atoms/app-layout.js +102 -0
  13. package/dist/atoms/app-notice.d.ts +90 -0
  14. package/dist/atoms/app-notice.js +59 -0
  15. package/dist/atoms/app-query-state.d.ts +191 -0
  16. package/dist/atoms/app-query-state.js +161 -0
  17. package/dist/atoms/app-radio-card.d.ts +80 -0
  18. package/dist/atoms/app-radio-card.js +72 -0
  19. package/dist/atoms/app-search-box.d.ts +80 -0
  20. package/dist/atoms/app-search-box.js +64 -0
  21. package/dist/atoms/app-select.d.ts +106 -0
  22. package/dist/atoms/app-select.js +74 -0
  23. package/dist/atoms/app-switch.d.ts +72 -0
  24. package/dist/atoms/app-switch.js +66 -0
  25. package/dist/atoms/app-textarea.d.ts +89 -0
  26. package/dist/atoms/app-textarea.js +61 -0
  27. package/dist/atoms/app-tooltip.d.ts +70 -0
  28. package/dist/atoms/app-tooltip.js +48 -0
  29. package/dist/atoms/atoms.css +679 -0
  30. package/dist/atoms/state-illustration.d.ts +21 -0
  31. package/dist/atoms/state-illustration.js +101 -0
  32. package/dist/components/app-badge.d.ts +72 -0
  33. package/dist/components/app-badge.js +40 -0
  34. package/dist/components/app-dialog.d.ts +164 -0
  35. package/dist/components/app-dialog.js +121 -0
  36. package/dist/components/app-filter.d.ts +173 -0
  37. package/dist/components/app-filter.js +200 -0
  38. package/dist/components/app-form.d.ts +446 -0
  39. package/dist/components/app-form.js +159 -0
  40. package/dist/components/app-pagination.d.ts +78 -0
  41. package/dist/components/app-pagination.js +57 -0
  42. package/dist/components/app-panel.d.ts +399 -0
  43. package/dist/components/app-panel.js +213 -0
  44. package/dist/components/app-section.d.ts +68 -0
  45. package/dist/components/app-section.js +28 -0
  46. package/dist/components/app-steps.d.ts +115 -0
  47. package/dist/components/app-steps.js +108 -0
  48. package/dist/components/app-table.d.ts +415 -0
  49. package/dist/components/app-table.js +479 -0
  50. package/dist/components/app-tabs.d.ts +58 -0
  51. package/dist/components/app-tabs.js +54 -0
  52. package/dist/components/app-tree.d.ts +273 -0
  53. package/dist/components/app-tree.js +222 -0
  54. package/dist/components/components.css +597 -0
  55. package/dist/composables/use-client-pagination.d.ts +39 -0
  56. package/dist/composables/use-client-pagination.js +29 -0
  57. package/dist/entry/create-query-client.d.ts +8 -0
  58. package/dist/entry/create-query-client.js +14 -0
  59. package/dist/entry/create-sub-app.d.ts +45 -0
  60. package/dist/entry/create-sub-app.js +110 -0
  61. package/dist/entry/index.d.ts +4 -0
  62. package/dist/entry/index.js +12 -0
  63. package/dist/entry/initial-guard.d.ts +12 -0
  64. package/dist/entry/initial-guard.js +23 -0
  65. package/dist/index.d.ts +37 -0
  66. package/dist/index.js +67 -0
  67. package/dist/providers/setup-i18n.d.ts +19 -0
  68. package/dist/providers/setup-i18n.js +24 -0
  69. package/dist/services/app-container.d.ts +15 -0
  70. package/dist/services/app-container.js +7 -0
  71. package/dist/services/app-context.d.ts +4 -0
  72. package/dist/services/app-context.js +17 -0
  73. package/dist/services/index.d.ts +5 -0
  74. package/dist/services/loading.d.ts +16 -0
  75. package/dist/services/loading.js +27 -0
  76. package/dist/services/message-box.d.ts +84 -0
  77. package/dist/services/message-box.js +65 -0
  78. package/dist/services/modal.d.ts +51 -0
  79. package/dist/services/modal.js +51 -0
  80. package/dist/services/notify.d.ts +24 -0
  81. package/dist/services/notify.js +22 -0
  82. package/dist/shell/AppShell.d.ts +139 -0
  83. package/dist/shell/AppShell.js +171 -0
  84. package/dist/shell/shell.css +153 -0
  85. package/dist/styles/farris-bridge.css +129 -0
  86. package/dist/styles/index.css +16 -0
  87. package/dist/styles/markdown.css +85 -0
  88. package/dist/styles/reset.css +74 -0
  89. package/dist/styles/tokens.css +111 -0
  90. package/lint/__tests__/fixtures/clean-src/styles.css +14 -0
  91. package/lint/__tests__/fixtures/clean-src/views/good-page.tsx +15 -0
  92. package/lint/__tests__/fixtures/violations-src/styles.css +18 -0
  93. package/lint/__tests__/fixtures/violations-src/views/bad-page.tsx +38 -0
  94. package/lint/__tests__/fixtures/violations-src/views/no-shell-page.tsx +4 -0
  95. package/lint/__tests__/guardrails.spec.mjs +144 -0
  96. package/lint/component-audit.mjs +131 -0
  97. package/lint/guardrails.config.schema.json +74 -0
  98. package/lint/pre-commit.sample +26 -0
  99. package/lint/run-all.mjs +59 -0
  100. package/lint/shared.mjs +347 -0
  101. package/lint/structure-audit.mjs +254 -0
  102. package/lint/style-audit.mjs +200 -0
  103. package/package.json +78 -0
@@ -0,0 +1,28 @@
1
+ import { defineComponent, createVNode } from "vue";
2
+ const AppSection = /* @__PURE__ */ defineComponent({
3
+ name: "AppSection",
4
+ inheritAttrs: false,
5
+ props: {
6
+ title: {
7
+ type: String,
8
+ default: void 0
9
+ }
10
+ },
11
+ slots: Object,
12
+ setup(props, {
13
+ slots,
14
+ attrs
15
+ }) {
16
+ return () => createVNode("div", {
17
+ "class": ["ak-section", attrs.class].filter(Boolean).join(" "),
18
+ "style": attrs.style
19
+ }, [props.title ? createVNode("div", {
20
+ "class": "ak-section__title"
21
+ }, [createVNode("span", {
22
+ "class": "ak-section__title-text"
23
+ }, [props.title]), slots.extra?.()]) : null, slots.default?.()]);
24
+ }
25
+ });
26
+ export {
27
+ AppSection
28
+ };
@@ -0,0 +1,115 @@
1
+ import { type PropType } from 'vue';
2
+ export interface AppStepItem {
3
+ /** 步骤标识(仅作渲染 key 与消费方对账用,不参与展示) */
4
+ key: string;
5
+ /** 步骤名(步骤条只展示这一行) */
6
+ title: string;
7
+ /** 该步是否禁止点击跳转(与 `clickable` 叠加:本步禁用优先) */
8
+ disabled?: boolean;
9
+ }
10
+ /**
11
+ * 步骤条(**封装 farris `FStep`**):拿它的状态机与布局(横排 / `fill` 均分 / 连接线与三角),
12
+ * 换掉它默认的节点内容与点击语义。
13
+ *
14
+ * 上游三处坑在内部消化(均按 1.8.4 编译产物核实):
15
+ * 1. **`clickable` prop 完全没被使用**(源码没有任何一处读它),真正拦住跳转的只有单个 step 的
16
+ * `disabled` —— 故 `clickable=false` 由本件自己在门控里兜(并挂 `ak-steps--static` 去掉手型光标);
17
+ * 2. **默认模板只渲染 `title`**(`description` / `icon` / `class` / `status` 四个字段压根没被读取)——
18
+ * 故本件**不提供副标题**:步骤条只展示步骤名,说明文案写到页面正文里。
19
+ * 节点内容仍由 `stepTemplate` 自绘,唯一目的是把完成勾换成 `@manohub/icon`
20
+ * (不依赖 farris 图标字体);复刻的是上游 DOM 契约 ——
21
+ * `li > .f-progressstep-row(.step-active/.step-finish) > .f-progress-step-content >
22
+ * [.step-icon, .f-progress-step-title > .step-name] + .f-progress-step-line` ——
23
+ * 所以上游的节点配色与连接线样式照旧生效。升级 farris 后若 `app-steps.spec.ts` 变红,先对账这段契约。
24
+ * (要副标题时用上游 `stepTemplate` 就能加,不必为它引入新维度。)
25
+ * 3. **上游会自己改内部态**:放行时执行 `a.value = index`(父级不改 `modelValue` 也会跳走),
26
+ * 受控语义会被带跑 —— 故门控**始终返回 false** 掐掉内部跳转,改由本件上抛
27
+ * `update:modelValue` / `onChange`,让 `modelValue` 成为唯一状态源(与 `AppSwitch` 处理视觉回退同一思路)。
28
+ *
29
+ * 索引语义是 **0 基**(与上游 `activeIndex` 一致),与 `AppPagination` 的 0 基口径相同。
30
+ *
31
+ * @example
32
+ * <AppSteps items={stepItems} modelValue={currentStep} clickable={isEditMode}
33
+ * onBeforeChange={(index) => index <= maxVisitedStep}
34
+ * onChange={(index) => (currentStep = index)} />
35
+ */
36
+ export declare const AppSteps: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
37
+ /** 步骤定义(`key` 必填且唯一;`description` 有值才渲染第二行) */
38
+ items: {
39
+ type: PropType<AppStepItem[]>;
40
+ default: () => never[];
41
+ };
42
+ /** 当前步骤索引(0 基,受控) */
43
+ modelValue: {
44
+ type: NumberConstructor;
45
+ default: number;
46
+ };
47
+ /** 是否允许点击跳转;false = 整条只读(上游同名 prop 无效,由本件门控承担) */
48
+ clickable: {
49
+ type: BooleanConstructor;
50
+ default: boolean;
51
+ };
52
+ /** 步骤平分整条宽度(向导步骤条的标准形态;竖向场景另有上游能力,本件暂不开放) */
53
+ fill: {
54
+ type: BooleanConstructor;
55
+ default: boolean;
56
+ };
57
+ /**
58
+ * 跳转前门控:返回 `false`(或 resolve 为 `false`)则阻止跳转,其余返回值放行。
59
+ * 与上游 `beforeClickStep` 同语义,可用它实现「只能回退、不能前跳」。
60
+ */
61
+ onBeforeChange: {
62
+ type: PropType<(index: number) => boolean | void | Promise<boolean | void>>;
63
+ default: undefined;
64
+ };
65
+ /** 值变更回调(点击导致的索引变化;重复点击当前步骤不触发) */
66
+ onChange: {
67
+ type: PropType<(index: number) => void>;
68
+ default: undefined;
69
+ };
70
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
71
+ 'update:modelValue': (value: number) => true;
72
+ }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
73
+ /** 步骤定义(`key` 必填且唯一;`description` 有值才渲染第二行) */
74
+ items: {
75
+ type: PropType<AppStepItem[]>;
76
+ default: () => never[];
77
+ };
78
+ /** 当前步骤索引(0 基,受控) */
79
+ modelValue: {
80
+ type: NumberConstructor;
81
+ default: number;
82
+ };
83
+ /** 是否允许点击跳转;false = 整条只读(上游同名 prop 无效,由本件门控承担) */
84
+ clickable: {
85
+ type: BooleanConstructor;
86
+ default: boolean;
87
+ };
88
+ /** 步骤平分整条宽度(向导步骤条的标准形态;竖向场景另有上游能力,本件暂不开放) */
89
+ fill: {
90
+ type: BooleanConstructor;
91
+ default: boolean;
92
+ };
93
+ /**
94
+ * 跳转前门控:返回 `false`(或 resolve 为 `false`)则阻止跳转,其余返回值放行。
95
+ * 与上游 `beforeClickStep` 同语义,可用它实现「只能回退、不能前跳」。
96
+ */
97
+ onBeforeChange: {
98
+ type: PropType<(index: number) => boolean | void | Promise<boolean | void>>;
99
+ default: undefined;
100
+ };
101
+ /** 值变更回调(点击导致的索引变化;重复点击当前步骤不触发) */
102
+ onChange: {
103
+ type: PropType<(index: number) => void>;
104
+ default: undefined;
105
+ };
106
+ }>> & Readonly<{
107
+ "onUpdate:modelValue"?: ((value: number) => any) | undefined;
108
+ }>, {
109
+ fill: boolean;
110
+ onChange: (index: number) => void;
111
+ modelValue: number;
112
+ items: AppStepItem[];
113
+ clickable: boolean;
114
+ onBeforeChange: (index: number) => boolean | void | Promise<boolean | void>;
115
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,108 @@
1
+ import { defineComponent, createVNode } from "vue";
2
+ import { FStep } from "@farris/ui-vue";
3
+ import { Icon } from "@manohub/icon";
4
+ const AppSteps = /* @__PURE__ */ defineComponent({
5
+ name: "AppSteps",
6
+ inheritAttrs: false,
7
+ props: {
8
+ /** 步骤定义(`key` 必填且唯一;`description` 有值才渲染第二行) */
9
+ items: {
10
+ type: Array,
11
+ default: () => []
12
+ },
13
+ /** 当前步骤索引(0 基,受控) */
14
+ modelValue: {
15
+ type: Number,
16
+ default: 0
17
+ },
18
+ /** 是否允许点击跳转;false = 整条只读(上游同名 prop 无效,由本件门控承担) */
19
+ clickable: {
20
+ type: Boolean,
21
+ default: true
22
+ },
23
+ /** 步骤平分整条宽度(向导步骤条的标准形态;竖向场景另有上游能力,本件暂不开放) */
24
+ fill: {
25
+ type: Boolean,
26
+ default: true
27
+ },
28
+ /**
29
+ * 跳转前门控:返回 `false`(或 resolve 为 `false`)则阻止跳转,其余返回值放行。
30
+ * 与上游 `beforeClickStep` 同语义,可用它实现「只能回退、不能前跳」。
31
+ */
32
+ onBeforeChange: {
33
+ type: Function,
34
+ default: void 0
35
+ },
36
+ /** 值变更回调(点击导致的索引变化;重复点击当前步骤不触发) */
37
+ onChange: {
38
+ type: Function,
39
+ default: void 0
40
+ }
41
+ },
42
+ emits: {
43
+ "update:modelValue": (value) => true
44
+ },
45
+ setup(props, {
46
+ emit,
47
+ attrs
48
+ }) {
49
+ const farrisSteps = () => props.items.map((item) => ({
50
+ id: item.key,
51
+ title: item.title,
52
+ disabled: !!item.disabled
53
+ }));
54
+ const handleBeforeClickStep = async (payload) => {
55
+ const index = payload?.index;
56
+ if (typeof index !== "number" || !props.clickable) return false;
57
+ if (props.items[index]?.disabled) return false;
58
+ if (index === props.modelValue) return false;
59
+ if (props.onBeforeChange) {
60
+ const allowed = await props.onBeforeChange(index);
61
+ if (allowed === false) return false;
62
+ }
63
+ emit("update:modelValue", index);
64
+ props.onChange?.(index);
65
+ return false;
66
+ };
67
+ const renderStep = (payload) => {
68
+ const {
69
+ index,
70
+ length,
71
+ activeIndex
72
+ } = payload;
73
+ const item = props.items[index];
74
+ if (!item) return null;
75
+ const isCurrent = index === activeIndex;
76
+ const isDone = index < activeIndex;
77
+ return createVNode("div", {
78
+ "class": ["f-progressstep-row", isCurrent ? "step-active step-current" : "", isDone ? "step-finish" : ""].filter(Boolean).join(" ")
79
+ }, [createVNode("div", {
80
+ "class": "f-progress-step-content"
81
+ }, [createVNode("span", {
82
+ "class": "step-icon"
83
+ }, [isDone ? createVNode(Icon, {
84
+ "name": "check",
85
+ "size": 14
86
+ }, null) : index + 1]), createVNode("div", {
87
+ "class": "f-progress-step-title"
88
+ }, [createVNode("p", {
89
+ "class": isDone ? "step-name step-name-success" : "step-name"
90
+ }, [item.title])])]), index !== length - 1 ? createVNode("div", {
91
+ "class": isCurrent ? "f-progress-step-line f-progress-step-line-success" : "f-progress-step-line"
92
+ }, [createVNode("span", {
93
+ "class": "triangle"
94
+ }, null)]) : null]);
95
+ };
96
+ return () => createVNode(FStep, {
97
+ "steps": farrisSteps(),
98
+ "activeIndex": props.modelValue,
99
+ "fill": props.fill,
100
+ "beforeClickStep": handleBeforeClickStep,
101
+ "stepTemplate": renderStep,
102
+ "customClass": ["ak-steps", props.clickable ? "" : "ak-steps--static", attrs.class].filter(Boolean).join(" ")
103
+ }, null);
104
+ }
105
+ });
106
+ export {
107
+ AppSteps
108
+ };
@@ -0,0 +1,415 @@
1
+ import { type PropType } from 'vue';
2
+ export interface AppTableColumn<T = Record<string, unknown>> {
3
+ key: string;
4
+ /**
5
+ * 列标题。两种形态:
6
+ * - `string`:普通单行标题;
7
+ * - `() => unknown`:**自定义表头节点**(如双行表头「来源列1 / srcCol01」),
8
+ * 内部翻译为 farris 的 `headerFormatter`(此时 `title` 传空串)。
9
+ */
10
+ title: string | (() => unknown);
11
+ /**
12
+ * 列宽。两种形态(与迁移前的 farris 用法一一对应):
13
+ * - `number`:作为**权重**参与内部 `fitMode:'percentage'` 的比例分配(不是绝对 px);
14
+ * - `` `${number}%` ``:百分比字符串,直接交给 farris 按百分比分配。
15
+ * 同一列集合内允许两种形态混排(分配规则由 farris 决定,与迁移前行为一致)。
16
+ */
17
+ width?: number | `${number}%`;
18
+ align?: 'left' | 'center' | 'right';
19
+ /** 自定义单元格渲染:只收业务对象,不收 farris 的 cell/row 包装 */
20
+ render?: (row: T, index: number) => unknown;
21
+ }
22
+ /**
23
+ * 选中契约(方案 §9.1)。
24
+ *
25
+ * 受控 / 非受控只看 **是否传入 `selected`**:
26
+ * - **受控**(传 `selected`):显示态完全由它决定,AppTable 绝不改写消费方集合 —— 翻页、
27
+ * 重载、数据刷新都保留(跨页选中的正确语义);`onSelectedChange` 上报**增量**
28
+ * (本次发生翻转的 id 列表,消费方按「翻转这些 id 的成员关系」合并)。
29
+ * - **非受控**(不传 `selected`):内部维护选中集,`onSelectedChange` 上报**全量**;
30
+ * `rows` 变化时与现存行取交集 —— 同页刷新保留选中,翻页后旧页 id 不在数据里即自然清空
31
+ * (「默认仅当前页」语义,无需消费方干预)。
32
+ *
33
+ * 自绘选择列(不启用 farris 内置选择):farris 的选中态是内部单通道、与外部集合无法对齐,
34
+ * 且 `keepSelectingOnPaging` 等语义与受控契约冲突。故 AppTable 自绘首列并保持
35
+ * 「外部集合 = 唯一状态源」。
36
+ */
37
+ export interface AppTableSelection<T = Record<string, unknown>> {
38
+ /** multiple 渲染复选框列 + 表头全选;single 渲染单选框列(选中集恒为 0 或 1 个 id) */
39
+ mode?: 'single' | 'multiple';
40
+ /** 受控选中集(行主键 id 列表)。传入即受控 */
41
+ selected?: string[];
42
+ /** 选中变化:受控上报增量 id,非受控上报全量 id */
43
+ onSelectedChange?: (ids: string[]) => void;
44
+ /** 行级可勾选判定;返回 false 的行禁用且不参与全选 */
45
+ selectable?: (row: T) => boolean;
46
+ /** 自定义表头全选语义(如「仅本页待处理项」);不传则默认对本页可选行全选 / 全不选 */
47
+ onSelectAll?: (rows: T[]) => void;
48
+ }
49
+ export interface AppTableProps<T = Record<string, unknown>> {
50
+ rows: T[];
51
+ columns: AppTableColumn<T>[];
52
+ /** 行主键字段名(业务字段,内部翻译为 farris idField) */
53
+ rowKey: string;
54
+ loading?: boolean;
55
+ error?: unknown;
56
+ /** 空态文案;不传显示默认 */
57
+ empty?: string;
58
+ /** 序号列:true 默认 60px 宽,或显式传 { heading, width } */
59
+ rowNumber?: boolean | {
60
+ heading?: string;
61
+ width?: number;
62
+ };
63
+ /** 行高(px);不传沿用 farris 自动行高(§11.6 的 32px 统一属批次 5 视觉收敛) */
64
+ rowHeight?: number;
65
+ /**
66
+ * 表头高度(px);**不传即沿用 farris 默认(32px)**。
67
+ *
68
+ * 用途:`columns[].title` 传函数(双行表头)时,默认 32px 装不下第二行。
69
+ * 实现走 bridge 白名单里的 `.ak-table--custom-header` 规则(farris 把表头高度内联写死,
70
+ * 只能由 `!important` 压过),只在本 prop 传入时生效。
71
+ */
72
+ headerHeight?: number;
73
+ /** 斑马纹;不传沿用 farris 默认(true)。设计稿无斑马纹者显式传 false */
74
+ stripe?: boolean;
75
+ /** 表格外框(清单卡形态:1px 描边 + 8px 圆角,样式在 app-kit 内);不传则无外框 */
76
+ framed?: boolean;
77
+ /**
78
+ * 单元格读取的外部响应式状态(授权概要/来源名等)。
79
+ *
80
+ * `render` 在响应式渲染函数内执行时 Vue 会追踪依赖,多数场景不需要它;
81
+ * 本 prop 是为「列定义被提取为模块级静态常量、闭包不追踪」的场景准备的逃生舱 ——
82
+ * 值变化即沿同一条重推路径刷新一次数据源。传一个包含这些状态的数组/对象即可。
83
+ */
84
+ refreshKey?: unknown;
85
+ /** 选中契约;false(默认)不渲染选择列 */
86
+ selection?: false | AppTableSelection<T>;
87
+ /**
88
+ * 行高亮(**单值、无选择列**):传行主键值即把该行染成选中态。
89
+ *
90
+ * 用于「选择模式」这类场景:需要一眼看出当前选中哪行,但**不想要复选框/单选框列**
91
+ * (列会挤压内容,且语义上不是多选)。
92
+ * 与 `selection` 互不影响:只传本 prop 不会渲染选择列;两者同时传时应只用其一。
93
+ */
94
+ rowHighlightKey?: string;
95
+ /**
96
+ * 行级样式钩子(farris `rowOption.customRowStyle` 的收敛形态)。
97
+ *
98
+ * 返回 class 字符串或 `{ 类名: 布尔 }` 对象,用于「来源值组合重复的行标红」这类行级高亮。
99
+ * 只透传 class:行内联样式(style)不对外开放。
100
+ */
101
+ rowClass?: (row: T) => string | Record<string, boolean> | undefined;
102
+ onRowClick?: (row: T) => void;
103
+ /** 双击行(编辑入口) */
104
+ onRowDoubleClick?: (row: T) => void;
105
+ /**
106
+ * 强制重挂逃生舱:farris 在 mount 时把行高与列宽固化为内联 px,改 prop 不重算。
107
+ * 缩放档位 / 尺寸基准变化时递增本值即可重建网格(等价于迁移前的
108
+ * `key={gridKey}` 写法)。日常的容器宽度变化不需要它 —— 见 onContainerResize。
109
+ */
110
+ tableKey?: string | number;
111
+ /**
112
+ * 容器宽度变化回调(**已在内部做过 150ms 防抖**)。
113
+ * 收到回调后由消费方决定是否递增 `tableKey` 重挂;不传则不观察容器,
114
+ * 也不会产生额外的包裹元素(DOM 结构与不使用本 prop 时完全一致)。
115
+ */
116
+ onContainerResize?: (width: number) => void;
117
+ /**
118
+ * 容器宽度的轮询间隔(ms)。用于 **CSS zoom(平台顶部缩放按钮)** 场景:
119
+ * 该缩放不触发 resize / ResizeObserver,只能轮询 `clientWidth` 兜底。
120
+ * 不传则只用 ResizeObserver;传入即开启轮询,卸载时自动清理。
121
+ */
122
+ resizePollInterval?: number;
123
+ }
124
+ /**
125
+ * 数据表格(封装 farris FDataGrid)。
126
+ *
127
+ * 内部一次消化 farris 的全部已知坑,调用方只面对朴素业务值:
128
+ * - data/columns 只取初始值 → 内部 watch rows 后单条 updateDataSource 重推路径
129
+ * - 单元格回调拿到包装对象(业务数据在 row.raw)→ render(row, index) 直接给业务对象
130
+ * - readonly proxy 炸序号列 → 内部扁平化({...row})
131
+ * - 三态(loading/empty/error)内建
132
+ * - 选中态自绘(见 AppTableSelection 契约),farris 内置选择恒关闭,
133
+ * 避免「farris 内部选中 + 外部集合」双通道(另注:farris 该键名拼写为 `enabelSelectRow`)
134
+ *
135
+ * @example
136
+ * const columns: AppTableColumn<Topic>[] = [
137
+ * { key: 'name', title: t('topic.nameLabel'), width: 220 },
138
+ * { key: 'enabled', title: t('topic.enabledLabel'), width: 100,
139
+ * render: (row) => <AppSwitch modelValue={row.enabled} onChange={(v) => handleToggle(row, v)} /> },
140
+ * ]
141
+ * <AppTable rows={topics} columns={columns} rowKey="id" rowNumber loading={isLoading} />
142
+ *
143
+ * @example 受控跨页多选(选中集由页面持有,翻页不清空)
144
+ * <AppTable rows={rows} columns={columns} rowKey="upstreamSkillId"
145
+ * selection={{
146
+ * mode: 'multiple',
147
+ * selected: [...selectedIds], // 受控:显示态由此决定
148
+ * onSelectedChange: (delta) => { // 增量:翻转这些 id 的成员关系
149
+ * const next = new Set(selectedIds)
150
+ * for (const id of delta) next.has(id) ? next.delete(id) : next.add(id)
151
+ * selectedIds = next
152
+ * },
153
+ * selectable: (row) => row.admissionStatus === 'PENDING',
154
+ * onSelectAll: (pageRows) => toggleAllPending(pageRows), // 自定义全选语义
155
+ * }} />
156
+ */
157
+ export declare const AppTable: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
158
+ rows: {
159
+ type: PropType<unknown[]>;
160
+ required: true;
161
+ };
162
+ columns: {
163
+ type: PropType<AppTableColumn<never>[]>;
164
+ required: true;
165
+ };
166
+ rowKey: {
167
+ type: StringConstructor;
168
+ required: true;
169
+ };
170
+ loading: {
171
+ type: BooleanConstructor;
172
+ default: boolean;
173
+ };
174
+ error: {
175
+ type: PropType<any>;
176
+ default: undefined;
177
+ };
178
+ empty: {
179
+ type: StringConstructor;
180
+ default: string;
181
+ };
182
+ emptyDescription: {
183
+ type: StringConstructor;
184
+ default: undefined;
185
+ };
186
+ /** 错误态标题(默认「加载失败」);错误原文会自动作为副文案显示 */
187
+ errorTitle: {
188
+ type: StringConstructor;
189
+ default: string;
190
+ };
191
+ /** 空态操作按钮(如「新建」);与 `onEmptyAction` 同时传才渲染 */
192
+ emptyActionText: {
193
+ type: StringConstructor;
194
+ default: undefined;
195
+ };
196
+ onEmptyAction: {
197
+ type: PropType<() => void>;
198
+ default: undefined;
199
+ };
200
+ /** 错误态操作按钮(如「重试」);与 `onErrorAction` 同时传才渲染 */
201
+ errorActionText: {
202
+ type: StringConstructor;
203
+ default: undefined;
204
+ };
205
+ onErrorAction: {
206
+ type: PropType<() => void>;
207
+ default: undefined;
208
+ };
209
+ skeletonRows: {
210
+ type: NumberConstructor;
211
+ default: number;
212
+ };
213
+ rowNumber: {
214
+ type: PropType<boolean | {
215
+ heading?: string;
216
+ width?: number;
217
+ }>;
218
+ default: boolean;
219
+ };
220
+ rowHeight: {
221
+ type: NumberConstructor;
222
+ default: undefined;
223
+ };
224
+ headerHeight: {
225
+ type: NumberConstructor;
226
+ default: undefined;
227
+ };
228
+ stripe: {
229
+ type: BooleanConstructor;
230
+ default: undefined;
231
+ };
232
+ framed: {
233
+ type: BooleanConstructor;
234
+ default: boolean;
235
+ };
236
+ refreshKey: {
237
+ type: PropType<any>;
238
+ default: undefined;
239
+ };
240
+ selection: {
241
+ type: PropType<false | AppTableSelection<never>>;
242
+ default: boolean;
243
+ };
244
+ rowHighlightKey: {
245
+ type: StringConstructor;
246
+ default: undefined;
247
+ };
248
+ rowClass: {
249
+ type: PropType<(row: never) => string | Record<string, boolean> | undefined>;
250
+ default: undefined;
251
+ };
252
+ onRowClick: {
253
+ type: PropType<(row: never) => void>;
254
+ default: undefined;
255
+ };
256
+ onRowDoubleClick: {
257
+ type: PropType<(row: never) => void>;
258
+ default: undefined;
259
+ };
260
+ tableKey: {
261
+ type: PropType<string | number>;
262
+ default: undefined;
263
+ };
264
+ onContainerResize: {
265
+ type: PropType<(width: number) => void>;
266
+ default: undefined;
267
+ };
268
+ resizePollInterval: {
269
+ type: NumberConstructor;
270
+ default: undefined;
271
+ };
272
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
273
+ rows: {
274
+ type: PropType<unknown[]>;
275
+ required: true;
276
+ };
277
+ columns: {
278
+ type: PropType<AppTableColumn<never>[]>;
279
+ required: true;
280
+ };
281
+ rowKey: {
282
+ type: StringConstructor;
283
+ required: true;
284
+ };
285
+ loading: {
286
+ type: BooleanConstructor;
287
+ default: boolean;
288
+ };
289
+ error: {
290
+ type: PropType<any>;
291
+ default: undefined;
292
+ };
293
+ empty: {
294
+ type: StringConstructor;
295
+ default: string;
296
+ };
297
+ emptyDescription: {
298
+ type: StringConstructor;
299
+ default: undefined;
300
+ };
301
+ /** 错误态标题(默认「加载失败」);错误原文会自动作为副文案显示 */
302
+ errorTitle: {
303
+ type: StringConstructor;
304
+ default: string;
305
+ };
306
+ /** 空态操作按钮(如「新建」);与 `onEmptyAction` 同时传才渲染 */
307
+ emptyActionText: {
308
+ type: StringConstructor;
309
+ default: undefined;
310
+ };
311
+ onEmptyAction: {
312
+ type: PropType<() => void>;
313
+ default: undefined;
314
+ };
315
+ /** 错误态操作按钮(如「重试」);与 `onErrorAction` 同时传才渲染 */
316
+ errorActionText: {
317
+ type: StringConstructor;
318
+ default: undefined;
319
+ };
320
+ onErrorAction: {
321
+ type: PropType<() => void>;
322
+ default: undefined;
323
+ };
324
+ skeletonRows: {
325
+ type: NumberConstructor;
326
+ default: number;
327
+ };
328
+ rowNumber: {
329
+ type: PropType<boolean | {
330
+ heading?: string;
331
+ width?: number;
332
+ }>;
333
+ default: boolean;
334
+ };
335
+ rowHeight: {
336
+ type: NumberConstructor;
337
+ default: undefined;
338
+ };
339
+ headerHeight: {
340
+ type: NumberConstructor;
341
+ default: undefined;
342
+ };
343
+ stripe: {
344
+ type: BooleanConstructor;
345
+ default: undefined;
346
+ };
347
+ framed: {
348
+ type: BooleanConstructor;
349
+ default: boolean;
350
+ };
351
+ refreshKey: {
352
+ type: PropType<any>;
353
+ default: undefined;
354
+ };
355
+ selection: {
356
+ type: PropType<false | AppTableSelection<never>>;
357
+ default: boolean;
358
+ };
359
+ rowHighlightKey: {
360
+ type: StringConstructor;
361
+ default: undefined;
362
+ };
363
+ rowClass: {
364
+ type: PropType<(row: never) => string | Record<string, boolean> | undefined>;
365
+ default: undefined;
366
+ };
367
+ onRowClick: {
368
+ type: PropType<(row: never) => void>;
369
+ default: undefined;
370
+ };
371
+ onRowDoubleClick: {
372
+ type: PropType<(row: never) => void>;
373
+ default: undefined;
374
+ };
375
+ tableKey: {
376
+ type: PropType<string | number>;
377
+ default: undefined;
378
+ };
379
+ onContainerResize: {
380
+ type: PropType<(width: number) => void>;
381
+ default: undefined;
382
+ };
383
+ resizePollInterval: {
384
+ type: NumberConstructor;
385
+ default: undefined;
386
+ };
387
+ }>> & Readonly<{}>, {
388
+ loading: boolean;
389
+ error: any;
390
+ empty: string;
391
+ emptyDescription: string;
392
+ errorTitle: string;
393
+ emptyActionText: string;
394
+ onEmptyAction: () => void;
395
+ errorActionText: string;
396
+ onErrorAction: () => void;
397
+ skeletonRows: number;
398
+ rowNumber: boolean | {
399
+ heading?: string;
400
+ width?: number;
401
+ };
402
+ rowHeight: number;
403
+ headerHeight: number;
404
+ stripe: boolean;
405
+ framed: boolean;
406
+ refreshKey: any;
407
+ selection: false | AppTableSelection<never>;
408
+ rowHighlightKey: string;
409
+ rowClass: (row: never) => string | Record<string, boolean> | undefined;
410
+ onRowClick: (row: never) => void;
411
+ onRowDoubleClick: (row: never) => void;
412
+ tableKey: string | number;
413
+ onContainerResize: (width: number) => void;
414
+ resizePollInterval: number;
415
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;