dsh-plugin-core 0.22.0 → 0.23.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/dist/ui/AlertModal.d.ts +7 -0
- package/dist/ui/AlertModal.d.ts.map +1 -1
- package/dist/ui/AlertModal.js +8 -1
- package/dist/ui/AlertModal.js.map +1 -1
- package/dist/ui/Button.d.ts +9 -0
- package/dist/ui/Button.d.ts.map +1 -1
- package/dist/ui/Button.js +69 -11
- package/dist/ui/Button.js.map +1 -1
- package/dist/ui/ConfirmModal.d.ts +9 -0
- package/dist/ui/ConfirmModal.d.ts.map +1 -1
- package/dist/ui/ConfirmModal.js +15 -1
- package/dist/ui/ConfirmModal.js.map +1 -1
- package/dist/ui/InputGroup.d.ts +9 -2
- package/dist/ui/InputGroup.d.ts.map +1 -1
- package/dist/ui/InputGroup.js +4 -1
- package/dist/ui/InputGroup.js.map +1 -1
- package/dist/ui/modal-host.d.ts +4 -3
- package/dist/ui/modal-host.d.ts.map +1 -1
- package/dist/ui/modal-host.js +16 -6
- package/dist/ui/modal-host.js.map +1 -1
- package/dist/ui/thenable.d.ts +6 -0
- package/dist/ui/thenable.d.ts.map +1 -1
- package/dist/ui/thenable.js +8 -0
- package/dist/ui/thenable.js.map +1 -1
- package/docs/help/ui.doc.ts +52 -1
- package/docs/help/ui.md +46 -1
- package/docs/requirements.md +11 -0
- package/package.json +1 -1
package/dist/ui/AlertModal.d.ts
CHANGED
|
@@ -12,6 +12,13 @@ export interface AlertModalProps {
|
|
|
12
12
|
severity?: AlertSeverity;
|
|
13
13
|
/** 确认按钮文案(默认 i18n「知道了」)。 */
|
|
14
14
|
confirmText?: string;
|
|
15
|
+
/** 确认钮定宽(px 或任意 CSS 宽度值);loading 转圈会把按钮撑宽,定宽后不跳。 */
|
|
16
|
+
confirmWidth?: number | string;
|
|
17
|
+
/**
|
|
18
|
+
* loading 时是否保留按钮文案(默认 true)。传 `false`:loading 期间清文字、
|
|
19
|
+
* 锁在「有文案」的宽度上、只留一枚居中的圈(见 `Button.loadingText`)。
|
|
20
|
+
*/
|
|
21
|
+
loadingText?: boolean;
|
|
15
22
|
/** 点遮罩是否关闭(默认 true)。 */
|
|
16
23
|
closeOnMask?: boolean;
|
|
17
24
|
/** 外部驱动确认钮 loading(如别处正在刷新)。与按钮自己的异步状态取或。 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlertModal.d.ts","sourceRoot":"","sources":["../../src/ui/AlertModal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACpE,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAElD,OAAO,EAAK,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAIpD,2CAA2C;AAC3C,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAA;AASpE,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,mBAAmB;IACnB,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,aAAa,CAAA;IACxB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,wBAAwB;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,wBAAwB;IACxB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAA;IACzB,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"AlertModal.d.ts","sourceRoot":"","sources":["../../src/ui/AlertModal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACpE,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAElD,OAAO,EAAK,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAIpD,2CAA2C;AAC3C,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAA;AASpE,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,mBAAmB;IACnB,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,aAAa,CAAA;IACxB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,wBAAwB;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,wBAAwB;IACxB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAA;IACzB,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CA6BvE"}
|
package/dist/ui/AlertModal.js
CHANGED
|
@@ -30,7 +30,14 @@ export function AlertModal(props) {
|
|
|
30
30
|
closeOnMask: props.closeOnMask,
|
|
31
31
|
busy,
|
|
32
32
|
onClose: props.onConfirm,
|
|
33
|
-
footer: h(Button, {
|
|
33
|
+
footer: h(Button, {
|
|
34
|
+
variant: 'primary',
|
|
35
|
+
width: props.confirmWidth,
|
|
36
|
+
loadingText: props.loadingText,
|
|
37
|
+
loading: props.confirmLoading === true,
|
|
38
|
+
onBusyChange: setRunning,
|
|
39
|
+
onClick: () => props.onConfirm?.(),
|
|
40
|
+
}, props.confirmText ?? tt('dialogOk')),
|
|
34
41
|
}, props.message ?? null);
|
|
35
42
|
}
|
|
36
43
|
//# sourceMappingURL=AlertModal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlertModal.js","sourceRoot":"","sources":["../../src/ui/AlertModal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AACpE,OAAO,EAAE,KAAK,EAAkB,MAAM,YAAY,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,CAAC,EAAkB,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAKhD,MAAM,cAAc,GAAkC;IACpD,IAAI,EAAE,GAAG;IACT,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,GAAG;IACZ,KAAK,EAAE,GAAG;CACX,CAAA;
|
|
1
|
+
{"version":3,"file":"AlertModal.js","sourceRoot":"","sources":["../../src/ui/AlertModal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AACpE,OAAO,EAAE,KAAK,EAAkB,MAAM,YAAY,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,CAAC,EAAkB,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAKhD,MAAM,cAAc,GAAkC;IACpD,IAAI,EAAE,GAAG;IACT,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,GAAG;IACZ,KAAK,EAAE,GAAG;CACX,CAAA;AA6BD;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,qBAAqB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;IAC/C,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,IAAI,CAAC,CAAA;IAC/B,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,MAAM,CAAA;IACzC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC7C,gCAAgC;IAChC,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,CAAC,cAAc,KAAK,IAAI,CAAA;IACrD,OAAO,CAAC,CACN,KAAK,EACL;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,oCAAoC,QAAQ,EAAE,EAAE,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;QACxG,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;QACxB,UAAU,EAAE,KAAK,CAAC,KAAK,KAAK,SAAS;QACrC,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,IAAI;QACJ,OAAO,EAAE,KAAK,CAAC,SAAS;QACxB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;YAChB,OAAO,EAAE,SAAS;YAClB,KAAK,EAAE,KAAK,CAAC,YAAY;YACzB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,OAAO,EAAE,KAAK,CAAC,cAAc,KAAK,IAAI;YACtC,YAAY,EAAE,UAAU;YACxB,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE;SACnC,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC;KACxC,EACD,KAAK,CAAC,OAAO,IAAI,IAAI,CACtB,CAAA;AACH,CAAC"}
|
package/dist/ui/Button.d.ts
CHANGED
|
@@ -19,6 +19,15 @@ export interface ButtonProps {
|
|
|
19
19
|
color?: string;
|
|
20
20
|
/** 加载中:文案前显示同色小圈,并自动禁用点击。与「点击自动 loading」是或关系,任一为真就转圈。 */
|
|
21
21
|
loading?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* loading 时是否保留文案(默认 true)。
|
|
24
|
+
* 传 `false`:loading 期间**清掉文案**、把按钮锁在「有文案时」的宽度上,只剩一枚居中的圈,
|
|
25
|
+
* settle 后文案与自适应宽度一起回来 —— 用于文案长、不想让按钮被圈撑宽的场景。
|
|
26
|
+
*
|
|
27
|
+
* 两条前提:① 文案被清掉后读屏只剩「按钮」,`children` 不是字符串时请自己传 `aria-label`;
|
|
28
|
+
* ② 首帧就是 loading(没有「有文案的宽度」可量)时不锁宽,请改用 `width` 定宽。
|
|
29
|
+
*/
|
|
30
|
+
loadingText?: boolean;
|
|
22
31
|
/**
|
|
23
32
|
* 点击回调。**返回 Promise 即自动进入 loading**(转圈 + 禁用 + 防连点),settle 后自己恢复;
|
|
24
33
|
* reject 会恢复并把错误打到控制台。同步返回值 = 老行为,不转圈。
|
package/dist/ui/Button.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/ui/Button.ts"],"names":[],"mappings":"AAwBA,OAAO,
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/ui/Button.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/Button.js
CHANGED
|
@@ -22,10 +22,15 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { MarqueeText } from './MarqueeText.js';
|
|
24
24
|
import { Loader } from './Loader.js';
|
|
25
|
-
import { createElement as h, useState } from 'react';
|
|
25
|
+
import { createElement as h, useEffect, useLayoutEffect, useRef, useState, } from 'react';
|
|
26
26
|
import { ensureComponentStyles } from './css.js';
|
|
27
27
|
import { BUTTON_CSS } from './controls-css.js';
|
|
28
28
|
import { isThenable } from './thenable.js';
|
|
29
|
+
/**
|
|
30
|
+
* 有 DOM 时用 layout effect(绘制前锁宽,用户看不到中间态),SSR 退化成 useEffect(服务端本就不跑)。
|
|
31
|
+
* 直接用 `useLayoutEffect` 会在服务端渲染时告警。
|
|
32
|
+
*/
|
|
33
|
+
const useIsoLayoutEffect = typeof document === 'undefined' ? useEffect : useLayoutEffect;
|
|
29
34
|
/** 实心档(color 参数按「底色」处理;其余档按「字色 + 描边色」处理)。 */
|
|
30
35
|
const SOLID_VARIANTS = [
|
|
31
36
|
'primary', 'secondary', 'danger', 'success', 'warning', 'info',
|
|
@@ -62,8 +67,9 @@ function buttonClass(variant, size, block, hasIcon, extra) {
|
|
|
62
67
|
/**
|
|
63
68
|
* 异步点击:`onClick` 返回 thenable 就自己转圈(并禁用),settle 后恢复。
|
|
64
69
|
* 不用 `onBusyChange` 也能单独工作 —— 它只是把状态报给外面(弹窗锁关闭用)。
|
|
70
|
+
* `onBusyStart` 在 setBusy 之前跑:那时按钮还是「有文案」的样子,要量宽度只能抓这一刻。
|
|
65
71
|
*/
|
|
66
|
-
function useAsyncClick(onClick, onBusyChange) {
|
|
72
|
+
function useAsyncClick(onClick, onBusyChange, onBusyStart) {
|
|
67
73
|
const [busy, setBusy] = useState(false);
|
|
68
74
|
const click = (event) => {
|
|
69
75
|
if (onClick === undefined)
|
|
@@ -71,6 +77,7 @@ function useAsyncClick(onClick, onBusyChange) {
|
|
|
71
77
|
const out = onClick(event);
|
|
72
78
|
if (!isThenable(out))
|
|
73
79
|
return;
|
|
80
|
+
onBusyStart?.(event.currentTarget);
|
|
74
81
|
setBusy(true);
|
|
75
82
|
onBusyChange?.(true);
|
|
76
83
|
const done = () => {
|
|
@@ -93,40 +100,91 @@ function useAsyncClick(onClick, onBusyChange) {
|
|
|
93
100
|
*/
|
|
94
101
|
export function Button(props) {
|
|
95
102
|
ensureComponentStyles('button', BUTTON_CSS);
|
|
96
|
-
const { variant = 'outline', size = 'lg', icon, iconRight, color, loading: loadingProp = false, block = false, width, minWidth, maxWidth, className, style, children, onClick, onBusyChange, ...rest } = props;
|
|
97
|
-
const
|
|
103
|
+
const { variant = 'outline', size = 'lg', icon, iconRight, color, loading: loadingProp = false, loadingText = true, block = false, width, minWidth, maxWidth, className, style, children, onClick, onBusyChange, ...rest } = props;
|
|
104
|
+
const btnRef = useRef(null);
|
|
105
|
+
// 「有文案时的宽度」:只在非 loading 的布局里记,loading 时用它锁宽。
|
|
106
|
+
const idleWidth = useRef(null);
|
|
107
|
+
const [lockWidth, setLockWidth] = useState(null);
|
|
108
|
+
// 调用方自己定了宽(width 参数或 style.width)⇒ 不测量、不锁,照他的来。
|
|
109
|
+
const hasOwnWidth = width !== undefined || (style !== undefined && style.width !== undefined);
|
|
110
|
+
const lockable = !loadingText && !hasOwnWidth && !block;
|
|
111
|
+
const asyncClick = useAsyncClick(onClick, onBusyChange, (el) => {
|
|
112
|
+
if (!lockable)
|
|
113
|
+
return;
|
|
114
|
+
// 点击这一刻 DOM 还是「有文案」的样子,量到的是要锁的那个宽度。
|
|
115
|
+
const w = el.getBoundingClientRect().width;
|
|
116
|
+
if (w > 0) {
|
|
117
|
+
idleWidth.current = w;
|
|
118
|
+
setLockWidth(w);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
98
121
|
// 两个来源取或:外部传的 loading(别处刷新也能点亮它)+ 自己异步在跑
|
|
99
122
|
const loading = loadingProp || asyncClick.busy;
|
|
123
|
+
// 外部驱动的 loading 没有点击可抓:进 loading 那一次用上次记下的宽度补锁(绘制前重渲染,不见中间态)。
|
|
124
|
+
useIsoLayoutEffect(() => {
|
|
125
|
+
const el = btnRef.current;
|
|
126
|
+
if (el === null)
|
|
127
|
+
return;
|
|
128
|
+
if (!loading) {
|
|
129
|
+
const w = el.getBoundingClientRect().width;
|
|
130
|
+
if (w > 0)
|
|
131
|
+
idleWidth.current = w;
|
|
132
|
+
if (lockWidth !== null)
|
|
133
|
+
setLockWidth(null);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (!lockable) {
|
|
137
|
+
if (lockWidth !== null)
|
|
138
|
+
setLockWidth(null);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (lockWidth === null && idleWidth.current !== null)
|
|
142
|
+
setLockWidth(idleWidth.current);
|
|
143
|
+
}, [loading, lockable, lockWidth]);
|
|
100
144
|
// 三轴互斥:固定宽优先,min / max 失效;否则 min / max 各自生效。
|
|
101
145
|
const widthStyle = {};
|
|
102
146
|
if (width !== undefined) {
|
|
103
147
|
widthStyle.width = width;
|
|
104
148
|
}
|
|
149
|
+
else if (loading && lockWidth !== null) {
|
|
150
|
+
// 锁宽只在 loading 期间生效:结束时这一帧就回到自适应,不留额外一拍。
|
|
151
|
+
widthStyle.width = lockWidth;
|
|
152
|
+
}
|
|
105
153
|
else {
|
|
106
154
|
if (minWidth !== undefined)
|
|
107
155
|
widthStyle.minWidth = minWidth;
|
|
108
156
|
if (maxWidth !== undefined)
|
|
109
157
|
widthStyle.maxWidth = maxWidth;
|
|
110
158
|
}
|
|
159
|
+
// loading 且不保留文案 ⇒ 文字整块不渲染,按钮只剩一枚居中的圈。
|
|
160
|
+
const hideText = loading && !loadingText;
|
|
111
161
|
// 最大宽 + 纯文字标签 ⇒ 折叠省略号、hover 跑马灯(复用全站唯一 MarqueeText)。
|
|
112
|
-
const marqueeLabel = maxWidth !== undefined && width === undefined && typeof children === 'string';
|
|
162
|
+
const marqueeLabel = !hideText && maxWidth !== undefined && width === undefined && typeof children === 'string';
|
|
163
|
+
// 文案没了,读屏名称得留住:字符串 children 自动补;复合 children 由调用方传 aria-label。
|
|
164
|
+
const autoLabel = hideText && typeof children === 'string' ? children : undefined;
|
|
113
165
|
const attrs = {
|
|
114
166
|
...rest,
|
|
167
|
+
ref: btnRef,
|
|
115
168
|
type: rest.type ?? 'button',
|
|
116
169
|
disabled: rest.disabled === true || loading,
|
|
170
|
+
// 与 IconButton 同一口径:文字还在,但让读屏知道它正在忙、不是单纯不可点
|
|
171
|
+
'aria-busy': loading || undefined,
|
|
172
|
+
...(autoLabel !== undefined && rest['aria-label'] === undefined ? { 'aria-label': autoLabel } : {}),
|
|
117
173
|
onClick: asyncClick.click,
|
|
118
174
|
className: buttonClass(variant, size, block, icon !== undefined && icon !== null && !loading, className),
|
|
119
175
|
style: { ...colorVars(variant, color), ...widthStyle, ...style },
|
|
120
176
|
};
|
|
121
177
|
return h('button', attrs, loading
|
|
122
|
-
// 转圈统一走 Loader
|
|
123
|
-
//
|
|
124
|
-
? h(Loader, { size: 'xs' })
|
|
178
|
+
// 转圈统一走 Loader:包在图标容器里 ⇒ 尺寸/对齐与常规前置图标完全一致,
|
|
179
|
+
// 「有 icon 的按钮」切 loading 时宽度一点不动(容器内 svg 被 1em 规则接管)。
|
|
180
|
+
? h('span', { className: 'dshpc-btn__icon' }, h(Loader, { size: 'xs' }))
|
|
125
181
|
: icon !== undefined && icon !== null
|
|
126
182
|
? h('span', { className: 'dshpc-btn__icon' }, icon)
|
|
127
|
-
: null,
|
|
128
|
-
?
|
|
129
|
-
:
|
|
183
|
+
: null, hideText
|
|
184
|
+
? null
|
|
185
|
+
: marqueeLabel
|
|
186
|
+
? h(MarqueeText, { text: children, className: 'dshpc-btn__label' })
|
|
187
|
+
: children,
|
|
130
188
|
// 转圈期间所有图标位都让位:前置位被 Loader 顶替,后置位(展开 / 外链)留在禁用态里只会挤版面
|
|
131
189
|
iconRight !== undefined && iconRight !== null && !loading
|
|
132
190
|
? h('span', { className: 'dshpc-btn__icon-end' }, iconRight)
|
package/dist/ui/Button.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../src/ui/Button.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,
|
|
1
|
+
{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../src/ui/Button.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,15 @@ export interface ConfirmModalProps {
|
|
|
13
13
|
confirmText?: string;
|
|
14
14
|
/** 取消钮文案(默认 i18n「取消」)。 */
|
|
15
15
|
cancelText?: string;
|
|
16
|
+
/** 确认钮定宽(px 或任意 CSS 宽度值);loading 转圈会把按钮撑宽,定宽后不跳。 */
|
|
17
|
+
confirmWidth?: number | string;
|
|
18
|
+
/** 取消钮定宽;同上。 */
|
|
19
|
+
cancelWidth?: number | string;
|
|
20
|
+
/**
|
|
21
|
+
* loading 时是否保留按钮文案(默认 true)。传 `false`:loading 期间按钮清文字、
|
|
22
|
+
* 锁在「有文案」的宽度上、只留一枚居中的圈,settle 后一起还原(见 `Button.loadingText`)。
|
|
23
|
+
*/
|
|
24
|
+
loadingText?: boolean;
|
|
16
25
|
/** 点遮罩是否关闭(默认 true;点了 = 取消)。 */
|
|
17
26
|
closeOnMask?: boolean;
|
|
18
27
|
/** 外部驱动确认钮 loading(如别处正在刷新)。与按钮自己的异步状态取或。 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmModal.d.ts","sourceRoot":"","sources":["../../src/ui/ConfirmModal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACpE,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAElD,OAAO,EAAK,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEpD,uBAAuB;AACvB,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAA;AAE1D,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,mBAAmB;IACnB,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,0BAA0B;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gCAAgC;IAChC,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,OAAO,CAAA;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAA;IACxB,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"ConfirmModal.d.ts","sourceRoot":"","sources":["../../src/ui/ConfirmModal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACpE,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAElD,OAAO,EAAK,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEpD,uBAAuB;AACvB,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAA;AAE1D,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,mBAAmB;IACnB,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,0BAA0B;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,gBAAgB;IAChB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC7B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,gCAAgC;IAChC,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,OAAO,CAAA;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAA;IACxB,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAyC3E"}
|
package/dist/ui/ConfirmModal.js
CHANGED
|
@@ -25,7 +25,21 @@ export function ConfirmModal(props) {
|
|
|
25
25
|
closeOnMask: props.closeOnMask,
|
|
26
26
|
busy,
|
|
27
27
|
onClose: props.onCancel,
|
|
28
|
-
footer: h('div', { style: { display: 'flex', gap: '8px', justifyContent: 'flex-end' } }, h(Button, {
|
|
28
|
+
footer: h('div', { style: { display: 'flex', gap: '8px', justifyContent: 'flex-end' } }, h(Button, {
|
|
29
|
+
variant: 'outline',
|
|
30
|
+
width: props.cancelWidth,
|
|
31
|
+
loadingText: props.loadingText,
|
|
32
|
+
loading: props.cancelLoading === true,
|
|
33
|
+
onBusyChange: setCancelBusy,
|
|
34
|
+
onClick: () => props.onCancel?.(),
|
|
35
|
+
}, props.cancelText ?? tt('cancel')), h(Button, {
|
|
36
|
+
variant: confirmVariant,
|
|
37
|
+
width: props.confirmWidth,
|
|
38
|
+
loadingText: props.loadingText,
|
|
39
|
+
loading: props.confirmLoading === true,
|
|
40
|
+
onBusyChange: setConfirmBusy,
|
|
41
|
+
onClick: () => props.onConfirm?.(),
|
|
42
|
+
}, props.confirmText ?? tt('confirm'))),
|
|
29
43
|
}, props.message ?? null);
|
|
30
44
|
}
|
|
31
45
|
//# sourceMappingURL=ConfirmModal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmModal.js","sourceRoot":"","sources":["../../src/ui/ConfirmModal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AACpE,OAAO,EAAE,KAAK,EAAkB,MAAM,YAAY,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,CAAC,EAAkB,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"ConfirmModal.js","sourceRoot":"","sources":["../../src/ui/ConfirmModal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AACpE,OAAO,EAAE,KAAK,EAAkB,MAAM,YAAY,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,CAAC,EAAkB,MAAM,kBAAkB,CAAA;AAsCpD;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,IAAI,CAAC,CAAA;IAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,SAAS,CAAA;IACpC,MAAM,cAAc,GAAG,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;IAChG,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACrD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACnD,2BAA2B;IAC3B,MAAM,IAAI,GAAG,WAAW,IAAI,UAAU,IAAI,KAAK,CAAC,cAAc,KAAK,IAAI,IAAI,KAAK,CAAC,aAAa,KAAK,IAAI,CAAA;IACvG,OAAO,CAAC,CACN,KAAK,EACL;QACE,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;QACxB,UAAU,EAAE,KAAK,CAAC,KAAK,KAAK,SAAS;QACrC,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,IAAI;QACJ,OAAO,EAAE,KAAK,CAAC,QAAQ;QACvB,MAAM,EAAE,CAAC,CACP,KAAK,EACL,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,EAAE,EACtE,CAAC,CAAC,MAAM,EAAE;YACR,OAAO,EAAE,SAAS;YAClB,KAAK,EAAE,KAAK,CAAC,WAAW;YACxB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,OAAO,EAAE,KAAK,CAAC,aAAa,KAAK,IAAI;YACrC,YAAY,EAAE,aAAa;YAC3B,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE;SAClC,EAAE,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,EACpC,CAAC,CAAC,MAAM,EAAE;YACR,OAAO,EAAE,cAAc;YACvB,KAAK,EAAE,KAAK,CAAC,YAAY;YACzB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,OAAO,EAAE,KAAK,CAAC,cAAc,KAAK,IAAI;YACtC,YAAY,EAAE,cAAc;YAC5B,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE;SACnC,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,CACvC;KACF,EACD,KAAK,CAAC,OAAO,IAAI,IAAI,CACtB,CAAA;AACH,CAAC"}
|
package/dist/ui/InputGroup.d.ts
CHANGED
|
@@ -33,10 +33,17 @@ export interface InputGroupAction {
|
|
|
33
33
|
variant?: ButtonVariant;
|
|
34
34
|
/** 单钮禁用。 */
|
|
35
35
|
disabled?: boolean;
|
|
36
|
+
/** 定宽(px 或任意 CSS 宽度值);loading 转圈会把按钮撑宽并挤到输入框,定宽后不跳。 */
|
|
37
|
+
width?: number | string;
|
|
38
|
+
/**
|
|
39
|
+
* loading 时是否保留按钮文案(默认 true)。传 `false`:loading 期间清文字、
|
|
40
|
+
* 锁在「有文案」的宽度上、只留一枚居中的圈(见 `Button.loadingText`)。
|
|
41
|
+
*/
|
|
42
|
+
loadingText?: boolean;
|
|
36
43
|
/** 无障碍名:只有图标时必给(否则读屏只知道「按钮」)。 */
|
|
37
44
|
ariaLabel?: string;
|
|
38
|
-
/**
|
|
39
|
-
onClick: () =>
|
|
45
|
+
/** 点击。**返回 Promise 时按钮自动转圈禁用**(同 Button / IconButton)。 */
|
|
46
|
+
onClick: () => unknown;
|
|
40
47
|
}
|
|
41
48
|
export interface InputGroupProps {
|
|
42
49
|
/** 当前值。 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputGroup.d.ts","sourceRoot":"","sources":["../../src/ui/InputGroup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,aAAa,IAAI,CAAC,EAAoB,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAChG,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAI5D,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB;IACxB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,YAAY;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,
|
|
1
|
+
{"version":3,"file":"InputGroup.d.ts","sourceRoot":"","sources":["../../src/ui/InputGroup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,aAAa,IAAI,CAAC,EAAoB,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAChG,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AAI5D,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB;IACxB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,YAAY;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0DAA0D;IAC1D,OAAO,EAAE,MAAM,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW;IACX,KAAK,EAAE,MAAM,CAAA;IACb,YAAY;IACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU;IACV,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kBAAkB;IAClB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,YAAY;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,wCAAwC;IACxC,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,2BAA2B;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc;IACd,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kBAAkB;IAClB,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CA4FvE"}
|
package/dist/ui/InputGroup.js
CHANGED
|
@@ -85,7 +85,8 @@ export function InputGroup(props) {
|
|
|
85
85
|
actions.forEach((action, i) => {
|
|
86
86
|
if (action.label === undefined && (action.icon === undefined || action.icon === null))
|
|
87
87
|
return;
|
|
88
|
-
|
|
88
|
+
// 必须把返回值透出去:Button / IconButton 靠「返回值是不是 Promise」决定要不要转圈
|
|
89
|
+
const run = () => { commit(); return action.onClick(); };
|
|
89
90
|
const off = disabled === true || action.disabled === true;
|
|
90
91
|
const onlyIcon = action.label === undefined;
|
|
91
92
|
nodes.push(onlyIcon
|
|
@@ -103,6 +104,8 @@ export function InputGroup(props) {
|
|
|
103
104
|
variant: action.variant ?? 'info',
|
|
104
105
|
size,
|
|
105
106
|
icon: action.icon,
|
|
107
|
+
width: action.width,
|
|
108
|
+
loadingText: action.loadingText,
|
|
106
109
|
disabled: off,
|
|
107
110
|
onClick: run,
|
|
108
111
|
}, action.label));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputGroup.js","sourceRoot":"","sources":["../../src/ui/InputGroup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,aAAa,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAsC,MAAM,OAAO,CAAA;AAChG,OAAO,EAAE,MAAM,EAAE,UAAU,EAAsB,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAkB,MAAM,YAAY,CAAA;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"InputGroup.js","sourceRoot":"","sources":["../../src/ui/InputGroup.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/modal-host.d.ts
CHANGED
|
@@ -21,14 +21,14 @@ export declare function registerHostDialog(handlers: HostDialogHandlers): void;
|
|
|
21
21
|
type DialogHandler = () => unknown;
|
|
22
22
|
export type ConfirmOptions = Omit<ConfirmModalProps, 'onConfirm' | 'onCancel' | 'confirmLoading' | 'cancelLoading'> & {
|
|
23
23
|
skin?: 'core' | 'host';
|
|
24
|
-
/** 确认回调;异步期间确认钮转圈、整框不可关,resolve 后按 `true` 关闭,reject
|
|
24
|
+
/** 确认回调;异步期间确认钮转圈、整框不可关,resolve 后按 `true` 关闭,reject 后恢复可点;返回 `false` 不关。 */
|
|
25
25
|
onConfirm?: DialogHandler;
|
|
26
|
-
/** 取消 / 遮罩 / Esc 回调;异步语义同 `onConfirm`,resolve 后按 `false`
|
|
26
|
+
/** 取消 / 遮罩 / Esc 回调;异步语义同 `onConfirm`,resolve 后按 `false` 关闭(返回 `false` 同样不关)。 */
|
|
27
27
|
onCancel?: DialogHandler;
|
|
28
28
|
};
|
|
29
29
|
export type AlertOptions = Omit<AlertModalProps, 'onConfirm' | 'confirmLoading'> & {
|
|
30
30
|
skin?: 'core' | 'host';
|
|
31
|
-
/** 确认回调(遮罩 / Esc 同一个出口);异步期间转圈并锁死关闭,
|
|
31
|
+
/** 确认回调(遮罩 / Esc 同一个出口);异步期间转圈并锁死关闭,settle 后才关,返回 `false` 不关。 */
|
|
32
32
|
onConfirm?: DialogHandler;
|
|
33
33
|
};
|
|
34
34
|
/**
|
|
@@ -39,6 +39,7 @@ export declare function confirmModal(opts: ConfirmOptions): Promise<boolean>;
|
|
|
39
39
|
/**
|
|
40
40
|
* 命令式警告框:Promise 在关闭时 resolve(单按钮,关闭即确认)。`skin:"host"` 走宿主原生 Modal。
|
|
41
41
|
* 回调返回 Promise 时进入 loading(按钮转圈 + 遮罩 / Esc 锁死),settle 后才真正关闭。
|
|
42
|
+
* 回调返回 `false`(同步或 resolve 成 `false`)⇒ 本次当作没成,框不关。
|
|
42
43
|
*/
|
|
43
44
|
export declare function alertModal(opts: AlertOptions): Promise<void>;
|
|
44
45
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-host.d.ts","sourceRoot":"","sources":["../../src/ui/modal-host.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAoDxE,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AACD,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AACD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACpD,KAAK,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9C;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAErE;AAED,yCAAyC;AACzC,KAAK,aAAa,GAAG,MAAM,OAAO,CAAA;AAElC,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,UAAU,GAAG,gBAAgB,GAAG,eAAe,CAAC,GAAG;IACpH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,
|
|
1
|
+
{"version":3,"file":"modal-host.d.ts","sourceRoot":"","sources":["../../src/ui/modal-host.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAoDxE,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AACD,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AACD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACpD,KAAK,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9C;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAErE;AAED,yCAAyC;AACzC,KAAK,aAAa,GAAG,MAAM,OAAO,CAAA;AAElC,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,UAAU,GAAG,gBAAgB,GAAG,eAAe,CAAC,GAAG;IACpH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,aAAa,CAAA;CACzB,CAAA;AACD,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,gBAAgB,CAAC,GAAG;IACjF,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,iEAAiE;IACjE,SAAS,CAAC,EAAE,aAAa,CAAA;CAC1B,CAAA;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CA8CnE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAuC5D"}
|
package/dist/ui/modal-host.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createRoot } from 'react-dom/client';
|
|
|
3
3
|
import { ensureControls, getStyleKit } from './css.js';
|
|
4
4
|
import { AlertModal } from './AlertModal.js';
|
|
5
5
|
import { ConfirmModal } from './ConfirmModal.js';
|
|
6
|
-
import { isThenable } from './thenable.js';
|
|
6
|
+
import { isSuccess, isThenable } from './thenable.js';
|
|
7
7
|
// ⚠️ core 的 StyleKit / i18n 都是**模块级单例**(见 css.ts 注释),不依赖 React Context,
|
|
8
8
|
// 所以命令式弹窗所在的独立 root 天然能读到它们——无需手动注入插件上下文。
|
|
9
9
|
// 唯一读不到的是「插件自己定义的 React Context」,那是用户的私有环境,命令式本就不继承。
|
|
@@ -80,12 +80,17 @@ export function confirmModal(opts) {
|
|
|
80
80
|
if (closed)
|
|
81
81
|
return undefined;
|
|
82
82
|
const out = (which === 'confirm' ? onConfirm : onCancel)?.();
|
|
83
|
+
// 只有明确的 false 表示「这次没成」:框留着让人重试(消费方自己去提示)
|
|
84
|
+
const settle = (value) => {
|
|
85
|
+
if (isSuccess(value))
|
|
86
|
+
close(which === 'confirm');
|
|
87
|
+
};
|
|
83
88
|
if (!isThenable(out)) {
|
|
84
|
-
|
|
89
|
+
settle(out);
|
|
85
90
|
return undefined;
|
|
86
91
|
}
|
|
87
|
-
// reject
|
|
88
|
-
void out.then(
|
|
92
|
+
// reject 也不关:按钮已自己恢复可点,错误由 Button 打到控制台
|
|
93
|
+
void out.then(settle, () => { });
|
|
89
94
|
return out;
|
|
90
95
|
};
|
|
91
96
|
entries.push({
|
|
@@ -98,6 +103,7 @@ export function confirmModal(opts) {
|
|
|
98
103
|
/**
|
|
99
104
|
* 命令式警告框:Promise 在关闭时 resolve(单按钮,关闭即确认)。`skin:"host"` 走宿主原生 Modal。
|
|
100
105
|
* 回调返回 Promise 时进入 loading(按钮转圈 + 遮罩 / Esc 锁死),settle 后才真正关闭。
|
|
106
|
+
* 回调返回 `false`(同步或 resolve 成 `false`)⇒ 本次当作没成,框不关。
|
|
101
107
|
*/
|
|
102
108
|
export function alertModal(opts) {
|
|
103
109
|
if (opts.skin === 'host') {
|
|
@@ -127,11 +133,15 @@ export function alertModal(opts) {
|
|
|
127
133
|
if (closed)
|
|
128
134
|
return undefined;
|
|
129
135
|
const out = onConfirm?.();
|
|
136
|
+
const settle = (value) => {
|
|
137
|
+
if (isSuccess(value))
|
|
138
|
+
close();
|
|
139
|
+
};
|
|
130
140
|
if (!isThenable(out)) {
|
|
131
|
-
|
|
141
|
+
settle(out);
|
|
132
142
|
return undefined;
|
|
133
143
|
}
|
|
134
|
-
void out.then(
|
|
144
|
+
void out.then(settle, () => { });
|
|
135
145
|
return out;
|
|
136
146
|
};
|
|
137
147
|
entries.push({ id, node: h(AlertModal, { ...core, onConfirm: () => run() }) });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-host.js","sourceRoot":"","sources":["../../src/ui/modal-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AACpE,OAAO,EAAE,UAAU,EAAa,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,EAAE,UAAU,EAAwB,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,YAAY,EAA0B,MAAM,mBAAmB,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"modal-host.js","sourceRoot":"","sources":["../../src/ui/modal-host.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/thenable.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
/** 返回值是不是 thenable。Button 的自动 loading 与命令式弹窗的收尾共用这一份判定。 */
|
|
2
2
|
export declare function isThenable(value: unknown): value is PromiseLike<unknown>;
|
|
3
|
+
/**
|
|
4
|
+
* 回调的返回值算不算「成功」(命令式弹窗据此决定关不关):
|
|
5
|
+
* 只有明确的 `false` 表示这次没成 —— `true` / `undefined` / 别的都照常关。
|
|
6
|
+
* 用返回值表达业务失败,消费方就不必在调用点包 try/catch(错误自己处理、自己提示)。
|
|
7
|
+
*/
|
|
8
|
+
export declare function isSuccess(value: unknown): boolean;
|
|
3
9
|
//# sourceMappingURL=thenable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thenable.d.ts","sourceRoot":"","sources":["../../src/ui/thenable.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAAC,OAAO,CAAC,CAGxE"}
|
|
1
|
+
{"version":3,"file":"thenable.d.ts","sourceRoot":"","sources":["../../src/ui/thenable.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAAC,OAAO,CAAC,CAGxE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEjD"}
|
package/dist/ui/thenable.js
CHANGED
|
@@ -4,4 +4,12 @@ export function isThenable(value) {
|
|
|
4
4
|
return false;
|
|
5
5
|
return typeof value.then === 'function';
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* 回调的返回值算不算「成功」(命令式弹窗据此决定关不关):
|
|
9
|
+
* 只有明确的 `false` 表示这次没成 —— `true` / `undefined` / 别的都照常关。
|
|
10
|
+
* 用返回值表达业务失败,消费方就不必在调用点包 try/catch(错误自己处理、自己提示)。
|
|
11
|
+
*/
|
|
12
|
+
export function isSuccess(value) {
|
|
13
|
+
return value !== false;
|
|
14
|
+
}
|
|
7
15
|
//# sourceMappingURL=thenable.js.map
|
package/dist/ui/thenable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thenable.js","sourceRoot":"","sources":["../../src/ui/thenable.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IACvD,OAAO,OAAQ,KAA4B,CAAC,IAAI,KAAK,UAAU,CAAA;AACjE,CAAC"}
|
|
1
|
+
{"version":3,"file":"thenable.js","sourceRoot":"","sources":["../../src/ui/thenable.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IACvD,OAAO,OAAQ,KAA4B,CAAC,IAAI,KAAK,UAAU,CAAA;AACjE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,KAAK,KAAK,KAAK,CAAA;AACxB,CAAC"}
|
package/docs/help/ui.doc.ts
CHANGED
|
@@ -310,6 +310,10 @@ const doc: DocTopic = {
|
|
|
310
310
|
zh: '两者的 loading 语义一致:`onClick` 返回 Promise 就转圈(纯图标钮把图标位换成小圈,`aria-label` 不变、补 `aria-busy`),`onBusyChange` 把「在跑」报出去;受控 `loading` 与它取或 —— 别处刷新也能点亮同一颗按钮。转圈期间按钮自己的图标位(`icon` / `iconRight`)全部让位,只留转圈 + 文字。',
|
|
311
311
|
en: 'Both share one loading semantics: a Promise-returning `onClick` spins (an icon button swaps its icon for the spinner, keeps `aria-label` and adds `aria-busy`), `onBusyChange` reports "running", and the controlled `loading` prop is OR-ed in — an external refresh lights the same button too. While spinning, the button’s own icon slots (`icon` / `iconRight`) all step aside: spinner plus label only.',
|
|
312
312
|
},
|
|
313
|
+
{
|
|
314
|
+
zh: 'loading 会把前置圈插进按钮:无 icon 的按钮因此宽出 18px(圈 12 + 间距 6),把旁边的按钮挤开。要完全不跳有两条路:给 `width` 定宽(按最长文案 + 18px 留),或传 `loadingText={false}` 让 loading 时只剩一圈。',
|
|
315
|
+
en: 'Loading inserts the spinner into the button, so a button without an icon grows 18px (12px spinner + 6px gap) and shoves its neighbours. To keep it rock-steady, either set `width` (longest label + 18px) or pass `loadingText={false}` so only the spinner remains while loading.',
|
|
316
|
+
},
|
|
313
317
|
{
|
|
314
318
|
zh: 'Segmented:`items`(必填)支持单选 / 多选,`size`(默认 lg;三档总高 24 / 28 / 32)、`bordered`(1px 外框,总高不变)、`multiple`(多选)。外观只有一套:灰底轨道 + 白色选中片,选中片的描边环与阴影由宿主 elevation token 提供(离线兜底值没有那圈环)。选中片配色只经 `tone`:传内置色名(与 Chip 同名的 business / success / warning / danger / purple / pink / cyan / teal / orange / indigo / rose / slate)时底与字由核心定、深浅两主题各自成立;传 `{ bg, fg }` 时两个主题都用调用方这一对颜色(对比度由调用方负责)。段内 `icon` 是前置图标槽(官方图标组件 / 数组 / 自绘节点均可),`label` 也可传节点;顺序固定为 icon → label → count。只有图标(无文字 / 计数 / 角标)时该段自动变正方形(宽 = 段高),读屏名用 `ariaLabel`,缺省退回 `tooltip`。段内 `count`(弱化灰字,选中段内自动跟着选中片字色提亮)/ `badge`(红角标)接受 `number | string`:数字 ≤0 不显示,字符串原样显示(如 `1K` / `99+`)。',
|
|
315
319
|
en: 'Segmented: `items` (required) supports single or multiple selection; `size` (default lg; totals 24 / 28 / 32), `bordered` (1px outer frame, same total height), `multiple` (multi-select). One look only: grey track + white selected pill; its stroke ring and shadow come from the host elevation token (the offline fallback has no ring). The selected pill’s colors go through `tone` only: a built-in color name (business / success / warning / danger / purple / pink / cyan / teal / orange / indigo / rose / slate, same names as Chip) lets the core pick background and text per theme; `{ bg, fg }` uses that pair verbatim in both themes (contrast is the caller’s call). An item’s leading `icon` takes any node (official icon component, array, or custom); `label` also accepts a node; order is always icon → label → count. With only an icon (no label / count / badge) the segment squares itself (width = segment height), and the accessible name comes from `ariaLabel`, falling back to `tooltip`. An item’s `count` (muted text; auto-lightened to follow the selected pill’s text color while selected) and `badge` (red pill) take `number | string`: numbers ≤0 render nothing, strings render as given (e.g. `\'1K\'` / `\'99+\'`).',
|
|
@@ -325,6 +329,7 @@ const doc: DocTopic = {
|
|
|
325
329
|
{ name: 'iconRight', type: 'ReactNode', def: '—', desc: { zh: '后置图标(展开箭头、外链)', en: 'Trailing icon (expand arrow, external link)' } },
|
|
326
330
|
{ name: 'color', type: 'string', def: '—', desc: { zh: '自定义主色:实心档作底色,线框 / 无底档作主色', en: 'Custom main color: background for solid tiers, main color for outline/bare' } },
|
|
327
331
|
{ name: 'loading', type: 'boolean', def: "'false'", desc: { zh: '受控 loading:文案前显示同色小圈并自动 disabled(别处刷新也能点亮它);与「点击自动 loading」取或', en: 'Controlled loading: same-color spinner before the label plus auto-disable (an external refresh can light it up too); OR-ed with automatic click loading' } },
|
|
332
|
+
{ name: 'loadingText', type: 'boolean', def: 'true', desc: { zh: '传 false:loading 时清掉文案、把按钮锁在「有文案时」的宽度上、只留一枚居中的圈;settle 后文案与自适应宽度一起还原。文案清掉后读屏靠 aria-label(字符串 children 自动补),首帧就是 loading 时锁不到宽,改用 width', en: 'Pass false to drop the label while loading, freeze the button at its labelled width and show a single centred spinner; label and auto width come back on settle. Screen readers fall back to aria-label (auto-filled for string children); a button that starts out loading has no labelled width to freeze — set width instead' } },
|
|
328
333
|
{ name: 'onClick', type: '(...) => unknown', def: '—', desc: { zh: '**返回 Promise 即自动 loading**:转圈 + 禁用 + 防连点,settle 后自己恢复;reject 也恢复并把错误打到控制台。同步返回值 = 老行为', en: '**Returning a Promise enables loading automatically**: spinner, disabled, no double-clicks, restored on settle; a rejection also restores and logs the error. Sync return values behave as before' } },
|
|
329
334
|
{ name: 'onBusyChange', type: '(busy: boolean) => void', def: '—', desc: { zh: '把「这个按钮正在跑」报出去(配合 `Modal` / `SideSheet` 的 `busy` 锁死关闭),不改变按钮自身行为', en: 'Reports "this button is running" outward (pair with `busy` on `Modal` / `SideSheet` to lock closing); does not change the button itself' } },
|
|
330
335
|
{ name: 'block', type: 'boolean', def: "'false'", desc: { zh: '撑满父宽', en: 'Fill parent width' } },
|
|
@@ -473,7 +478,7 @@ const doc: DocTopic = {
|
|
|
473
478
|
rows: [
|
|
474
479
|
{ name: 'value / onChange(v)', type: 'string / (v: string) => void', def: '—', desc: { zh: '受控值', en: 'Controlled value' } },
|
|
475
480
|
{ name: 'label', type: 'string', def: '—', desc: { zh: '前置标题(同格灰底);同时作为整组无障碍名的兜底', en: 'Leading title in the same cell (sunken background); also the fallback accessible name for the group' } },
|
|
476
|
-
{ name: 'actions', type: 'InputGroupAction[]', def: '—', desc: { zh: '{ icon?, label?, variant?, disabled?, ariaLabel?, onClick };只给 icon 退化成正方形图标钮(ariaLabel 必给),给 label 走 Button;variant 默认 info,语义色就用 Button 现成的档(success / info / warning / danger
|
|
481
|
+
{ name: 'actions', type: 'InputGroupAction[]', def: '—', desc: { zh: '{ icon?, label?, variant?, disabled?, width?, loadingText?, ariaLabel?, onClick };只给 icon 退化成正方形图标钮(ariaLabel 必给),给 label 走 Button;variant 默认 info,语义色就用 Button 现成的档(success / info / warning / danger),不另调色;**onClick 返回 Promise 时那枚按钮自动转圈禁用**,不用自己传 loading;转圈会把按钮撑宽并挤窄输入框,用 width 或 loadingText={false} 压住', en: '{ icon?, label?, variant?, disabled?, width?, loadingText?, ariaLabel?, onClick }; icon-only degrades to a square icon button (pass ariaLabel), a label renders a Button; variant defaults to info — for a semantic colour pass Button’s own variant (success / info / warning / danger) instead of a custom colour; **a Promise-returning onClick spins and disables that button** — no loading prop to manage; spinning widens the button and squeezes the input, so hold it with width or loadingText={false}' } },
|
|
477
482
|
{ name: 'undoable / undoLabel', type: 'boolean / string', def: "false / '撤销'", desc: { zh: '最前面加撤销钮,回到上一次提交前的值', en: 'Prepends an undo button returning to the value before the last commit' } },
|
|
478
483
|
{ name: 'size / height', type: "'sm' | 'md' | 'lg' / number(px)", def: "'lg' / —", desc: { zh: 'height 给了就压过 size 档', en: 'height overrides the size preset' } },
|
|
479
484
|
{ name: 'error / disabled', type: 'boolean', def: '—', desc: { zh: 'error 描红整组;disabled 禁用输入与所有按钮', en: 'error turns the whole shell red; disabled disables the input and every button' } },
|
|
@@ -760,6 +765,14 @@ const doc: DocTopic = {
|
|
|
760
765
|
zh: '遮罩右边界读 `--dshpc-page-inset-right`(多个 dock 求和),自动让开右侧分栏,弹窗在**剩余区域**居中。弹窗无需任何遮罩参数;也别自己量分栏宽度(挂载异步,恒为 0)。',
|
|
761
766
|
en: 'The mask’s right edge reads `--dshpc-page-inset-right` (summed across docks) and yields to the right column, centering the dialog in the **remaining** area. The dialog needs no mask props; never measure the column yourself (mounting is async, it always reads 0).',
|
|
762
767
|
},
|
|
768
|
+
{
|
|
769
|
+
zh: '命令式 `confirmModal(opts)` / `alertModal(opts)` 返回 Promise:前者 resolve `true`(确定)或 `false`(取消 / 遮罩 / Esc),后者关闭即 resolve。回调返回 Promise 时对应按钮自己转圈、整框锁死,settle 后才关。',
|
|
770
|
+
en: 'The imperative `confirmModal(opts)` / `alertModal(opts)` return a Promise: the former resolves `true` (confirmed) or `false` (cancel / mask / Esc), the latter resolves on close. When a callback returns a Promise, its button spins and the dialog locks until it settles.',
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
zh: '回调的返回值决定关不关:**只有 `false`**(同步返回,或 resolve 成 `false`)表示这次没成 —— 框留着让人重试;`true` / `undefined` / 其他返回值照常关;reject 也不关(错误打到控制台)。失败提示由回调自己出,调用点不必包 `try/catch`。',
|
|
774
|
+
en: 'The callback’s return value decides whether it closes: **only `false`** (returned directly, or resolved to `false`) means it did not succeed — the dialog stays for a retry; `true` / `undefined` / anything else closes as usual; a rejection also keeps it open (the error is logged). The callback owns its failure message, so call sites need no `try/catch`.',
|
|
775
|
+
},
|
|
763
776
|
],
|
|
764
777
|
api: [
|
|
765
778
|
{
|
|
@@ -800,6 +813,44 @@ const doc: DocTopic = {
|
|
|
800
813
|
{ name: 'children', type: 'ReactNode', def: '—', desc: { zh: '主体', en: 'Body' } },
|
|
801
814
|
],
|
|
802
815
|
},
|
|
816
|
+
{
|
|
817
|
+
id: 'ui-confirm-dialog',
|
|
818
|
+
rows: [
|
|
819
|
+
{ name: 'title / message', type: 'ReactNode', def: '—', desc: { zh: '标题 / 说明文字或任意内容;无标题时整条头部消失', en: 'Title / body text or any content; no title means no header row' } },
|
|
820
|
+
{ name: 'tone', type: "'primary' | 'danger' | 'warning'", def: "'primary'", desc: { zh: '确认钮语义档(决定按钮颜色)', en: 'Confirm button tone (sets its colour)' } },
|
|
821
|
+
{ name: 'confirmText / cancelText', type: 'string', def: '内置字典「确定」/「取消」', desc: { zh: '按钮文案', en: 'Button labels' } },
|
|
822
|
+
{ name: 'confirmWidth / cancelWidth', type: 'number | string', def: '—', desc: { zh: '两颗钮各自定宽(px 或任意 CSS 宽度);loading 转圈会把按钮撑宽,定宽后不跳', en: 'Per-button fixed width (px or any CSS width); loading would otherwise widen the button and shift its neighbour' } },
|
|
823
|
+
{ name: 'loadingText', type: 'boolean', def: 'true', desc: { zh: '传 false:loading 时两颗钮清文案、锁住有文案的宽度、只留居中的圈(见 `Button.loadingText`)', en: 'Pass false: while loading, both buttons drop their labels, freeze at the labelled width and show a centred spinner (see `Button.loadingText`)' } },
|
|
824
|
+
{ name: 'onConfirm / onCancel', type: '() => unknown', def: '—', desc: { zh: '确认 / 取消回调;返回 Promise 时按钮转圈、整框锁死,settle 后恢复;返回 `false` 不关', en: 'Confirm / cancel callback; a Promise makes its button spin and locks the dialog until it settles; `false` keeps it open' } },
|
|
825
|
+
{ name: 'confirmLoading / cancelLoading', type: 'boolean', def: 'false', desc: { zh: '外部驱动对应按钮 loading,与按钮自身异步状态取或', en: 'External loading for that button, OR-ed with its own async state' } },
|
|
826
|
+
{ name: 'closeOnMask', type: 'boolean', def: "'true'", desc: { zh: '点遮罩关闭(等于取消)', en: 'Close on mask click (treated as cancel)' } },
|
|
827
|
+
{ name: 'size', type: 'ModalSize', def: "'sm'", desc: { zh: '尺寸档', en: 'Size tier' } },
|
|
828
|
+
{ name: 'translate', type: 'Translate', def: '内置字典', desc: { zh: '覆盖确定 / 取消文案', en: 'Override confirm / cancel copy' } },
|
|
829
|
+
],
|
|
830
|
+
},
|
|
831
|
+
{
|
|
832
|
+
id: 'ui-alert-dialog',
|
|
833
|
+
rows: [
|
|
834
|
+
{ name: 'title / message', type: 'ReactNode', def: '—', desc: { zh: '标题 / 说明文字或任意内容;无标题时整条头部消失', en: 'Title / body text or any content; no title means no header row' } },
|
|
835
|
+
{ name: 'severity', type: "'info' | 'success' | 'warning' | 'error'", def: "'info'", desc: { zh: '信号档:头部图标与配色由它决定', en: 'Signal tier: sets the header glyph and colour' } },
|
|
836
|
+
{ name: 'confirmText', type: 'string', def: '内置字典「知道了」', desc: { zh: '按钮文案', en: 'Button label' } },
|
|
837
|
+
{ name: 'confirmWidth', type: 'number | string', def: '—', desc: { zh: '确认钮定宽(px 或任意 CSS 宽度);loading 转圈会把按钮撑宽,定宽后不跳', en: 'Fixed width for the confirm button (px or any CSS width); loading would otherwise widen it' } },
|
|
838
|
+
{ name: 'loadingText', type: 'boolean', def: 'true', desc: { zh: '传 false:loading 时清文案、锁住有文案的宽度、只留居中的圈(见 `Button.loadingText`)', en: 'Pass false: while loading, drop the label, freeze at the labelled width and show a centred spinner (see `Button.loadingText`)' } },
|
|
839
|
+
{ name: 'onConfirm', type: '() => unknown', def: '—', desc: { zh: '确认 / 遮罩 / Esc 的统一出口;返回 Promise 时转圈锁框,返回 `false` 不关', en: 'Single exit for confirm / mask / Esc; a Promise spins and locks it, `false` keeps it open' } },
|
|
840
|
+
{ name: 'confirmLoading', type: 'boolean', def: 'false', desc: { zh: '外部驱动按钮 loading,与按钮自身异步状态取或', en: 'External button loading, OR-ed with its own async state' } },
|
|
841
|
+
{ name: 'closeOnMask', type: 'boolean', def: "'true'", desc: { zh: '点遮罩关闭', en: 'Close on mask click' } },
|
|
842
|
+
{ name: 'size', type: 'ModalSize', def: "'sm'", desc: { zh: '尺寸档', en: 'Size tier' } },
|
|
843
|
+
{ name: 'translate', type: 'Translate', def: '内置字典', desc: { zh: '覆盖按钮文案', en: 'Override the button copy' } },
|
|
844
|
+
],
|
|
845
|
+
},
|
|
846
|
+
{
|
|
847
|
+
id: 'ui-imperative-dialog',
|
|
848
|
+
rows: [
|
|
849
|
+
{ name: 'confirmModal(opts)', type: 'Promise<boolean>', def: '—', desc: { zh: '命令式确认框;opts 同 `ConfirmModal`,另有 `skin`;`true` = 确定', en: 'Imperative confirm; opts match `ConfirmModal` plus `skin`; `true` = confirmed' } },
|
|
850
|
+
{ name: 'alertModal(opts)', type: 'Promise<void>', def: '—', desc: { zh: '命令式警告框;opts 同 `AlertModal`,另有 `skin`;关闭即 resolve', en: 'Imperative alert; opts match `AlertModal` plus `skin`; resolves on close' } },
|
|
851
|
+
{ name: 'skin', type: "'core' | 'host'", def: "'core'", desc: { zh: 'host 走宿主原生 Modal(需先引入适配层 `official.js`,未注册则回落 core 并告警)', en: 'host uses the host’s native Modal (requires the `official.js` adapter; falls back to core with a warning when unregistered)' } },
|
|
852
|
+
],
|
|
853
|
+
},
|
|
803
854
|
],
|
|
804
855
|
},
|
|
805
856
|
{
|
package/docs/help/ui.md
CHANGED
|
@@ -47,6 +47,10 @@ IconButton:variant: plain|outline|danger(默认 plain,**无底色**)、s
|
|
|
47
47
|
|
|
48
48
|
> EN: Both share one loading semantics: a Promise-returning `onClick` spins (an icon button swaps its icon for the spinner, keeps `aria-label` and adds `aria-busy`), `onBusyChange` reports "running", and the controlled `loading` prop is OR-ed in — an external refresh lights the same button too. While spinning, the button’s own icon slots (`icon` / `iconRight`) all step aside: spinner plus label only.
|
|
49
49
|
|
|
50
|
+
loading 会把前置圈插进按钮:无 icon 的按钮因此宽出 18px(圈 12 + 间距 6),把旁边的按钮挤开。要完全不跳有两条路:给 `width` 定宽(按最长文案 + 18px 留),或传 `loadingText={false}` 让 loading 时只剩一圈。
|
|
51
|
+
|
|
52
|
+
> EN: Loading inserts the spinner into the button, so a button without an icon grows 18px (12px spinner + 6px gap) and shoves its neighbours. To keep it rock-steady, either set `width` (longest label + 18px) or pass `loadingText={false}` so only the spinner remains while loading.
|
|
53
|
+
|
|
50
54
|
Segmented:`items`(必填)支持单选 / 多选,`size`(默认 lg;三档总高 24 / 28 / 32)、`bordered`(1px 外框,总高不变)、`multiple`(多选)。外观只有一套:灰底轨道 + 白色选中片,选中片的描边环与阴影由宿主 elevation token 提供(离线兜底值没有那圈环)。选中片配色只经 `tone`:传内置色名(与 Chip 同名的 business / success / warning / danger / purple / pink / cyan / teal / orange / indigo / rose / slate)时底与字由核心定、深浅两主题各自成立;传 `{ bg, fg }` 时两个主题都用调用方这一对颜色(对比度由调用方负责)。段内 `icon` 是前置图标槽(官方图标组件 / 数组 / 自绘节点均可),`label` 也可传节点;顺序固定为 icon → label → count。只有图标(无文字 / 计数 / 角标)时该段自动变正方形(宽 = 段高),读屏名用 `ariaLabel`,缺省退回 `tooltip`。段内 `count`(弱化灰字,选中段内自动跟着选中片字色提亮)/ `badge`(红角标)接受 `number | string`:数字 ≤0 不显示,字符串原样显示(如 `1K` / `99+`)。
|
|
51
55
|
|
|
52
56
|
> EN: Segmented: `items` (required) supports single or multiple selection; `size` (default lg; totals 24 / 28 / 32), `bordered` (1px outer frame, same total height), `multiple` (multi-select). One look only: grey track + white selected pill; its stroke ring and shadow come from the host elevation token (the offline fallback has no ring). The selected pill’s colors go through `tone` only: a built-in color name (business / success / warning / danger / purple / pink / cyan / teal / orange / indigo / rose / slate, same names as Chip) lets the core pick background and text per theme; `{ bg, fg }` uses that pair verbatim in both themes (contrast is the caller’s call). An item’s leading `icon` takes any node (official icon component, array, or custom); `label` also accepts a node; order is always icon → label → count. With only an icon (no label / count / badge) the segment squares itself (width = segment height), and the accessible name comes from `ariaLabel`, falling back to `tooltip`. An item’s `count` (muted text; auto-lightened to follow the selected pill’s text color while selected) and `badge` (red pill) take `number | string`: numbers ≤0 render nothing, strings render as given (e.g. `'1K'` / `'99+'`).
|
|
@@ -59,6 +63,7 @@ Segmented:`items`(必填)支持单选 / 多选,`size`(默认 lg;三
|
|
|
59
63
|
| `iconRight` | `ReactNode` | — | 后置图标(展开箭头、外链) | Trailing icon (expand arrow, external link) |
|
|
60
64
|
| `color` | `string` | — | 自定义主色:实心档作底色,线框 / 无底档作主色 | Custom main color: background for solid tiers, main color for outline/bare |
|
|
61
65
|
| `loading` | `boolean` | 'false' | 受控 loading:文案前显示同色小圈并自动 disabled(别处刷新也能点亮它);与「点击自动 loading」取或 | Controlled loading: same-color spinner before the label plus auto-disable (an external refresh can light it up too); OR-ed with automatic click loading |
|
|
66
|
+
| `loadingText` | `boolean` | true | 传 false:loading 时清掉文案、把按钮锁在「有文案时」的宽度上、只留一枚居中的圈;settle 后文案与自适应宽度一起还原。文案清掉后读屏靠 aria-label(字符串 children 自动补),首帧就是 loading 时锁不到宽,改用 width | Pass false to drop the label while loading, freeze the button at its labelled width and show a single centred spinner; label and auto width come back on settle. Screen readers fall back to aria-label (auto-filled for string children); a button that starts out loading has no labelled width to freeze — set width instead |
|
|
62
67
|
| `onClick` | `(...) => unknown` | — | **返回 Promise 即自动 loading**:转圈 + 禁用 + 防连点,settle 后自己恢复;reject 也恢复并把错误打到控制台。同步返回值 = 老行为 | **Returning a Promise enables loading automatically**: spinner, disabled, no double-clicks, restored on settle; a rejection also restores and logs the error. Sync return values behave as before |
|
|
63
68
|
| `onBusyChange` | `(busy: boolean) => void` | — | 把「这个按钮正在跑」报出去(配合 `Modal` / `SideSheet` 的 `busy` 锁死关闭),不改变按钮自身行为 | Reports "this button is running" outward (pair with `busy` on `Modal` / `SideSheet` to lock closing); does not change the button itself |
|
|
64
69
|
| `block` | `boolean` | 'false' | 撑满父宽 | Fill parent width |
|
|
@@ -203,7 +208,7 @@ h(SplitGroup, null,
|
|
|
203
208
|
|---|---|---|---|---|
|
|
204
209
|
| `value / onChange(v)` | `string / (v: string) => void` | — | 受控值 | Controlled value |
|
|
205
210
|
| `label` | `string` | — | 前置标题(同格灰底);同时作为整组无障碍名的兜底 | Leading title in the same cell (sunken background); also the fallback accessible name for the group |
|
|
206
|
-
| `actions` | `InputGroupAction[]` | — | { icon?, label?, variant?, disabled?, ariaLabel?, onClick };只给 icon 退化成正方形图标钮(ariaLabel 必给),给 label 走 Button;variant 默认 info,语义色就用 Button 现成的档(success / info / warning / danger
|
|
211
|
+
| `actions` | `InputGroupAction[]` | — | { icon?, label?, variant?, disabled?, width?, loadingText?, ariaLabel?, onClick };只给 icon 退化成正方形图标钮(ariaLabel 必给),给 label 走 Button;variant 默认 info,语义色就用 Button 现成的档(success / info / warning / danger),不另调色;**onClick 返回 Promise 时那枚按钮自动转圈禁用**,不用自己传 loading;转圈会把按钮撑宽并挤窄输入框,用 width 或 loadingText={false} 压住 | { icon?, label?, variant?, disabled?, width?, loadingText?, ariaLabel?, onClick }; icon-only degrades to a square icon button (pass ariaLabel), a label renders a Button; variant defaults to info — for a semantic colour pass Button’s own variant (success / info / warning / danger) instead of a custom colour; **a Promise-returning onClick spins and disables that button** — no loading prop to manage; spinning widens the button and squeezes the input, so hold it with width or loadingText={false} |
|
|
207
212
|
| `undoable / undoLabel` | `boolean / string` | false / '撤销' | 最前面加撤销钮,回到上一次提交前的值 | Prepends an undo button returning to the value before the last commit |
|
|
208
213
|
| `size / height` | `'sm' \| 'md' \| 'lg' / number(px)` | 'lg' / — | height 给了就压过 size 档 | height overrides the size preset |
|
|
209
214
|
| `error / disabled` | `boolean` | — | error 描红整组;disabled 禁用输入与所有按钮 | error turns the whole shell red; disabled disables the input and every button |
|
|
@@ -637,6 +642,14 @@ Modal 是自绘 overlay,不走 react-dom portal。
|
|
|
637
642
|
|
|
638
643
|
> EN: The mask’s right edge reads `--dshpc-page-inset-right` (summed across docks) and yields to the right column, centering the dialog in the **remaining** area. The dialog needs no mask props; never measure the column yourself (mounting is async, it always reads 0).
|
|
639
644
|
|
|
645
|
+
命令式 `confirmModal(opts)` / `alertModal(opts)` 返回 Promise:前者 resolve `true`(确定)或 `false`(取消 / 遮罩 / Esc),后者关闭即 resolve。回调返回 Promise 时对应按钮自己转圈、整框锁死,settle 后才关。
|
|
646
|
+
|
|
647
|
+
> EN: The imperative `confirmModal(opts)` / `alertModal(opts)` return a Promise: the former resolves `true` (confirmed) or `false` (cancel / mask / Esc), the latter resolves on close. When a callback returns a Promise, its button spins and the dialog locks until it settles.
|
|
648
|
+
|
|
649
|
+
回调的返回值决定关不关:**只有 `false`**(同步返回,或 resolve 成 `false`)表示这次没成 —— 框留着让人重试;`true` / `undefined` / 其他返回值照常关;reject 也不关(错误打到控制台)。失败提示由回调自己出,调用点不必包 `try/catch`。
|
|
650
|
+
|
|
651
|
+
> EN: The callback’s return value decides whether it closes: **only `false`** (returned directly, or resolved to `false`) means it did not succeed — the dialog stays for a retry; `true` / `undefined` / anything else closes as usual; a rejection also keeps it open (the error is logged). The callback owns its failure message, so call sites need no `try/catch`.
|
|
652
|
+
|
|
640
653
|
| 参数 | 类型 | 默认 | 说明(zh) | 说明(en) |
|
|
641
654
|
|---|---|---|---|---|
|
|
642
655
|
| `showToast(message, opts?)` | `` | | 官方 Sonner 原味(轻量原生观感;demo 统一用 notify)。opts: `{ variant?, durationMs?, color?, onDismiss?, position? }`,6 向定位,明暗跟随宿主 | Raw official Sonner flavour (lightweight, native look; the demo standardises on notify). opts `{ variant?, durationMs?, color?, onDismiss?, position? }`, 6-way placement, theme follows host |
|
|
@@ -671,6 +684,38 @@ Modal 是自绘 overlay,不走 react-dom portal。
|
|
|
671
684
|
| `className` | `string` | — | 追加 class(只补布局 / 视觉修饰,别覆盖皮肤) | Extra class (layout / visual tweaks only; do not override the skin) |
|
|
672
685
|
| `children` | `ReactNode` | — | 主体 | Body |
|
|
673
686
|
|
|
687
|
+
| 参数 | 类型 | 默认 | 说明(zh) | 说明(en) |
|
|
688
|
+
|---|---|---|---|---|
|
|
689
|
+
| `title / message` | `ReactNode` | — | 标题 / 说明文字或任意内容;无标题时整条头部消失 | Title / body text or any content; no title means no header row |
|
|
690
|
+
| `tone` | `'primary' \| 'danger' \| 'warning'` | 'primary' | 确认钮语义档(决定按钮颜色) | Confirm button tone (sets its colour) |
|
|
691
|
+
| `confirmText / cancelText` | `string` | 内置字典「确定」/「取消」 | 按钮文案 | Button labels |
|
|
692
|
+
| `confirmWidth / cancelWidth` | `number \| string` | — | 两颗钮各自定宽(px 或任意 CSS 宽度);loading 转圈会把按钮撑宽,定宽后不跳 | Per-button fixed width (px or any CSS width); loading would otherwise widen the button and shift its neighbour |
|
|
693
|
+
| `loadingText` | `boolean` | true | 传 false:loading 时两颗钮清文案、锁住有文案的宽度、只留居中的圈(见 `Button.loadingText`) | Pass false: while loading, both buttons drop their labels, freeze at the labelled width and show a centred spinner (see `Button.loadingText`) |
|
|
694
|
+
| `onConfirm / onCancel` | `() => unknown` | — | 确认 / 取消回调;返回 Promise 时按钮转圈、整框锁死,settle 后恢复;返回 `false` 不关 | Confirm / cancel callback; a Promise makes its button spin and locks the dialog until it settles; `false` keeps it open |
|
|
695
|
+
| `confirmLoading / cancelLoading` | `boolean` | false | 外部驱动对应按钮 loading,与按钮自身异步状态取或 | External loading for that button, OR-ed with its own async state |
|
|
696
|
+
| `closeOnMask` | `boolean` | 'true' | 点遮罩关闭(等于取消) | Close on mask click (treated as cancel) |
|
|
697
|
+
| `size` | `ModalSize` | 'sm' | 尺寸档 | Size tier |
|
|
698
|
+
| `translate` | `Translate` | 内置字典 | 覆盖确定 / 取消文案 | Override confirm / cancel copy |
|
|
699
|
+
|
|
700
|
+
| 参数 | 类型 | 默认 | 说明(zh) | 说明(en) |
|
|
701
|
+
|---|---|---|---|---|
|
|
702
|
+
| `title / message` | `ReactNode` | — | 标题 / 说明文字或任意内容;无标题时整条头部消失 | Title / body text or any content; no title means no header row |
|
|
703
|
+
| `severity` | `'info' \| 'success' \| 'warning' \| 'error'` | 'info' | 信号档:头部图标与配色由它决定 | Signal tier: sets the header glyph and colour |
|
|
704
|
+
| `confirmText` | `string` | 内置字典「知道了」 | 按钮文案 | Button label |
|
|
705
|
+
| `confirmWidth` | `number \| string` | — | 确认钮定宽(px 或任意 CSS 宽度);loading 转圈会把按钮撑宽,定宽后不跳 | Fixed width for the confirm button (px or any CSS width); loading would otherwise widen it |
|
|
706
|
+
| `loadingText` | `boolean` | true | 传 false:loading 时清文案、锁住有文案的宽度、只留居中的圈(见 `Button.loadingText`) | Pass false: while loading, drop the label, freeze at the labelled width and show a centred spinner (see `Button.loadingText`) |
|
|
707
|
+
| `onConfirm` | `() => unknown` | — | 确认 / 遮罩 / Esc 的统一出口;返回 Promise 时转圈锁框,返回 `false` 不关 | Single exit for confirm / mask / Esc; a Promise spins and locks it, `false` keeps it open |
|
|
708
|
+
| `confirmLoading` | `boolean` | false | 外部驱动按钮 loading,与按钮自身异步状态取或 | External button loading, OR-ed with its own async state |
|
|
709
|
+
| `closeOnMask` | `boolean` | 'true' | 点遮罩关闭 | Close on mask click |
|
|
710
|
+
| `size` | `ModalSize` | 'sm' | 尺寸档 | Size tier |
|
|
711
|
+
| `translate` | `Translate` | 内置字典 | 覆盖按钮文案 | Override the button copy |
|
|
712
|
+
|
|
713
|
+
| 参数 | 类型 | 默认 | 说明(zh) | 说明(en) |
|
|
714
|
+
|---|---|---|---|---|
|
|
715
|
+
| `confirmModal(opts)` | `Promise<boolean>` | — | 命令式确认框;opts 同 `ConfirmModal`,另有 `skin`;`true` = 确定 | Imperative confirm; opts match `ConfirmModal` plus `skin`; `true` = confirmed |
|
|
716
|
+
| `alertModal(opts)` | `Promise<void>` | — | 命令式警告框;opts 同 `AlertModal`,另有 `skin`;关闭即 resolve | Imperative alert; opts match `AlertModal` plus `skin`; resolves on close |
|
|
717
|
+
| `skin` | `'core' \| 'host'` | 'core' | host 走宿主原生 Modal(需先引入适配层 `official.js`,未注册则回落 core 并告警) | host uses the host’s native Modal (requires the `official.js` adapter; falls back to core with a warning when unregistered) |
|
|
718
|
+
|
|
674
719
|
## SideSheet(侧边抽屉)
|
|
675
720
|
|
|
676
721
|
> EN: SideSheet (side drawer)
|
package/docs/requirements.md
CHANGED
|
@@ -114,7 +114,18 @@ dsh-plugin-core/
|
|
|
114
114
|
受控 `loading` 与之取或(**别处刷新也能点亮同一颗按钮**);`onBusyChange` 把「在跑」报出去。
|
|
115
115
|
`Modal` / `SideSheet` 只认 `busy`(遮罩 / Esc / ✕ 一并失效,footer 皮肤各弹窗自管),
|
|
116
116
|
`ConfirmModal` / `AlertModal` 退化成薄壳,命令式 `confirmModal` / `alertModal` 只负责「跑完关不关」。
|
|
117
|
+
这个「关不关」由回调返回值决定(2026-11-03 用户拍板):**只有明确的 `false`**(同步返回,或 Promise
|
|
118
|
+
resolve 成 `false`)算「这次没成」,弹窗留着让人重试;`true` / `undefined` / 其它照常关。失败怎么提示
|
|
119
|
+
由回调自己决定(核心不弹 Toast),这样调用点就不必在外面包 `try/catch`。同步与异步两条路径同一份判据。
|
|
117
120
|
转圈期间按钮自己的 `icon` / `iconRight` 一律让位,只留转圈(+ 文字)。内测期不设兼容层。
|
|
121
|
+
- 转圈会插一枚 12px 圈 + 6px 间距 ⇒ 无 icon 的按钮宽出 18px(2026-11-03 用户拍板的两条通道):
|
|
122
|
+
① `ConfirmModal`(`confirmWidth` / `cancelWidth`)、`AlertModal`(`confirmWidth`)、
|
|
123
|
+
`InputGroupAction`(`width`)透传 `Button.width`,调用方按「最长文案 + 18px」定宽;
|
|
124
|
+
② `Button.loadingText={false}`(ConfirmModal / AlertModal / InputGroupAction 同名透传):
|
|
125
|
+
loading 时**清掉文案、锁住「有文案时」的宽度、只留一枚居中的圈**,settle 后文案与自适应宽度一起还原。
|
|
126
|
+
清文案后读屏名称靠 `aria-label`(字符串 children 自动补,复合 children 由调用方给);
|
|
127
|
+
首帧就是 loading(没有「有文案的宽度」可量)时锁不到宽,走 ① 的 `width`。
|
|
128
|
+
loading 圈包进 `.dshpc-btn__icon`(svg 被 1em 规则接管)⇒ 有 icon 的按钮切 loading 宽度零差。
|
|
118
129
|
- `Loading` 是旧的「自带定位 + 自带 pill 背景」复合件,**保留不删**但标 `@deprecated`,新代码用 `Loader`。
|
|
119
130
|
- 布局基础:`PanelDock` / `DockPanel` / `createPanelDock`(**可停靠分栏容器**:多面板并存、按组名寻址、拖拽拉栏、宽度记忆;2026-10-20 拍板用此名,替代早先的 `SidebarLayout` / `SplitPane`)。只做右侧;组名与窗口一对一;默认上限 3,超限拒绝新开;不做 tab 切换 / 自动淘汰 / 多份同名;**面板本身始终是布局成员,不做面板浮层**(2026-10-28 补:**收起** = 面板退出布局、另出右侧一只独立的 `position: fixed` 耳朵,点耳朵展开并还原宽度;关闭不留耳朵——耳朵是独立浮层,不是把面板变浮层)。**结构照成熟库口径写 children,`open/close` 只传 id,不把页面树塞进调用参数**
|
|
120
131
|
- 浮动快捷工具栏:`QuickToolbar`(2026-10-31 用户拍板):右侧一列独立圆钮,纵向**恒贴屏幕底边**(默认 16px);横向默认贴屏幕右缘,传 `anchorId` / `anchor()` 时贴到指定控件右缘外侧,右侧放不下则退回屏幕右缘(控件找不到按跟随窗口处理)。内置回顶部默认 `when:'scroll'`、阈值 320,`backToTop:false` 可关掉,对象可调 `order` / `label` / `threshold`;自定义项 `items` 支持 `icon` / `label` / `onClick` / `visible` / `when` / `order` / `threshold` / `color` / `fgColor`,统一 `onAction`。旧的 `BackToTop` **全部删除**,只保留这一份,不做迁移。
|
package/package.json
CHANGED