element-plus-suite 0.0.0-stage → 0.0.2

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/README.md CHANGED
@@ -1,3 +1,128 @@
1
- # Temporary Holding Version
1
+ # Element Plus Suite
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Element Plus Suite 是基于 Element Plus 二次封装的组件库,开箱即用。可以显著地提升制作 CRUD 页面的效率,轻松搬砖。
4
+
5
+ [文档](https://th74100.github.io/element-plus-suite/) · [GitHub](https://github.com/th74100/element-plus-suite)
6
+
7
+ ## 特性
8
+
9
+ - **🚀 高效开发**:提供常用业务组件,减少重复代码
10
+ - **🎯 灵活配置**:支持 JSON 配置式和模板式,满足不同场景需求
11
+ - **💪 TypeScript**:提供完整的类型定义,更好的开发体验
12
+ - **🔥 Element Plus**:基于 Element Plus,支持主题定制
13
+
14
+ ## 环境要求
15
+
16
+ - Vue 3.2 或更高版本
17
+ - Element Plus 2.0 或更高版本
18
+ - 支持 ESM 的现代构建工具
19
+
20
+ ## 安装
21
+
22
+ ```bash
23
+ npm install element-plus-suite
24
+ ```
25
+
26
+ ## 注册组件
27
+
28
+ 如果项目已经全局注册 Element Plus,可以直接注册组件库:
29
+
30
+ ```ts
31
+ import { createApp } from 'vue'
32
+ import ElementPlusSuite from 'element-plus-suite'
33
+ import App from './App.vue'
34
+
35
+ const app = createApp(App)
36
+
37
+ app.use(ElementPlusSuite)
38
+ app.mount('#app')
39
+ ```
40
+
41
+ 如果需要一起注册 Element Plus:
42
+
43
+ ```ts
44
+ import { createApp } from 'vue'
45
+ import ElementPlus from 'element-plus'
46
+ import 'element-plus/dist/index.css'
47
+ import ElementPlusSuite from 'element-plus-suite'
48
+ import App from './App.vue'
49
+
50
+ const app = createApp(App)
51
+
52
+ app.use(ElementPlus)
53
+ app.use(ElementPlusSuite)
54
+ app.mount('#app')
55
+ ```
56
+
57
+ 也可以按需导入:
58
+
59
+ ```ts
60
+ import { ElTablePro } from 'element-plus-suite'
61
+ ```
62
+
63
+ ## 快速开始
64
+
65
+ ```vue
66
+ <script setup lang="ts">
67
+ import { ElTablePro, type TableProColumn } from 'element-plus-suite'
68
+
69
+ interface User {
70
+ id: number
71
+ name: string
72
+ email: string
73
+ }
74
+
75
+ const columns: TableProColumn<User>[] = [
76
+ { prop: 'name', label: '姓名', minWidth: 140 },
77
+ { prop: 'email', label: '邮箱', minWidth: 220 },
78
+ ]
79
+
80
+ const dataSource: User[] = [
81
+ { id: 1, name: '林晓', email: 'linxiao@example.com' },
82
+ { id: 2, name: '陈默', email: 'chenmo@example.com' },
83
+ ]
84
+ </script>
85
+
86
+ <template>
87
+ <ElTablePro
88
+ :columns="columns"
89
+ :data="dataSource"
90
+ row-key="id"
91
+ :pagination="false"
92
+ />
93
+ </template>
94
+ ```
95
+
96
+ ## 远程数据
97
+
98
+ 将 `data` 换成 `request` 即可接入远程数据。`request` 接收当前分页参数和取消信号,并返回统一的数据结构:
99
+
100
+ ```ts
101
+ import type { TableProRequest } from 'element-plus-suite'
102
+
103
+ const requestUsers: TableProRequest<User> = async ({
104
+ page,
105
+ pageSize,
106
+ signal,
107
+ }) => {
108
+ const params = new URLSearchParams({
109
+ page: String(page ?? 1),
110
+ pageSize: String(pageSize ?? 20),
111
+ })
112
+ const response = await fetch(`/api/users?${params}`, { signal })
113
+ const payload = await response.json()
114
+
115
+ return {
116
+ data: payload.list,
117
+ total: payload.total,
118
+ }
119
+ }
120
+ ```
121
+
122
+ 接口的原始返回结构在 `request` 内部适配即可,组件只接收 `data` 和 `total`。
123
+
124
+ 更多用法请查看[文档](https://th74100.github.io/element-plus-suite/)。
125
+
126
+ ## License
127
+
128
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const o=require("vue"),b=require("element-plus");function M(e,t){return e.flatMap(r=>{if(r.visible===!1)return[];const{visible:l,slot:c,headerSlot:s,render:u,headerRender:n,autoMerge:a,children:d,...m}=r,p={...m},g={},h=c?t[c]:void 0,y=s?t[s]:void 0;if(h?g.default=h:u&&(g.default=f=>u({row:f.row,column:f.column,$index:f.$index})),y?g.header=y:n&&(g.header=f=>n({column:f.column,$index:f.$index,store:f.store,_self:f._self})),d?.length){const f={default:()=>M(d,t)};return g.header&&(f.header=g.header),[o.h(b.ElTableColumn,p,f)]}return[o.h(b.ElTableColumn,p,Object.keys(g).length?g:void 0)]})}function z(e){return e.prop??e.property}function x(e,t){if(e===null||typeof e!="object")return;const r=e;if(Object.prototype.hasOwnProperty.call(r,t))return r[t];if(!t.includes("."))return;let l=r;for(const c of t.split(".")){if(l===null||typeof l!="object")return;l=l[c]}return l}function q(e){return e.flatMap(t=>t.visible===!1?[]:t.children?.length?q(t.children):[t])}function C(e,t=[]){const r=q(e),l=new Map;for(const n of r){const a=z(n);a&&!l.has(a)&&l.set(a,n)}const c=new Set,s=[],u=n=>{!n||c.has(n)||!l.has(n)||(c.add(n),s.push({key:n,getValue:a=>x(a,n)}))};return t.forEach(u),r.forEach(n=>{n.autoMerge&&u(z(n))}),s}function D(e,t){const r=e.length,l=new Map(t.map(u=>[u.key,Array.from({length:r},()=>1)]));if(!r||!t.length)return l;const c=e.map(u=>t.map(n=>n.getValue(u))),s=t.map(()=>0);for(let u=1;u<=r;u+=1){let n=!0;for(let a=0;a<t.length;a+=1){const d=u<r&&n&&c[u][a]===c[u-1][a];if(!d){const m=l.get(t[a].key),p=s[a],g=u-p;m[p]=g;for(let h=p+1;h<u;h+=1)m[h]=0;s[a]=u}n=d}}return l}function I(e,t="children"){return e.some(r=>{if(r===null||typeof r!="object")return!1;const l=r[t];return Array.isArray(l)&&l.length>0})}function L(e){const t=o.computed(()=>C(e.columns(),e.mergeFields())),r=o.computed(()=>t.value.length?e.tableRef.value?.store?.states?.data?.value??e.data.value:e.data.value),l=o.computed(()=>{if(!t.value.length||e.lazy())return new Map;const s=e.treeProps()?.children??"children",u=r.value;return I(u,s)?new Map:D(u,t.value)});return{spanMethod:o.computed(()=>{const s=e.userSpanMethod();return t.value.length?u=>{const n=s?.(u);if(n!==void 0)return n;const a=u.column.property,d=a?l.value.get(a)?.[u.rowIndex]:void 0;if(!(d===void 0||d===1))return{rowspan:d,colspan:1}}:s}),spanMap:l}}const T={page:1,pageSize:20,pageSizes:[10,20,50,100],layout:"total, sizes, prev, pager, next, jumper",background:!0};function _(e){return e===!1?null:{...T,...e===!0?{}:e??{}}}function O(e){const t=o.computed(()=>_(e())),r=o.shallowRef(t.value?.page??1),l=o.shallowRef(t.value?.pageSize??20);o.watch(()=>t.value?.page,n=>{n!==void 0&&(r.value=n)}),o.watch(()=>t.value?.pageSize,n=>{n!==void 0&&(l.value=n)});const c=o.computed(()=>t.value?r.value:null),s=o.computed(()=>t.value?l.value:null);function u(n){l.value=n,r.value=1}return{enabled:o.computed(()=>t.value!=null),config:t,currentPage:r,pageSize:l,requestPage:c,requestPageSize:s,setPageSize:u}}function j(e){const t=o.shallowRef(!1);let r=null,l=0;async function c(){const u=e.request();if(!u)return;r?.abort(),r=new AbortController;const n=++l,a=r;t.value=!0;try{const d=await u({page:e.page(),pageSize:e.pageSize(),signal:a.signal});if(a.signal.aborted||n!==l)return;e.onData?.(d),e.onLoaded?.(d)}catch(d){if(a.signal.aborted||n!==l)return;e.onError?.(d)}finally{n===l&&(t.value=!1)}}function s(){r?.abort(),l+=1,t.value=!1}return o.onBeforeUnmount(s),{loading:t,load:c,cancel:s}}const A=o.defineComponent({name:"ElTablePro",inheritAttrs:!1,props:{columns:{type:Array,default:()=>[]},request:{type:Function,default:void 0},pagination:{type:[Boolean,Object],default:!0},mergeFields:{type:Array,default:()=>[]},data:{type:Array,default:()=>[]},rowKey:{type:[String,Function],required:!0}},emits:{loaded:e=>!0,error:e=>!0},setup(e,{attrs:t,emit:r,expose:l}){const c=o.useSlots(),s=o.shallowRef(null),u=o.shallowRef([]),n=o.shallowRef(0),a=O(()=>e.pagination),d=o.computed(()=>{const i=e.rowKey;return typeof i=="function"?v=>String(i(v)):i}),{loading:m,load:p,cancel:g}=j({request:()=>e.request,page:()=>a.requestPage.value,pageSize:()=>a.requestPageSize.value,onData:i=>{u.value=i.data,n.value=i.total},onLoaded:i=>r("loaded",i),onError:i=>r("error",i)}),h=o.computed(()=>m.value),y=o.computed(()=>{if(e.request)return u.value;if(!e.data)return[];if(!a.config.value)return e.data;const i=(a.currentPage.value-1)*a.pageSize.value;return e.data.slice(i,i+a.pageSize.value)}),f=o.computed(()=>e.request?n.value:e.data?.length??0),{spanMethod:R}=L({tableRef:s,columns:()=>e.columns,data:y,mergeFields:()=>e.mergeFields,userSpanMethod:()=>t.spanMethod,treeProps:()=>t.treeProps,lazy:()=>!!t.lazy});async function S(i){i?.page!==void 0&&(a.currentPage.value=i.page),await p()}o.watch(()=>e.request,i=>{u.value=[],n.value=0,i?S():g()}),o.watch(()=>[a.requestPage.value,a.requestPageSize.value],()=>{e.request&&S()});const F=new Proxy({},{get(i,v){if(v==="reload")return S;const P=s.value;if(!P)return;const w=P[v];return typeof w=="function"?w.bind(P):w},has(i,v){return v==="reload"?!0:s.value!=null&&v in s.value}});return l(F),o.onMounted(()=>{e.request&&S()}),()=>{const i=o.h(b.ElTable,{...t,ref:s,data:y.value,rowKey:d.value,spanMethod:R.value},{default:()=>M(e.columns,c),empty:c.empty,append:c.append});return[o.withDirectives(i,[[b.vLoading,h.value]]),a.enabled.value?o.h(b.ElPagination,{currentPage:a.currentPage.value,pageSize:a.pageSize.value,total:f.value,pageSizes:[...a.config.value?.pageSizes??[]],layout:a.config.value?.layout,background:a.config.value?.background,"onUpdate:currentPage":v=>{a.currentPage.value=v},"onUpdate:pageSize":v=>{a.setPageSize(v)}}):null]}}}),k=[A];function E(e){k.forEach(t=>{const r=t.name;r&&e.component(r,t)})}const B={install:E};exports.ElTablePro=A;exports.TABLE_PRO_DEFAULT_PAGINATION=T;exports.default=B;exports.install=E;exports.normalizePagination=_;
@@ -0,0 +1,9 @@
1
+ import { App } from 'vue';
2
+ import { ElTablePro } from './table-pro';
3
+ export * from './table-pro';
4
+ export { ElTablePro };
5
+ export declare function install(app: App): void;
6
+ declare const _default: {
7
+ install: typeof install;
8
+ };
9
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,338 @@
1
+ import { h as P, computed as g, shallowRef as m, watch as z, onBeforeUnmount as F, defineComponent as C, useSlots as D, onMounted as R, withDirectives as j } from "vue";
2
+ import { ElTableColumn as q, ElTable as I, vLoading as L, ElPagination as k } from "element-plus";
3
+ function T(e, t) {
4
+ return e.flatMap((r) => {
5
+ if (r.visible === !1) return [];
6
+ const {
7
+ visible: l,
8
+ slot: s,
9
+ headerSlot: o,
10
+ render: u,
11
+ headerRender: n,
12
+ autoMerge: a,
13
+ children: c,
14
+ ...y
15
+ } = r, p = { ...y }, f = {}, h = s ? t[s] : void 0, b = o ? t[o] : void 0;
16
+ if (h ? f.default = h : u && (f.default = (d) => u({
17
+ row: d.row,
18
+ column: d.column,
19
+ $index: d.$index
20
+ })), b ? f.header = b : n && (f.header = (d) => n({
21
+ column: d.column,
22
+ $index: d.$index,
23
+ store: d.store,
24
+ _self: d._self
25
+ })), c?.length) {
26
+ const d = {
27
+ default: () => T(c, t)
28
+ };
29
+ return f.header && (d.header = f.header), [P(q, p, d)];
30
+ }
31
+ return [
32
+ P(
33
+ q,
34
+ p,
35
+ Object.keys(f).length ? f : void 0
36
+ )
37
+ ];
38
+ });
39
+ }
40
+ function x(e) {
41
+ return e.prop ?? e.property;
42
+ }
43
+ function O(e, t) {
44
+ if (e === null || typeof e != "object") return;
45
+ const r = e;
46
+ if (Object.prototype.hasOwnProperty.call(r, t))
47
+ return r[t];
48
+ if (!t.includes(".")) return;
49
+ let l = r;
50
+ for (const s of t.split(".")) {
51
+ if (l === null || typeof l != "object") return;
52
+ l = l[s];
53
+ }
54
+ return l;
55
+ }
56
+ function _(e) {
57
+ return e.flatMap((t) => t.visible === !1 ? [] : t.children?.length ? _(t.children) : [t]);
58
+ }
59
+ function V(e, t = []) {
60
+ const r = _(e), l = /* @__PURE__ */ new Map();
61
+ for (const n of r) {
62
+ const a = x(n);
63
+ a && !l.has(a) && l.set(a, n);
64
+ }
65
+ const s = /* @__PURE__ */ new Set(), o = [], u = (n) => {
66
+ !n || s.has(n) || !l.has(n) || (s.add(n), o.push({
67
+ key: n,
68
+ getValue: (a) => O(a, n)
69
+ }));
70
+ };
71
+ return t.forEach(u), r.forEach((n) => {
72
+ n.autoMerge && u(x(n));
73
+ }), o;
74
+ }
75
+ function B(e, t) {
76
+ const r = e.length, l = new Map(
77
+ t.map((u) => [u.key, Array.from({ length: r }, () => 1)])
78
+ );
79
+ if (!r || !t.length) return l;
80
+ const s = e.map((u) => t.map((n) => n.getValue(u))), o = t.map(() => 0);
81
+ for (let u = 1; u <= r; u += 1) {
82
+ let n = !0;
83
+ for (let a = 0; a < t.length; a += 1) {
84
+ const c = u < r && n && s[u][a] === s[u - 1][a];
85
+ if (!c) {
86
+ const y = l.get(t[a].key), p = o[a], f = u - p;
87
+ y[p] = f;
88
+ for (let h = p + 1; h < u; h += 1)
89
+ y[h] = 0;
90
+ o[a] = u;
91
+ }
92
+ n = c;
93
+ }
94
+ }
95
+ return l;
96
+ }
97
+ function K(e, t = "children") {
98
+ return e.some((r) => {
99
+ if (r === null || typeof r != "object") return !1;
100
+ const l = r[t];
101
+ return Array.isArray(l) && l.length > 0;
102
+ });
103
+ }
104
+ function U(e) {
105
+ const t = g(
106
+ () => V(e.columns(), e.mergeFields())
107
+ ), r = g(() => t.value.length ? e.tableRef.value?.store?.states?.data?.value ?? e.data.value : e.data.value), l = g(() => {
108
+ if (!t.value.length || e.lazy())
109
+ return /* @__PURE__ */ new Map();
110
+ const o = e.treeProps()?.children ?? "children", u = r.value;
111
+ return K(u, o) ? /* @__PURE__ */ new Map() : B(u, t.value);
112
+ });
113
+ return {
114
+ spanMethod: g(() => {
115
+ const o = e.userSpanMethod();
116
+ return t.value.length ? (u) => {
117
+ const n = o?.(u);
118
+ if (n !== void 0) return n;
119
+ const a = u.column.property, c = a ? l.value.get(a)?.[u.rowIndex] : void 0;
120
+ if (!(c === void 0 || c === 1))
121
+ return { rowspan: c, colspan: 1 };
122
+ } : o;
123
+ }),
124
+ spanMap: l
125
+ };
126
+ }
127
+ const $ = {
128
+ page: 1,
129
+ pageSize: 20,
130
+ pageSizes: [10, 20, 50, 100],
131
+ layout: "total, sizes, prev, pager, next, jumper",
132
+ background: !0
133
+ };
134
+ function N(e) {
135
+ return e === !1 ? null : {
136
+ ...$,
137
+ ...e === !0 ? {} : e ?? {}
138
+ };
139
+ }
140
+ function G(e) {
141
+ const t = g(() => N(e())), r = m(t.value?.page ?? 1), l = m(t.value?.pageSize ?? 20);
142
+ z(
143
+ () => t.value?.page,
144
+ (n) => {
145
+ n !== void 0 && (r.value = n);
146
+ }
147
+ ), z(
148
+ () => t.value?.pageSize,
149
+ (n) => {
150
+ n !== void 0 && (l.value = n);
151
+ }
152
+ );
153
+ const s = g(
154
+ () => t.value ? r.value : null
155
+ ), o = g(
156
+ () => t.value ? l.value : null
157
+ );
158
+ function u(n) {
159
+ l.value = n, r.value = 1;
160
+ }
161
+ return {
162
+ // 模板直接依赖这个布尔值,避免访问可能为 null 的配置。
163
+ enabled: g(() => t.value != null),
164
+ config: t,
165
+ currentPage: r,
166
+ pageSize: l,
167
+ requestPage: s,
168
+ requestPageSize: o,
169
+ setPageSize: u
170
+ };
171
+ }
172
+ function H(e) {
173
+ const t = m(!1);
174
+ let r = null, l = 0;
175
+ async function s() {
176
+ const u = e.request();
177
+ if (!u) return;
178
+ r?.abort(), r = new AbortController();
179
+ const n = ++l, a = r;
180
+ t.value = !0;
181
+ try {
182
+ const c = await u({
183
+ page: e.page(),
184
+ pageSize: e.pageSize(),
185
+ signal: a.signal
186
+ });
187
+ if (a.signal.aborted || n !== l)
188
+ return;
189
+ e.onData?.(c), e.onLoaded?.(c);
190
+ } catch (c) {
191
+ if (a.signal.aborted || n !== l)
192
+ return;
193
+ e.onError?.(c);
194
+ } finally {
195
+ n === l && (t.value = !1);
196
+ }
197
+ }
198
+ function o() {
199
+ r?.abort(), l += 1, t.value = !1;
200
+ }
201
+ return F(o), { loading: t, load: s, cancel: o };
202
+ }
203
+ const J = /* @__PURE__ */ C({
204
+ name: "ElTablePro",
205
+ inheritAttrs: !1,
206
+ props: {
207
+ columns: {
208
+ type: Array,
209
+ default: () => []
210
+ },
211
+ request: {
212
+ type: Function,
213
+ default: void 0
214
+ },
215
+ pagination: {
216
+ type: [Boolean, Object],
217
+ default: !0
218
+ },
219
+ mergeFields: {
220
+ type: Array,
221
+ default: () => []
222
+ },
223
+ data: {
224
+ type: Array,
225
+ default: () => []
226
+ },
227
+ rowKey: {
228
+ type: [String, Function],
229
+ required: !0
230
+ }
231
+ },
232
+ emits: {
233
+ loaded: (e) => !0,
234
+ error: (e) => !0
235
+ },
236
+ setup(e, {
237
+ attrs: t,
238
+ emit: r,
239
+ expose: l
240
+ }) {
241
+ const s = D(), o = m(null), u = m([]), n = m(0), a = G(() => e.pagination), c = g(() => {
242
+ const i = e.rowKey;
243
+ return typeof i == "function" ? (v) => String(i(v)) : i;
244
+ }), {
245
+ loading: y,
246
+ load: p,
247
+ cancel: f
248
+ } = H({
249
+ request: () => e.request,
250
+ page: () => a.requestPage.value,
251
+ pageSize: () => a.requestPageSize.value,
252
+ onData: (i) => {
253
+ u.value = i.data, n.value = i.total;
254
+ },
255
+ onLoaded: (i) => r("loaded", i),
256
+ onError: (i) => r("error", i)
257
+ }), h = g(() => y.value), b = g(() => {
258
+ if (e.request) return u.value;
259
+ if (!e.data) return [];
260
+ if (!a.config.value) return e.data;
261
+ const i = (a.currentPage.value - 1) * a.pageSize.value;
262
+ return e.data.slice(i, i + a.pageSize.value);
263
+ }), d = g(() => e.request ? n.value : e.data?.length ?? 0), {
264
+ spanMethod: A
265
+ } = U({
266
+ tableRef: o,
267
+ columns: () => e.columns,
268
+ data: b,
269
+ mergeFields: () => e.mergeFields,
270
+ userSpanMethod: () => t.spanMethod,
271
+ treeProps: () => t.treeProps,
272
+ lazy: () => !!t.lazy
273
+ });
274
+ async function S(i) {
275
+ i?.page !== void 0 && (a.currentPage.value = i.page), await p();
276
+ }
277
+ z(() => e.request, (i) => {
278
+ u.value = [], n.value = 0, i ? S() : f();
279
+ }), z(() => [a.requestPage.value, a.requestPageSize.value], () => {
280
+ e.request && S();
281
+ });
282
+ const E = new Proxy({}, {
283
+ get(i, v) {
284
+ if (v === "reload") return S;
285
+ const M = o.value;
286
+ if (!M) return;
287
+ const w = M[v];
288
+ return typeof w == "function" ? w.bind(M) : w;
289
+ },
290
+ has(i, v) {
291
+ return v === "reload" ? !0 : o.value != null && v in o.value;
292
+ }
293
+ });
294
+ return l(E), R(() => {
295
+ e.request && S();
296
+ }), () => {
297
+ const i = P(I, {
298
+ ...t,
299
+ ref: o,
300
+ data: b.value,
301
+ rowKey: c.value,
302
+ spanMethod: A.value
303
+ }, {
304
+ default: () => T(e.columns, s),
305
+ empty: s.empty,
306
+ append: s.append
307
+ });
308
+ return [j(i, [[L, h.value]]), a.enabled.value ? P(k, {
309
+ currentPage: a.currentPage.value,
310
+ pageSize: a.pageSize.value,
311
+ total: d.value,
312
+ pageSizes: [...a.config.value?.pageSizes ?? []],
313
+ layout: a.config.value?.layout,
314
+ background: a.config.value?.background,
315
+ "onUpdate:currentPage": (v) => {
316
+ a.currentPage.value = v;
317
+ },
318
+ "onUpdate:pageSize": (v) => {
319
+ a.setPageSize(v);
320
+ }
321
+ }) : null];
322
+ };
323
+ }
324
+ }), Q = [J];
325
+ function W(e) {
326
+ Q.forEach((t) => {
327
+ const r = t.name;
328
+ r && e.component(r, t);
329
+ });
330
+ }
331
+ const Z = { install: W };
332
+ export {
333
+ J as ElTablePro,
334
+ $ as TABLE_PRO_DEFAULT_PAGINATION,
335
+ Z as default,
336
+ W as install,
337
+ N as normalizePagination
338
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ import { ComputedRef, ShallowRef } from 'vue';
2
+ import { TableProColumn, TableProSpanMethodParams, TableProTableInstance, TableProTableProps } from '../types';
3
+ interface UseTableMergeOptions<Row> {
4
+ tableRef: ShallowRef<TableProTableInstance | null>;
5
+ columns: () => TableProColumn<Row>[];
6
+ data: ComputedRef<Row[]>;
7
+ mergeFields: () => string[];
8
+ userSpanMethod: () => TableProTableProps['spanMethod'];
9
+ treeProps: () => TableProTableProps['treeProps'];
10
+ lazy: () => boolean;
11
+ }
12
+ export declare function useTableMerge<Row>(options: UseTableMergeOptions<Row>): {
13
+ spanMethod: ComputedRef<import('..').TableProSpanMethod<any> | ((params: TableProSpanMethodParams<Row>) => {
14
+ rowspan: number;
15
+ colspan: number;
16
+ } | number[] | undefined) | undefined>;
17
+ spanMap: ComputedRef<Map<string, number[]>>;
18
+ };
19
+ export {};
@@ -0,0 +1,14 @@
1
+ import { TableProPagination } from '../types';
2
+ /**
3
+ * 管理 TablePro 的分页状态。
4
+ * false 表示关闭分页,此时传给 request 的 page/pageSize 都是 null。
5
+ */
6
+ export declare function useTablePagination(pagination: () => boolean | TableProPagination | undefined): {
7
+ enabled: import('vue').ComputedRef<boolean>;
8
+ config: import('vue').ComputedRef<import('..').ResolvedTableProPagination | null>;
9
+ currentPage: import('vue').ShallowRef<number, number>;
10
+ pageSize: import('vue').ShallowRef<number, number>;
11
+ requestPage: import('vue').ComputedRef<number | null>;
12
+ requestPageSize: import('vue').ComputedRef<number | null>;
13
+ setPageSize: (size: number) => void;
14
+ };
@@ -0,0 +1,20 @@
1
+ import { TableProRequest, TableProRequestResult } from '../types';
2
+ interface UseTableRequestOptions<Row> {
3
+ request: () => TableProRequest<Row> | undefined;
4
+ page: () => number | null;
5
+ pageSize: () => number | null;
6
+ onLoaded?: (result: TableProRequestResult<Row>) => void;
7
+ onError?: (error: unknown) => void;
8
+ onData?: (result: TableProRequestResult<Row>) => void;
9
+ }
10
+ /**
11
+ * 管理远程请求生命周期。
12
+ * 同时使用 AbortController 和递增 requestId,
13
+ * 即使调用方没有透传 signal,旧请求也不会覆盖新数据。
14
+ */
15
+ export declare function useTableRequest<Row>(options: UseTableRequestOptions<Row>): {
16
+ loading: import('vue').ShallowRef<boolean, boolean>;
17
+ load: () => Promise<void>;
18
+ cancel: () => void;
19
+ };
20
+ export {};
@@ -0,0 +1,3 @@
1
+ export { default as ElTablePro } from './index.vue';
2
+ export type { TableProColumn, TableProColumnContext, TableProColumnHeaderRenderScope, TableProColumnRenderScope, TableProInstance, TableProOwnInstance, TableProOwnProps, TableProPagination, TableProProps, TableProRequest, TableProRequestParams, TableProRequestResult, TableProSpanMethod, TableProSpanMethodParams, TableProSpanMethodResult, TableProTableInstance, TableProTableProps, TableProTreeProps, ResolvedTableProPagination, } from './types';
3
+ export { TABLE_PRO_DEFAULT_PAGINATION, normalizePagination, } from './types';
@@ -0,0 +1,68 @@
1
+ import { PropType } from 'vue';
2
+ import { TableProColumn, TableProPagination, TableProRequest, TableProRequestResult } from './types';
3
+ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
4
+ columns: {
5
+ type: PropType<TableProColumn<any>[]>;
6
+ default: () => never[];
7
+ };
8
+ request: {
9
+ type: PropType<TableProRequest<any>>;
10
+ default: undefined;
11
+ };
12
+ pagination: {
13
+ type: PropType<boolean | TableProPagination>;
14
+ default: boolean;
15
+ };
16
+ mergeFields: {
17
+ type: PropType<string[]>;
18
+ default: () => never[];
19
+ };
20
+ data: {
21
+ type: PropType<any[]>;
22
+ default: () => never[];
23
+ };
24
+ rowKey: {
25
+ type: PropType<string | ((row: any) => string | number)>;
26
+ required: true;
27
+ };
28
+ }>, () => (import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
29
+ [key: string]: any;
30
+ }> | null)[], {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
31
+ loaded: (_result: TableProRequestResult<any>) => true;
32
+ error: (_error: unknown) => true;
33
+ }, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
34
+ columns: {
35
+ type: PropType<TableProColumn<any>[]>;
36
+ default: () => never[];
37
+ };
38
+ request: {
39
+ type: PropType<TableProRequest<any>>;
40
+ default: undefined;
41
+ };
42
+ pagination: {
43
+ type: PropType<boolean | TableProPagination>;
44
+ default: boolean;
45
+ };
46
+ mergeFields: {
47
+ type: PropType<string[]>;
48
+ default: () => never[];
49
+ };
50
+ data: {
51
+ type: PropType<any[]>;
52
+ default: () => never[];
53
+ };
54
+ rowKey: {
55
+ type: PropType<string | ((row: any) => string | number)>;
56
+ required: true;
57
+ };
58
+ }>> & Readonly<{
59
+ onError?: ((_error: unknown) => any) | undefined;
60
+ onLoaded?: ((_result: TableProRequestResult<any>) => any) | undefined;
61
+ }>, {
62
+ data: any[];
63
+ columns: TableProColumn<any>[];
64
+ request: TableProRequest<any>;
65
+ pagination: boolean | TableProPagination;
66
+ mergeFields: string[];
67
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
68
+ export default _default;
@@ -0,0 +1,9 @@
1
+ import { Slots, VNode } from 'vue';
2
+ import { TableProColumn } from './types';
3
+ /**
4
+ * 把列配置转换成 ElTableColumn 节点。
5
+ *
6
+ * 注意:ElTable 依赖直接子节点注册列,所以调用方必须把返回值
7
+ * 直接放进 ElTable 的默认插槽,不能再包一层组件。
8
+ */
9
+ export declare function renderTableColumns(columns: TableProColumn<any>[], slots: Slots): VNode[];
@@ -0,0 +1,189 @@
1
+ import { Ref, VNode, VNodeChild } from 'vue';
2
+ /**
3
+ * 表格列在运行时由 Element Plus 提供。
4
+ * 这里只声明组件库会用到的公共字段,其余字段保持开放
5
+ */
6
+ export interface TableProColumnContext<Row = any> {
7
+ id?: string;
8
+ realWidth?: number | null;
9
+ type?: string;
10
+ label?: string;
11
+ className?: string;
12
+ labelClassName?: string;
13
+ property?: string;
14
+ prop?: string;
15
+ width?: string | number;
16
+ minWidth?: string | number;
17
+ renderHeader?: (data: any) => VNode;
18
+ sortable?: boolean | string;
19
+ sortMethod?: (a: Row, b: Row) => number;
20
+ sortBy?: string | ((row: Row, index: number, array?: Row[]) => string) | string[];
21
+ formatter?: (row: Row, column: TableProColumnContext<Row>, cellValue: any, index: number) => string | VNode;
22
+ filters?: {
23
+ text: string;
24
+ value: string;
25
+ }[];
26
+ filteredValue?: string[];
27
+ children?: TableProColumnContext<Row>[];
28
+ [key: string]: any;
29
+ }
30
+ export interface TableProTableStore {
31
+ states?: {
32
+ data?: Ref<any[]>;
33
+ columns?: Ref<TableProColumnContext<any>[]>;
34
+ };
35
+ [key: string]: any;
36
+ }
37
+ /**
38
+ * 使用 Proxy 暴露 ElTable 实例能力。
39
+ */
40
+ export interface TableProTableInstance {
41
+ store: TableProTableStore;
42
+ setCurrentRow: (row: any) => void;
43
+ getSelectionRows?: () => any;
44
+ toggleRowSelection: (row: any, selected?: boolean) => void;
45
+ clearSelection: () => void;
46
+ clearFilter: (columnKeys?: string | string[]) => void;
47
+ toggleAllSelection: () => void;
48
+ toggleRowExpansion: (row: any, expanded?: boolean) => void;
49
+ clearSort: () => void;
50
+ doLayout: () => void;
51
+ sort: (prop: string, order: string) => void;
52
+ [key: string]: any;
53
+ }
54
+ export interface TableProTreeProps {
55
+ hasChildren?: string;
56
+ children?: string;
57
+ [key: string]: any;
58
+ }
59
+ export interface TableProSpanMethodParams<Row = any> {
60
+ row: Row;
61
+ rowIndex: number;
62
+ column: TableProColumnContext<Row>;
63
+ columnIndex: number;
64
+ }
65
+ export type TableProSpanMethodResult = number[] | {
66
+ rowspan: number;
67
+ colspan: number;
68
+ } | undefined;
69
+ export type TableProSpanMethod<Row = any> = (params: TableProSpanMethodParams<Row>) => TableProSpanMethodResult;
70
+ /** TablePro 使用的 ElTable 公共属性;其余原生属性通过开放索引接收。 */
71
+ export interface TableProTableProps {
72
+ spanMethod?: TableProSpanMethod;
73
+ treeProps?: TableProTreeProps;
74
+ [key: string]: any;
75
+ }
76
+ export interface TableProRequestParams {
77
+ page: number | null;
78
+ pageSize: number | null;
79
+ signal: AbortSignal;
80
+ }
81
+ export interface TableProRequestResult<Row> {
82
+ data: Row[];
83
+ total: number;
84
+ }
85
+ export interface TableProColumnHeaderRenderScope<Row extends Record<string, any>> {
86
+ column: TableProColumnContext<Row>;
87
+ $index: number;
88
+ store: TableProTableInstance['store'];
89
+ _self: unknown;
90
+ }
91
+ export interface TableProColumnRenderScope<Row> {
92
+ row: Row;
93
+ column: TableProColumnContext<any>;
94
+ $index: number;
95
+ }
96
+ export type TableProRequest<Row> = (params: TableProRequestParams) => Promise<TableProRequestResult<Row>>;
97
+ type ElTableColumnProps = {
98
+ type?: string;
99
+ label?: string;
100
+ className?: string;
101
+ labelClassName?: string;
102
+ property?: string;
103
+ prop?: string;
104
+ width?: string | number;
105
+ minWidth?: string | number;
106
+ renderHeader?: (data: any) => VNode;
107
+ sortable?: boolean | string;
108
+ sortMethod?: (a: any, b: any) => number;
109
+ sortBy?: string | ((row: any, index: number, array?: any[]) => string) | string[];
110
+ resizable?: boolean;
111
+ columnKey?: string;
112
+ align?: string;
113
+ headerAlign?: string;
114
+ showOverflowTooltip?: boolean | Record<string, any>;
115
+ tooltipFormatter?: (data: any) => string;
116
+ fixed?: boolean | string;
117
+ formatter?: (row: any, column: TableProColumnContext<any>, cellValue: any, index: number) => string | VNode;
118
+ selectable?: (row: any, index: number) => boolean;
119
+ reserveSelection?: boolean;
120
+ filterMethod?: (value: string, row: any, column: TableProColumnContext<any>) => void;
121
+ filteredValue?: string[];
122
+ filters?: {
123
+ text: string;
124
+ value: string;
125
+ }[];
126
+ filterPlacement?: string;
127
+ filterMultiple?: boolean;
128
+ filterClassName?: string;
129
+ index?: number | ((index: number) => number);
130
+ sortOrders?: ('ascending' | 'descending' | null)[];
131
+ [key: string]: any;
132
+ };
133
+ export interface TableProColumnExtra<Row> {
134
+ visible?: boolean;
135
+ slot?: string;
136
+ headerSlot?: string;
137
+ /** 使用渲染函数生成单元格内容 */
138
+ render?: (scope: TableProColumnRenderScope<Row>) => VNodeChild;
139
+ /** 使用渲染函数生成表头内容 */
140
+ headerRender?: (scope: TableProColumnHeaderRenderScope<Row & Record<string, any>>) => VNodeChild;
141
+ /** 当前页内连续相同值时自动合并单元格 */
142
+ autoMerge?: boolean;
143
+ children?: TableProColumn<Row>[];
144
+ }
145
+ export type TableProColumn<Row> = Omit<ElTableColumnProps, 'prop' | 'children' | 'formatter'> & TableProColumnExtra<Row> & {
146
+ prop?: string;
147
+ formatter?: (row: Row, column: TableProColumnContext<any>, cellValue: unknown, index: number) => string | VNode | undefined;
148
+ };
149
+ export interface TableProPagination {
150
+ page?: number;
151
+ pageSize?: number;
152
+ pageSizes?: number[];
153
+ layout?: string;
154
+ background?: boolean;
155
+ }
156
+ export interface TableProOwnProps<Row> {
157
+ columns?: TableProColumn<Row>[];
158
+ request?: TableProRequest<Row>;
159
+ pagination?: boolean | TableProPagination;
160
+ /** 按数组顺序逐级合并连续同值字段 */
161
+ mergeFields?: string[];
162
+ }
163
+ type ElTableProps = Partial<TableProTableProps>;
164
+ export type TableProProps<Row extends Record<string, any>> = Omit<ElTableProps, 'data' | 'rowKey'> & TableProOwnProps<Row> & {
165
+ data?: Row[];
166
+ rowKey: (keyof Row & string) | ((row: Row) => string | number);
167
+ };
168
+ export interface TableProOwnInstance {
169
+ reload: (options?: {
170
+ page?: number;
171
+ }) => Promise<void>;
172
+ }
173
+ export type TableProInstance = TableProOwnInstance & TableProTableInstance;
174
+ export declare const TABLE_PRO_DEFAULT_PAGINATION: {
175
+ readonly page: 1;
176
+ readonly pageSize: 20;
177
+ readonly pageSizes: readonly [10, 20, 50, 100];
178
+ readonly layout: "total, sizes, prev, pager, next, jumper";
179
+ readonly background: true;
180
+ };
181
+ export type ResolvedTableProPagination = {
182
+ page: number;
183
+ pageSize: number;
184
+ pageSizes: readonly number[];
185
+ layout: string;
186
+ background: boolean;
187
+ };
188
+ export declare function normalizePagination(pagination: boolean | TableProPagination | undefined): ResolvedTableProPagination | null;
189
+ export {};
@@ -0,0 +1,14 @@
1
+ import { TableProColumn } from '../types';
2
+ export interface TableProMergeField<Row> {
3
+ key: string;
4
+ getValue: (row: Row) => unknown;
5
+ }
6
+ /**
7
+ * mergeFields 的顺序决定多级合并层级;autoMerge 列按列顺序补充。
8
+ */
9
+ export declare function resolveMergeFields<Row>(columns: TableProColumn<Row>[], mergeFields?: string[]): TableProMergeField<Row>[];
10
+ /**
11
+ * 只合并连续同值。后一个字段必须处在前一个字段的同一组内。
12
+ */
13
+ export declare function calculateRowSpans<Row>(dataSource: readonly Row[], fields: TableProMergeField<Row>[]): Map<string, number[]>;
14
+ export declare function hasTreeRows(dataSource: readonly unknown[], childrenField?: string): boolean;
package/package.json CHANGED
@@ -1,6 +1,32 @@
1
- {
2
- "name": "element-plus-suite",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {
2
+ "name": "element-plus-suite",
3
+ "version": "0.0.2",
4
+ "description": "Unofficial enhancement components for Element Plus",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "main": "./dist/index.cjs",
11
+ "module": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "require": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "scripts": {
21
+ "build": "vite build",
22
+ "typecheck": "vue-tsc --noEmit"
23
+ },
24
+ "peerDependencies": {
25
+ "element-plus": "^2.0.0",
26
+ "vue": "^3.2.0"
27
+ },
28
+ "devDependencies": {
29
+ "element-plus": "^2.11.7",
30
+ "vue": "^3.5.24"
31
+ }
32
+ }