@manohub/ui 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +4 -4
  2. package/dist/components/button/index.d.ts +14 -8
  3. package/dist/components/capsule/index.d.ts +13 -9
  4. package/dist/components/capsule/index.js +1 -1
  5. package/dist/components/card/index.d.ts +1 -1
  6. package/dist/components/card/index.js +7 -4
  7. package/dist/components/checkbox/index.js +1 -0
  8. package/dist/components/dialog/index.d.ts +1 -1
  9. package/dist/components/form/index.d.ts +142 -62
  10. package/dist/components/form/index.js +41 -29
  11. package/dist/components/input/index.d.ts +74 -6
  12. package/dist/components/input/index.js +13 -1
  13. package/dist/components/layout/index.d.ts +43 -1
  14. package/dist/components/layout/index.js +22 -2
  15. package/dist/components/list-view/index.d.ts +1 -1
  16. package/dist/components/notice/index.d.ts +2 -2
  17. package/dist/components/notification/index.d.ts +2 -2
  18. package/dist/components/page/index.js +4 -4
  19. package/dist/components/pagination/index.d.ts +2 -2
  20. package/dist/components/pagination/index.js +1 -1
  21. package/dist/components/panel/index.js +4 -4
  22. package/dist/components/part-padding.d.ts +9 -6
  23. package/dist/components/part-padding.js +2 -1
  24. package/dist/components/query-state/index.d.ts +18 -2
  25. package/dist/components/radio/index.d.ts +1 -1
  26. package/dist/components/radio/index.js +1 -0
  27. package/dist/components/select/index.d.ts +32 -30
  28. package/dist/components/select/index.js +46 -82
  29. package/dist/components/select/select-list.d.ts +125 -0
  30. package/dist/components/select/select-list.js +95 -0
  31. package/dist/components/select/select-panel.d.ts +106 -0
  32. package/dist/components/select/select-panel.js +72 -0
  33. package/dist/components/select/select-shared.d.ts +64 -0
  34. package/dist/components/select/select-shared.js +24 -0
  35. package/dist/components/select/select-tree-filter.d.ts +61 -0
  36. package/dist/components/select/select-tree-filter.js +63 -0
  37. package/dist/components/select/select-tree.d.ts +274 -0
  38. package/dist/components/select/select-tree.js +263 -0
  39. package/dist/components/select/select-trigger.d.ts +132 -0
  40. package/dist/components/select/select-trigger.js +101 -0
  41. package/dist/components/steps/index.d.ts +232 -6
  42. package/dist/components/steps/index.js +84 -26
  43. package/dist/components/switch/index.d.ts +29 -5
  44. package/dist/components/switch/index.js +8 -2
  45. package/dist/components/tabbar/index.d.ts +184 -0
  46. package/dist/components/tabbar/index.js +161 -0
  47. package/dist/components/table/index.d.ts +99 -12
  48. package/dist/components/table/index.js +69 -16
  49. package/dist/components/tabs/index.d.ts +142 -126
  50. package/dist/components/tabs/index.js +87 -119
  51. package/dist/components/tag/index.d.ts +2 -2
  52. package/dist/components/text/index.d.ts +7 -2
  53. package/dist/components/toast/index.d.ts +8 -8
  54. package/dist/components/tree/index.d.ts +28 -2
  55. package/dist/components/tree/index.js +14 -1
  56. package/dist/index.d.ts +6 -6
  57. package/dist/index.js +6 -3
  58. package/dist/styles/components/capsule.css +4 -4
  59. package/dist/styles/components/form.css +198 -39
  60. package/dist/styles/components/input.css +53 -1
  61. package/dist/styles/components/layout.css +2 -0
  62. package/dist/styles/components/select.css +21 -0
  63. package/dist/styles/components/select.tokens.css +3 -0
  64. package/dist/styles/components/steps.css +48 -0
  65. package/dist/styles/components/{tabs.css → tabbar.css} +66 -65
  66. package/dist/styles/components/tabbar.tokens.css +30 -0
  67. package/dist/styles/components/table.css +50 -1
  68. package/dist/styles/components/table.tokens.css +3 -0
  69. package/dist/styles/index.css +3 -3
  70. package/dist/styles/operations/tabs.css +73 -0
  71. package/package.json +2 -2
  72. package/dist/components/tabset/index.d.ts +0 -109
  73. package/dist/components/tabset/index.js +0 -75
  74. package/dist/styles/components/tabs.tokens.css +0 -30
  75. package/dist/styles/operations/tabset.css +0 -57
