/* 自动生成 — 请勿手改。来源 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: '',
/** 对勾(完成/选中) */
check: '',
/** 关闭 */
x: '',
/** 添加图片(反馈附图) */
imagePlus: '',
/** 钥匙(权限引导) */
key: '',
/** 下拉箭头(Select 等展开指示) */
chevronDown: ''
};
// 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 });
})();