@manohub/ui 1.0.6 → 1.0.8
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/dist/components/code-block/index.d.ts +7 -7
- package/dist/components/input/index.d.ts +16 -3
- package/dist/components/input/index.js +2 -1
- package/dist/components/table/index.d.ts +32 -42
- package/dist/components/table/index.js +164 -119
- package/dist/index.d.ts +1 -1
- package/dist/styles/components/table.css +41 -20
- package/dist/styles/components/table.tokens.css +1 -1
- package/package.json +2 -2
|
@@ -111,9 +111,9 @@ export declare const CodeView: import("vue").DefineComponent<import("vue").Extra
|
|
|
111
111
|
plain: boolean;
|
|
112
112
|
code: string;
|
|
113
113
|
onCopy: (ok: boolean) => void;
|
|
114
|
+
maxHeight: string | number;
|
|
114
115
|
language: string;
|
|
115
116
|
copyable: boolean;
|
|
116
|
-
maxHeight: string | number;
|
|
117
117
|
}, SlotsType<{
|
|
118
118
|
default?: () => VNodeChild;
|
|
119
119
|
}>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -260,8 +260,8 @@ export declare const CodeEditor: import("vue").DefineComponent<import("vue").Ext
|
|
|
260
260
|
modelValue: string;
|
|
261
261
|
readonly: boolean;
|
|
262
262
|
autoSize: boolean | CodeEditorAutoSize;
|
|
263
|
-
language: string;
|
|
264
263
|
maxHeight: string | number;
|
|
264
|
+
language: string;
|
|
265
265
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
266
266
|
/** `CodeBlock` 的 props:**两形态的并集** + 切换开关(按 `editable` 分两组,见各条说明) */
|
|
267
267
|
export interface CodeBlockProps extends CodeViewProps, CodeEditorProps {
|
|
@@ -366,9 +366,9 @@ export declare const CodeBlock: {
|
|
|
366
366
|
modelValue: string;
|
|
367
367
|
readonly: boolean;
|
|
368
368
|
autoSize: boolean | CodeEditorAutoSize;
|
|
369
|
+
maxHeight: string | number;
|
|
369
370
|
language: string;
|
|
370
371
|
copyable: boolean;
|
|
371
|
-
maxHeight: string | number;
|
|
372
372
|
editable: boolean;
|
|
373
373
|
}, true, {}, SlotsType<{
|
|
374
374
|
default?: () => VNodeChild;
|
|
@@ -464,9 +464,9 @@ export declare const CodeBlock: {
|
|
|
464
464
|
modelValue: string;
|
|
465
465
|
readonly: boolean;
|
|
466
466
|
autoSize: boolean | CodeEditorAutoSize;
|
|
467
|
+
maxHeight: string | number;
|
|
467
468
|
language: string;
|
|
468
469
|
copyable: boolean;
|
|
469
|
-
maxHeight: string | number;
|
|
470
470
|
editable: boolean;
|
|
471
471
|
}>;
|
|
472
472
|
__isFragment?: never;
|
|
@@ -559,9 +559,9 @@ export declare const CodeBlock: {
|
|
|
559
559
|
modelValue: string;
|
|
560
560
|
readonly: boolean;
|
|
561
561
|
autoSize: boolean | CodeEditorAutoSize;
|
|
562
|
+
maxHeight: string | number;
|
|
562
563
|
language: string;
|
|
563
564
|
copyable: boolean;
|
|
564
|
-
maxHeight: string | number;
|
|
565
565
|
editable: boolean;
|
|
566
566
|
}, {}, string, SlotsType<{
|
|
567
567
|
default?: () => VNodeChild;
|
|
@@ -638,9 +638,9 @@ export declare const CodeBlock: {
|
|
|
638
638
|
plain: boolean;
|
|
639
639
|
code: string;
|
|
640
640
|
onCopy: (ok: boolean) => void;
|
|
641
|
+
maxHeight: string | number;
|
|
641
642
|
language: string;
|
|
642
643
|
copyable: boolean;
|
|
643
|
-
maxHeight: string | number;
|
|
644
644
|
}, SlotsType<{
|
|
645
645
|
default?: () => VNodeChild;
|
|
646
646
|
}>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -739,8 +739,8 @@ export declare const CodeBlock: {
|
|
|
739
739
|
modelValue: string;
|
|
740
740
|
readonly: boolean;
|
|
741
741
|
autoSize: boolean | CodeEditorAutoSize;
|
|
742
|
-
language: string;
|
|
743
742
|
maxHeight: string | number;
|
|
743
|
+
language: string;
|
|
744
744
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
745
745
|
};
|
|
746
746
|
/** 含成员的 `CodeBlock` 类型(与 `CodeBlockCompoundType` 同义,两个名字都为对齐本仓既有的 `XxxCompound` 口径) */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type PropType, type SlotsType, type VNodeChild } from 'vue';
|
|
1
|
+
import { type HTMLAttributes, type PropType, type SlotsType, type VNodeChild } from 'vue';
|
|
2
2
|
import type { ControlSize } from '../control-size';
|
|
3
3
|
/** 校验状态(`error` 红、`warning` 黄;缺省无校验态) */
|
|
4
4
|
export type InputStatus = 'error' | 'warning';
|
|
@@ -26,10 +26,11 @@ export interface TextareaAutoSize {
|
|
|
26
26
|
* `class` / `style` → 表壳 `.mh-input__wrap`(整件的宽度与显式锚);**其余 attrs 一律透传到控件**
|
|
27
27
|
* (`id` / `name` / `aria-*` / `data-*` / `title` / 原生事件)—— 壳只是排版容器,属性落它上面等于丢掉
|
|
28
28
|
* —— 见 `forwardAttrs`;触发器形态另有 `controlClass` / `controlAttrs` 两个**专口子**(同名键以它为准)。
|
|
29
|
+
* 这组属性在**类型面**同步放开(两形态共认的键):`onClick` / `title` / `data-*` / `aria-*` 直接写在组件上即可。
|
|
29
30
|
*
|
|
30
31
|
* 用法见 `docs/demos/input/`(每个维度一份可运行样例;文档页 `docs/components/input.md`)。
|
|
31
32
|
*/
|
|
32
|
-
|
|
33
|
+
declare const InputBase: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
33
34
|
/** 受控值 */
|
|
34
35
|
modelValue: {
|
|
35
36
|
type: StringConstructor;
|
|
@@ -299,6 +300,16 @@ export declare const Input: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
299
300
|
prefix?: () => VNodeChild;
|
|
300
301
|
suffix?: () => VNodeChild;
|
|
301
302
|
}>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
303
|
+
/**
|
|
304
|
+
* 控件元素上的原生属性 / 事件(`HTMLAttributes` 即输入框与触发器共有的那张基表):
|
|
305
|
+
* 本件不登记它们,运行时按 attrs 透传到控件,这里只把类型面同步放开。
|
|
306
|
+
*/
|
|
307
|
+
type InputControlAttrs = Omit<HTMLAttributes, keyof InstanceType<typeof InputBase>['$props']>;
|
|
308
|
+
export declare const Input: typeof InputBase & {
|
|
309
|
+
new (): {
|
|
310
|
+
$props: InstanceType<typeof InputBase>["$props"] & InputControlAttrs;
|
|
311
|
+
};
|
|
312
|
+
};
|
|
302
313
|
export interface TextareaProps {
|
|
303
314
|
/** 受控值 */
|
|
304
315
|
modelValue?: string;
|
|
@@ -933,7 +944,9 @@ export declare const InputCompound: {
|
|
|
933
944
|
default?: () => VNodeChild;
|
|
934
945
|
prefix?: () => VNodeChild;
|
|
935
946
|
suffix?: () => VNodeChild;
|
|
936
|
-
}>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & {
|
|
947
|
+
}>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & (new () => {
|
|
948
|
+
$props: InstanceType<typeof InputBase>["$props"] & InputControlAttrs;
|
|
949
|
+
}) & {
|
|
937
950
|
Textarea: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
938
951
|
modelValue: {
|
|
939
952
|
type: StringConstructor;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineComponent, ref, computed, createVNode, mergeProps, createTextVNode } from "vue";
|
|
2
2
|
import { Icon } from "@manohub/icon";
|
|
3
3
|
import { borderedClassOf } from "./bordered.js";
|
|
4
|
-
const
|
|
4
|
+
const InputBase = /* @__PURE__ */ defineComponent({
|
|
5
5
|
name: "Input",
|
|
6
6
|
inheritAttrs: false,
|
|
7
7
|
props: {
|
|
@@ -242,6 +242,7 @@ const Input = /* @__PURE__ */ defineComponent({
|
|
|
242
242
|
}, [current.value?.length ?? 0, createTextVNode("/"), props.maxlength]) : null]);
|
|
243
243
|
}
|
|
244
244
|
});
|
|
245
|
+
const Input = InputBase;
|
|
245
246
|
const Textarea = /* @__PURE__ */ defineComponent({
|
|
246
247
|
name: "Textarea",
|
|
247
248
|
inheritAttrs: false,
|
|
@@ -43,6 +43,8 @@ export interface TableColumn {
|
|
|
43
43
|
sortable?: boolean;
|
|
44
44
|
}
|
|
45
45
|
export type TableSortOrder = 'asc' | 'desc' | null;
|
|
46
|
+
/** 满高档取值:不传 / `false` = 高度由内容撑起;`true` / `'parent'` = 占满父级;`number` = 表体滚动上限(px) */
|
|
47
|
+
export type TableFill = boolean | 'parent' | number;
|
|
46
48
|
/** 行数据:至少能用 `rowKey` 取到稳定标识 */
|
|
47
49
|
export type TableRow = Record<string, unknown>;
|
|
48
50
|
/** 行级事件(`onRow` 的返回):给整行挂点击与类,省掉「每列都写一次 onClick」 */
|
|
@@ -73,23 +75,15 @@ export interface TableCellSlotScope {
|
|
|
73
75
|
}
|
|
74
76
|
/** 行级可勾选判定(`selectable` 的函数形态):返回 `false` 的行渲染**禁用态**勾选框,且不进表头全选的增删范围;签名与 `onRow` / `rowClass` 一致(都给 `index`)。 */
|
|
75
77
|
export type TableRowSelectable = (row: TableRow, index: number) => boolean;
|
|
76
|
-
/** 分页档:`false` 不渲染;给对象就渲染分页条(**本件不切片,`data` 是当前页数据**) */
|
|
77
|
-
export interface TablePagination {
|
|
78
|
-
total: number;
|
|
79
|
-
current?: number;
|
|
80
|
-
pageSize?: number;
|
|
81
|
-
pageSizeOptions?: number[];
|
|
82
|
-
onChange?: (page: number, pageSize: number) => void;
|
|
83
|
-
}
|
|
84
78
|
/**
|
|
85
|
-
* 表格(**自绘**;列 × 数据的表格骨架 + 选择列 + 展开行 + 排序事件 +
|
|
79
|
+
* 表格(**自绘**;列 × 数据的表格骨架 + 选择列 + 展开行 + 排序事件 + 三态)。
|
|
86
80
|
*
|
|
87
81
|
* ## 这个组件负责什么、不负责什么(都是刻意的)
|
|
88
82
|
*
|
|
89
83
|
* **负责**:把 `columns` × `data` 渲成表格;列对齐 / 宽度 / 省略 / 必填;行选中(勾选列复用本包的
|
|
90
84
|
* `Checkbox` 组件 —— 它内部才是真实 `<input type="checkbox">`,故面上的
|
|
91
85
|
* `tr:has(.mh-table__col-check input:checked)` 零 JS 路径仍成立;选择器**限定在勾选列内**,否则功能列的
|
|
92
|
-
* `Switch`
|
|
86
|
+
* `Switch` 也会把整行点亮);展开行;排序按钮的**状态与事件**;加载态与空态;
|
|
93
87
|
* `rowClass` / `onRow` 让调用方标分组行、禁用行与挂行级点击。
|
|
94
88
|
*
|
|
95
89
|
* **不负责**:
|
|
@@ -97,8 +91,7 @@ export interface TablePagination {
|
|
|
97
91
|
* - **排序算法归调用方**(列宽拖拽同理):规范只给了 `↕` 字形与拖拽线两处视觉,而 `↕` 是文字符号(本包禁
|
|
98
92
|
* 拿文字符号冒充图标),故朝向改用现成字形 `chevron-up` / `chevron-down` 表达 —— 本件发 `sort` 事件、
|
|
99
93
|
* 画态,真正排序 / 改列宽由调用方决定(它有数据、也知道业务口径);
|
|
100
|
-
* -
|
|
101
|
-
* 让「服务端分页」与「客户端分页」两套口径藏在同一个 prop 里;
|
|
94
|
+
* - **分页条**:本件不内建(`data` 始终是给它的那页数据),页码状态、切片与分页条的摆放都归调用方;
|
|
102
95
|
* - **错误态**:归 `QueryState`(表格只管列数据)。
|
|
103
96
|
*/
|
|
104
97
|
export declare const Table: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
@@ -172,9 +165,19 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
172
165
|
type: BooleanConstructor;
|
|
173
166
|
default: boolean;
|
|
174
167
|
};
|
|
175
|
-
/**
|
|
168
|
+
/**
|
|
169
|
+
* 满高档(高度与滚动归属;详见 `docs/components/table.md` 的「满高与滚动」):
|
|
170
|
+
*
|
|
171
|
+
* - 不传 / `false` —— 高度由内容撑起(单表结构,与不带本 prop 时完全一致);
|
|
172
|
+
* - `true` / `'parent'` —— 占满父级高度(`height: 100%`),**表体滚、表头固定在表体上方**,
|
|
173
|
+
* 外框与圆角归包裹层;父级需可确定高度(`auto` 父级下 `100%` 解析不出来);
|
|
174
|
+
* - `number` —— 表体滚动上限 = 该像素值,**父级高度不确定时的显式兜底档**
|
|
175
|
+
* (CSS 无法探测父级是否定高,故兜底只能由调用方声明)。
|
|
176
|
+
*
|
|
177
|
+
* 满高档一律按 `table-layout: fixed` 渲染(表头与表体是两个表格盒,`auto` 各自算宽必然错列)。
|
|
178
|
+
*/
|
|
176
179
|
fill: {
|
|
177
|
-
type:
|
|
180
|
+
type: PropType<TableFill>;
|
|
178
181
|
default: boolean;
|
|
179
182
|
};
|
|
180
183
|
/**
|
|
@@ -190,10 +193,6 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
190
193
|
type: PropType<"auto" | "fixed">;
|
|
191
194
|
default: string;
|
|
192
195
|
};
|
|
193
|
-
stickyHead: {
|
|
194
|
-
type: BooleanConstructor;
|
|
195
|
-
default: boolean;
|
|
196
|
-
};
|
|
197
196
|
stickyCol: {
|
|
198
197
|
type: BooleanConstructor;
|
|
199
198
|
default: boolean;
|
|
@@ -252,11 +251,6 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
252
251
|
type: PropType<(keys: Array<string | number>) => void>;
|
|
253
252
|
default: undefined;
|
|
254
253
|
};
|
|
255
|
-
/** 分页档:`false` 不渲染底部分页条 */
|
|
256
|
-
pagination: {
|
|
257
|
-
type: PropType<false | TablePagination>;
|
|
258
|
-
default: boolean;
|
|
259
|
-
};
|
|
260
254
|
}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
261
255
|
/** 选中行 key 列表(`v-model`) */
|
|
262
256
|
'update:modelValue': (keys: Array<string | number>) => boolean;
|
|
@@ -338,9 +332,19 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
338
332
|
type: BooleanConstructor;
|
|
339
333
|
default: boolean;
|
|
340
334
|
};
|
|
341
|
-
/**
|
|
335
|
+
/**
|
|
336
|
+
* 满高档(高度与滚动归属;详见 `docs/components/table.md` 的「满高与滚动」):
|
|
337
|
+
*
|
|
338
|
+
* - 不传 / `false` —— 高度由内容撑起(单表结构,与不带本 prop 时完全一致);
|
|
339
|
+
* - `true` / `'parent'` —— 占满父级高度(`height: 100%`),**表体滚、表头固定在表体上方**,
|
|
340
|
+
* 外框与圆角归包裹层;父级需可确定高度(`auto` 父级下 `100%` 解析不出来);
|
|
341
|
+
* - `number` —— 表体滚动上限 = 该像素值,**父级高度不确定时的显式兜底档**
|
|
342
|
+
* (CSS 无法探测父级是否定高,故兜底只能由调用方声明)。
|
|
343
|
+
*
|
|
344
|
+
* 满高档一律按 `table-layout: fixed` 渲染(表头与表体是两个表格盒,`auto` 各自算宽必然错列)。
|
|
345
|
+
*/
|
|
342
346
|
fill: {
|
|
343
|
-
type:
|
|
347
|
+
type: PropType<TableFill>;
|
|
344
348
|
default: boolean;
|
|
345
349
|
};
|
|
346
350
|
/**
|
|
@@ -356,10 +360,6 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
356
360
|
type: PropType<"auto" | "fixed">;
|
|
357
361
|
default: string;
|
|
358
362
|
};
|
|
359
|
-
stickyHead: {
|
|
360
|
-
type: BooleanConstructor;
|
|
361
|
-
default: boolean;
|
|
362
|
-
};
|
|
363
363
|
stickyCol: {
|
|
364
364
|
type: BooleanConstructor;
|
|
365
365
|
default: boolean;
|
|
@@ -418,11 +418,6 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
418
418
|
type: PropType<(keys: Array<string | number>) => void>;
|
|
419
419
|
default: undefined;
|
|
420
420
|
};
|
|
421
|
-
/** 分页档:`false` 不渲染底部分页条 */
|
|
422
|
-
pagination: {
|
|
423
|
-
type: PropType<false | TablePagination>;
|
|
424
|
-
default: boolean;
|
|
425
|
-
};
|
|
426
421
|
}>> & Readonly<{
|
|
427
422
|
onSort?: ((payload: {
|
|
428
423
|
key: string;
|
|
@@ -431,7 +426,7 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
431
426
|
onChange?: ((keys: (string | number)[]) => any) | undefined;
|
|
432
427
|
"onUpdate:modelValue"?: ((keys: (string | number)[]) => any) | undefined;
|
|
433
428
|
}>, {
|
|
434
|
-
fill:
|
|
429
|
+
fill: TableFill;
|
|
435
430
|
layout: "fixed" | "auto";
|
|
436
431
|
size: ControlSize;
|
|
437
432
|
compact: boolean;
|
|
@@ -447,7 +442,6 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
447
442
|
selectable: boolean | TableRowSelectable;
|
|
448
443
|
striped: boolean;
|
|
449
444
|
onCellChange: (row: TableRow, key: string, value: unknown, index: number) => void;
|
|
450
|
-
stickyHead: boolean;
|
|
451
445
|
stickyCol: boolean;
|
|
452
446
|
showHeader: boolean;
|
|
453
447
|
sortKey: string;
|
|
@@ -455,19 +449,15 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
455
449
|
rowClass: (row: TableRow, index: number) => string;
|
|
456
450
|
onRow: (row: TableRow, index: number) => TableRowProps;
|
|
457
451
|
expandable: (row: TableRow, index: number) => VNodeChild;
|
|
458
|
-
pagination: false | TablePagination;
|
|
459
452
|
}, SlotsType<{
|
|
460
453
|
/** 单元格插槽:`{ row, column, value, index, setValue }`(不给则直接输出原值)。**编辑格也走这里** —— 本件不替调用方渲染控件,只给值、给位置、给一个受控的回写口。 */
|
|
461
454
|
cell?: (context: TableCellSlotScope) => VNodeChild;
|
|
462
|
-
/** 行尾操作区:`{ row, index }`(面里用 `align: 'right'` 的列承载) */
|
|
463
|
-
actions?: (context: {
|
|
464
|
-
row: TableRow;
|
|
465
|
-
index: number;
|
|
466
|
-
}) => VNodeChild;
|
|
467
455
|
/** 批量栏:选中非空时出现在表格上方(`{ selected }`) */
|
|
468
456
|
batch?: (context: {
|
|
469
457
|
selected: Array<string | number>;
|
|
470
458
|
}) => VNodeChild;
|
|
471
459
|
/** 空态自定义(插画 + 操作按钮);不给则渲染 `emptyText` 一行 */
|
|
472
460
|
empty?: () => VNodeChild;
|
|
461
|
+
/** 合计行:渲染在滚动区之外(表格下方),容器与标签 / 数值子样式见 `.mh-table__summary*` */
|
|
462
|
+
summary?: () => VNodeChild;
|
|
473
463
|
}>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { defineComponent, computed, ref, createVNode } from "vue";
|
|
1
|
+
import { defineComponent, computed, ref, onMounted, onUpdated, createVNode } from "vue";
|
|
2
2
|
import { Icon } from "@manohub/icon";
|
|
3
3
|
import { Checkbox } from "../checkbox/index.js";
|
|
4
|
-
import { Pagination } from "../pagination/index.js";
|
|
5
4
|
const Table = /* @__PURE__ */ defineComponent({
|
|
6
5
|
name: "Table",
|
|
7
6
|
inheritAttrs: false,
|
|
@@ -76,9 +75,19 @@ const Table = /* @__PURE__ */ defineComponent({
|
|
|
76
75
|
type: Boolean,
|
|
77
76
|
default: true
|
|
78
77
|
},
|
|
79
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* 满高档(高度与滚动归属;详见 `docs/components/table.md` 的「满高与滚动」):
|
|
80
|
+
*
|
|
81
|
+
* - 不传 / `false` —— 高度由内容撑起(单表结构,与不带本 prop 时完全一致);
|
|
82
|
+
* - `true` / `'parent'` —— 占满父级高度(`height: 100%`),**表体滚、表头固定在表体上方**,
|
|
83
|
+
* 外框与圆角归包裹层;父级需可确定高度(`auto` 父级下 `100%` 解析不出来);
|
|
84
|
+
* - `number` —— 表体滚动上限 = 该像素值,**父级高度不确定时的显式兜底档**
|
|
85
|
+
* (CSS 无法探测父级是否定高,故兜底只能由调用方声明)。
|
|
86
|
+
*
|
|
87
|
+
* 满高档一律按 `table-layout: fixed` 渲染(表头与表体是两个表格盒,`auto` 各自算宽必然错列)。
|
|
88
|
+
*/
|
|
80
89
|
fill: {
|
|
81
|
-
type: Boolean,
|
|
90
|
+
type: [Boolean, String, Number],
|
|
82
91
|
default: false
|
|
83
92
|
},
|
|
84
93
|
/**
|
|
@@ -94,10 +103,6 @@ const Table = /* @__PURE__ */ defineComponent({
|
|
|
94
103
|
type: String,
|
|
95
104
|
default: "auto"
|
|
96
105
|
},
|
|
97
|
-
stickyHead: {
|
|
98
|
-
type: Boolean,
|
|
99
|
-
default: false
|
|
100
|
-
},
|
|
101
106
|
stickyCol: {
|
|
102
107
|
type: Boolean,
|
|
103
108
|
default: false
|
|
@@ -155,11 +160,6 @@ const Table = /* @__PURE__ */ defineComponent({
|
|
|
155
160
|
onExpandChange: {
|
|
156
161
|
type: Function,
|
|
157
162
|
default: void 0
|
|
158
|
-
},
|
|
159
|
-
/** 分页档:`false` 不渲染底部分页条 */
|
|
160
|
-
pagination: {
|
|
161
|
-
type: [Boolean, Object],
|
|
162
|
-
default: false
|
|
163
163
|
}
|
|
164
164
|
},
|
|
165
165
|
emits: {
|
|
@@ -242,120 +242,165 @@ const Table = /* @__PURE__ */ defineComponent({
|
|
|
242
242
|
return "asc";
|
|
243
243
|
};
|
|
244
244
|
const sortGlyph = (key) => props.sortKey === key && props.sortOrder === "asc" ? "chevron-up" : "chevron-down";
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
245
|
+
const renderHead = () => createVNode("thead", null, [createVNode("tr", null, [props.expandable ? createVNode("th", {
|
|
246
|
+
"class": "mh-table__col-expand",
|
|
247
|
+
"aria-label": "展开"
|
|
248
|
+
}, null) : null, hasSelectColumn.value ? createVNode("th", {
|
|
249
|
+
"class": "mh-table__col-check"
|
|
250
|
+
}, [createVNode(Checkbox, {
|
|
251
|
+
"aria-label": "全选",
|
|
252
|
+
"modelValue": allSelected.value,
|
|
253
|
+
"indeterminate": someSelected.value && !allSelected.value,
|
|
254
|
+
"disabled": headerCheckboxDisabled.value,
|
|
255
|
+
"onChange": toggleAll
|
|
256
|
+
}, null)]) : null, props.columns.map((column) => createVNode("th", {
|
|
257
|
+
"key": column.key,
|
|
258
|
+
"class": [column.required ? "mh-table__cell-required" : "", column.align === "center" ? "mh-table__cell-center" : "", column.align === "right" ? "mh-table__col-right" : ""].filter(Boolean).join(" ")
|
|
259
|
+
}, [column.title, column.sortable ? createVNode("button", {
|
|
260
|
+
"type": "button",
|
|
261
|
+
"class": ["mh-table__sort", props.sortKey === column.key && props.sortOrder ? "mh-table__sort--active" : ""].filter(Boolean).join(" "),
|
|
262
|
+
"aria-label": `按${column.title}排序`,
|
|
263
|
+
"onClick": () => emit("sort", {
|
|
264
|
+
key: column.key,
|
|
265
|
+
order: nextOrder(column.key)
|
|
266
|
+
})
|
|
267
|
+
}, [createVNode(Icon, {
|
|
268
|
+
"name": sortGlyph(column.key),
|
|
269
|
+
"class": ["mh-table__sort-icon", props.sortKey === column.key && props.sortOrder === "asc" ? "mh-table__sort-icon--asc" : "", props.sortKey === column.key && props.sortOrder === "desc" ? "mh-table__sort-icon--desc" : ""].filter(Boolean).join(" ")
|
|
270
|
+
}, null)]) : null]))])]);
|
|
271
|
+
const renderBody = () => createVNode("tbody", null, [isEmpty.value ? createVNode("tr", {
|
|
272
|
+
"class": "mh-table__empty-row"
|
|
273
|
+
}, [createVNode("td", {
|
|
274
|
+
"class": "mh-table__empty",
|
|
275
|
+
"colspan": columnCount.value
|
|
276
|
+
}, [slots.empty ? slots.empty() : props.emptyText])]) : null, props.data.map((row, index) => {
|
|
277
|
+
const key = row[props.rowKey];
|
|
278
|
+
const rowProps = props.onRow?.(row, index);
|
|
279
|
+
const isExpanded = expanded.value.includes(key);
|
|
280
|
+
const rowState = [props.striped && index % 2 === 1 ? "is-striped" : "", selected.value.includes(key) ? "is-selected" : "", rowProps?.onClick ? "is-clickable" : "", rowProps?.class ?? "", props.rowClass?.(row, index) ?? ""].filter(Boolean).join(" ");
|
|
281
|
+
return [createVNode("tr", {
|
|
282
|
+
"key": key,
|
|
283
|
+
"class": rowState,
|
|
284
|
+
"data-state": selected.value.includes(key) ? "selected" : "idle",
|
|
285
|
+
"onClick": rowProps?.onClick ? (event) => rowProps.onClick?.(row, index, event) : void 0
|
|
286
|
+
}, [props.expandable ? createVNode("td", {
|
|
287
|
+
"class": "mh-table__col-expand"
|
|
288
|
+
}, [createVNode("button", {
|
|
272
289
|
"type": "button",
|
|
273
|
-
"class":
|
|
274
|
-
"aria-label":
|
|
275
|
-
"
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
290
|
+
"class": "mh-table__expand",
|
|
291
|
+
"aria-label": isExpanded ? "收起" : "展开",
|
|
292
|
+
"aria-expanded": isExpanded ? "true" : "false",
|
|
293
|
+
"onClick": (event) => {
|
|
294
|
+
event.stopPropagation();
|
|
295
|
+
toggleExpand(key);
|
|
296
|
+
}
|
|
279
297
|
}, [createVNode(Icon, {
|
|
280
|
-
"name":
|
|
281
|
-
"class":
|
|
282
|
-
}, null)])
|
|
283
|
-
|
|
298
|
+
"name": "chevron-down",
|
|
299
|
+
"class": "mh-table__expand-icon"
|
|
300
|
+
}, null)])]) : null, hasSelectColumn.value ? (
|
|
301
|
+
/* 勾选列复用 `Checkbox`(不手写原生 input)。行本身可能带 `onRow` 的 onClick:勾选不该顺带触发行
|
|
302
|
+
点击 —— 阻断挂在**单元格**上(`Checkbox` 的根是 `label`,点它会冒泡两次,只挡 input 挡不住)。
|
|
303
|
+
`selectable` 为函数时逐行判定:返回 `false` 的行给禁用态(置灰 + not-allowed)。 */
|
|
304
|
+
createVNode("td", {
|
|
305
|
+
"class": "mh-table__col-check",
|
|
306
|
+
"onClick": (event) => event.stopPropagation()
|
|
307
|
+
}, [createVNode(Checkbox, {
|
|
308
|
+
"aria-label": "选择本行",
|
|
309
|
+
"modelValue": selected.value.includes(key),
|
|
310
|
+
"disabled": !isRowSelectable(row, index),
|
|
311
|
+
"onChange": () => toggleRow(key)
|
|
312
|
+
}, null)])
|
|
313
|
+
) : null, props.columns.map((column) => createVNode("td", {
|
|
314
|
+
"key": column.key,
|
|
315
|
+
"class": cellClass(column).join(" ")
|
|
316
|
+
}, [slots.cell ? (
|
|
317
|
+
/* 展示格与编辑格都走这条(含行尾操作列):值、位置、回写口一并交给调用方 */
|
|
318
|
+
slots.cell({
|
|
319
|
+
row,
|
|
320
|
+
column,
|
|
321
|
+
value: row[column.key],
|
|
322
|
+
index,
|
|
323
|
+
setValue: cellSetValue(row, column, index)
|
|
324
|
+
})
|
|
325
|
+
) : String(row[column.key] ?? "")]))]), isExpanded ? createVNode("tr", {
|
|
326
|
+
"key": `${key}-expand`,
|
|
327
|
+
"class": "mh-table__expand-row"
|
|
284
328
|
}, [createVNode("td", {
|
|
285
|
-
"class": "mh-table__empty",
|
|
286
329
|
"colspan": columnCount.value
|
|
287
|
-
}, [
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
"modelValue": selected.value.includes(key),
|
|
321
|
-
"disabled": !isRowSelectable(row, index),
|
|
322
|
-
"onChange": () => toggleRow(key)
|
|
323
|
-
}, null)])
|
|
324
|
-
) : null, props.columns.map((column) => createVNode("td", {
|
|
325
|
-
"key": column.key,
|
|
326
|
-
"class": cellClass(column).join(" ")
|
|
327
|
-
}, [slots.cell ? (
|
|
328
|
-
/* 编辑格与展示格都走这条:值、位置、回写口一并交给调用方 */
|
|
329
|
-
slots.cell({
|
|
330
|
-
row,
|
|
331
|
-
column,
|
|
332
|
-
value: row[column.key],
|
|
333
|
-
index,
|
|
334
|
-
setValue: cellSetValue(row, column, index)
|
|
335
|
-
})
|
|
336
|
-
) : slots.actions && column.align === "right" ? slots.actions({
|
|
337
|
-
row,
|
|
338
|
-
index
|
|
339
|
-
}) : String(row[column.key] ?? "")]))]), isExpanded ? createVNode("tr", {
|
|
340
|
-
"key": `${key}-expand`,
|
|
341
|
-
"class": "mh-table__expand-row"
|
|
342
|
-
}, [createVNode("td", {
|
|
343
|
-
"colspan": columnCount.value
|
|
344
|
-
}, [props.expandable?.(row, index)])]) : null];
|
|
345
|
-
})])]), props.loading ? createVNode("div", {
|
|
330
|
+
}, [props.expandable?.(row, index)])]) : null];
|
|
331
|
+
})]);
|
|
332
|
+
const headBoxRef = ref(null);
|
|
333
|
+
const headTableRef = ref(null);
|
|
334
|
+
const scrollBoxRef = ref(null);
|
|
335
|
+
const syncHead = () => {
|
|
336
|
+
const box = scrollBoxRef.value;
|
|
337
|
+
const head = headBoxRef.value;
|
|
338
|
+
if (!box) return;
|
|
339
|
+
if (headTableRef.value) headTableRef.value.style.transform = `translateX(${-box.scrollLeft}px)`;
|
|
340
|
+
if (head) {
|
|
341
|
+
const gutter = `${box.offsetWidth - box.clientWidth}px`;
|
|
342
|
+
if (head.style.paddingRight !== gutter) head.style.paddingRight = gutter;
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
onMounted(syncHead);
|
|
346
|
+
onUpdated(syncHead);
|
|
347
|
+
return () => {
|
|
348
|
+
const fill = props.fill !== false;
|
|
349
|
+
const tableClass = ["mh-table", resolvedSize.value === "sm" ? "mh-table--xs" : "", resolvedSize.value === "lg" ? "mh-table--lg" : "", props.bordered ? "" : "mh-table--borderless", fill ? "mh-table--fill" : "", fill || props.layout === "fixed" ? "mh-table--fixed" : "", attrs.class].filter(Boolean).join(" ");
|
|
350
|
+
const bodyTableClass = props.stickyCol ? `${tableClass} mh-table--sticky-col` : tableClass;
|
|
351
|
+
const cellTokens = fill || props.layout === "fixed" ? {
|
|
352
|
+
"--ui-control-min-width": "0"
|
|
353
|
+
} : void 0;
|
|
354
|
+
const batchBar = slots.batch && selected.value.length > 0 ? createVNode("div", {
|
|
355
|
+
"class": "mh-table__batch"
|
|
356
|
+
}, [slots.batch({
|
|
357
|
+
selected: selected.value
|
|
358
|
+
})]) : null;
|
|
359
|
+
const summaryBar = slots.summary ? createVNode("div", {
|
|
360
|
+
"class": "mh-table__summary"
|
|
361
|
+
}, [slots.summary()]) : null;
|
|
362
|
+
const loadingOverlay = props.loading ? createVNode("div", {
|
|
346
363
|
"class": "mh-table__loading",
|
|
347
364
|
"aria-busy": "true"
|
|
348
365
|
}, [createVNode("span", {
|
|
349
366
|
"class": "mh-table__spinner"
|
|
350
|
-
}, null)]) : null
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
"
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
367
|
+
}, null)]) : null;
|
|
368
|
+
if (!fill) {
|
|
369
|
+
return createVNode("div", {
|
|
370
|
+
"class": "mh-table-wrapper",
|
|
371
|
+
"style": attrs.style
|
|
372
|
+
}, [batchBar, createVNode("table", {
|
|
373
|
+
"class": bodyTableClass,
|
|
374
|
+
"style": cellTokens
|
|
375
|
+
}, [colElements(), props.showHeader ? renderHead() : null, renderBody()]), summaryBar, loadingOverlay]);
|
|
376
|
+
}
|
|
377
|
+
const wrapperStyle = props.fill === true || props.fill === "parent" ? [{
|
|
378
|
+
height: "100%"
|
|
379
|
+
}, attrs.style] : attrs.style;
|
|
380
|
+
const scrollStyle = typeof props.fill === "number" ? {
|
|
381
|
+
maxHeight: `${props.fill}px`
|
|
382
|
+
} : void 0;
|
|
383
|
+
return createVNode("div", {
|
|
384
|
+
"class": "mh-table-wrapper mh-table-wrapper--fill",
|
|
385
|
+
"style": wrapperStyle
|
|
386
|
+
}, [batchBar, props.showHeader ? createVNode("div", {
|
|
387
|
+
"class": "mh-table__head",
|
|
388
|
+
"ref": headBoxRef
|
|
389
|
+
}, [createVNode("table", {
|
|
390
|
+
"class": tableClass,
|
|
391
|
+
"ref": headTableRef,
|
|
392
|
+
"style": cellTokens
|
|
393
|
+
}, [colElements(), renderHead()])]) : null, createVNode("div", {
|
|
394
|
+
"class": "mh-table__body"
|
|
395
|
+
}, [createVNode("div", {
|
|
396
|
+
"class": "mh-table-scroll",
|
|
397
|
+
"ref": scrollBoxRef,
|
|
398
|
+
"onScroll": syncHead,
|
|
399
|
+
"style": scrollStyle
|
|
400
|
+
}, [createVNode("table", {
|
|
401
|
+
"class": bodyTableClass,
|
|
402
|
+
"style": cellTokens
|
|
403
|
+
}, [colElements(), renderBody()])]), loadingOverlay]), summaryBar]);
|
|
359
404
|
};
|
|
360
405
|
}
|
|
361
406
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ export { Notification, type NotificationTone, } from './components/notification'
|
|
|
45
45
|
export { Dialog, type DialogWidth } from './components/dialog';
|
|
46
46
|
export { Drawer, type DrawerSide } from './components/drawer';
|
|
47
47
|
export { Tooltip, type TooltipSide, type TooltipAlign, } from './components/tooltip';
|
|
48
|
-
export { Table, type TableColumn, type TableCellSlotScope, type TableRow, type TableRowSelectable, type TableSortOrder, } from './components/table';
|
|
48
|
+
export { Table, type TableColumn, type TableCellSlotScope, type TableFill, type TableRow, type TableRowSelectable, type TableSortOrder, } from './components/table';
|
|
49
49
|
export { Pagination, type PaginationPageItem } from './components/pagination';
|
|
50
50
|
export { TabBar, type TabBarOption, type TabBarValue } from './components/tabbar';
|
|
51
51
|
export { Steps, type CanJump, type StepsItem, type StepsVariant, type StepsCompound, type StepsCompoundType, } from './components/steps';
|
|
@@ -30,14 +30,41 @@
|
|
|
30
30
|
.mh-table-wrapper {
|
|
31
31
|
overflow: auto;
|
|
32
32
|
}
|
|
33
|
-
/*
|
|
34
|
-
|
|
33
|
+
/* ===== 满高档(两表结构:表头盒 + 表体滚动盒)=====
|
|
34
|
+
* 外框从表移交给包裹层(表自己不再画框),**表头不在滚动盒里** —— 表头固定是结构给的,不靠 sticky。 */
|
|
35
|
+
.mh-table-wrapper--fill {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
overflow: hidden; /* 表头底 / 末行跟着外框圆角收边 */
|
|
35
39
|
border: 1px solid var(--ui-table-border);
|
|
36
40
|
border-radius: var(--ui-table-radius);
|
|
37
41
|
}
|
|
42
|
+
/* 滚动区外的常驻块不被压缩(表体盒吃剩余高度) */
|
|
43
|
+
.mh-table-wrapper--fill > .mh-table__batch,
|
|
44
|
+
.mh-table-wrapper--fill > .mh-table__summary {
|
|
45
|
+
flex: none;
|
|
46
|
+
}
|
|
47
|
+
/* 表头盒:裁切横向平移的表头(平移由组件同步,不在这里做) */
|
|
48
|
+
.mh-table__head {
|
|
49
|
+
flex: none;
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
}
|
|
52
|
+
/* 表体盒:表体的定位上下文(满高档的加载罩按它铺满,不再盖到表头) */
|
|
53
|
+
.mh-table__body {
|
|
54
|
+
position: relative;
|
|
55
|
+
flex: 1 1 auto;
|
|
56
|
+
min-height: 0;
|
|
57
|
+
}
|
|
58
|
+
/* 表体滚动盒:满高档唯一的滚动落点 */
|
|
38
59
|
.mh-table-scroll {
|
|
39
|
-
|
|
60
|
+
height: 100%;
|
|
61
|
+
max-height: var(--ui-table-scroll-height); /* 基础上限;「占满父级」档由下面那条解除 */
|
|
40
62
|
overflow: auto;
|
|
63
|
+
scrollbar-gutter: stable; /* 滚动条槽常驻:表体宽度不随内容长短跳变 */
|
|
64
|
+
}
|
|
65
|
+
/* 满高档:滚动范围由包裹层高度(或调用方给的内联上限)决定 */
|
|
66
|
+
.mh-table-wrapper--fill > .mh-table__body > .mh-table-scroll {
|
|
67
|
+
max-height: none;
|
|
41
68
|
}
|
|
42
69
|
|
|
43
70
|
/* 几何只挂在 `<table>` 上:令牌在同名 `.tokens.css`(锚 `[data-manohub-ui]`),几何若跟着挂会给包裹层加边框与圆角 */
|
|
@@ -195,7 +222,7 @@
|
|
|
195
222
|
width: var(--ui-table-col-check);
|
|
196
223
|
text-align: center;
|
|
197
224
|
}
|
|
198
|
-
.mh-table__col-
|
|
225
|
+
.mh-table__col-right {
|
|
199
226
|
text-align: right;
|
|
200
227
|
}
|
|
201
228
|
|
|
@@ -207,7 +234,7 @@
|
|
|
207
234
|
.mh-table thead th.mh-table__cell-center {
|
|
208
235
|
text-align: center;
|
|
209
236
|
}
|
|
210
|
-
.mh-table thead th.mh-table__col-
|
|
237
|
+
.mh-table thead th.mh-table__col-right {
|
|
211
238
|
text-align: right;
|
|
212
239
|
}
|
|
213
240
|
/* `--sticky-col`:首列钉住(必须自带底,见文件头第 4 条) */
|
|
@@ -222,14 +249,8 @@
|
|
|
222
249
|
z-index: 2; /* 表头既钉顶又钉左,压住表头其余列 */
|
|
223
250
|
background: var(--ui-table-head-bg);
|
|
224
251
|
}
|
|
225
|
-
/* `--sticky-head
|
|
226
|
-
*
|
|
227
|
-
* `stickyHead` 静默失效。`sticky` 同样是定位元素,照样给表头里的拖拽线当包含块,故加 `tr` 不损失原能力。 */
|
|
228
|
-
.mh-table--sticky-head thead tr th {
|
|
229
|
-
position: sticky;
|
|
230
|
-
top: 0;
|
|
231
|
-
z-index: 1;
|
|
232
|
-
}
|
|
252
|
+
/* `--sticky-head` 已退场(2026-10-10):表头固定改由满高档的两表结构承担 —— 表头不在滚动盒里,
|
|
253
|
+
* 不需要 sticky,也就没有「特异性压不过 `position: relative`」那类静默失效。 */
|
|
233
254
|
|
|
234
255
|
/* ===== 单元格类型 ===== */
|
|
235
256
|
.mh-table__cell-center {
|
|
@@ -416,6 +437,13 @@
|
|
|
416
437
|
text-align: center;
|
|
417
438
|
color: var(--ui-base-content-muted);
|
|
418
439
|
}
|
|
440
|
+
/* 满高档的空态:空态格撑满表体可见高度(按行选择 —— 空数据时才有那一行,有数据时行高不受影响) */
|
|
441
|
+
.mh-table-wrapper--fill .mh-table-scroll > .mh-table:has(.mh-table__empty-row) {
|
|
442
|
+
height: 100%;
|
|
443
|
+
}
|
|
444
|
+
.mh-table-wrapper--fill .mh-table__empty {
|
|
445
|
+
height: 100%;
|
|
446
|
+
}
|
|
419
447
|
.mh-table__empty-row:hover td {
|
|
420
448
|
background: transparent;
|
|
421
449
|
}
|
|
@@ -460,10 +488,3 @@
|
|
|
460
488
|
padding: var(--ui-space-4) var(--ui-table-padding-x);
|
|
461
489
|
background: var(--ui-base-200);
|
|
462
490
|
}
|
|
463
|
-
|
|
464
|
-
/* ===== 分页条(贴在表格下方、右对齐;分页件自身的面归 pagination.css) ===== */
|
|
465
|
-
.mh-table__pagination {
|
|
466
|
-
display: flex;
|
|
467
|
-
justify-content: flex-end;
|
|
468
|
-
padding: var(--ui-space-4) 0 0;
|
|
469
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manohub/ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "AIHub 自绘组件层:不依赖 farris 的手写 Vue TSX 组件 + 自带令牌层(Farris 规范视觉 · daisyUI 式语义令牌 · shadcn 式 API 词汇)。",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"vue": "^3.5.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@manohub/icon": "^1.0.
|
|
38
|
+
"@manohub/icon": "^1.0.8"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^24.0.0",
|