@@ -1,72 +1,64 @@
1
- import { defineComponent, ref, computed, createVNode, Fragment, mergeProps } from "vue";
2
- import { Icon } from "@manohub/icon";
1
+ import { defineComponent, ref, createVNode } from "vue";
2
+ import { TabBar } from "../tabbar/index.js";
3
+ const TabPanel = /* @__PURE__ */ defineComponent({
4
+ name: "TabPanel",
5
+ /* 渲染的是插槽内容(片段根),属性无处可继承 —— 壳归 `Tabs`,属性由它在渲染期搬过去 */
6
+ inheritAttrs: false,
7
+ props: {
8
+ name: {
9
+ type: String,
10
+ required: true
11
+ },
12
+ value: {
13
+ type: [String, Number],
14
+ default: void 0
15
+ },
16
+ disabled: {
17
+ type: Boolean,
18
+ default: false
19
+ },
20
+ lazy: {
21
+ type: Boolean,
22
+ default: false
23
+ }
24
+ },
25
+ slots: Object,
26
+ setup(_props, {
27
+ slots
28
+ }) {
29
+ return () => slots.default?.() ?? null;
30
+ }
31
+ });
32
+ const flattenChildren = (raw) => (Array.isArray(raw) ? raw : raw == null ? [] : [raw]).flatMap((child) => Array.isArray(child) ? child : [child]).filter((child) => child !== null && child !== void 0 && child !== false && child !== true && child !== "");
33
+ const isTabPanel = (child) => !!child && typeof child === "object" && child.type === TabPanel;
34
+ const panelPropsOf = (child) => isTabPanel(child) ? child.props ?? {} : null;
3
35
  const Tabs = /* @__PURE__ */ defineComponent({
4
36
  name: "Tabs",
5
37
  inheritAttrs: false,
6
38
  props: {
7
39
  options: {
8
40
  type: Array,
9
- required: true
41
+ default: void 0
10
42
  },
11
- /** 受控选中值;不传即非受控(由 `defaultValue` 起) */
12
43
  value: {
13
44
  type: [String, Number],
14
45
  default: void 0
15
46
  },
16
- /** 非受控初始选中值,缺省第一项 */
17
47
  defaultValue: {
18
48
  type: [String, Number],
19
49
  default: void 0
20
50
  },
21
- /** 选中变化回调(受控与非受控都会调) */
22
51
  onChange: {
23
52
  type: Function,
24
53
  default: void 0
25
54
  },
26
- /** 形态:`line` 下划线 / `card` 选项卡 */
27
- type: {
28
- type: String,
29
- default: "line"
30
- },
31
- /** 整体居中(页签少、要撑满整行时用) */
32
- centered: {
33
- type: Boolean,
34
- default: false
35
- },
36
- /** 尺寸档(24 / 32 / 40,只覆盖令牌) */
37
- size: {
38
- type: String,
39
- default: "md"
40
- },
41
- /** 每项带关闭位(单项可用 `option.closable` 覆写) */
42
- closable: {
43
- type: Boolean,
44
- default: false
45
- },
46
- /** 尾部「新增」按钮 */
47
- addable: {
55
+ lazy: {
48
56
  type: Boolean,
49
57
  default: false
50
- },
51
- /** 「更多」页签的文字 */
52
- moreLabel: {
53
- type: String,
54
- default: "更多"
55
- },
56
- /** 关闭某项(只回调,**不从 `options` 里删** —— 数据归调用方) */
57
- onClose: {
58
- type: Function,
59
- default: void 0
60
- },
61
- /** 点新增(只回调) */
62
- onAdd: {
63
- type: Function,
64
- default: void 0
65
58
  }
66
59
  },
67
- /* 受控值必须 emit 回 `update:value`,否则 `v-model:value="x"` 是**静默失效**的:
68
- 受控时 `props.value !== undefined` ⇒ 内部状态不更新,而外部又收不到新值 ⇒ 点 tab 毫无反应
69
- (不报错、不警告)。本件 0.6.x 就漏了这条 —— 文档示例教 `v-model:value` 却点了不动。 */
60
+ /* 同 `TabBar`:受控值必须 emit 回 `update:value`,否则 `v-model:value="current"` 静默失效
61
+ (受控时内部状态不更新、外部又收不到 ⇒ 点选项毫无反应)。 */
70
62
  emits: {
71
63
  "update:value": (value) => true
72
64
  },
@@ -76,86 +68,62 @@ const Tabs = /* @__PURE__ */ defineComponent({
76
68
  attrs,
77
69
  emit
78
70
  }) {
79
- const innerValue = ref(props.value ?? props.defaultValue ?? props.options[0]?.value);
80
- const current = computed(() => props.value ?? innerValue.value);
81
- const moreId = `mh-tabs-${Math.random().toString(36).slice(2, 10)}`;
71
+ const innerValue = ref(props.defaultValue);
72
+ let items = [];
82
73
  const select = (value) => {
83
- const target = props.options.find((option) => option.value === value);
84
- if (target?.disabled) return;
74
+ if (items.find((option) => option.value === value)?.disabled) return;
85
75
  if (props.value === void 0) innerValue.value = value;
86
76
  emit("update:value", value);
87
77
  props.onChange?.(value);
88
78
  };
89
- const isClosable = (option) => option.closable ?? props.closable;
90
- return () => createVNode("nav", {
91
- "class": [
92
- "mh-tabs",
93
- /* `mh-popup-host` 是操作层展开转向的**宿主标记**(popup.css 靠它 :has 反推面板开合):
94
- 没有它,「更多」的 caret 展开时不会翻向 —— 与 Select / Tooltip 同一分工。 */
95
- "mh-popup-host",
96
- props.type === "card" ? "mh-tabs--card" : "",
97
- props.centered ? "mh-tabs--centered" : "",
98
- props.size === "md" ? "" : `mh-tabs--${props.size}`,
99
- attrs.class
100
- ].filter(Boolean).join(" "),
101
- "style": attrs.style,
102
- "role": "tablist"
103
- }, [props.options.map((option) => {
104
- const active = option.value === current.value;
105
- return createVNode("button", {
106
- "key": option.value,
107
- "type": "button",
108
- "role": "tab",
109
- "class": ["mh-tabs__tab", active ? "is-selected" : "", option.disabled ? "is-disabled" : ""].filter(Boolean).join(" "),
110
- "data-state": active ? "active" : "inactive",
111
- "aria-selected": active,
112
- "disabled": option.disabled,
113
- "onClick": () => select(option.value)
114
- }, [option.label, isClosable(option) && !option.disabled ? (
115
- /* 关闭位不是 `<button>`:页签自己是按钮,按钮里嵌按钮是非法 HTML。
116
- 用 `role="button"` + `stopPropagation` 表达同样的语义与行为。 */
117
- createVNode("span", {
118
- "class": "mh-tabs__close",
119
- "role": "button",
120
- "tabindex": -1,
121
- "aria-label": `关闭${option.label}`,
122
- "onClick": (event) => {
123
- event.stopPropagation();
124
- event.preventDefault();
125
- props.onClose?.(option.value);
126
- }
127
- }, [createVNode(Icon, {
128
- "name": "close"
129
- }, null)])
130
- ) : null]);
131
- }), props.addable ? createVNode("button", {
132
- "type": "button",
133
- "class": "mh-tabs__add",
134
- "aria-label": "新增页签",
135
- "onClick": () => props.onAdd?.()
136
- }, [createVNode(Icon, {
137
- "name": "plus"
138
- }, null)]) : null, slots.more ? createVNode(Fragment, null, [createVNode("button", mergeProps({
139
- "type": "button",
140
- "class": "mh-tabs__tab mh-tabs__tab--more",
141
- "data-state": "inactive"
142
- }, {
143
- popovertarget: moreId
144
- }), [props.moreLabel, createVNode(Icon, {
145
- "name": "chevron-down",
146
- "class": "mh-popup-caret"
147
- }, null)]), createVNode("div", mergeProps({
148
- "id": moreId,
149
- "class": "mh-popup",
150
- "data-side": "bottom",
151
- "data-align": "end"
152
- }, {
153
- popover: "auto"
154
- }), [slots.more({
155
- options: props.options
156
- })])]) : null]);
79
+ return () => {
80
+ const nodes = flattenChildren(slots.default?.());
81
+ const panelMode = nodes.some(isTabPanel);
82
+ const list = panelMode ? nodes.filter(isTabPanel) : nodes;
83
+ const blockItems = list.map((node, index) => {
84
+ const info = panelPropsOf(node);
85
+ if (info) {
86
+ return {
87
+ label: info.name,
88
+ value: info.value ?? info.name,
89
+ disabled: info.disabled ?? false
90
+ };
91
+ }
92
+ return props.options?.[index] ?? null;
93
+ });
94
+ items = blockItems.filter((item) => item !== null);
95
+ const current = props.value ?? innerValue.value ?? items[0]?.value;
96
+ const panels = list.map((node, index) => {
97
+ const item = blockItems[index];
98
+ const info = panelPropsOf(node);
99
+ const active = item !== null && item.value === current;
100
+ if ((props.lazy || info?.lazy) && !active) return null;
101
+ const raw = info ? node.props ?? {} : {};
102
+ return createVNode("div", {
103
+ "key": String(item?.value ?? index),
104
+ "class": ["mh-tabs-panel", raw.class].filter(Boolean).join(" "),
105
+ "style": raw.style,
106
+ "hidden": !active
107
+ }, [node]);
108
+ });
109
+ return createVNode("div", {
110
+ "class": ["mh-tabs", attrs.class].filter(Boolean).join(" "),
111
+ "style": attrs.style
112
+ }, [slots.selector ? slots.selector({
113
+ value: current,
114
+ options: items,
115
+ select
116
+ }) : createVNode(TabBar, {
117
+ "options": items,
118
+ "value": current,
119
+ "onChange": select
120
+ }, null), createVNode("div", {
121
+ "class": "mh-tabs-panels"
122
+ }, [panels])]);
123
+ };
157
124
  }
158
125
  });
159
126
  export {
127
+ TabPanel,
160
128
  Tabs
161
129
  };
@@ -185,7 +185,7 @@ export declare const Tag: import("vue").DefineComponent<import("vue").ExtractPro
185
185
  }>> & Readonly<{}>, {
186
186
  color: string;
187
187
  size: ControlSize;
188
- icon: "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
188
+ icon: "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
189
189
  disabled: boolean;
190
190
  name: string;
191
191
  value: string | number;
@@ -196,8 +196,8 @@ export declare const Tag: import("vue").DefineComponent<import("vue").ExtractPro
196
196
  selected: boolean;
197
197
  lg: boolean;
198
198
  shape: "add" | "select" | "chip" | "regular" | "status" | undefined;
199
- tone: "error" | "info" | "success" | "warning" | undefined;
200
199
  closable: boolean;
200
+ tone: "error" | "info" | "success" | "warning" | undefined;
201
201
  }, SlotsType<{
202
202
  default?: () => VNodeChild;
203
203
  }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -1,7 +1,12 @@
