911ceca079
Select 组件(用户拍板:下拉框全端共用一个真相源): - design/components/forms/Select.jsx:自绘下拉——触发器同 Input (control-sm/radius-sm/border-1 + chevronDown),弹层同菜单 (radius-md/shadow-menu、选中项前置对勾、hover surface-2), 外点/Esc 收起;登记簿加卡;icons.js 新增 chevronDown 并登记 icon-map - 原型 SettingsTray 与桌面 SettingsApp 同步换用(替换原生 select—— 其系统弹层样式/位置不可控,即 12A 截图问题) 原型组件运行时可再生(修复单源缺口): - design-pipeline/bundle-components.mjs:用 desktop 现成 esbuild 重建 _ds_bundle.js(此前为 Claude 导出产物、仓库内无法再生,组件一改即 过期);import 'react' 经全局 shim,命名空间不变;已实测原型页正常 - _ds_bundle.js 重建(15 个组件,含 Select/Icon) 设置窗口无边框: - tauri.conf settings 窗口 titleBarStyle=Overlay + hiddenTitle, 系统红绿灯悬浮左上;SettingsApp 自绘顶条(surface-2 + 下边框 + data-tauri-drag-region 可拖拽),对齐原型 MacWindow 规格 合并 feat/design-truth-source(真相源与闸体系)进本分支 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
512 lines
23 KiB
JavaScript
512 lines
23 KiB
JavaScript
/* 自动生成 — 请勿手改。来源 design/components/ + icons.js
|
||
重新生成:node design-pipeline/bundle-components.mjs
|
||
运行时依赖:页面全局 React(ui_kits 页先加载 unpkg UMD React)。
|
||
导出命名空间:window.DuduDesignSystem_2e0172(组件 15 个)*/
|
||
(() => {
|
||
// design/components/core/Badge.jsx
|
||
var ddBadgeCss = `
|
||
.dd-badge {
|
||
display: inline-flex; align-items: center; gap: 4px;
|
||
font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--weight-semibold);
|
||
padding: 2px 10px; border-radius: var(--radius-full); line-height: var(--leading-normal);
|
||
}
|
||
.dd-badge--neutral { background: var(--surface-2); color: var(--text-2); }
|
||
.dd-badge--blue { background: var(--accent-soft); color: var(--accent-text); }
|
||
.dd-badge--green { background: var(--positive-soft); color: var(--positive); }
|
||
.dd-badge--orange { background: var(--warning-soft); color: var(--warning); }
|
||
.dd-badge--red { background: var(--danger-soft); color: var(--danger); }
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-badge-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-badge-css";
|
||
s.textContent = ddBadgeCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Badge({ tone = "neutral", children, ...rest }) {
|
||
return /* @__PURE__ */ React.createElement("span", { className: `dd-badge dd-badge--${tone}`, ...rest }, children);
|
||
}
|
||
|
||
// design/components/core/Button.jsx
|
||
var ddButtonCss = `
|
||
.dd-btn {
|
||
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
||
font-family: var(--font-sans); font-weight: var(--weight-medium);
|
||
border-radius: var(--radius-sm); border: 1px solid transparent;
|
||
cursor: pointer; white-space: nowrap; user-select: none;
|
||
transition: background var(--dur-fast) var(--ease-out),
|
||
border-color var(--dur-fast) var(--ease-out),
|
||
color var(--dur-fast) var(--ease-out);
|
||
}
|
||
.dd-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
||
.dd-btn--sm { height: var(--control-sm); padding: 0 12px; font-size: var(--text-sm); }
|
||
.dd-btn--md { height: var(--control-md); padding: 0 16px; font-size: var(--text-base); }
|
||
.dd-btn--lg { height: var(--control-lg); padding: 0 20px; font-size: var(--text-md); }
|
||
.dd-btn--block { width: 100%; }
|
||
.dd-btn--primary { background: var(--accent); color: var(--text-on-accent); }
|
||
.dd-btn--primary:hover { background: var(--accent-hover); }
|
||
.dd-btn--primary:active { background: var(--accent-press); }
|
||
.dd-btn--secondary { background: var(--surface-card); border-color: var(--border-2); color: var(--text-1); }
|
||
.dd-btn--secondary:hover { background: var(--surface-2); }
|
||
.dd-btn--secondary:active { background: var(--surface-3); }
|
||
.dd-btn--ghost { background: transparent; color: var(--accent-text); }
|
||
.dd-btn--ghost:hover { background: var(--accent-soft); }
|
||
.dd-btn--ghost:active { background: var(--accent-soft-2); }
|
||
.dd-btn--danger { background: var(--danger); color: #fff; }
|
||
.dd-btn--danger:hover { filter: brightness(0.94); }
|
||
.dd-btn[disabled] { opacity: 0.45; pointer-events: none; }
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-button-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-button-css";
|
||
s.textContent = ddButtonCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Button({ variant = "primary", size = "md", block = false, disabled = false, children, ...rest }) {
|
||
const cls = `dd-btn dd-btn--${variant} dd-btn--${size}${block ? " dd-btn--block" : ""}`;
|
||
return /* @__PURE__ */ React.createElement("button", { type: "button", className: cls, disabled, ...rest }, children);
|
||
}
|
||
|
||
// design/components/core/Card.jsx
|
||
var ddCardCss = `
|
||
.dd-card {
|
||
background: var(--surface-card); border: 1px solid var(--border-1);
|
||
border-radius: var(--radius-md); box-shadow: var(--shadow-card);
|
||
}
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-card-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-card-css";
|
||
s.textContent = ddCardCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Card({ padding = "var(--space-5)", style, children, ...rest }) {
|
||
return /* @__PURE__ */ React.createElement("div", { className: "dd-card", style: { padding, ...style }, ...rest }, children);
|
||
}
|
||
|
||
// design/icons.js
|
||
var icons = {
|
||
/** 麦克风(识别/录音) */
|
||
mic: '<path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/>',
|
||
/** 对勾(完成/选中) */
|
||
check: '<path d="M20 6 9 17l-5-5"/>',
|
||
/** 关闭 */
|
||
x: '<path d="M18 6 6 18M6 6l12 12"/>',
|
||
/** 添加图片(反馈附图) */
|
||
imagePlus: '<path d="M16 5h6"/><path d="M19 2v6"/><path d="M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>',
|
||
/** 钥匙(权限引导) */
|
||
key: '<path d="m15.5 7.5 3 3L22 7l-3-3"/><path d="m21 2-9.6 9.6"/><circle cx="7.5" cy="15.5" r="5.5"/>',
|
||
/** 下拉箭头(Select 等展开指示) */
|
||
chevronDown: '<path d="m6 9 6 6 6-6"/>'
|
||
};
|
||
|
||
// design/components/core/Icon.jsx
|
||
function Icon({ name, size = 16, sw = 2, ...rest }) {
|
||
const body = icons[name];
|
||
if (!body) throw new Error(`unknown icon: ${name}\uFF08\u5148\u5728 design/icons.js \u767B\u8BB0\uFF09`);
|
||
return /* @__PURE__ */ React.createElement(
|
||
"svg",
|
||
{
|
||
width: size,
|
||
height: size,
|
||
viewBox: "0 0 24 24",
|
||
fill: "none",
|
||
stroke: "currentColor",
|
||
strokeWidth: sw,
|
||
strokeLinecap: "round",
|
||
strokeLinejoin: "round",
|
||
"aria-hidden": "true",
|
||
dangerouslySetInnerHTML: { __html: body },
|
||
...rest
|
||
}
|
||
);
|
||
}
|
||
|
||
// design/components/core/IconButton.jsx
|
||
var ddIconBtnCss = `
|
||
.dd-iconbtn {
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
border: none; background: transparent; color: var(--text-2);
|
||
border-radius: var(--radius-sm); cursor: pointer;
|
||
transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
|
||
}
|
||
.dd-iconbtn:hover { background: var(--surface-2); color: var(--text-1); }
|
||
.dd-iconbtn:active { background: var(--surface-3); }
|
||
.dd-iconbtn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
||
.dd-iconbtn[disabled] { opacity: 0.45; pointer-events: none; }
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-iconbtn-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-iconbtn-css";
|
||
s.textContent = ddIconBtnCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function IconButton({ size = 32, label, disabled = false, children, ...rest }) {
|
||
return /* @__PURE__ */ React.createElement(
|
||
"button",
|
||
{
|
||
type: "button",
|
||
className: "dd-iconbtn",
|
||
"aria-label": label,
|
||
title: label,
|
||
style: { width: size, height: size },
|
||
disabled,
|
||
...rest
|
||
},
|
||
children
|
||
);
|
||
}
|
||
|
||
// design/components/core/Kbd.jsx
|
||
var ddKbdCss = `
|
||
.dd-kbd {
|
||
display: inline-block; background: var(--surface-2);
|
||
border: 1px solid var(--border-2); border-bottom-width: 2px;
|
||
border-radius: var(--radius-xs); padding: 1px 7px;
|
||
font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-1);
|
||
line-height: 1.5;
|
||
}
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-kbd-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-kbd-css";
|
||
s.textContent = ddKbdCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Kbd({ children, ...rest }) {
|
||
return /* @__PURE__ */ React.createElement("kbd", { className: "dd-kbd", ...rest }, children);
|
||
}
|
||
function HotkeyCombo({ keys = [], gap = 4 }) {
|
||
return /* @__PURE__ */ React.createElement("span", { style: { display: "inline-flex", gap, alignItems: "center" } }, keys.map((k, i) => /* @__PURE__ */ React.createElement(Kbd, { key: i }, k)));
|
||
}
|
||
|
||
// design/components/core/ProgressBar.jsx
|
||
var ddProgressCss = `
|
||
.dd-progress { background: var(--surface-3); border-radius: var(--radius-full); overflow: hidden; }
|
||
.dd-progress i { display: block; height: 100%; border-radius: var(--radius-full);
|
||
background: var(--accent); transition: width var(--dur-slow) var(--ease-out); }
|
||
.dd-progress--warning i { background: var(--warning); }
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-progress-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-progress-css";
|
||
s.textContent = ddProgressCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function ProgressBar({ value = 0, max = 100, height = 6, warnAt = 0.9, style, ...rest }) {
|
||
const ratio = Math.min(1, max > 0 ? value / max : 0);
|
||
const warning = ratio >= warnAt;
|
||
return /* @__PURE__ */ React.createElement(
|
||
"div",
|
||
{
|
||
className: `dd-progress${warning ? " dd-progress--warning" : ""}`,
|
||
style: { height, ...style },
|
||
role: "progressbar",
|
||
"aria-valuenow": value,
|
||
"aria-valuemax": max,
|
||
...rest
|
||
},
|
||
/* @__PURE__ */ React.createElement("i", { style: { width: `${ratio * 100}%` } })
|
||
);
|
||
}
|
||
|
||
// design/components/forms/Input.jsx
|
||
var ddInputCss = `
|
||
.dd-input {
|
||
display: block; width: 100%; box-sizing: border-box;
|
||
height: var(--control-md); padding: 0 12px;
|
||
font-family: var(--font-sans); font-size: var(--text-base); color: var(--text-1);
|
||
background: var(--surface-card); border: 1px solid var(--border-2);
|
||
border-radius: var(--radius-sm);
|
||
transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
|
||
}
|
||
.dd-input::placeholder { color: var(--text-3); }
|
||
.dd-input:hover { border-color: var(--gray-400); }
|
||
.dd-input:focus { outline: none; border-color: var(--accent); box-shadow: var(--focus-ring); }
|
||
.dd-input[disabled] { opacity: 0.45; pointer-events: none; }
|
||
.dd-input--lg { height: var(--control-lg); font-size: var(--text-md); border-radius: var(--radius-sm); }
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-input-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-input-css";
|
||
s.textContent = ddInputCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Input({ size = "md", style, ...rest }) {
|
||
return /* @__PURE__ */ React.createElement("input", { className: `dd-input${size === "lg" ? " dd-input--lg" : ""}`, style, ...rest });
|
||
}
|
||
|
||
// react-shim:react
|
||
var R = globalThis.React;
|
||
var useState = R.useState;
|
||
var useEffect = R.useEffect;
|
||
var useRef = R.useRef;
|
||
var useMemo = R.useMemo;
|
||
var useCallback = R.useCallback;
|
||
var useContext = R.useContext;
|
||
var createElement = R.createElement;
|
||
var Fragment = R.Fragment;
|
||
|
||
// design/components/forms/Select.jsx
|
||
var ddSelectCss = `
|
||
.dd-select { position: relative; display: inline-block; font-family: var(--font-sans); }
|
||
.dd-select__trigger {
|
||
display: inline-flex; align-items: center; gap: 6px;
|
||
height: var(--control-sm); padding: 0 26px 0 10px;
|
||
border-radius: var(--radius-sm); border: 1px solid var(--border-1);
|
||
background: var(--surface-card); color: var(--text-1);
|
||
font-size: var(--text-sm); font-family: inherit; cursor: pointer;
|
||
transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
|
||
white-space: nowrap;
|
||
}
|
||
.dd-select__trigger:hover { background: var(--surface-2); }
|
||
.dd-select__trigger:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
||
.dd-select__chev {
|
||
position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
|
||
pointer-events: none; color: var(--text-3); display: inline-flex;
|
||
}
|
||
.dd-select__menu {
|
||
position: absolute; top: calc(100% + 4px); right: 0; z-index: 60;
|
||
min-width: 100%; max-width: 300px; padding: 4px; margin: 0;
|
||
background: var(--surface-card); border: 1px solid var(--border-1);
|
||
border-radius: var(--radius-md); box-shadow: var(--shadow-menu);
|
||
list-style: none;
|
||
}
|
||
.dd-select__opt {
|
||
display: flex; align-items: center; gap: 7px; width: 100%;
|
||
height: 28px; padding: 0 10px 0 8px; border: none; border-radius: var(--radius-sm);
|
||
background: transparent; color: var(--text-1);
|
||
font-size: var(--text-sm); font-family: inherit; cursor: pointer;
|
||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: left;
|
||
}
|
||
.dd-select__opt:hover { background: var(--surface-2); }
|
||
.dd-select__opt .dd-select__tick { width: 14px; flex: none; display: inline-flex; color: var(--accent-text); visibility: hidden; }
|
||
.dd-select__opt[aria-selected="true"] .dd-select__tick { visibility: visible; }
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-select-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-select-css";
|
||
s.textContent = ddSelectCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Select({ value, onChange, options = [], placeholder = "\u8BF7\u9009\u62E9", ...rest }) {
|
||
const [open, setOpen] = useState(false);
|
||
const rootRef = useRef(null);
|
||
const items = options.map((o) => typeof o === "string" ? { value: o, label: o } : o);
|
||
const current = items.find((o) => o.value === value);
|
||
useEffect(() => {
|
||
if (!open) return;
|
||
const onDown = (e) => {
|
||
if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
|
||
};
|
||
const onKey = (e) => {
|
||
if (e.key === "Escape") setOpen(false);
|
||
};
|
||
document.addEventListener("mousedown", onDown);
|
||
document.addEventListener("keydown", onKey);
|
||
return () => {
|
||
document.removeEventListener("mousedown", onDown);
|
||
document.removeEventListener("keydown", onKey);
|
||
};
|
||
}, [open]);
|
||
return /* @__PURE__ */ React.createElement("span", { className: "dd-select", ref: rootRef, ...rest }, /* @__PURE__ */ React.createElement(
|
||
"button",
|
||
{
|
||
type: "button",
|
||
className: "dd-select__trigger",
|
||
"aria-haspopup": "listbox",
|
||
"aria-expanded": open,
|
||
onClick: () => setOpen((v) => !v)
|
||
},
|
||
current ? current.label : placeholder
|
||
), /* @__PURE__ */ React.createElement("span", { className: "dd-select__chev" }, /* @__PURE__ */ React.createElement(Icon, { name: "chevronDown", size: 13 })), open && /* @__PURE__ */ React.createElement("ul", { className: "dd-select__menu", role: "listbox" }, items.map((o) => /* @__PURE__ */ React.createElement("li", { key: o.value }, /* @__PURE__ */ React.createElement(
|
||
"button",
|
||
{
|
||
type: "button",
|
||
className: "dd-select__opt",
|
||
role: "option",
|
||
"aria-selected": o.value === value,
|
||
onClick: () => {
|
||
onChange?.(o.value);
|
||
setOpen(false);
|
||
}
|
||
},
|
||
/* @__PURE__ */ React.createElement("span", { className: "dd-select__tick" }, /* @__PURE__ */ React.createElement(Icon, { name: "check", size: 12, sw: 2.5 })),
|
||
o.label
|
||
)))));
|
||
}
|
||
|
||
// design/components/forms/SettingRow.jsx
|
||
var ddSettingRowCss = `
|
||
.dd-setrow {
|
||
display: flex; align-items: center; justify-content: space-between; gap: 16px;
|
||
padding: 12px 0; border-bottom: 1px solid var(--border-1);
|
||
font-family: var(--font-sans); font-size: var(--text-base);
|
||
}
|
||
.dd-setrow:last-child { border-bottom: none; }
|
||
.dd-setrow__label { color: var(--text-1); }
|
||
.dd-setrow__desc { font-size: var(--text-xs); color: var(--text-3); margin-top: 2px; }
|
||
.dd-setrow__control { display: flex; align-items: center; gap: 8px; color: var(--text-2); font-size: var(--text-sm); }
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-setrow-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-setrow-css";
|
||
s.textContent = ddSettingRowCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function SettingRow({ label, description, children, ...rest }) {
|
||
return /* @__PURE__ */ React.createElement("div", { className: "dd-setrow", ...rest }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "dd-setrow__label" }, label), description ? /* @__PURE__ */ React.createElement("div", { className: "dd-setrow__desc" }, description) : null), /* @__PURE__ */ React.createElement("div", { className: "dd-setrow__control" }, children));
|
||
}
|
||
|
||
// design/components/forms/Switch.jsx
|
||
var ddSwitchCss = `
|
||
.dd-switch {
|
||
position: relative; display: inline-block; width: 40px; height: 24px;
|
||
border-radius: var(--radius-full); background: var(--surface-3);
|
||
border: none; cursor: pointer; padding: 0; flex: none;
|
||
transition: background var(--dur-base) var(--ease-out);
|
||
}
|
||
.dd-switch::after {
|
||
content: ''; position: absolute; top: 3px; left: 3px;
|
||
width: 18px; height: 18px; border-radius: 50%;
|
||
background: #fff; box-shadow: 0 1px 3px rgba(17,19,26,0.25); /* ds-ignore: \u62C7\u6307\u6295\u5F71\uFF0Cgray-950 \u7684 25% \u6D3E\u751F */
|
||
transition: transform var(--dur-base) var(--ease-out);
|
||
}
|
||
.dd-switch[aria-checked="true"] { background: var(--accent); }
|
||
.dd-switch[aria-checked="true"]::after { transform: translateX(16px); }
|
||
.dd-switch:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
||
.dd-switch[disabled] { opacity: 0.45; pointer-events: none; }
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-switch-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-switch-css";
|
||
s.textContent = ddSwitchCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function Switch({ checked = false, onChange, disabled = false, ...rest }) {
|
||
return /* @__PURE__ */ React.createElement(
|
||
"button",
|
||
{
|
||
type: "button",
|
||
role: "switch",
|
||
className: "dd-switch",
|
||
"aria-checked": checked ? "true" : "false",
|
||
disabled,
|
||
onClick: () => onChange && onChange(!checked),
|
||
...rest
|
||
}
|
||
);
|
||
}
|
||
|
||
// design/components/voice/Waveform.jsx
|
||
var ddWaveCss = `
|
||
.dd-wave { display: inline-flex; align-items: center; gap: 3px; }
|
||
.dd-wave i { display: block; width: 3px; border-radius: 2px; background: currentColor; }
|
||
.dd-wave--active i { animation: dd-wave-bounce 0.9s var(--ease-in-out) infinite alternate; }
|
||
@keyframes dd-wave-bounce {
|
||
from { transform: scaleY(0.35); }
|
||
to { transform: scaleY(1); }
|
||
}
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.dd-wave--active i { animation: none; }
|
||
}
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-wave-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-wave-css";
|
||
s.textContent = ddWaveCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
var DD_WAVE_PATTERN = [0.3, 0.55, 0.85, 0.45, 0.7, 1, 0.4, 0.6, 0.25, 0.8, 0.5, 0.35];
|
||
function Waveform({ bars = 12, active = false, height = 26, color = "var(--accent)", style }) {
|
||
const items = [];
|
||
for (let i = 0; i < bars; i++) {
|
||
const h = Math.round(DD_WAVE_PATTERN[i % DD_WAVE_PATTERN.length] * height);
|
||
items.push(/* @__PURE__ */ React.createElement("i", { key: i, style: { height: Math.max(4, h), animationDelay: `${i % 6 * 0.07}s` } }));
|
||
}
|
||
return /* @__PURE__ */ React.createElement(
|
||
"span",
|
||
{
|
||
className: `dd-wave${active ? " dd-wave--active" : ""}`,
|
||
style: { height, color, ...style },
|
||
"aria-hidden": "true"
|
||
},
|
||
items
|
||
);
|
||
}
|
||
|
||
// design/components/voice/MicBar.jsx
|
||
var ddMicBarCss = `
|
||
.dd-micbar {
|
||
display: flex; align-items: center; justify-content: center; gap: 8px;
|
||
width: 100%; height: var(--control-xl); border: none; cursor: pointer;
|
||
border-radius: var(--radius-full);
|
||
font-family: var(--font-sans); font-size: var(--text-md); font-weight: var(--weight-semibold);
|
||
user-select: none; -webkit-user-select: none; touch-action: none;
|
||
transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
|
||
}
|
||
.dd-micbar--idle { background: var(--accent); color: var(--text-on-accent); }
|
||
.dd-micbar--idle:active { background: var(--accent-press); }
|
||
.dd-micbar--recording { background: var(--positive); color: #fff; }
|
||
.dd-micbar--disabled { background: var(--surface-3); color: var(--text-3); cursor: default; }
|
||
.dd-micbar--quota { background: var(--warning); color: #fff; }
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-micbar-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-micbar-css";
|
||
s.textContent = ddMicBarCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function DdMicIcon({ size = 20 }) {
|
||
return /* @__PURE__ */ React.createElement(Icon, { name: "mic", size });
|
||
}
|
||
var DD_MICBAR_LABELS = {
|
||
idle: "\u6309\u4F4F\u8BF4\u8BDD",
|
||
recording: "\u677E\u5F00\u5B8C\u6210 \xB7 \u4E0A\u6ED1\u53D6\u6D88",
|
||
disabled: "\u6253\u5F00 dudu App \u767B\u5F55",
|
||
quota: "\u4ECA\u65E5\u8BD5\u7528\u5DF2\u7528\u5B8C\uFF0C\u53BB\u8D2D\u4E70\u65F6\u957F"
|
||
};
|
||
function MicBar({ state = "idle", label, ...rest }) {
|
||
const text = label || DD_MICBAR_LABELS[state] || DD_MICBAR_LABELS.idle;
|
||
return /* @__PURE__ */ React.createElement("button", { type: "button", className: `dd-micbar dd-micbar--${state}`, ...rest }, state === "recording" ? /* @__PURE__ */ React.createElement(Waveform, { active: true, bars: 9, height: 18, color: "rgba(255,255,255,0.95)" }) : /* @__PURE__ */ React.createElement(DdMicIcon, null), /* @__PURE__ */ React.createElement("span", null, text));
|
||
}
|
||
|
||
// design/components/voice/RecognitionOverlay.jsx
|
||
var ddOverlayCss = `
|
||
.dd-overlay {
|
||
box-sizing: border-box; width: 340px;
|
||
background: var(--overlay-bg); color: var(--overlay-text);
|
||
border-radius: var(--radius-lg); padding: 14px 18px;
|
||
box-shadow: var(--shadow-overlay);
|
||
font-family: var(--font-sans);
|
||
backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
|
||
}
|
||
.dd-overlay__status {
|
||
display: flex; align-items: center; gap: 8px;
|
||
color: var(--overlay-text-2); font-size: var(--text-base); margin-top: 8px;
|
||
}
|
||
.dd-overlay__text { font-size: var(--text-md); line-height: 1.6; margin-top: 8px; min-height: 24px; }
|
||
.dd-overlay__text .dd-partial { color: var(--overlay-text-2); }
|
||
.dd-overlay__hint { font-size: 11px; color: var(--overlay-text-3); margin-top: 8px; text-align: right; }
|
||
`;
|
||
if (typeof document !== "undefined" && !document.getElementById("dd-overlay-css")) {
|
||
const s = document.createElement("style");
|
||
s.id = "dd-overlay-css";
|
||
s.textContent = ddOverlayCss;
|
||
document.head.appendChild(s);
|
||
}
|
||
function RecognitionOverlay({
|
||
state = "listening",
|
||
finalText = "",
|
||
partialText = "",
|
||
hint = "\u677E\u5F00 \u2318\u21E7Space \u5B8C\u6210\u8F93\u5165",
|
||
width = 340,
|
||
style
|
||
}) {
|
||
return /* @__PURE__ */ React.createElement("div", { className: "dd-overlay", style: { width, ...style }, role: "status" }, /* @__PURE__ */ React.createElement(Waveform, { active: true, bars: 12, height: 24, color: "var(--overlay-wave)" }), state === "listening" ? /* @__PURE__ */ React.createElement("div", { className: "dd-overlay__status" }, /* @__PURE__ */ React.createElement(Icon, { name: "mic", size: 16 }), /* @__PURE__ */ React.createElement("span", null, "\u8046\u542C\u4E2D\u2026")) : /* @__PURE__ */ React.createElement("div", { className: "dd-overlay__text" }, finalText, partialText ? /* @__PURE__ */ React.createElement("span", { className: "dd-partial" }, partialText) : null), /* @__PURE__ */ React.createElement("div", { className: "dd-overlay__hint" }, hint));
|
||
}
|
||
|
||
// design/_ds_entry.js
|
||
var ns = globalThis.DuduDesignSystem_2e0172 = globalThis.DuduDesignSystem_2e0172 || {};
|
||
Object.assign(ns, { Badge, Button, Card, Icon, IconButton, Kbd, HotkeyCombo, ProgressBar, Input, Select, SettingRow, Switch, MicBar, RecognitionOverlay, Waveform });
|
||
})();
|