@manohub/ui 0.6.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.
- package/README.md +141 -0
- package/dist/components/avatar/index.d.ts +283 -0
- package/dist/components/avatar/index.js +167 -0
- package/dist/components/badge/index.d.ts +132 -0
- package/dist/components/badge/index.js +99 -0
- package/dist/components/button/index.d.ts +578 -0
- package/dist/components/button/index.js +191 -0
- package/dist/components/capsule/index.d.ts +161 -0
- package/dist/components/capsule/index.js +101 -0
- package/dist/components/card/index.d.ts +456 -0
- package/dist/components/card/index.js +231 -0
- package/dist/components/checkbox/index.d.ts +331 -0
- package/dist/components/checkbox/index.js +165 -0
- package/dist/components/code/index.d.ts +134 -0
- package/dist/components/code/index.js +117 -0
- package/dist/components/code-editor/index.d.ts +163 -0
- package/dist/components/code-editor/index.js +98 -0
- package/dist/components/collapse/index.d.ts +125 -0
- package/dist/components/collapse/index.js +95 -0
- package/dist/components/control-size.d.ts +8 -0
- package/dist/components/dialog/index.d.ts +224 -0
- package/dist/components/dialog/index.js +194 -0
- package/dist/components/divider/index.d.ts +64 -0
- package/dist/components/divider/index.js +62 -0
- package/dist/components/drawer/index.d.ts +226 -0
- package/dist/components/drawer/index.js +190 -0
- package/dist/components/filter/index.d.ts +391 -0
- package/dist/components/filter/index.js +203 -0
- package/dist/components/form/index.d.ts +704 -0
- package/dist/components/form/index.js +329 -0
- package/dist/components/input/index.d.ts +980 -0
- package/dist/components/input/index.js +334 -0
- package/dist/components/layout/index.d.ts +162 -0
- package/dist/components/layout/index.js +100 -0
- package/dist/components/list-view/index.d.ts +563 -0
- package/dist/components/list-view/index.js +221 -0
- package/dist/components/loading/index.d.ts +77 -0
- package/dist/components/loading/index.js +40 -0
- package/dist/components/nav/index.d.ts +293 -0
- package/dist/components/nav/index.js +164 -0
- package/dist/components/notice/index.d.ts +137 -0
- package/dist/components/notice/index.js +101 -0
- package/dist/components/notification/index.d.ts +118 -0
- package/dist/components/notification/index.js +99 -0
- package/dist/components/page/index.d.ts +276 -0
- package/dist/components/page/index.js +351 -0
- package/dist/components/page/split-resize.d.ts +42 -0
- package/dist/components/page/split-resize.js +36 -0
- package/dist/components/pagination/index.d.ts +171 -0
- package/dist/components/pagination/index.js +226 -0
- package/dist/components/panel/index.d.ts +401 -0
- package/dist/components/panel/index.js +193 -0
- package/dist/components/part-padding.d.ts +27 -0
- package/dist/components/part-padding.js +23 -0
- package/dist/components/query-state/index.d.ts +207 -0
- package/dist/components/query-state/index.js +181 -0
- package/dist/components/radio/index.d.ts +473 -0
- package/dist/components/radio/index.js +250 -0
- package/dist/components/search/index.d.ts +167 -0
- package/dist/components/search/index.js +105 -0
- package/dist/components/select/index.d.ts +252 -0
- package/dist/components/select/index.js +281 -0
- package/dist/components/skeleton/index.d.ts +88 -0
- package/dist/components/skeleton/index.js +56 -0
- package/dist/components/steps/index.d.ts +199 -0
- package/dist/components/steps/index.js +117 -0
- package/dist/components/switch/index.d.ts +150 -0
- package/dist/components/switch/index.js +103 -0
- package/dist/components/table/index.d.ts +351 -0
- package/dist/components/table/index.js +286 -0
- package/dist/components/tabs/index.d.ts +179 -0
- package/dist/components/tabs/index.js +153 -0
- package/dist/components/tabset/index.d.ts +105 -0
- package/dist/components/tabset/index.js +68 -0
- package/dist/components/tag/index.d.ts +203 -0
- package/dist/components/tag/index.js +144 -0
- package/dist/components/toast/index.d.ts +271 -0
- package/dist/components/toast/index.js +116 -0
- package/dist/components/tooltip/index.d.ts +126 -0
- package/dist/components/tooltip/index.js +97 -0
- package/dist/components/tree/index.d.ts +317 -0
- package/dist/components/tree/index.js +251 -0
- package/dist/components/upload/index.d.ts +384 -0
- package/dist/components/upload/index.js +172 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +102 -0
- package/dist/services/base.d.ts +21 -0
- package/dist/services/base.js +42 -0
- package/dist/services/dialog.d.ts +41 -0
- package/dist/services/dialog.js +83 -0
- package/dist/services/index.d.ts +12 -0
- package/dist/services/loading.d.ts +21 -0
- package/dist/services/loading.js +41 -0
- package/dist/services/toast.d.ts +40 -0
- package/dist/services/toast.js +74 -0
- package/dist/styles/components/avatar.css +128 -0
- package/dist/styles/components/avatar.tokens.css +24 -0
- package/dist/styles/components/badge.css +237 -0
- package/dist/styles/components/button.css +454 -0
- package/dist/styles/components/button.tokens.css +56 -0
- package/dist/styles/components/capsule.css +120 -0
- package/dist/styles/components/capsule.tokens.css +27 -0
- package/dist/styles/components/card.css +192 -0
- package/dist/styles/components/checkbox.css +145 -0
- package/dist/styles/components/checkbox.tokens.css +26 -0
- package/dist/styles/components/code-editor.css +91 -0
- package/dist/styles/components/code-editor.tokens.css +24 -0
- package/dist/styles/components/code.css +153 -0
- package/dist/styles/components/code.tokens.css +29 -0
- package/dist/styles/components/collapse.css +62 -0
- package/dist/styles/components/collapse.tokens.css +20 -0
- package/dist/styles/components/dialog.css +106 -0
- package/dist/styles/components/dialog.tokens.css +24 -0
- package/dist/styles/components/divider.css +71 -0
- package/dist/styles/components/divider.tokens.css +21 -0
- package/dist/styles/components/drawer.css +143 -0
- package/dist/styles/components/drawer.tokens.css +22 -0
- package/dist/styles/components/filter.css +41 -0
- package/dist/styles/components/filter.tokens.css +14 -0
- package/dist/styles/components/form.css +220 -0
- package/dist/styles/components/form.tokens.css +15 -0
- package/dist/styles/components/input.css +445 -0
- package/dist/styles/components/input.tokens.css +41 -0
- package/dist/styles/components/layout.css +198 -0
- package/dist/styles/components/list-view.css +244 -0
- package/dist/styles/components/loading.css +76 -0
- package/dist/styles/components/loading.tokens.css +23 -0
- package/dist/styles/components/nav.css +48 -0
- package/dist/styles/components/notice.css +153 -0
- package/dist/styles/components/notice.tokens.css +17 -0
- package/dist/styles/components/notification.css +159 -0
- package/dist/styles/components/notification.tokens.css +37 -0
- package/dist/styles/components/page.css +473 -0
- package/dist/styles/components/pagination.css +297 -0
- package/dist/styles/components/pagination.tokens.css +32 -0
- package/dist/styles/components/panel.css +77 -0
- package/dist/styles/components/query-state.css +88 -0
- package/dist/styles/components/radio.css +271 -0
- package/dist/styles/components/radio.tokens.css +26 -0
- package/dist/styles/components/search.css +30 -0
- package/dist/styles/components/select.css +242 -0
- package/dist/styles/components/select.tokens.css +33 -0
- package/dist/styles/components/skeleton.css +60 -0
- package/dist/styles/components/skeleton.tokens.css +27 -0
- package/dist/styles/components/steps.css +157 -0
- package/dist/styles/components/steps.tokens.css +42 -0
- package/dist/styles/components/switch.css +165 -0
- package/dist/styles/components/switch.tokens.css +26 -0
- package/dist/styles/components/table.css +439 -0
- package/dist/styles/components/table.tokens.css +41 -0
- package/dist/styles/components/tabs.css +234 -0
- package/dist/styles/components/tabs.tokens.css +30 -0
- package/dist/styles/components/tag.css +200 -0
- package/dist/styles/components/tag.tokens.css +30 -0
- package/dist/styles/components/toast.css +150 -0
- package/dist/styles/components/toast.tokens.css +26 -0
- package/dist/styles/components/tooltip.css +89 -0
- package/dist/styles/components/tooltip.tokens.css +25 -0
- package/dist/styles/components/tree.css +139 -0
- package/dist/styles/components/tree.tokens.css +20 -0
- package/dist/styles/components/upload.css +150 -0
- package/dist/styles/components/upload.tokens.css +27 -0
- package/dist/styles/index.css +149 -0
- package/dist/styles/operations/collapse.css +84 -0
- package/dist/styles/operations/popup.css +189 -0
- package/dist/styles/operations/tabset.css +57 -0
- package/dist/utils/state-illustration.d.ts +31 -0
- package/dist/utils/state-illustration.js +156 -0
- package/package.json +62 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { defineComponent, ref, createVNode, Fragment, createTextVNode } from "vue";
|
|
2
|
+
function formatFileSize(bytes) {
|
|
3
|
+
if (bytes === void 0 || Number.isNaN(bytes)) return "";
|
|
4
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
5
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
6
|
+
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
7
|
+
}
|
|
8
|
+
const Upload = /* @__PURE__ */ defineComponent({
|
|
9
|
+
name: "Upload",
|
|
10
|
+
inheritAttrs: false,
|
|
11
|
+
props: {
|
|
12
|
+
/** 已选文件(受控;本件只渲染与回调) */
|
|
13
|
+
files: {
|
|
14
|
+
type: Array,
|
|
15
|
+
default: () => []
|
|
16
|
+
},
|
|
17
|
+
/** 原生 accept(如 `.pdf,.xls`) */
|
|
18
|
+
accept: {
|
|
19
|
+
type: String,
|
|
20
|
+
default: void 0
|
|
21
|
+
},
|
|
22
|
+
multiple: {
|
|
23
|
+
type: Boolean,
|
|
24
|
+
default: true
|
|
25
|
+
},
|
|
26
|
+
disabled: {
|
|
27
|
+
type: Boolean,
|
|
28
|
+
default: false
|
|
29
|
+
},
|
|
30
|
+
/** 主文案(缺省「点击上传,或将文件拖到此处」) */
|
|
31
|
+
title: {
|
|
32
|
+
type: String,
|
|
33
|
+
default: void 0
|
|
34
|
+
},
|
|
35
|
+
/** 副文案(类型 / 大小上限这类提示) */
|
|
36
|
+
hint: {
|
|
37
|
+
type: String,
|
|
38
|
+
default: void 0
|
|
39
|
+
},
|
|
40
|
+
/** 选择(点击或拖拽都会走这里)回调 */
|
|
41
|
+
/** 数量上限(`0` = 不限):超出部分由本件在入口截断,并回调 `onExceed` */
|
|
42
|
+
maxCount: {
|
|
43
|
+
type: Number,
|
|
44
|
+
default: 0
|
|
45
|
+
},
|
|
46
|
+
/** 超出上限(参数是本次被拒的全部文件) */
|
|
47
|
+
onExceed: {
|
|
48
|
+
type: Function,
|
|
49
|
+
default: void 0
|
|
50
|
+
},
|
|
51
|
+
onSelect: {
|
|
52
|
+
type: Function,
|
|
53
|
+
default: void 0
|
|
54
|
+
},
|
|
55
|
+
/** 拖拽落文件回调(需要与点击区分时用) */
|
|
56
|
+
onDrop: {
|
|
57
|
+
type: Function,
|
|
58
|
+
default: void 0
|
|
59
|
+
},
|
|
60
|
+
/** 删除某一行回调 */
|
|
61
|
+
onRemove: {
|
|
62
|
+
type: Function,
|
|
63
|
+
default: void 0
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
slots: Object,
|
|
67
|
+
setup(props, {
|
|
68
|
+
slots,
|
|
69
|
+
attrs
|
|
70
|
+
}) {
|
|
71
|
+
const dragover = ref(false);
|
|
72
|
+
const onDragEnter = (event) => {
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
if (!props.disabled) dragover.value = true;
|
|
75
|
+
};
|
|
76
|
+
const onDragOver = (event) => event.preventDefault();
|
|
77
|
+
const onDragLeave = () => {
|
|
78
|
+
dragover.value = false;
|
|
79
|
+
};
|
|
80
|
+
const onDrop = (event) => {
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
dragover.value = false;
|
|
83
|
+
if (props.disabled) return;
|
|
84
|
+
const picked = Array.from(event.dataTransfer?.files ?? []);
|
|
85
|
+
if (!picked.length) return;
|
|
86
|
+
props.onDrop?.(picked);
|
|
87
|
+
props.onSelect?.(picked);
|
|
88
|
+
};
|
|
89
|
+
const onPick = (event) => {
|
|
90
|
+
const input = event.target;
|
|
91
|
+
const picked = Array.from(input.files ?? []);
|
|
92
|
+
input.value = "";
|
|
93
|
+
if (!picked.length) return;
|
|
94
|
+
const room = props.maxCount > 0 ? Math.max(0, props.maxCount - props.files.length) : picked.length;
|
|
95
|
+
if (picked.length > room) props.onExceed?.(picked);
|
|
96
|
+
const accepted = picked.slice(0, room);
|
|
97
|
+
if (accepted.length) props.onSelect?.(accepted);
|
|
98
|
+
};
|
|
99
|
+
return () => createVNode("div", {
|
|
100
|
+
"class": ["mh-upload", attrs.class].filter(Boolean).join(" "),
|
|
101
|
+
"style": attrs.style
|
|
102
|
+
}, [createVNode("label", {
|
|
103
|
+
"class": ["mh-upload__zone", props.disabled ? "is-disabled" : "", dragover.value ? "is-dragover" : ""].filter(Boolean).join(" "),
|
|
104
|
+
"data-state": dragover.value ? "dragover" : "idle",
|
|
105
|
+
"onDragenter": onDragEnter,
|
|
106
|
+
"onDragover": onDragOver,
|
|
107
|
+
"onDragleave": onDragLeave,
|
|
108
|
+
"onDrop": onDrop
|
|
109
|
+
}, [createVNode("input", {
|
|
110
|
+
"class": "mh-upload__input",
|
|
111
|
+
"type": "file",
|
|
112
|
+
"accept": props.accept,
|
|
113
|
+
"multiple": props.multiple,
|
|
114
|
+
"disabled": props.disabled,
|
|
115
|
+
"onChange": onPick
|
|
116
|
+
}, null), slots.default ? slots.default() : createVNode(Fragment, null, [createVNode("span", {
|
|
117
|
+
"class": "mh-upload__zone-main"
|
|
118
|
+
}, [props.title ? props.title : createVNode(Fragment, null, [createVNode("span", {
|
|
119
|
+
"class": "mh-upload__link"
|
|
120
|
+
}, [createTextVNode("点击上传")]), createTextVNode(",或将文件拖到此处")])]), props.hint ? createVNode("span", {
|
|
121
|
+
"class": "mh-upload__zone-hint"
|
|
122
|
+
}, [props.hint]) : null])]), props.files.length ? createVNode("div", {
|
|
123
|
+
"class": "mh-upload__list"
|
|
124
|
+
}, [props.files.map((file, index) => createVNode("div", {
|
|
125
|
+
"class": "mh-upload__item",
|
|
126
|
+
"key": `${file.name}-${index}`
|
|
127
|
+
}, [createVNode("span", {
|
|
128
|
+
"class": "mh-upload__item-name"
|
|
129
|
+
}, [file.name]), createVNode("span", {
|
|
130
|
+
"class": "mh-upload__item-size"
|
|
131
|
+
}, [formatFileSize(file.size)]), createVNode("button", {
|
|
132
|
+
"type": "button",
|
|
133
|
+
"class": "mh-button mh-button--text mh-button--danger mh-upload__item-remove",
|
|
134
|
+
"aria-label": `移除 ${file.name}`,
|
|
135
|
+
"disabled": props.disabled,
|
|
136
|
+
"onClick": () => props.onRemove?.(file, index)
|
|
137
|
+
}, [createTextVNode("删除")])]))]) : null]);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
const UploadThumbs = /* @__PURE__ */ defineComponent({
|
|
141
|
+
name: "UploadThumbs",
|
|
142
|
+
inheritAttrs: false,
|
|
143
|
+
props: {
|
|
144
|
+
files: {
|
|
145
|
+
type: Array,
|
|
146
|
+
default: () => []
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
setup(props, {
|
|
150
|
+
attrs
|
|
151
|
+
}) {
|
|
152
|
+
const extensionOf = (name) => name.split(".").pop()?.toUpperCase() ?? "";
|
|
153
|
+
return () => createVNode("div", {
|
|
154
|
+
"class": ["mh-upload__thumbs", attrs.class].filter(Boolean).join(" "),
|
|
155
|
+
"style": attrs.style
|
|
156
|
+
}, [props.files.map((file, index) => createVNode("div", {
|
|
157
|
+
"class": "mh-upload__thumb",
|
|
158
|
+
"key": `${file.name}-${index}`
|
|
159
|
+
}, [file.thumb ? createVNode("img", {
|
|
160
|
+
"class": "mh-upload__thumb-img",
|
|
161
|
+
"src": file.thumb,
|
|
162
|
+
"alt": file.name
|
|
163
|
+
}, null) : createVNode("span", null, [extensionOf(file.name)])]))]);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
Object.assign(Upload, {
|
|
167
|
+
Thumbs: UploadThumbs
|
|
168
|
+
});
|
|
169
|
+
export {
|
|
170
|
+
Upload,
|
|
171
|
+
formatFileSize
|
|
172
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @manohub/ui 对外导出白名单。
|
|
3
|
+
*
|
|
4
|
+
* 三条约束:
|
|
5
|
+
* 1. **禁 `export *`**:导出面必须逐条列出,改名/删除都得过一次编译;
|
|
6
|
+
* 2. **零 farris**:本包不 import `@farris/ui-vue`,也不 re-export 任何 farris 类型或组件
|
|
7
|
+
* (产物文本级护栏在仓根 `scripts/verify-pack.mjs` 的 ui 分支);
|
|
8
|
+
* 3. **公开名一旦发布即冻结**(改名属破坏性变更,需要大版本 + 迁移说明),
|
|
9
|
+
* 故 `Card` / `Panel` / … 这些名字与类型名一个都不能变。
|
|
10
|
+
*
|
|
11
|
+
* 复合件的成员(`Card.Header` / `Form.Item` / `Panel.Body` …)**不平级导出**,一律走点号,
|
|
12
|
+
* 复合件用 `Object.assign` 挂成员(成员不平级导出)。
|
|
13
|
+
*
|
|
14
|
+
* 四层分工(本文件只做出口,不承载实现):
|
|
15
|
+
* `theme/<主题>/` 令牌(值)| `styles/` 组件面(类 + 状态协议,零 JS)| `components/` Vue 层(增强)
|
|
16
|
+
* | `services/` 命令式服务(宿主 + 队列 + 生命周期;共用上面三层的组件与面,不另造浮层)
|
|
17
|
+
*/
|
|
18
|
+
export { Page, type PageCompound, type PagePadding, type PageHeaderProps, type PageBodyProps, type PageSplitProps, type PageSplitSidebarProps, } from './components/page';
|
|
19
|
+
export { Panel, type PanelProps, type PanelPadding, type PanelCompound } from './components/panel';
|
|
20
|
+
export { Card, type CardProps, type CardVariant, type CardPadding, type CardHeaderIcon, type CardCompound, } from './components/card';
|
|
21
|
+
export { Divider, type DividerProps } from './components/divider';
|
|
22
|
+
export { Nav, type NavVariant } from './components/nav';
|
|
23
|
+
export { Collapse, type CollapseProps, type CollapseCompound } from './components/collapse';
|
|
24
|
+
export { Tabset, type TabsetOption, type TabsetProps } from './components/tabset';
|
|
25
|
+
export { Layout, type LayoutGap, type LayoutAlign, type LayoutJustify, type LayoutColumns, type LayoutSpan, } from './components/layout';
|
|
26
|
+
export { Avatar, type AvatarProps, type AvatarSize, type AvatarCompound } from './components/avatar';
|
|
27
|
+
export { Skeleton, type SkeletonProps } from './components/skeleton';
|
|
28
|
+
export { Radio, type RadioProps, type RadioCompound, type RadioCompoundType, type RadioCardItem, type RadioCardValue, } from './components/radio';
|
|
29
|
+
export { Tag, type TagProps } from './components/tag';
|
|
30
|
+
export { Tree, type TreeNode } from './components/tree';
|
|
31
|
+
export { ListView, type ListViewProps, type ListViewStatus, type ListViewStatusTone, type ListViewCardItemProps, type ListViewCompound, } from './components/list-view';
|
|
32
|
+
export { Badge, type BadgeTone, type BadgeShape, type BadgeSize, type BadgeDot, type BadgeStatus, } from './components/badge';
|
|
33
|
+
export { Button, type ButtonVariant, type ButtonCompound, type ButtonCompoundType, } from './components/button';
|
|
34
|
+
export { Input, Textarea, type TextareaProps, type InputCompound, type InputCompoundType, } from './components/input';
|
|
35
|
+
export { Search, type SearchProps } from './components/search';
|
|
36
|
+
export { Select, type SelectOption, type SelectValue } from './components/select';
|
|
37
|
+
export { Switch } from './components/switch';
|
|
38
|
+
export { Capsule, type CapsuleOption, type CapsuleShape } from './components/capsule';
|
|
39
|
+
export { Form, type FormProps, type FormHeaderProps, type FormItemProps, type FormValues, type FormItemSlotScope, type FormLabelAlign, type FormPadding, type FormCompound, } from './components/form';
|
|
40
|
+
export { Checkbox, type CheckboxOption, type CheckboxCompound, type CheckboxCompoundType, } from './components/checkbox';
|
|
41
|
+
export { Filter, FilterItem, FILTER_ALL, normalizeFilterValue, type FilterValue, type FilterValues, type FilterProps, type FilterItemProps, type FilterItemSlotScope, type FilterCompound, } from './components/filter';
|
|
42
|
+
export { Notice, type NoticeTone } from './components/notice';
|
|
43
|
+
export { Notification, type NotificationTone, } from './components/notification';
|
|
44
|
+
export { Dialog, type DialogWidth } from './components/dialog';
|
|
45
|
+
export { Drawer, type DrawerSide } from './components/drawer';
|
|
46
|
+
export { Tooltip, type TooltipSide, type TooltipAlign, } from './components/tooltip';
|
|
47
|
+
export { Table, type TableColumn, type TableRow, type TableSortOrder, } from './components/table';
|
|
48
|
+
export { Pagination, type PaginationPageItem } from './components/pagination';
|
|
49
|
+
export { Tabs, type TabsOption, type TabsValue } from './components/tabs';
|
|
50
|
+
export { Steps, type StepsItem, type StepsVariant, type StepsCompound, type StepsCompoundType, } from './components/steps';
|
|
51
|
+
export { Toast, type ToastTone, type ToastCompound, type ToastCompoundType, } from './components/toast';
|
|
52
|
+
export { Code } from './components/code';
|
|
53
|
+
export { CodeEditor, type CodeEditorProps, type CodeEditorAutoSize, } from './components/code-editor';
|
|
54
|
+
export { Upload, formatFileSize, type UploadFile, type UploadCompound, type UploadCompoundType, } from './components/upload';
|
|
55
|
+
export { QueryState, type QueryStateKind, type QueryStateProps } from './components/query-state';
|
|
56
|
+
export { Loading, type LoadingOverlay, type LoadingProps } from './components/loading';
|
|
57
|
+
export type { ControlSize } from './components/control-size';
|
|
58
|
+
export type { Padding } from './components/part-padding';
|
|
59
|
+
export { partPaddingStyle, mergePartStyle } from './components/part-padding';
|
|
60
|
+
export { configureHost, getHostSelector, resolveHost } from './services';
|
|
61
|
+
export { toast, clearToasts, type ToastHandle, type ToastServiceOptions } from './services';
|
|
62
|
+
export { alert, closeAllDialogs, confirm, type ConfirmOptions } from './services';
|
|
63
|
+
export { hideLoading, showLoading } from './services';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Page } from "./components/page/index.js";
|
|
2
|
+
import { Panel } from "./components/panel/index.js";
|
|
3
|
+
import { Card } from "./components/card/index.js";
|
|
4
|
+
import { Divider } from "./components/divider/index.js";
|
|
5
|
+
import { Nav } from "./components/nav/index.js";
|
|
6
|
+
import { Collapse } from "./components/collapse/index.js";
|
|
7
|
+
import { Tabset } from "./components/tabset/index.js";
|
|
8
|
+
import { Layout } from "./components/layout/index.js";
|
|
9
|
+
import { Avatar } from "./components/avatar/index.js";
|
|
10
|
+
import { Skeleton } from "./components/skeleton/index.js";
|
|
11
|
+
import { Radio } from "./components/radio/index.js";
|
|
12
|
+
import { Tag } from "./components/tag/index.js";
|
|
13
|
+
import { Tree } from "./components/tree/index.js";
|
|
14
|
+
import { ListView } from "./components/list-view/index.js";
|
|
15
|
+
import { Badge } from "./components/badge/index.js";
|
|
16
|
+
import { Button } from "./components/button/index.js";
|
|
17
|
+
import { Input, Textarea } from "./components/input/index.js";
|
|
18
|
+
import { Search } from "./components/search/index.js";
|
|
19
|
+
import { Select } from "./components/select/index.js";
|
|
20
|
+
import { Switch } from "./components/switch/index.js";
|
|
21
|
+
import { Capsule } from "./components/capsule/index.js";
|
|
22
|
+
import { Form } from "./components/form/index.js";
|
|
23
|
+
import { Checkbox } from "./components/checkbox/index.js";
|
|
24
|
+
import { FILTER_ALL, Filter, FilterItem, normalizeFilterValue } from "./components/filter/index.js";
|
|
25
|
+
import { Notice } from "./components/notice/index.js";
|
|
26
|
+
import { Notification } from "./components/notification/index.js";
|
|
27
|
+
import { Dialog } from "./components/dialog/index.js";
|
|
28
|
+
import { Drawer } from "./components/drawer/index.js";
|
|
29
|
+
import { Tooltip } from "./components/tooltip/index.js";
|
|
30
|
+
import { Table } from "./components/table/index.js";
|
|
31
|
+
import { Pagination } from "./components/pagination/index.js";
|
|
32
|
+
import { Tabs } from "./components/tabs/index.js";
|
|
33
|
+
import { Steps } from "./components/steps/index.js";
|
|
34
|
+
import { Toast } from "./components/toast/index.js";
|
|
35
|
+
import { Code } from "./components/code/index.js";
|
|
36
|
+
import { CodeEditor } from "./components/code-editor/index.js";
|
|
37
|
+
import { Upload, formatFileSize } from "./components/upload/index.js";
|
|
38
|
+
import { QueryState } from "./components/query-state/index.js";
|
|
39
|
+
import { Loading } from "./components/loading/index.js";
|
|
40
|
+
import { mergePartStyle, partPaddingStyle } from "./components/part-padding.js";
|
|
41
|
+
import { alert, closeAllDialogs, confirm } from "./services/dialog.js";
|
|
42
|
+
import { clearToasts, toast } from "./services/toast.js";
|
|
43
|
+
import { configureHost, getHostSelector, resolveHost } from "./services/base.js";
|
|
44
|
+
import { hideLoading, showLoading } from "./services/loading.js";
|
|
45
|
+
export {
|
|
46
|
+
Avatar,
|
|
47
|
+
Badge,
|
|
48
|
+
Button,
|
|
49
|
+
Capsule,
|
|
50
|
+
Card,
|
|
51
|
+
Checkbox,
|
|
52
|
+
Code,
|
|
53
|
+
CodeEditor,
|
|
54
|
+
Collapse,
|
|
55
|
+
Dialog,
|
|
56
|
+
Divider,
|
|
57
|
+
Drawer,
|
|
58
|
+
FILTER_ALL,
|
|
59
|
+
Filter,
|
|
60
|
+
FilterItem,
|
|
61
|
+
Form,
|
|
62
|
+
Input,
|
|
63
|
+
Layout,
|
|
64
|
+
ListView,
|
|
65
|
+
Loading,
|
|
66
|
+
Nav,
|
|
67
|
+
Notice,
|
|
68
|
+
Notification,
|
|
69
|
+
Page,
|
|
70
|
+
Pagination,
|
|
71
|
+
Panel,
|
|
72
|
+
QueryState,
|
|
73
|
+
Radio,
|
|
74
|
+
Search,
|
|
75
|
+
Select,
|
|
76
|
+
Skeleton,
|
|
77
|
+
Steps,
|
|
78
|
+
Switch,
|
|
79
|
+
Table,
|
|
80
|
+
Tabs,
|
|
81
|
+
Tabset,
|
|
82
|
+
Tag,
|
|
83
|
+
Textarea,
|
|
84
|
+
Toast,
|
|
85
|
+
Tooltip,
|
|
86
|
+
Tree,
|
|
87
|
+
Upload,
|
|
88
|
+
alert,
|
|
89
|
+
clearToasts,
|
|
90
|
+
closeAllDialogs,
|
|
91
|
+
configureHost,
|
|
92
|
+
confirm,
|
|
93
|
+
formatFileSize,
|
|
94
|
+
getHostSelector,
|
|
95
|
+
hideLoading,
|
|
96
|
+
mergePartStyle,
|
|
97
|
+
normalizeFilterValue,
|
|
98
|
+
partPaddingStyle,
|
|
99
|
+
resolveHost,
|
|
100
|
+
showLoading,
|
|
101
|
+
toast
|
|
102
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** 注册宿主变更时的清理动作(服务层内部用;后注册的也按注册顺序执行) */
|
|
2
|
+
export declare function onHostReset(hook: () => void): void;
|
|
3
|
+
/** 显式指定服务层宿主;传 `null` 恢复自动解析 */
|
|
4
|
+
export declare function configureHost(el: Element | null): void;
|
|
5
|
+
/** 解析当前宿主(顺序见文件头;浏览器环境外直接抛错 —— 命令式服务没有可渲染的宿主) */
|
|
6
|
+
export declare function resolveHost(): Element;
|
|
7
|
+
/**
|
|
8
|
+
* 同 `resolveHost()`,但返回**选择器字符串** —— 给「只吃字符串宿主」的上游件用。
|
|
9
|
+
*
|
|
10
|
+
* 为什么不能直接给 Element:有的上游件把宿主当选择器解析(`document.querySelector(host)`),
|
|
11
|
+
* 传 Element 会拿到 `"[object HTMLDivElement]"` 这个非法选择器而当场抛错。给字符串又要避免
|
|
12
|
+
* 「门户里多应用并存时串到第一个 `[data-manohub-ui]`」,故给容器补一个**进程内唯一 id** 再返回它。
|
|
13
|
+
*/
|
|
14
|
+
export declare function getHostSelector(): string;
|
|
15
|
+
/**
|
|
16
|
+
* 建一个挂载容器并挂到宿主下。
|
|
17
|
+
*
|
|
18
|
+
* 挂在宿主**内部**而不是拿宿主本身当挂载点:宿主是应用自己的根节点,直接挂上去会让
|
|
19
|
+
* `app.unmount()` 把应用自己的渲染结果一起抹掉。
|
|
20
|
+
*/
|
|
21
|
+
export declare function createHostContainer(): HTMLElement;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
let configuredHost = null;
|
|
2
|
+
const resetHooks = [];
|
|
3
|
+
function onHostReset(hook) {
|
|
4
|
+
resetHooks.push(hook);
|
|
5
|
+
}
|
|
6
|
+
function configureHost(el) {
|
|
7
|
+
configuredHost = el;
|
|
8
|
+
for (const hook of resetHooks) hook();
|
|
9
|
+
}
|
|
10
|
+
function resolveHost() {
|
|
11
|
+
if (configuredHost) return configuredHost;
|
|
12
|
+
if (typeof document === "undefined") {
|
|
13
|
+
throw new Error("命令式服务只能在浏览器环境使用:当前上下文没有 document,无法解析渲染宿主");
|
|
14
|
+
}
|
|
15
|
+
return document.querySelector("[data-manohub-ui]") ?? document.body;
|
|
16
|
+
}
|
|
17
|
+
let idSeq = 0;
|
|
18
|
+
const containerIds = /* @__PURE__ */ new WeakMap();
|
|
19
|
+
function getHostSelector() {
|
|
20
|
+
const host = resolveHost();
|
|
21
|
+
if (host === document.body) return "body";
|
|
22
|
+
if (host.id) return `#${host.id}`;
|
|
23
|
+
let id = containerIds.get(host);
|
|
24
|
+
if (!id) {
|
|
25
|
+
id = `mh-service-host-${idSeq += 1}`;
|
|
26
|
+
containerIds.set(host, id);
|
|
27
|
+
host.id = id;
|
|
28
|
+
}
|
|
29
|
+
return `#${id}`;
|
|
30
|
+
}
|
|
31
|
+
function createHostContainer() {
|
|
32
|
+
const container = document.createElement("div");
|
|
33
|
+
resolveHost().appendChild(container);
|
|
34
|
+
return container;
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
configureHost,
|
|
38
|
+
createHostContainer,
|
|
39
|
+
getHostSelector,
|
|
40
|
+
onHostReset,
|
|
41
|
+
resolveHost
|
|
42
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface ConfirmOptions {
|
|
2
|
+
/** 标题(缺省不渲染页头,只剩内容与底栏) */
|
|
3
|
+
title?: string;
|
|
4
|
+
/** 正文(纯文本;复杂内容请直接用 `Dialog` 组件) */
|
|
5
|
+
detail?: string;
|
|
6
|
+
/** 确定按钮文案 */
|
|
7
|
+
okText?: string;
|
|
8
|
+
/** 取消按钮文案(`alert` 不使用) */
|
|
9
|
+
cancelText?: string;
|
|
10
|
+
/** 确定按钮的危险色(删除类确认) */
|
|
11
|
+
okDanger?: boolean;
|
|
12
|
+
/** 是否显示关闭位(缺省开:用户总得有第三条退路) */
|
|
13
|
+
closable?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 确认框(命令式):确定 → `true`,取消 / 关闭位 / Esc / 点遮罩 → `false`。
|
|
17
|
+
*
|
|
18
|
+
* 与 `Dialog` 组件的分工:组件是「受控弹窗」,本函数补齐命令式调用缺的那一层(宿主 + 收场 Promise)。
|
|
19
|
+
* 语义与主流库一致:**任何非确定路径都折成 `false`**,调用方 `if (await confirm(...))` 一处判断即可。
|
|
20
|
+
*
|
|
21
|
+
* 需要「确定按钮进加载态」的异步确认请直接用 `Dialog` 组件(`onOk` 返回 Promise 时自动进加载态)——
|
|
22
|
+
* 命令式形态刻意不引入跨 tick 的加载态,免得调用方以为弹窗已经关了。
|
|
23
|
+
*
|
|
24
|
+
* @example 删除确认
|
|
25
|
+
* if (await confirm({ title: '删除确认', detail: '删除后不可恢复,确认继续?', okText: '删除', okDanger: true })) {
|
|
26
|
+
* await remove()
|
|
27
|
+
* }
|
|
28
|
+
*/
|
|
29
|
+
export declare function confirm(options?: ConfirmOptions): Promise<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* 告知框(命令式):只有一个「知道了」,任意收场路径都 resolve。
|
|
32
|
+
*
|
|
33
|
+
* 底栏**自绘**而不是用内建底栏:内建底栏固定是「取消 + 确定」两枚,而告知框没有「取消」可言
|
|
34
|
+
* (给两枚按钮会让用户以为还有一条分支)。
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* await alert({ title: '导入完成', detail: '共 128 条,其中 3 条被跳过。' })
|
|
38
|
+
*/
|
|
39
|
+
export declare function alert(options?: ConfirmOptions): Promise<void>;
|
|
40
|
+
/** 收掉全部在档弹窗(逐个折成 `false`);幂等。换应用 / 卸载时调 */
|
|
41
|
+
export declare function closeAllDialogs(): void;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { ref, createApp, defineComponent, nextTick, h } from "vue";
|
|
2
|
+
import { Button } from "../components/button/index.js";
|
|
3
|
+
import { Dialog } from "../components/dialog/index.js";
|
|
4
|
+
import { createHostContainer, onHostReset } from "./base.js";
|
|
5
|
+
const pending = /* @__PURE__ */ new Set();
|
|
6
|
+
function openDialog(render) {
|
|
7
|
+
return new Promise((resolve) => {
|
|
8
|
+
const open = ref(true);
|
|
9
|
+
const container = createHostContainer();
|
|
10
|
+
let settled = false;
|
|
11
|
+
let app = null;
|
|
12
|
+
const finish = (value) => {
|
|
13
|
+
if (settled) return;
|
|
14
|
+
settled = true;
|
|
15
|
+
pending.delete(finish);
|
|
16
|
+
open.value = false;
|
|
17
|
+
resolve(value);
|
|
18
|
+
void nextTick(() => {
|
|
19
|
+
app?.unmount();
|
|
20
|
+
app = null;
|
|
21
|
+
container.remove();
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
const ctx = { isOpen: () => open.value, finish };
|
|
25
|
+
pending.add(finish);
|
|
26
|
+
app = createApp(
|
|
27
|
+
defineComponent({
|
|
28
|
+
name: "DialogServiceView",
|
|
29
|
+
setup: () => () => render(ctx)
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
app.mount(container);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function confirm(options = {}) {
|
|
36
|
+
return openDialog(
|
|
37
|
+
(ctx) => h(
|
|
38
|
+
Dialog,
|
|
39
|
+
{
|
|
40
|
+
open: ctx.isOpen(),
|
|
41
|
+
title: options.title,
|
|
42
|
+
closable: options.closable ?? true,
|
|
43
|
+
okText: options.okText ?? "确定",
|
|
44
|
+
cancelText: options.cancelText ?? "取消",
|
|
45
|
+
okDanger: options.okDanger ?? false,
|
|
46
|
+
onOk: () => ctx.finish(true),
|
|
47
|
+
onCancel: () => ctx.finish(false),
|
|
48
|
+
onClose: () => ctx.finish(false)
|
|
49
|
+
},
|
|
50
|
+
{ default: () => options.detail }
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
function alert(options = {}) {
|
|
55
|
+
return openDialog(
|
|
56
|
+
(ctx) => h(
|
|
57
|
+
Dialog,
|
|
58
|
+
{
|
|
59
|
+
open: ctx.isOpen(),
|
|
60
|
+
title: options.title,
|
|
61
|
+
closable: options.closable ?? true,
|
|
62
|
+
// 关闭位与 Esc 都算「看过了」
|
|
63
|
+
onCancel: () => ctx.finish(true),
|
|
64
|
+
onClose: () => ctx.finish(true)
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
default: () => options.detail,
|
|
68
|
+
footer: () => h(Button, { variant: "primary", onClick: () => ctx.finish(true) }, {
|
|
69
|
+
default: () => options.okText ?? "知道了"
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
).then(() => void 0);
|
|
74
|
+
}
|
|
75
|
+
function closeAllDialogs() {
|
|
76
|
+
for (const finish of [...pending]) finish(false);
|
|
77
|
+
}
|
|
78
|
+
onHostReset(() => closeAllDialogs());
|
|
79
|
+
export {
|
|
80
|
+
alert,
|
|
81
|
+
closeAllDialogs,
|
|
82
|
+
confirm
|
|
83
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 服务层出口(命令式反馈:消息提示 / 确认框 / 全屏加载)。
|
|
3
|
+
*
|
|
4
|
+
* 与组件层的分工:**组件的可见性归调用方**(受控、到点只回调);本层补齐命令式调用缺的那三样
|
|
5
|
+
* ——宿主、队列与生命周期。二者共用同一批组件与同一份面,不另造一套浮层。
|
|
6
|
+
*
|
|
7
|
+
* 宿主解析见 `./base`:微前端下必须落回**本应用自己的容器**,否则令牌与应用侧样式同时失效。
|
|
8
|
+
*/
|
|
9
|
+
export { configureHost, getHostSelector, resolveHost } from './base';
|
|
10
|
+
export { toast, clearToasts, type ToastHandle, type ToastServiceOptions } from './toast';
|
|
11
|
+
export { alert, closeAllDialogs, confirm, type ConfirmOptions } from './dialog';
|
|
12
|
+
export { hideLoading, showLoading } from './loading';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 显示全屏加载遮罩(命令式),返回**幂等的关闭句柄**。
|
|
3
|
+
*
|
|
4
|
+
* 遮罩落在服务宿主(应用自己的 `[data-manohub-ui]` 容器)内 —— 令牌与应用侧样式都跟着它走。
|
|
5
|
+
* 层级压在同包的 `Toast` 堆叠之上、模态层(`<dialog>` 的 top layer)之下。
|
|
6
|
+
*
|
|
7
|
+
* @example 配平用法(推荐:句柄只关自己那一次)
|
|
8
|
+
* const done = showLoading('保存中…')
|
|
9
|
+
* try {
|
|
10
|
+
* await save()
|
|
11
|
+
* } finally {
|
|
12
|
+
* done()
|
|
13
|
+
* }
|
|
14
|
+
*
|
|
15
|
+
* @example 文案可后置(同一批并发里最后一次给的文案生效)
|
|
16
|
+
* showLoading()
|
|
17
|
+
* showLoading('正在导入,请勿关闭页面')
|
|
18
|
+
*/
|
|
19
|
+
export declare function showLoading(value?: string): () => void;
|
|
20
|
+
/** 关闭一次(引用计数递减);计数归零时收掉宿主与实例。已是 0 时是 no-op */
|
|
21
|
+
export declare function hideLoading(): void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createApp, ref, defineComponent, h } from "vue";
|
|
2
|
+
import { Loading } from "../components/loading/index.js";
|
|
3
|
+
import { createHostContainer, onHostReset } from "./base.js";
|
|
4
|
+
let count = 0;
|
|
5
|
+
let app = null;
|
|
6
|
+
let container = null;
|
|
7
|
+
const text = ref(void 0);
|
|
8
|
+
const LoadingServiceView = defineComponent({
|
|
9
|
+
name: "LoadingServiceView",
|
|
10
|
+
setup: () => () => h(Loading, { overlay: "screen", text: text.value })
|
|
11
|
+
});
|
|
12
|
+
function ensureApp() {
|
|
13
|
+
if (app) return;
|
|
14
|
+
container = createHostContainer();
|
|
15
|
+
app = createApp(LoadingServiceView);
|
|
16
|
+
app.mount(container);
|
|
17
|
+
}
|
|
18
|
+
function dispose() {
|
|
19
|
+
count = 0;
|
|
20
|
+
text.value = void 0;
|
|
21
|
+
app?.unmount();
|
|
22
|
+
app = null;
|
|
23
|
+
container?.remove();
|
|
24
|
+
container = null;
|
|
25
|
+
}
|
|
26
|
+
function showLoading(value) {
|
|
27
|
+
ensureApp();
|
|
28
|
+
count += 1;
|
|
29
|
+
text.value = value;
|
|
30
|
+
return () => hideLoading();
|
|
31
|
+
}
|
|
32
|
+
function hideLoading() {
|
|
33
|
+
if (count === 0) return;
|
|
34
|
+
count -= 1;
|
|
35
|
+
if (count === 0) dispose();
|
|
36
|
+
}
|
|
37
|
+
onHostReset(() => dispose());
|
|
38
|
+
export {
|
|
39
|
+
hideLoading,
|
|
40
|
+
showLoading
|
|
41
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type ToastTone } from '../components/toast';
|
|
2
|
+
export interface ToastServiceOptions {
|
|
3
|
+
/** 自动消失毫秒数(缺省 3000;`0` = 常驻,必须由调用方或用户自行关掉) */
|
|
4
|
+
duration?: number;
|
|
5
|
+
/** 动作位(文案 + 回调):如「导出失败 → 重试」 */
|
|
6
|
+
action?: {
|
|
7
|
+
text: string;
|
|
8
|
+
onClick: () => void;
|
|
9
|
+
};
|
|
10
|
+
/** 手动关闭位(缺省:常驻提示自动开、会自己消失的不开) */
|
|
11
|
+
closable?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** 单条提示的句柄:提前关掉它(如「保存中」完成后立刻收掉) */
|
|
14
|
+
export interface ToastHandle {
|
|
15
|
+
close: () => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 弹一条消息提示(命令式)。
|
|
19
|
+
*
|
|
20
|
+
* 与 `Toast` 组件的分工:组件是「一条提示的渲染与计时」,本函数补齐命令式调用缺的那一层
|
|
21
|
+
* ——**宿主、队列、上限、按需挂载**。四条语义:
|
|
22
|
+
* ① 首次调用才建宿主与 Vue 实例(模块顶层零 DOM 操作,不拖首屏);
|
|
23
|
+
* ② 队列空时自动收掉宿主;
|
|
24
|
+
* ③ 同屏最多 5 条,超出挤掉最早的;
|
|
25
|
+
* ④ 返回句柄可提前关掉它自己(其余各条互不影响)。
|
|
26
|
+
*
|
|
27
|
+
* @example 成功提示(3 秒自动消失)
|
|
28
|
+
* toast('success', '保存成功')
|
|
29
|
+
*
|
|
30
|
+
* @example 失败 + 重试动作
|
|
31
|
+
* toast('error', '导出失败', { action: { text: '重试', onClick: retry } })
|
|
32
|
+
*
|
|
33
|
+
* @example 常驻的「进行中」,完成后自己收掉
|
|
34
|
+
* const pending = toast('loading', '正在导入…', { duration: 0 })
|
|
35
|
+
* // …导入完成
|
|
36
|
+
* pending.close()
|
|
37
|
+
*/
|
|
38
|
+
export declare function toast(tone: ToastTone, text: string, options?: ToastServiceOptions): ToastHandle;
|
|
39
|
+
/** 清空全部提示并收掉宿主(换应用 / 卸载时调;幂等) */
|
|
40
|
+
export declare function clearToasts(): void;
|