1
1
  import { type PropType, type SlotsType, type VNodeChild } from 'vue';
2
2
  /** 字号档(每档都有一枚配套的行高令牌,故**不开放**只有字号的 micro / display) */
3
3
  export type TextSize = 'caption' | 'body' | 'heading' | 'title';
4
- /** 语义色档(`success` / `warning` 取 `-strong`,与 `Notice` / `Dialog` 同一张表) */
4
+ /**
5
+ * 语义色档(`success` / `warning` 取 `-strong`,与 `Notice` / `Dialog` 同一张表)。
6
+ *
7
+ * ⚠️ 自绘样式时要字色,一律落 `--ui-<tone>` / `--ui-<tone>-strong`(浅底深字)。
8
+ * `--ui-*-content` 那一族是**实心填充之上的白字**,配浅底(`-weak`)就是白字白底。
9
+ */
5
10
  export type TextTone = 'default' | 'muted' | 'subtle' | 'primary' | 'success' | 'warning' | 'error';
6
11
  /** 字重档(缺省**不设**,即继承上下文 —— 这样「在已加粗的区域里放一段普通文字」不必显式写 regular) */
7
12
  export type TextWeight = 'regular' | 'medium' | 'semibold';
@@ -30,7 +35,7 @@ export interface TextProps {
30
35
  * 但**没有件消费它们**:卡片描述、表单说明、只读值、列表次级信息这些「容器里的文字层级」
31
36
  * 于是无处可归 —— `Card` 只管卡片外壳,`Panel` 只管区域,两者都不管内容里的排版;
32
37
  * 而契约 L1-5 又禁应用侧写 `font-*` / `color`。**令牌有了、路径没有**,
33
- * 结果就是每个应用都要为「卡片里的文字」保留一条定版例外登记(本仓 repository 的 31 处里,
38
+ * 结果就是每个应用都要为「卡片里的文字」保留一条定版例外登记(首批迁移的登记项里,
34
39
  * 绝大多数属于这一类)。本件把这条路径补上。
35
40
  *
36
41
  * ## 与 `Title` / 平台默认的关系
@@ -99,9 +99,9 @@ export declare const Toast: import("vue").DefineComponent<import("vue").ExtractP
99
99
  onClose?: (() => any) | undefined;
100
100
  }>, {
101
101
  text: string;
102
- icon: boolean | "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
103
- tone: ToastTone;
102
+ icon: boolean | "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
104
103
  closable: boolean;
104
+ tone: ToastTone;
105
105
  action: string;
106
106
  onAction: () => void;
107
107
  duration: number;
@@ -151,9 +151,9 @@ export declare const ToastCompound: {
151
151
  close: () => true;
152
152
  }, import("vue").PublicProps, {
153
153
  text: string;
154
- icon: boolean | "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
155
- tone: ToastTone;
154
+ icon: boolean | "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
156
155
  closable: boolean;
156
+ tone: ToastTone;
157
157
  action: string;
158
158
  onAction: () => void;
159
159
  duration: number;
@@ -205,9 +205,9 @@ export declare const ToastCompound: {
205
205
  onClose?: (() => any) | undefined;
206
206
  }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, {
207
207
  text: string;
208
- icon: boolean | "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
209
- tone: ToastTone;
208
+ icon: boolean | "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
210
209
  closable: boolean;
210
+ tone: ToastTone;
211
211
  action: string;
212
212
  onAction: () => void;
213
213
  duration: number;
@@ -256,9 +256,9 @@ export declare const ToastCompound: {
256
256
  close: () => true;
257
257
  }, string, {
258
258
  text: string;
259
- icon: boolean | "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
260
- tone: ToastTone;
259
+ icon: boolean | "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
261
260
  closable: boolean;
261
+ tone: ToastTone;
262
262
  action: string;
263
263
  onAction: () => void;
264
264
  duration: number;
@@ -23,8 +23,7 @@ export interface TreeNode {
23
23
  * ## 为什么自建(对照计划登记的退路)
24
24
  *
25
25
  * farris `FTreeView` 实测结论:① 是列模板式网格(节点内容可用 `columnTemplate` 承载);
26
- * ② **只在挂载时填充一次可见行,data 变化不刷新**(仓内唯一的适配器
27
- * `apps/skill/src/features/skill/farris-file-tree.tsx` 正是用 `key` 强制重挂绕行);
26
+ * ② **只在挂载时填充一次可见行,data 变化不刷新**(**唯一**的兜底是 `key` 强制重挂 —— 那会丢展开态);
28
27
  * ③ 层级缩进不可控、节点图标走 farris 图标字体类。
29
28
  *
30
29
  * 而本组件的硬需求是「数据更新时**不丢**用户已展开的节点 / 滚动位置 / 焦点」——
@@ -80,6 +79,19 @@ export declare const Tree: import("vue").DefineComponent<import("vue").ExtractPr
80
79
  type: PropType<(node: TreeNode) => void>;
81
80
  default: undefined;
82
81
  };
82
+ /**
83
+ * 标签体的自定义渲染(**替掉** `labelKey` 的纯文本)。
84
+ *
85
+ * 与 `renderNode` 的分工:本 prop 渲染的是**标签本体**(占位、省略号、行内对齐都由 `.mh-tree__label`
86
+ * 承担,因此必须留在那个槽里);`renderNode` 渲染的是标签**之后**的常驻附加内容(计数徽标一类)。
87
+ * 典型用途是搜索命中的文本高亮(把标签切成多个片段)。
88
+ *
89
+ * 缺省不传时仍渲染 `labelKey` 的纯文本 —— 这是绝大多数消费方的路径,行为零变化。
90
+ */
91
+ renderLabel: {
92
+ type: PropType<(node: TreeNode) => unknown>;
93
+ default: undefined;
94
+ };
83
95
  /** 节点附加内容(计数徽标等),渲染在标签之后 */
84
96
  renderNode: {
85
97
  type: PropType<(node: TreeNode) => unknown>;
@@ -200,6 +212,19 @@ export declare const Tree: import("vue").DefineComponent<import("vue").ExtractPr
200
212
  type: PropType<(node: TreeNode) => void>;
201
213
  default: undefined;
202
214
  };
215
+ /**
216
+ * 标签体的自定义渲染(**替掉** `labelKey` 的纯文本)。
217
+ *
218
+ * 与 `renderNode` 的分工:本 prop 渲染的是**标签本体**(占位、省略号、行内对齐都由 `.mh-tree__label`
219
+ * 承担,因此必须留在那个槽里);`renderNode` 渲染的是标签**之后**的常驻附加内容(计数徽标一类)。
220
+ * 典型用途是搜索命中的文本高亮(把标签切成多个片段)。
221
+ *
222
+ * 缺省不传时仍渲染 `labelKey` 的纯文本 —— 这是绝大多数消费方的路径,行为零变化。
223
+ */
224
+ renderLabel: {
225
+ type: PropType<(node: TreeNode) => unknown>;
226
+ default: undefined;
227
+ };
203
228
  /** 节点附加内容(计数徽标等),渲染在标签之后 */
204
229
  renderNode: {
205
230
  type: PropType<(node: TreeNode) => unknown>;
@@ -305,6 +330,7 @@ export declare const Tree: import("vue").DefineComponent<import("vue").ExtractPr
305
330
  onErrorAction: () => void;
306
331
  labelKey: string;
307
332
  childrenKey: string;
333
+ renderLabel: (node: TreeNode) => unknown;
308
334
  renderNode: (node: TreeNode) => unknown;
309
335
  renderActions: (node: TreeNode) => unknown;
310
336
  expandedKeys: string[];
@@ -33,6 +33,19 @@ const Tree = /* @__PURE__ */ defineComponent({
33
33
  type: Function,
34
34
  default: void 0
35
35
  },
36
+ /**
37
+ * 标签体的自定义渲染(**替掉** `labelKey` 的纯文本)。
38
+ *
39
+ * 与 `renderNode` 的分工:本 prop 渲染的是**标签本体**(占位、省略号、行内对齐都由 `.mh-tree__label`
40
+ * 承担,因此必须留在那个槽里);`renderNode` 渲染的是标签**之后**的常驻附加内容(计数徽标一类)。
41
+ * 典型用途是搜索命中的文本高亮(把标签切成多个片段)。
42
+ *
43
+ * 缺省不传时仍渲染 `labelKey` 的纯文本 —— 这是绝大多数消费方的路径,行为零变化。
44
+ */
45
+ renderLabel: {
46
+ type: Function,
47
+ default: void 0
48
+ },
36
49
  /** 节点附加内容(计数徽标等),渲染在标签之后 */
37
50
  renderNode: {
38
51
  type: Function,
@@ -231,7 +244,7 @@ const Tree = /* @__PURE__ */ defineComponent({
231
244
  "class": "mh-tree__caret mh-tree__caret--empty"
232
245
  }, null), createVNode("span", {
233
246
  "class": "mh-tree__label"
234
- }, [String(node[props.labelKey] ?? "")]), props.renderNode ? createVNode("span", {
247
+ }, [props.renderLabel ? props.renderLabel(node) : String(node[props.labelKey] ?? "")]), props.renderNode ? createVNode("span", {
235
248
  "class": "mh-tree__extra"
236
249
  }, [props.renderNode(node)]) : null, props.renderActions ? createVNode("span", {
237
250
  "class": "mh-tree__actions",
package/dist/index.d.ts CHANGED
@@ -21,7 +21,7 @@ export { Card, type CardProps, type CardVariant, type CardPadding, type CardHead
21
21
  export { Divider, type DividerProps } from './components/divider';
22
22
  export { Nav, type NavVariant } from './components/nav';
23
23
  export { Collapse, type CollapseProps, type CollapseCompound } from './components/collapse';
24
- export { Tabset, type TabsetOption, type TabsetProps } from './components/tabset';
24
+ export { TabPanel, Tabs, type TabPanelProps, type TabsOption, type TabsProps } from './components/tabs';
25
25
  export { Layout, type LayoutGap, type LayoutAlign, type LayoutJustify, type LayoutColumns, type LayoutSpan, } from './components/layout';
26
26
  export { Avatar, type AvatarProps, type AvatarSize, type AvatarCompound } from './components/avatar';
27
27
  export { Skeleton, type SkeletonProps } from './components/skeleton';
@@ -34,10 +34,10 @@ export { Badge, type BadgeTone, type BadgeShape, type BadgeSize, type BadgeDot,
34
34
  export { Button, type ButtonVariant, type ButtonCompound, type ButtonCompoundType, } from './components/button';
35
35
  export { Input, Textarea, type TextareaProps, type InputCompound, type InputCompoundType, } from './components/input';
36
36
  export { Search, type SearchProps } from './components/search';
37
- export { Select, type SelectOption, type SelectValue } from './components/select';
37
+ export { Select, SelectTree, type SelectOption, type SelectValue } from './components/select';
38
38
  export { Switch } from './components/switch';
39
39
  export { Capsule, type CapsuleOption, type CapsuleShape } from './components/capsule';
40
- export { Form, type FormProps, type FormHeaderProps, type FormItemProps, type FormValues, type FormItemSlotScope, type FormLabelAlign, type FormPadding, type FormCompound, } from './components/form';
40
+ export { Form, type FormProps, type FormHeaderProps, type FormItemProps, type FormValues, type FormItemSlotScope, type FormItemAlign, type FormLabelAlign, type FormColumns, type FormPadding, type FormCompound, } from './components/form';
41
41
  export { Checkbox, type CheckboxOption, type CheckboxCompound, type CheckboxCompoundType, } from './components/checkbox';
42
42
  export { Filter, FilterItem, FILTER_ALL, normalizeFilterValue, type FilterValue, type FilterValues, type FilterProps, type FilterItemProps, type FilterItemSlotScope, type FilterCompound, } from './components/filter';
43
43
  export { Notice, type NoticeTone } from './components/notice';
@@ -45,10 +45,10 @@ 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 TableRow, type TableSortOrder, } from './components/table';
48
+ export { Table, type TableColumn, type TableRow, type TableRowSelectable, type TableSortOrder, } from './components/table';
49
49
  export { Pagination, type PaginationPageItem } from './components/pagination';
50
- export { Tabs, type TabsOption, type TabsValue } from './components/tabs';
51
- export { Steps, type StepsItem, type StepsVariant, type StepsCompound, type StepsCompoundType, } from './components/steps';
50
+ export { TabBar, type TabBarOption, type TabBarValue } from './components/tabbar';
51
+ export { Steps, type CanJump, type StepsItem, type StepsVariant, type StepsCompound, type StepsCompoundType, } from './components/steps';
52
52
  export { Toast, type ToastTone, type ToastCompound, type ToastCompoundType, } from './components/toast';
53
53
  export { Code } from './components/code';
54
54
  export { CodeEditor, type CodeEditorProps, type CodeEditorAutoSize, } from './components/code-editor';
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { Card } from "./components/card/index.js";
4
4
  import { Divider } from "./components/divider/index.js";
5
5
  import { Nav } from "./components/nav/index.js";
6
6
  import { Collapse } from "./components/collapse/index.js";
7
- import { Tabset } from "./components/tabset/index.js";
7
+ import { TabPanel, Tabs } from "./components/tabs/index.js";
8
8
  import { Layout } from "./components/layout/index.js";
9
9
  import { Avatar } from "./components/avatar/index.js";
10
10
  import { Skeleton } from "./components/skeleton/index.js";
@@ -30,7 +30,7 @@ import { Drawer } from "./components/drawer/index.js";
30
30
  import { Tooltip } from "./components/tooltip/index.js";
31
31
  import { Table } from "./components/table/index.js";
32
32
  import { Pagination } from "./components/pagination/index.js";
33
- import { Tabs } from "./components/tabs/index.js";
33
+ import { TabBar } from "./components/tabbar/index.js";
34
34
  import { Steps } from "./components/steps/index.js";
35
35
  import { Toast } from "./components/toast/index.js";
36
36
  import { Code } from "./components/code/index.js";
@@ -39,6 +39,7 @@ import { Upload, formatFileSize } from "./components/upload/index.js";
39
39
  import { QueryState } from "./components/query-state/index.js";
40
40
  import { Loading } from "./components/loading/index.js";
41
41
  import { mergePartStyle, partPaddingStyle } from "./components/part-padding.js";
42
+ import { SelectTree } from "./components/select/select-tree.js";
42
43
  import { alert, closeAllDialogs, confirm } from "./services/dialog.js";
43
44
  import { clearToasts, toast } from "./services/toast.js";
44
45
  import { configureHost, getHostSelector, resolveHost } from "./services/base.js";
@@ -74,12 +75,14 @@ export {
74
75
  Radio,
75
76
  Search,
76
77
  Select,
78
+ SelectTree,
77
79
  Skeleton,
78
80
  Steps,
79
81
  Switch,
82
+ TabBar,
83
+ TabPanel,
80
84
  Table,
81
85
  Tabs,
82
- Tabset,
83
86
  Tag,
84
87
  Text,
85
88
  Textarea,
@@ -14,11 +14,11 @@
14
14
  *
15
15
  * 状态三源等价:原生 `input:checked` / 组件下发 `[data-state='active']` / 静态档 `.is-selected`。
16
16
  *
17
- * **与面板组合**:要「选中即切面板」,外面套 `styles/operations/tabset.css` 的 `.mh-tabset` ——
18
- * 本族不认识它、它也不认识本族(两层零互指),壳层挂类即可。
17
+ * **与面板组合**:要「选中即切面板」,把本件塞进 `Tabs` 的 `selector` 插槽即可 ——
18
+ * 面板显隐由 `Tabs` 按受控值下发 `hidden`,本族不认识它、它也不认识本族(两层零互指)。
19
19
  *
20
- * **与 `Tabset` 的判据**:`Tabset` 是操作层(只给行为与档位表、不带面),面可由本件或按钮族的分段形态担任;
21
- * 本件是**带自己轨道与选中胶囊的轻量选择控件**。
20
+ * **与 `Tabs` 的判据**:`Tabs` 是操作层的**骨架**(只给根、面板组与收起态,不带面),
21
+ * 面可由本件或按钮族的分段形态担任;本件是**带自己轨道与选中胶囊的轻量选择控件**。
22
22
  */
23
23
  .mh-capsule {
24
24
  display: inline-flex;