@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,200 @@
1
+ import { defineComponent, ref, onMounted, onUnmounted, watch, createVNode } from "vue";
2
+ import { FQuerySolution } from "@farris/ui-vue";
3
+ const SENTINEL = "all";
4
+ const READY_TICK = 100;
5
+ function appFilterSelect(options) {
6
+ return {
7
+ type: "combo-list",
8
+ valueField: "value",
9
+ textField: "name",
10
+ enumValueType: "string",
11
+ data: options.map((o) => ({
12
+ value: o.value,
13
+ name: o.label
14
+ })),
15
+ enableClear: true
16
+ };
17
+ }
18
+ function appFilterInput(placeholder) {
19
+ return {
20
+ type: "input-group",
21
+ placeholder,
22
+ updateOn: "change"
23
+ };
24
+ }
25
+ function normalizeConditions(raw) {
26
+ const result = {};
27
+ for (const item of raw) {
28
+ const node = item ?? {};
29
+ const code = String(node.code ?? node.labelCode ?? node.FilterField ?? node.id ?? "");
30
+ if (!code) continue;
31
+ let value = node.Value;
32
+ if (typeof value !== "string" && typeof value !== "number") {
33
+ const legacy = node.value;
34
+ if (legacy && typeof legacy === "object" && "value" in legacy) {
35
+ value = legacy.value ?? "";
36
+ } else {
37
+ value = Array.isArray(legacy) ? legacy[0] ?? "" : legacy ?? "";
38
+ }
39
+ }
40
+ const text = String(value ?? "");
41
+ result[code] = text === SENTINEL ? "" : text;
42
+ }
43
+ return result;
44
+ }
45
+ const AppFilter = /* @__PURE__ */ defineComponent({
46
+ name: "AppFilter",
47
+ inheritAttrs: false,
48
+ props: {
49
+ fields: {
50
+ type: Array,
51
+ required: true
52
+ },
53
+ /** 默认值:字段 **id** → 业务值(哨兵 `all` 表示「全部」);内部翻译为 farris defaultValues */
54
+ defaults: {
55
+ type: Object,
56
+ default: void 0
57
+ },
58
+ searchFields: {
59
+ type: String,
60
+ default: void 0
61
+ },
62
+ searchPlaceholder: {
63
+ type: String,
64
+ default: ""
65
+ },
66
+ /** 条件区横向内联(farris isControlInline) */
67
+ inline: {
68
+ type: Boolean,
69
+ default: true
70
+ },
71
+ expanded: {
72
+ type: Boolean,
73
+ default: true
74
+ },
75
+ /** 关键字字段 code(命中者并入事件 meta.keyword,大小写不敏感) */
76
+ keywordCodes: {
77
+ type: Array,
78
+ default: () => ["fuzzysearch", "keyword", "name", "displayname"]
79
+ },
80
+ /** 就绪轮询上限(100ms/次) */
81
+ readyTries: {
82
+ type: Number,
83
+ default: 100
84
+ },
85
+ /** 忽略条件区重建后挂载即触发的首次空条件事件(就绪后自动复位) */
86
+ ignoreInitialEmpty: {
87
+ type: Boolean,
88
+ default: false
89
+ },
90
+ onChange: {
91
+ type: Function,
92
+ default: void 0
93
+ },
94
+ onQuery: {
95
+ type: Function,
96
+ default: void 0
97
+ },
98
+ onReady: {
99
+ type: Function,
100
+ default: void 0
101
+ }
102
+ },
103
+ setup(props, {
104
+ attrs
105
+ }) {
106
+ const solutionRef = ref(null);
107
+ const defaultValues = ref(null);
108
+ let solutionReady = false;
109
+ let readyTimer;
110
+ let ignoreEmpty = props.ignoreInitialEmpty;
111
+ const toFarrisDefaults = () => {
112
+ const data = Object.entries(props.defaults ?? {}).filter(([, value]) => value !== void 0 && value !== null && value !== "").map(([id, value]) => ({
113
+ id,
114
+ value: {
115
+ value: String(value)
116
+ }
117
+ }));
118
+ return {
119
+ scope: "default",
120
+ data
121
+ };
122
+ };
123
+ const applyFields = () => {
124
+ solutionRef.value?.updateFields?.(props.fields);
125
+ };
126
+ const applyDefaults = () => {
127
+ if (!solutionReady) return;
128
+ const next = toFarrisDefaults();
129
+ if (JSON.stringify(next) === JSON.stringify(defaultValues.value)) return;
130
+ defaultValues.value = next;
131
+ };
132
+ const stopReadyTimer = () => {
133
+ if (readyTimer !== void 0) {
134
+ window.clearInterval(readyTimer);
135
+ readyTimer = void 0;
136
+ }
137
+ };
138
+ const markReady = () => {
139
+ if (solutionReady) return;
140
+ solutionReady = true;
141
+ ignoreEmpty = false;
142
+ applyFields();
143
+ applyDefaults();
144
+ props.onReady?.();
145
+ };
146
+ const waitSolutionReady = () => {
147
+ stopReadyTimer();
148
+ let tries = 0;
149
+ readyTimer = window.setInterval(() => {
150
+ const ready = !!solutionRef.value?.getConditions?.().length;
151
+ if (ready || ++tries > props.readyTries) {
152
+ stopReadyTimer();
153
+ if (ready) markReady();
154
+ }
155
+ }, READY_TICK);
156
+ };
157
+ onMounted(waitSolutionReady);
158
+ onUnmounted(stopReadyTimer);
159
+ watch(() => props.fields, applyFields);
160
+ watch(() => props.defaults, applyDefaults, {
161
+ deep: true
162
+ });
163
+ const emitConditions = (raw, query) => {
164
+ const list = Array.isArray(raw) ? raw : [];
165
+ if (list.length === 0 && ignoreEmpty) return;
166
+ const values = normalizeConditions(list);
167
+ const lower = new Map(Object.keys(values).map((key) => [key.toLowerCase(), values[key]]));
168
+ const keyword = props.keywordCodes.map((code) => lower.get(code.toLowerCase()) ?? "").find((v) => v) ?? "";
169
+ const meta = {
170
+ keyword,
171
+ query
172
+ };
173
+ if (query) props.onQuery?.(values, meta);
174
+ else props.onChange?.(values, meta);
175
+ };
176
+ return () => createVNode("div", {
177
+ "class": ["ak-filter", "farris-form", "farris-form-controls-inline", attrs.class].filter(Boolean).join(" ")
178
+ }, [createVNode(FQuerySolution, {
179
+ "ref": solutionRef,
180
+ "fields": props.fields,
181
+ "presetFields": props.fields,
182
+ "defaultValues": defaultValues.value,
183
+ "searchFields": props.searchFields || void 0,
184
+ "searchPlaceHolder": props.searchPlaceholder,
185
+ "isControlInline": props.inline,
186
+ "expanded": props.expanded,
187
+ "changeQuery": false,
188
+ "initQuery": true,
189
+ "willSetDefaultValues": true,
190
+ "onQuery": (raw) => emitConditions(raw, true),
191
+ "onConditionChange": (raw) => emitConditions(raw, false),
192
+ "onLoadedSolution": markReady
193
+ }, null)]);
194
+ }
195
+ });
196
+ export {
197
+ AppFilter,
198
+ appFilterInput,
199
+ appFilterSelect
200
+ };
@@ -0,0 +1,446 @@
1
+ import { type PropType, type SlotsType, type VNodeChild } from 'vue';
2
+ /** label 列的水平对齐:`right`(默认,与 farris / 主流水平表单一致)或 `left` */
3
+ export type AppFormLabelAlign = 'left' | 'right';
4
+ export interface AppFormProps {
5
+ /** 表单级 label 列宽(px);缺省取令牌 `--ui-form-label-width`(120)。px 不跟随根字号,见 CONTRACT「已知偏差」 */
6
+ labelWidth?: number;
7
+ /**
8
+ * 表单级 label 对齐:`right`(默认,文本贴着控件列)或 `left`(所有 label 起点一致)。
9
+ * `AppForm.Item` 上再写则只改那一行。
10
+ */
11
+ labelAlign?: AppFormLabelAlign;
12
+ /**
13
+ * 表单级控件列宽上限(px);缺省**撑满**剩余宽度。
14
+ *
15
+ * 宽表单(>600px)里让输入框一路拉到右边缘很难看,两种收法二选一:
16
+ * ① 收宽度 —— 传 `controlWidth={360}`,控件列封顶、右侧留白;
17
+ * ② 分两列 —— 传 `columns={2}`,把行并排起来(更充分地用宽度,见下)。
18
+ */
19
+ controlWidth?: number;
20
+ /**
21
+ * 列数:`1`(默认,逐行)或 `2`(**容器够宽才并排**,窄了按列最小宽度自动回落一列)。
22
+ *
23
+ * 两列下每一行都要能独立成格,所以「整行内容」(说明行、卡片组、表格、文本域)记得
24
+ * 在对应 `AppForm.Item` 上给 `fullWidth`,否则会被压成半宽。
25
+ */
26
+ columns?: 1 | 2;
27
+ }
28
+ export interface AppFormItemProps {
29
+ /**
30
+ * 字段名(label 文本)。缺省且非必填时**不渲染 label 列**:控件列占满整行
31
+ * —— 用于无字段名的整块内容(如列编辑区)与纯说明行。
32
+ */
33
+ label?: string;
34
+ /** 必填标记:星号渲染在 label 文本**左侧**(沿 farris 表单字段的同一约定;label 整体右对齐) */
35
+ required?: boolean;
36
+ /** 校验错误文案:非空即进入 invalid 态,文案排布在控件**下方**(不遮挡后续行) */
37
+ error?: string;
38
+ /** 字段说明文案(常驻,排在错误之后) */
39
+ hint?: string;
40
+ /** 本行 label 列宽(px);覆盖 `AppForm` 的表单级设置 */
41
+ labelWidth?: number;
42
+ /** 本行 label 对齐;覆盖 `AppForm` 的表单级设置 */
43
+ labelAlign?: AppFormLabelAlign;
44
+ /**
45
+ * 本行控件列宽上限(px);覆盖 `AppForm` 的表单级设置。
46
+ * 缺省撑满剩余宽度(宽表单里的选型字段用它收敛,避免长条下拉)。
47
+ */
48
+ controlWidth?: number;
49
+ /** 在两列表单里跨满整行(说明行 / 卡片组 / 表格 / 文本域等整块内容) */
50
+ fullWidth?: boolean;
51
+ /**
52
+ * **只读文本形态**:传了它(含空串)即不走控件插槽,改为在控件位渲染纯文本 ——
53
+ * 用于「摘要 / 详情」这类静态表单行(同一个表单里 label 列、行距、错误、说明全部复用)。
54
+ *
55
+ * 空值(`''` / 全空白)由组件统一显示 `—`,消费方不必每处写 `value || '—'`;
56
+ * 换行符原样保留(SQL where 这类多行文本回显不会被压成一行)。
57
+ *
58
+ * 传了它这一行的 label 会降一档**次要色**(与正文色的值拉开层级),控件行不受影响。
59
+ */
60
+ text?: string;
61
+ /**
62
+ * **只读展示行**:只把 label 弱化(次要色),内容仍走默认插槽 ——
63
+ * 用于控件位不是纯文本的只读内容(徽标 / 链接这类)。
64
+ *
65
+ * 纯文本一律用 `text`(它自带只读语义,不必再传本开关);本开关与 `text` 互斥不会冲突 ——
66
+ * 两个都给时 `text` 优先(`readonly` 只是把 label 的弱化带过去)。
67
+ */
68
+ readonly?: boolean;
69
+ }
70
+ /**
71
+ * 表单行(**自建**):`label + 控件 + 错误 + 说明` 四件。
72
+ *
73
+ * 为什么不封装 farris 的 `FDynamicFormGroup`:那是动态表单(元数据驱动)体系里的分组件 ——
74
+ * 控件要经 `editor` 描述对象交给它渲染,label 宽度 / 控件限宽由 farris 表单类写死
75
+ * (inline 6rem 右对齐、字段 max-width 26.625rem),校验信息走**绝对定位的浮层提示条**。
76
+ * 与本仓三条口径冲突:① 控件由消费方直接写(不构造底层配置对象);② 数据入参只收朴素业务值;
77
+ * ③ 错误与说明按文档流排布(浮层在弹窗里会压住下一行的控件)。故按「缺件处置流程」自建,
78
+ * 沿 farris 的既有约定:必填星号固定在 label 文本左侧;**label 对齐是维度**(`labelAlign`,
79
+ * 默认 `right`(与 farris / 主流水平表单一致),`left` 时所有 label 起点一致)。
80
+ *
81
+ * ## 宽表单怎么处理(两条杠杆,可叠加)
82
+ *
83
+ * - **限宽**:`controlWidth` 封顶控件列(表单级给默认、逐行可覆盖)—— 单列表单不至于把输入框拉成长条;
84
+ * - **分两列**:`columns={2}` 让行并排,宽度用得更充分;列最小宽度取令牌
85
+ * `--ui-form-column-min`(默认 320),所以窄容器会**自动回落成一列**,不需要消费方写媒体查询。
86
+ * 两列下「整块内容」记得 `fullWidth`。
87
+ *
88
+ * `AppForm.Item` 是唯一入口(`AppForm` 只承载表单级设置与行间距/列数),
89
+ * 控件从默认插槽进,因此输入框 / 下拉 / 文本域 / 自绘分组卡片共用同一个容器。
90
+ *
91
+ * ## 静态表单(摘要 / 详情)
92
+ *
93
+ * `AppForm.Item` 传 `text` 即切成**只读文本行**,三类行可以在同一个表单里混排 ——
94
+ * label 列宽、行距、错误与说明全部共用,所以「向导最后一步的确认摘要」「详情弹窗」不需要
95
+ * 另起一套描述列表件(自绘表格的 label/value 几何与表单行迟早会漂开)。
96
+ * 空值占位 `—`、长文案折行、换行符保留都由组件给;只读行的 label 自动降一档次要色,
97
+ * 字段名与取值一眼分得开(应用侧写不了 `color`,这层区分只能由组件给)。
98
+ * 控件位要放徽标 / 链接这类**非文本**只读内容时传 `readonly`:内容走默认插槽,label 的弱化照旧。
99
+ *
100
+ * @example
101
+ * <AppForm labelWidth={120} columns={2}>
102
+ * <AppForm.Item label="编码" required error={errors.code} hint="保存后不可修改">
103
+ * <AppInput modelValue={form.code} onChange={(v) => (form.code = v)} />
104
+ * </AppForm.Item>
105
+ * <AppForm.Item label="缓存策略" controlWidth={360}>
106
+ * <AppSelect options={cacheOptions} modelValue={form.cache} onChange={…} />
107
+ * </AppForm.Item>
108
+ * <AppForm.Item label="过滤条件" fullWidth>
109
+ * <AppTextarea modelValue={form.filter} onChange={…} />
110
+ * </AppForm.Item>
111
+ * </AppForm>
112
+ */
113
+ export declare const AppFormItem: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
114
+ label: {
115
+ type: StringConstructor;
116
+ default: undefined;
117
+ };
118
+ required: {
119
+ type: BooleanConstructor;
120
+ default: boolean;
121
+ };
122
+ error: {
123
+ type: StringConstructor;
124
+ default: string;
125
+ };
126
+ hint: {
127
+ type: StringConstructor;
128
+ default: string;
129
+ };
130
+ labelWidth: {
131
+ type: NumberConstructor;
132
+ default: undefined;
133
+ };
134
+ labelAlign: {
135
+ type: PropType<AppFormLabelAlign>;
136
+ default: undefined;
137
+ };
138
+ controlWidth: {
139
+ type: NumberConstructor;
140
+ default: undefined;
141
+ };
142
+ fullWidth: {
143
+ type: BooleanConstructor;
144
+ default: boolean;
145
+ };
146
+ /** `undefined` 与「传了空串」必须区分:前者走插槽(控件形态),后者是「值为空的只读行」 */
147
+ text: {
148
+ type: StringConstructor;
149
+ default: undefined;
150
+ };
151
+ /** 只读展示行(label 弱化,内容走插槽):用于控件位是徽标 / 链接这类非文本的只读内容 */
152
+ readonly: {
153
+ type: BooleanConstructor;
154
+ default: boolean;
155
+ };
156
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
157
+ label: {
158
+ type: StringConstructor;
159
+ default: undefined;
160
+ };
161
+ required: {
162
+ type: BooleanConstructor;
163
+ default: boolean;
164
+ };
165
+ error: {
166
+ type: StringConstructor;
167
+ default: string;
168
+ };
169
+ hint: {
170
+ type: StringConstructor;
171
+ default: string;
172
+ };
173
+ labelWidth: {
174
+ type: NumberConstructor;
175
+ default: undefined;
176
+ };
177
+ labelAlign: {
178
+ type: PropType<AppFormLabelAlign>;
179
+ default: undefined;
180
+ };
181
+ controlWidth: {
182
+ type: NumberConstructor;
183
+ default: undefined;
184
+ };
185
+ fullWidth: {
186
+ type: BooleanConstructor;
187
+ default: boolean;
188
+ };
189
+ /** `undefined` 与「传了空串」必须区分:前者走插槽(控件形态),后者是「值为空的只读行」 */
190
+ text: {
191
+ type: StringConstructor;
192
+ default: undefined;
193
+ };
194
+ /** 只读展示行(label 弱化,内容走插槽):用于控件位是徽标 / 链接这类非文本的只读内容 */
195
+ readonly: {
196
+ type: BooleanConstructor;
197
+ default: boolean;
198
+ };
199
+ }>> & Readonly<{}>, {
200
+ label: string;
201
+ text: string;
202
+ error: string;
203
+ required: boolean;
204
+ readonly: boolean;
205
+ hint: string;
206
+ labelWidth: number;
207
+ labelAlign: AppFormLabelAlign;
208
+ controlWidth: number;
209
+ fullWidth: boolean;
210
+ }, SlotsType<{
211
+ default?: () => VNodeChild;
212
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
213
+ /**
214
+ * 表单内分组:**就是 `AppSection` 本身**(同一个对象、同一套样式),保留这个名字只为让表单里读起来贴语境
215
+ * ——「区块」这件事只有一套实现,不要在这里另写一份(改样式请改 `app-section.tsx` / `.ak-section*`)。
216
+ */
217
+ export declare const AppFormSection: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
218
+ title: {
219
+ type: StringConstructor;
220
+ default: undefined;
221
+ };
222
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
223
+ title: {
224
+ type: StringConstructor;
225
+ default: undefined;
226
+ };
227
+ }>> & Readonly<{}>, {
228
+ title: string;
229
+ }, SlotsType<{
230
+ default?: () => VNodeChild;
231
+ extra?: () => VNodeChild;
232
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
233
+ /** 复合件入口:`AppForm` + `AppForm.Item` + `AppForm.Section`(与 `AppPanel` / `AppShell` 同款 Object.assign 复合写法) */
234
+ export declare const AppForm: {
235
+ new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("vue").ExtractPropTypes<{
236
+ /** 表单级 label 列宽(px);`AppForm.Item` 的 `labelWidth` 优先级更高 */
237
+ labelWidth: {
238
+ type: NumberConstructor;
239
+ default: undefined;
240
+ };
241
+ /** 表单级 label 对齐;`AppForm.Item` 的 `labelAlign` 优先级更高 */
242
+ labelAlign: {
243
+ type: PropType<AppFormLabelAlign>;
244
+ default: undefined;
245
+ };
246
+ /** 表单级控件列宽上限(px);`AppForm.Item` 的 `controlWidth` 优先级更高 */
247
+ controlWidth: {
248
+ type: NumberConstructor;
249
+ default: undefined;
250
+ };
251
+ /** 列数:1(逐行,默认)/ 2(容器够宽才并排,窄了自动回落一列) */
252
+ columns: {
253
+ type: PropType<1 | 2>;
254
+ default: number;
255
+ };
256
+ }>> & Readonly<{}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, import("vue").PublicProps, {
257
+ columns: 1 | 2;
258
+ labelWidth: number;
259
+ labelAlign: AppFormLabelAlign;
260
+ controlWidth: number;
261
+ }, true, {}, SlotsType<{
262
+ default?: () => VNodeChild;
263
+ }>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
264
+ P: {};
265
+ B: {};
266
+ D: {};
267
+ C: {};
268
+ M: {};
269
+ Defaults: {};
270
+ }, Readonly<import("vue").ExtractPropTypes<{
271
+ /** 表单级 label 列宽(px);`AppForm.Item` 的 `labelWidth` 优先级更高 */
272
+ labelWidth: {
273
+ type: NumberConstructor;
274
+ default: undefined;
275
+ };
276
+ /** 表单级 label 对齐;`AppForm.Item` 的 `labelAlign` 优先级更高 */
277
+ labelAlign: {
278
+ type: PropType<AppFormLabelAlign>;
279
+ default: undefined;
280
+ };
281
+ /** 表单级控件列宽上限(px);`AppForm.Item` 的 `controlWidth` 优先级更高 */
282
+ controlWidth: {
283
+ type: NumberConstructor;
284
+ default: undefined;
285
+ };
286
+ /** 列数:1(逐行,默认)/ 2(容器够宽才并排,窄了自动回落一列) */
287
+ columns: {
288
+ type: PropType<1 | 2>;
289
+ default: number;
290
+ };
291
+ }>> & Readonly<{}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, {
292
+ columns: 1 | 2;
293
+ labelWidth: number;
294
+ labelAlign: AppFormLabelAlign;
295
+ controlWidth: number;
296
+ }>;
297
+ __isFragment?: never;
298
+ __isTeleport?: never;
299
+ __isSuspense?: never;
300
+ } & import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
301
+ /** 表单级 label 列宽(px);`AppForm.Item` 的 `labelWidth` 优先级更高 */
302
+ labelWidth: {
303
+ type: NumberConstructor;
304
+ default: undefined;
305
+ };
306
+ /** 表单级 label 对齐;`AppForm.Item` 的 `labelAlign` 优先级更高 */
307
+ labelAlign: {
308
+ type: PropType<AppFormLabelAlign>;
309
+ default: undefined;
310
+ };
311
+ /** 表单级控件列宽上限(px);`AppForm.Item` 的 `controlWidth` 优先级更高 */
312
+ controlWidth: {
313
+ type: NumberConstructor;
314
+ default: undefined;
315
+ };
316
+ /** 列数:1(逐行,默认)/ 2(容器够宽才并排,窄了自动回落一列) */
317
+ columns: {
318
+ type: PropType<1 | 2>;
319
+ default: number;
320
+ };
321
+ }>> & Readonly<{}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
322
+ columns: 1 | 2;
323
+ labelWidth: number;
324
+ labelAlign: AppFormLabelAlign;
325
+ controlWidth: number;
326
+ }, {}, string, SlotsType<{
327
+ default?: () => VNodeChild;
328
+ }>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & {
329
+ Item: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
330
+ label: {
331
+ type: StringConstructor;
332
+ default: undefined;
333
+ };
334
+ required: {
335
+ type: BooleanConstructor;
336
+ default: boolean;
337
+ };
338
+ error: {
339
+ type: StringConstructor;
340
+ default: string;
341
+ };
342
+ hint: {
343
+ type: StringConstructor;
344
+ default: string;
345
+ };
346
+ labelWidth: {
347
+ type: NumberConstructor;
348
+ default: undefined;
349
+ };
350
+ labelAlign: {
351
+ type: PropType<AppFormLabelAlign>;
352
+ default: undefined;
353
+ };
354
+ controlWidth: {
355
+ type: NumberConstructor;
356
+ default: undefined;
357
+ };
358
+ fullWidth: {
359
+ type: BooleanConstructor;
360
+ default: boolean;
361
+ };
362
+ /** `undefined` 与「传了空串」必须区分:前者走插槽(控件形态),后者是「值为空的只读行」 */
363
+ text: {
364
+ type: StringConstructor;
365
+ default: undefined;
366
+ };
367
+ /** 只读展示行(label 弱化,内容走插槽):用于控件位是徽标 / 链接这类非文本的只读内容 */
368
+ readonly: {
369
+ type: BooleanConstructor;
370
+ default: boolean;
371
+ };
372
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
373
+ label: {
374
+ type: StringConstructor;
375
+ default: undefined;
376
+ };
377
+ required: {
378
+ type: BooleanConstructor;
379
+ default: boolean;
380
+ };
381
+ error: {
382
+ type: StringConstructor;
383
+ default: string;
384
+ };
385
+ hint: {
386
+ type: StringConstructor;
387
+ default: string;
388
+ };
389
+ labelWidth: {
390
+ type: NumberConstructor;
391
+ default: undefined;
392
+ };
393
+ labelAlign: {
394
+ type: PropType<AppFormLabelAlign>;
395
+ default: undefined;
396
+ };
397
+ controlWidth: {
398
+ type: NumberConstructor;
399
+ default: undefined;
400
+ };
401
+ fullWidth: {
402
+ type: BooleanConstructor;
403
+ default: boolean;
404
+ };
405
+ /** `undefined` 与「传了空串」必须区分:前者走插槽(控件形态),后者是「值为空的只读行」 */
406
+ text: {
407
+ type: StringConstructor;
408
+ default: undefined;
409
+ };
410
+ /** 只读展示行(label 弱化,内容走插槽):用于控件位是徽标 / 链接这类非文本的只读内容 */
411
+ readonly: {
412
+ type: BooleanConstructor;
413
+ default: boolean;
414
+ };
415
+ }>> & Readonly<{}>, {
416
+ label: string;
417
+ text: string;
418
+ error: string;
419
+ required: boolean;
420
+ readonly: boolean;
421
+ hint: string;
422
+ labelWidth: number;
423
+ labelAlign: AppFormLabelAlign;
424
+ controlWidth: number;
425
+ fullWidth: boolean;
426
+ }, SlotsType<{
427
+ default?: () => VNodeChild;
428
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
429
+ Section: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
430
+ title: {
431
+ type: StringConstructor;
432
+ default: undefined;
433
+ };
434
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
435
+ title: {
436
+ type: StringConstructor;
437
+ default: undefined;
438
+ };
439
+ }>> & Readonly<{}>, {
440
+ title: string;
441
+ }, SlotsType<{
442
+ default?: () => VNodeChild;
443
+ extra?: () => VNodeChild;
444
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
445
+ };
446
+ export type AppFormCompound = typeof AppForm;