dsh-better-ask-user 0.1.5 → 0.1.6
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/lib/client.js +275 -147
- package/package.json +1 -1
- package/src/client/AskHistoryRow.module.css +47 -0
- package/src/client/AskHistoryRow.tsx +134 -0
- package/src/client/index.ts +10 -0
- package/src/client/locales.ts +6 -0
package/lib/client.js
CHANGED
|
@@ -483,6 +483,119 @@ function createQuestionDraftStore() {
|
|
|
483
483
|
});
|
|
484
484
|
}
|
|
485
485
|
|
|
486
|
+
// src/client/AskHistoryRow.tsx
|
|
487
|
+
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
488
|
+
|
|
489
|
+
// src/client/AskHistoryRow.module.css
|
|
490
|
+
var css = ".bau-row {\n display: flex;\n align-items: center;\n gap: 8px;\n min-height: 24px;\n min-width: 0;\n color: var(--dsw-alias-label-secondary);\n}\n.bau-icon {\n display: inline-flex;\n align-items: center;\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n}\n.bau-title {\n flex: none;\n font: var(--dsw-font-xs-strong-13);\n color: var(--dsw-alias-label-secondary);\n}\n.bau-summary {\n min-width: 0;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font: var(--dsw-font-xs-13);\n color: var(--dsw-alias-label-tertiary);\n}\n.bau-open {\n flex: none;\n cursor: pointer;\n border: .5px solid var(--dsw-alias-border-l4);\n border-radius: 999px;\n background: var(--dsw-alias-bg-base);\n color: var(--dsw-alias-label-secondary);\n padding: 1px 8px;\n font: var(--dsw-font-xxs-12);\n line-height: 16px;\n}\n.bau-open:hover {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-primary);\n}\n.bau-open:focus-visible {\n outline: var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));\n outline-offset: 1px;\n}";
|
|
491
|
+
var id = "dsh-better-ask-user/AskHistoryRow.module.css";
|
|
492
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]") === null) {
|
|
493
|
+
const tag = document.createElement("style");
|
|
494
|
+
tag.dataset.plugin = "dsh-better-ask-user";
|
|
495
|
+
tag.dataset.pluginCss = id;
|
|
496
|
+
tag.textContent = css;
|
|
497
|
+
document.head.appendChild(tag);
|
|
498
|
+
}
|
|
499
|
+
var AskHistoryRow_default = { "row": "bau-row", "icon": "bau-icon", "title": "bau-title", "summary": "bau-summary", "open": "bau-open" };
|
|
500
|
+
|
|
501
|
+
// src/client/AskHistoryRow.tsx
|
|
502
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
503
|
+
function isRecord(value) {
|
|
504
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
505
|
+
}
|
|
506
|
+
function parseJson(text) {
|
|
507
|
+
try {
|
|
508
|
+
return JSON.parse(text);
|
|
509
|
+
} catch {
|
|
510
|
+
return void 0;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
function resultText(content) {
|
|
514
|
+
const parts = [];
|
|
515
|
+
for (const block of content) {
|
|
516
|
+
if (!isRecord(block) || block.type !== "text" || typeof block.text !== "string") continue;
|
|
517
|
+
parts.push(block.text);
|
|
518
|
+
}
|
|
519
|
+
return parts.length === 0 ? void 0 : parts.join("\n");
|
|
520
|
+
}
|
|
521
|
+
function questionList(argsRaw) {
|
|
522
|
+
const parsed = parseJson(argsRaw);
|
|
523
|
+
if (!isRecord(parsed) || !Array.isArray(parsed.questions) || parsed.questions.length === 0) return void 0;
|
|
524
|
+
const questions = [];
|
|
525
|
+
for (const candidate of parsed.questions) {
|
|
526
|
+
if (!isRecord(candidate) || typeof candidate.id !== "string" || typeof candidate.question !== "string") return void 0;
|
|
527
|
+
questions.push({
|
|
528
|
+
id: candidate.id,
|
|
529
|
+
question: candidate.question,
|
|
530
|
+
...typeof candidate.header === "string" ? { header: candidate.header } : {},
|
|
531
|
+
...Array.isArray(candidate.options) ? {
|
|
532
|
+
options: candidate.options.flatMap((option) => isRecord(option) && typeof option.label === "string" ? [{
|
|
533
|
+
label: option.label,
|
|
534
|
+
...typeof option.description === "string" ? { description: option.description } : {}
|
|
535
|
+
}] : [])
|
|
536
|
+
} : {},
|
|
537
|
+
...typeof candidate.multi_select === "boolean" ? { multi_select: candidate.multi_select } : {}
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
return questions;
|
|
541
|
+
}
|
|
542
|
+
function answerList(text) {
|
|
543
|
+
if (text === void 0) return void 0;
|
|
544
|
+
const parsed = parseJson(text);
|
|
545
|
+
if (!isRecord(parsed) || !Array.isArray(parsed.answers)) return void 0;
|
|
546
|
+
const answers = [];
|
|
547
|
+
for (const candidate of parsed.answers) {
|
|
548
|
+
if (!isRecord(candidate) || typeof candidate.id !== "string" || !Array.isArray(candidate.selected) || !candidate.selected.every((value) => typeof value === "string") || candidate.custom !== void 0 && typeof candidate.custom !== "string") return void 0;
|
|
549
|
+
answers.push({
|
|
550
|
+
id: candidate.id,
|
|
551
|
+
selected: candidate.selected,
|
|
552
|
+
...candidate.custom === void 0 ? {} : { custom: candidate.custom }
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
return answers;
|
|
556
|
+
}
|
|
557
|
+
function isPending(text) {
|
|
558
|
+
if (text === void 0) return false;
|
|
559
|
+
const parsed = parseJson(text);
|
|
560
|
+
return isRecord(parsed) && parsed.pending === true;
|
|
561
|
+
}
|
|
562
|
+
function AskHistoryRow({
|
|
563
|
+
callId,
|
|
564
|
+
block,
|
|
565
|
+
phase,
|
|
566
|
+
revealPanel,
|
|
567
|
+
reviewPanel,
|
|
568
|
+
t
|
|
569
|
+
}) {
|
|
570
|
+
const argsRaw = "kind" in block ? block.call?.argsRaw ?? "" : block.argsRaw;
|
|
571
|
+
const output = "kind" in block ? resultText(block.content) : void 0;
|
|
572
|
+
const questions = questionList(argsRaw);
|
|
573
|
+
const answers = answerList(output);
|
|
574
|
+
const record = questions !== void 0 && answers !== void 0 ? { questions, answers } : void 0;
|
|
575
|
+
const summary = questions?.[0]?.question.split("\n").find((line) => line.trim() !== "")?.trim() ?? t("history.title");
|
|
576
|
+
const review = record !== void 0;
|
|
577
|
+
const action = review ? () => {
|
|
578
|
+
reviewPanel(callId, record);
|
|
579
|
+
} : isPending(output) || phase === "start" ? () => {
|
|
580
|
+
revealPanel(callId);
|
|
581
|
+
} : void 0;
|
|
582
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: AskHistoryRow_default.row, children: [
|
|
583
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: AskHistoryRow_default.icon, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconQuestionOutline14, {}) }),
|
|
584
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: AskHistoryRow_default.title, children: t("history.title") }),
|
|
585
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: AskHistoryRow_default.summary, title: summary, children: summary }),
|
|
586
|
+
action !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
587
|
+
"button",
|
|
588
|
+
{
|
|
589
|
+
type: "button",
|
|
590
|
+
className: AskHistoryRow_default.open,
|
|
591
|
+
onClick: action,
|
|
592
|
+
"aria-label": review ? t("history.review") : t("history.reopen"),
|
|
593
|
+
children: review ? t("history.review") : t("history.reopen")
|
|
594
|
+
}
|
|
595
|
+
)
|
|
596
|
+
] });
|
|
597
|
+
}
|
|
598
|
+
|
|
486
599
|
// src/client/QuestionComposer.tsx
|
|
487
600
|
var import_react2 = require("react");
|
|
488
601
|
|
|
@@ -503,26 +616,26 @@ function clsx() {
|
|
|
503
616
|
var clsx_default = clsx;
|
|
504
617
|
|
|
505
618
|
// src/client/QuestionComposer.tsx
|
|
506
|
-
var
|
|
619
|
+
var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
507
620
|
|
|
508
621
|
// src/client/PlanReviewPanel.tsx
|
|
509
622
|
var import_react = require("react");
|
|
510
|
-
var
|
|
623
|
+
var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
511
624
|
|
|
512
625
|
// src/client/PlanReviewPanel.module.css
|
|
513
|
-
var
|
|
514
|
-
var
|
|
515
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(
|
|
626
|
+
var css2 = ".bau-frame {\n display: flex;\n justify-content: center;\n /* Sides = clearance + 16px: the card lands on the shared content width\n (input card - 32) at every viewport. */\n padding: 6px calc(var(--dsh-composer-side-clearance) + 16px) 10px;\n}\n\n.bau-card {\n display: flex;\n overflow: hidden;\n flex-direction: column;\n width: 100%;\n max-width: var(--dsh-chat-content-width);\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l2);\n border: 0;\n border-radius: var(--dsw-radius-xl);\n background: var(--dsw-specific-input-major);\n box-shadow: var(--dsw-elevation-panel);\n color: var(--dsw-alias-label-primary);\n}\n\n.bau-card,\n.bau-card * {\n box-sizing: border-box;\n}\n\n/* Tinted full-width header band, as on the approval takeover. */\n.bau-strip {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n gap: 8px;\n padding: 12px 16px;\n background: var(--dsw-alias-state-warn-tertiary);\n color: var(--dsw-alias-state-warn-primary);\n font-size: 14px;\n line-height: 20px;\n}\n\n.bau-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n gap: 12px;\n padding: 8px 16px 12px;\n}\n\n.bau-feedback {\n min-height: 16px;\n color: var(--dsw-alias-state-error-primary);\n font-size: 11px;\n line-height: 16px;\n}\n\n.bau-actions {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n gap: 8px;\n}\n\n.bau-summary {\n min-width: 0;\n padding: 14px 16px 12px;\n}\n\n.bau-title {\n margin: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.bau-description {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow: hidden;\n margin: 8px 0 0;\n color: var(--dsw-alias-label-secondary);\n font-size: 14px;\n line-height: 24px;\n}\n\n.bau-discuss {\n gap: 6px;\n}\n\n@media (max-width: 720px) {\n .bau-card {\n border-radius: var(--dsw-radius-xl);\n }\n\n .bau-footer {\n align-items: flex-end;\n padding: 8px 12px 10px;\n }\n}\n\n.bau-previewActions {\n margin-left: auto;\n display: flex;\n align-items: center;\n}\n\n/* Better ask-user: long plan text and narrow screens. */\n.bau-title,\n.bau-description,\n.bau-summary,\n.bau-strip {\n min-width: 0;\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n\n.bau-title {\n max-height: 30vh;\n overflow-y: auto;\n}\n\n@media (max-width: 720px) {\n .bau-card {\n max-height: calc(100vh - 160px);\n max-height: calc(100dvh - 160px);\n }\n\n .bau-title {\n max-height: 24vh;\n max-height: 24dvh;\n }\n\n .bau-footer {\n flex-wrap: wrap;\n }\n\n .bau-actions {\n flex-wrap: wrap;\n }\n}\n";
|
|
627
|
+
var id2 = "dsh-better-ask-user/PlanReviewPanel.module.css";
|
|
628
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]") === null) {
|
|
516
629
|
const tag = document.createElement("style");
|
|
517
630
|
tag.dataset.plugin = "dsh-better-ask-user";
|
|
518
|
-
tag.dataset.pluginCss =
|
|
519
|
-
tag.textContent =
|
|
631
|
+
tag.dataset.pluginCss = id2;
|
|
632
|
+
tag.textContent = css2;
|
|
520
633
|
document.head.appendChild(tag);
|
|
521
634
|
}
|
|
522
635
|
var PlanReviewPanel_default = { "frame": "bau-frame", "card": "bau-card", "strip": "bau-strip", "footer": "bau-footer", "feedback": "bau-feedback", "actions": "bau-actions", "summary": "bau-summary", "title": "bau-title", "description": "bau-description", "discuss": "bau-discuss", "previewActions": "bau-previewActions" };
|
|
523
636
|
|
|
524
637
|
// src/client/PlanReviewPanel.tsx
|
|
525
|
-
var
|
|
638
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
526
639
|
function tooltip(description) {
|
|
527
640
|
return description === void 0 ? {} : { title: description };
|
|
528
641
|
}
|
|
@@ -547,29 +660,29 @@ function PlanReviewPanel({ pending, review, t, renderSlot }) {
|
|
|
547
660
|
settle(() => pending.answer({ answers: [{ id: review.id, selected: [label] }] }), pending.snapshot().channel === "rpc");
|
|
548
661
|
};
|
|
549
662
|
const summary = (0, import_react.useMemo)(() => {
|
|
550
|
-
const title = (0,
|
|
551
|
-
const description = (0,
|
|
663
|
+
const title = (0, import_dsh_client_ui_primitives2.extractMarkdownPlainText)(review.plan, { mode: "first-line" });
|
|
664
|
+
const description = (0, import_dsh_client_ui_primitives2.extractMarkdownPlainText)(review.plan, { mode: "first-paragraph" });
|
|
552
665
|
return { title, description: description === title ? "" : description };
|
|
553
666
|
}, [review.plan]);
|
|
554
|
-
return /* @__PURE__ */ (0,
|
|
555
|
-
/* @__PURE__ */ (0,
|
|
556
|
-
/* @__PURE__ */ (0,
|
|
667
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: PlanReviewPanel_default.frame, "data-plan-review-key": pending.key, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: PlanReviewPanel_default.card, "aria-label": review.question, "aria-busy": busy, children: [
|
|
668
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: PlanReviewPanel_default.strip, children: [
|
|
669
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.StateDot, { state: busy ? "ongoing" : "warning" }),
|
|
557
670
|
t("plan.header"),
|
|
558
|
-
/* @__PURE__ */ (0,
|
|
671
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: PlanReviewPanel_default.previewActions, children: renderSlot("conversation.plan-review.actions", { review, requestKey: pending.key }) })
|
|
559
672
|
] }),
|
|
560
|
-
/* @__PURE__ */ (0,
|
|
561
|
-
/* @__PURE__ */ (0,
|
|
562
|
-
summary.description !== "" && /* @__PURE__ */ (0,
|
|
673
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: PlanReviewPanel_default.summary, children: [
|
|
674
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: PlanReviewPanel_default.title, children: summary.title }),
|
|
675
|
+
summary.description !== "" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: PlanReviewPanel_default.description, children: summary.description })
|
|
563
676
|
] }),
|
|
564
|
-
/* @__PURE__ */ (0,
|
|
565
|
-
/* @__PURE__ */ (0,
|
|
566
|
-
/* @__PURE__ */ (0,
|
|
567
|
-
/* @__PURE__ */ (0,
|
|
568
|
-
|
|
677
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: PlanReviewPanel_default.footer, children: [
|
|
678
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: PlanReviewPanel_default.feedback, role: "status", children: error }),
|
|
679
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: PlanReviewPanel_default.actions, children: [
|
|
680
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
681
|
+
import_dsh_client_ui_primitives2.Button,
|
|
569
682
|
{
|
|
570
683
|
variant: "outline",
|
|
571
684
|
className: PlanReviewPanel_default.discuss,
|
|
572
|
-
icon: /* @__PURE__ */ (0,
|
|
685
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.IconEditOutlineRegular, { size: 14 }),
|
|
573
686
|
disabled: busy,
|
|
574
687
|
onClick: () => {
|
|
575
688
|
settle(() => pending.dismiss());
|
|
@@ -577,8 +690,8 @@ function PlanReviewPanel({ pending, review, t, renderSlot }) {
|
|
|
577
690
|
children: t("plan.discuss")
|
|
578
691
|
}
|
|
579
692
|
),
|
|
580
|
-
/* @__PURE__ */ (0,
|
|
581
|
-
|
|
693
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
694
|
+
import_dsh_client_ui_primitives2.Button,
|
|
582
695
|
{
|
|
583
696
|
variant: "primary",
|
|
584
697
|
...tooltip(review.approve.description),
|
|
@@ -595,19 +708,19 @@ function PlanReviewPanel({ pending, review, t, renderSlot }) {
|
|
|
595
708
|
}
|
|
596
709
|
|
|
597
710
|
// src/client/QuestionComposer.module.css
|
|
598
|
-
var css2 = "/* The takeover seats where the input card sits, centered on the InputBar\n axis at the shared content width (input card - 32): sides = clearance +\n 16px so the relation also holds on narrow viewports. */\n.bau-frame {\n display: flex;\n justify-content: center;\n padding: 6px calc(var(--dsh-composer-side-clearance) + 16px) 10px;\n}\n\n/* Figma Input 973:36348 body over the 1019:36938 header: no banner strip \u2014\n the card keeps zero padding and sections carry their own insets. */\n.bau-card {\n display: flex;\n flex-direction: column;\n width: 100%;\n max-width: var(--dsh-chat-content-width);\n /* Composer seat sits in a fixed-height conversation column (overflow\n hidden): cap the card against the viewport and scroll the option list\n so header and footer actions stay reachable on long batches. */\n max-height: min(60vh, 520px);\n padding: 0 0 10px;\n border: 0;\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l2-darkmode-thin);\n border-radius: var(--dsw-radius-xl);\n background: var(--dsw-specific-input-major);\n box-shadow: var(--dsw-elevation-panel);\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n /* Elevated surface in dark, same as the menus: the body inside scrolls\n once the card hits the cap above, so the thumb takes the l2 pair. Declared\n on the card because the elevation belongs to the surface, and the custom\n properties inherit down to `.bau-body` (see ui-theme styles/scrollbar.bau-css\n for the rebinding contract). */\n --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);\n --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);\n}\n\n.bau-card,\n.bau-card * {\n box-sizing: border-box;\n}\n\n/* Collapsed to the header strip: drop the height cap and the inner scroll\n seat so the card hugs the title row, freeing the viewport for the\n conversation above while the question stays pending. */\n.bau-cardMinimized {\n max-height: none;\n}\n\n/* The header strip is the whole card when collapsed: the title row needs\n bottom padding once the body that normally carries it is hidden. */\n.bau-cardMinimized .bau-header {\n padding-bottom: 14px;\n}\n\n/* Header button group: minimize sits next to the close action, both on the\n same 24px icon-button grid. */\n.bau-headerActions {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.bau-waitButton {\n white-space: nowrap;\n}\n\n.bau-waitStatus {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 24px;\n white-space: nowrap;\n}\n\n/* Figma 1019:36938 header, user-tuned: heading block left, close right; the\n pager sits in the footer to balance the card. */\n.bau-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n flex-shrink: 0;\n padding: 20px 16px 0 24px;\n}\n\n.bau-headingBlock {\n min-width: 0;\n}\n\n.bau-eyebrow {\n /* Eyebrow-to-title gap widened from the figma 2px (user-tuned). */\n margin-bottom: 5px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 16px;\n}\n\n.bau-title {\n margin: 0;\n font-size: 16px;\n line-height: 22px;\n font-weight: 500;\n}\n\n.bau-detail {\n margin: 0 2px 8px;\n}\n\n.bau-footerActions {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n}\n\n.bau-pager {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.bau-progress {\n padding: 0 4px;\n color: var(--dsw-alias-label-secondary);\n font-size: 14px;\n line-height: 24px;\n font-weight: 500;\n white-space: nowrap;\n /* Narrow the plain spaces around the slash without touching glyph tracking. */\n word-spacing: -2px;\n}\n\n.bau-iconButton {\n display: grid;\n place-items: center;\n width: 24px;\n height: 24px;\n padding: 0;\n border: none;\n border-radius: 999px;\n corner-shape: round;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n\n.bau-iconButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.bau-iconButton:disabled {\n color: var(--dsw-alias-label-dimmed);\n cursor: default;\n}\n\n.bau-body {\n display: flex;\n flex: 1 1 auto;\n flex-direction: column;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n.bau-options {\n display: flex;\n flex-direction: column;\n gap: 1px;\n margin: 8px 0 0;\n padding: 4px 12px;\n}\n\n.bau-option {\n display: flex;\n /* flex-start, not center: with a wrapped description the indicator must\n stay on the FIRST line (centering drifts it down the taller copy block).\n The 8px padding makes a single-line row 40px exactly, so nothing reads\n as top-heavy; .bau-number/.bau-checkbox re-center against the first line box. */\n align-items: flex-start;\n gap: 8px;\n width: 100%;\n min-height: 40px;\n /* Rows are the scroll content, never the slack absorber: a shrinkable row\n collapses to min-height while its wrapped copy keeps the taller\n intrinsic height, and centered content then paints outside the row box \u2014\n over the title and the next row. Overflow belongs to .bau-options. */\n flex-shrink: 0;\n padding: 8px 12px 8px 8px;\n border: 1px solid transparent;\n border-radius: var(--dsw-radius-md);\n background: transparent;\n color: inherit;\n text-align: left;\n cursor: pointer;\n transition: background-color 120ms ease, border-color 120ms ease;\n}\n\n.bau-option:hover:not(:disabled),\n.bau-optionSelected {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.bau-optionSelected {\n border-color: var(--dsw-alias-border-l2);\n}\n\n.bau-option:disabled {\n cursor: default;\n}\n\n/* Leading indicator (20\xD720): single-select shows the option\n number, multi-select swaps in a checkbox; the custom-answer row follows \u2014\n its checkbox mirrors the typed draft (styling only, exclusivity holds). */\n.bau-number {\n display: grid;\n place-items: center;\n flex: 0 0 20px;\n width: 20px;\n height: 20px;\n /* (24px first-line box \u2212 20px indicator) / 2: centers the indicator against\n the first text line under the row's flex-start alignment. */\n margin-top: 2px;\n border-radius: var(--dsw-radius-xs);\n background: var(--dsw-alias-bg-overlay);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n}\n\n/* Multi-select box (figma 1055:41594, user-tuned down to 14\xD714): a radius-4\n box centered in the 20px indicator seat; the box itself is the ::before\n layer so the check icon stacks over it in the same grid cell. */\n.bau-checkbox {\n display: grid;\n place-items: center;\n flex: 0 0 20px;\n width: 20px;\n height: 20px;\n /* Same first-line centering as .bau-number under flex-start alignment. */\n margin-top: 2px;\n}\n\n.bau-checkbox::before {\n content: '';\n grid-area: 1 / 1;\n width: 14px;\n height: 14px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-xs);\n transition: background-color 120ms ease, border-color 120ms ease;\n}\n\n.bau-checkbox > svg {\n grid-area: 1 / 1;\n}\n\n/* Checked: label-primary fill with a primary-foreground check \u2014 the pair\n inverts with the theme (dark fill in light mode, light fill in dark mode). */\n.bau-checkboxChecked {\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.bau-checkboxChecked::before {\n border-color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-label-primary);\n}\n\n.bau-optionCopy {\n min-width: 0;\n flex: 1;\n}\n\n.bau-optionLine {\n display: flex;\n align-items: baseline;\n flex-wrap: wrap;\n gap: 2px 6px;\n}\n\n.bau-optionLabel {\n font-size: 14px;\n line-height: 24px;\n font-weight: 500;\n}\n\n.bau-badge {\n padding: 0 4px;\n border-radius: var(--dsw-radius-xs);\n background: var(--dsw-specific-sidebar-nav-item-active-accent);\n color: var(--dsw-alias-button-info-fill);\n font-size: 11px;\n line-height: 18px;\n font-weight: 600;\n}\n\n.bau-description {\n color: var(--dsw-alias-label-tertiary);\n font-size: 14px;\n line-height: 24px;\n font-weight: 400;\n}\n\n/* Read-only note standing in for a question the user skipped: it takes the\n option rows' horizontal padding so it lines up with the choices above it. */\n.bau-reviewNote {\n margin: 0;\n padding: 8px 12px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 14px;\n line-height: 24px;\n}\n\n/* Custom answer row (figma 973:36427): an option-shaped row whose copy is an\n inline text input; focus or a typed draft gives it the selected look.\n While a single-select option is chosen, focus alone does not apply that\n look, so the radio group shows one selection; typing clears the option. */\n.bau-customRow {\n display: flex;\n /* Same first-line alignment as .bau-option \u2014 the indicator seat carries the\n 2px re-centering margin. */\n align-items: flex-start;\n gap: 8px;\n width: 100%;\n min-height: 40px;\n /* Same reason as .bau-option: the custom row is scroll content, and shrinking\n it pushes the inline input past the footer. */\n flex-shrink: 0;\n padding: 8px 12px 8px 8px;\n border: 1px solid transparent;\n border-radius: var(--dsw-radius-md);\n transition: background-color 120ms ease, border-color 120ms ease;\n}\n\n.bau-customRow:hover,\n.bau-customRow:focus-within:not(.bau-customRowYielded),\n.bau-customRowActive {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.bau-customRow:focus-within:not(.bau-customRowYielded),\n.bau-customRowActive {\n border-color: var(--dsw-alias-border-l2);\n}\n\n/* Auto-growing free-text answer (see AnswerField): mirror and textarea share\n one grid cell, the mirror sizes it, and the textarea stretches to it. The\n two layers MUST keep identical type, padding and wrapping \u2014 a mismatch\n makes the box the wrong height for the text the user is typing. */\n.bau-field {\n display: grid;\n min-width: 0;\n --dsh-answer-field-padding: 0;\n}\n\n.bau-field > * {\n grid-area: 1 / 1;\n min-width: 0;\n padding: var(--dsh-answer-field-padding);\n font: inherit;\n font-size: 14px;\n line-height: 24px;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n/* The height ruler, never painted. Growth stops at 6 lines: the card body is\n capped at 520px and still owes that budget to the title, the option rows and\n the footer actions, so a long answer scrolls in the textarea instead of\n pushing the choices it belongs to out of view.\n content-box overrides the card-wide border-box so the cap counts TEXT lines\n in both variants: under border-box the block variant's 16px of vertical\n padding eats two thirds of a line and the sixth one arrives as an 8px sliver.\n Width is unaffected \u2014 a stretched grid item's used width comes from the\n track, not from this box-sizing. */\n.bau-fieldMirror {\n box-sizing: content-box;\n max-height: 144px;\n overflow: hidden;\n visibility: hidden;\n}\n\n.bau-fieldInput {\n resize: none;\n /* The stack's only scrollport: past the mirror's cap the field stops growing\n and this scrolls. */\n overflow-y: auto;\n border: none;\n outline: none;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n caret-color: var(--dsw-alias-state-business-primary);\n}\n\n.bau-fieldInput::placeholder {\n color: var(--dsw-alias-label-caption);\n}\n\n/* Inline variant: the custom row's copy column, borrowing the row's chrome. */\n.bau-customInline {\n flex: 1;\n}\n\n/* Optionless question: the free-form answer is the whole body, so it carries\n its own frame. The 12px side margins add to the .bau-options 12px padding so both\n edges align with the title's 24px inset; two lines are reserved before the\n answer starts growing. */\n.bau-customBlock {\n min-height: 64px;\n flex-shrink: 0;\n margin: 0 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-alias-bg-module-platform);\n --dsh-answer-field-padding: 8px 12px;\n}\n\n.bau-customBlock:focus-within {\n border-color: var(--dsw-alias-state-business-primary);\n}\n\n.bau-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-shrink: 0;\n margin-top: 12px;\n padding: 0 10px 0 18px;\n}\n\n.bau-feedback {\n flex: 1;\n min-height: 16px;\n color: var(--dsw-alias-state-error-primary);\n font-size: 11px;\n line-height: 16px;\n text-align: right;\n}\n\n@media (max-width: 720px) {\n .bau-card {\n border-radius: var(--dsw-radius-xl);\n }\n\n .bau-header {\n padding: 10px 12px 0 18px;\n }\n\n .bau-options {\n padding: 4px 8px;\n }\n\n .bau-title {\n font-size: 15px;\n line-height: 21px;\n }\n\n .bau-option,\n .bau-customRow {\n padding: 8px 6px;\n }\n\n .bau-footer {\n align-items: flex-end;\n padding: 0 10px;\n }\n\n .bau-footerActions {\n flex-shrink: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .bau-option,\n .bau-customRow {\n transition: none;\n }\n}\n\n/* \u2500\u2500 Better ask-user adaptations: markdown / long text / narrow screens \u2500\u2500 */\n.bau-title,\n.bau-eyebrow,\n.bau-optionLabel,\n.bau-description {\n min-width: 0;\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n\n.bau-title {\n max-height: 30vh;\n overflow-y: auto;\n}\n\n.bau-title > div,\n.bau-eyebrow > div,\n.bau-optionLabel > div,\n.bau-description > div {\n margin: 0;\n}\n\n.bau-optionLabel {\n display: block;\n}\n\n.bau-description {\n display: block;\n}\n\n.bau-card {\n max-height: min(75vh, 640px);\n max-height: min(75dvh, 640px);\n}\n\n.bau-frame {\n padding-bottom: calc(10px + env(safe-area-inset-bottom));\n}\n\n@media (max-width: 720px) {\n .bau-header {\n flex-wrap: wrap;\n }\n\n .bau-headingBlock {\n flex: 1 1 100%;\n }\n\n .bau-headerActions {\n flex-wrap: wrap;\n justify-content: flex-end;\n margin-left: auto;\n }\n\n .bau-waitStatus {\n white-space: normal;\n }\n\n .bau-card {\n max-height: calc(100vh - 160px);\n max-height: calc(100dvh - 160px);\n }\n\n .bau-title {\n max-height: 24vh;\n max-height: 24dvh;\n font-size: 15px;\n line-height: 21px;\n }\n\n .bau-footer {\n flex-wrap: wrap;\n }\n\n .bau-feedback {\n flex: 1 1 100%;\n text-align: left;\n }\n\n .bau-footerActions {\n width: 100%;\n justify-content: flex-end;\n flex-wrap: wrap;\n }\n\n .bau-option,\n .bau-customRow {\n min-height: 44px;\n }\n}\n\n@media (max-width: 420px) {\n .bau-footer {\n align-items: stretch;\n flex-direction: column;\n }\n\n .bau-pager {\n justify-content: space-between;\n width: 100%;\n }\n\n .bau-footerActions {\n width: 100%;\n }\n\n .bau-footerActions > button {\n flex: 1 1 auto;\n }\n}\n";
|
|
599
|
-
var
|
|
600
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(
|
|
711
|
+
var css3 = "/* The takeover seats where the input card sits, centered on the InputBar\n axis at the shared content width (input card - 32): sides = clearance +\n 16px so the relation also holds on narrow viewports. */\n.bau-frame {\n display: flex;\n justify-content: center;\n padding: 6px calc(var(--dsh-composer-side-clearance) + 16px) 10px;\n}\n\n/* Figma Input 973:36348 body over the 1019:36938 header: no banner strip \u2014\n the card keeps zero padding and sections carry their own insets. */\n.bau-card {\n display: flex;\n flex-direction: column;\n width: 100%;\n max-width: var(--dsh-chat-content-width);\n /* Composer seat sits in a fixed-height conversation column (overflow\n hidden): cap the card against the viewport and scroll the option list\n so header and footer actions stay reachable on long batches. */\n max-height: min(60vh, 520px);\n padding: 0 0 10px;\n border: 0;\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l2-darkmode-thin);\n border-radius: var(--dsw-radius-xl);\n background: var(--dsw-specific-input-major);\n box-shadow: var(--dsw-elevation-panel);\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n /* Elevated surface in dark, same as the menus: the body inside scrolls\n once the card hits the cap above, so the thumb takes the l2 pair. Declared\n on the card because the elevation belongs to the surface, and the custom\n properties inherit down to `.bau-body` (see ui-theme styles/scrollbar.bau-css\n for the rebinding contract). */\n --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);\n --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);\n}\n\n.bau-card,\n.bau-card * {\n box-sizing: border-box;\n}\n\n/* Collapsed to the header strip: drop the height cap and the inner scroll\n seat so the card hugs the title row, freeing the viewport for the\n conversation above while the question stays pending. */\n.bau-cardMinimized {\n max-height: none;\n}\n\n/* The header strip is the whole card when collapsed: the title row needs\n bottom padding once the body that normally carries it is hidden. */\n.bau-cardMinimized .bau-header {\n padding-bottom: 14px;\n}\n\n/* Header button group: minimize sits next to the close action, both on the\n same 24px icon-button grid. */\n.bau-headerActions {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.bau-waitButton {\n white-space: nowrap;\n}\n\n.bau-waitStatus {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 24px;\n white-space: nowrap;\n}\n\n/* Figma 1019:36938 header, user-tuned: heading block left, close right; the\n pager sits in the footer to balance the card. */\n.bau-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n flex-shrink: 0;\n padding: 20px 16px 0 24px;\n}\n\n.bau-headingBlock {\n min-width: 0;\n}\n\n.bau-eyebrow {\n /* Eyebrow-to-title gap widened from the figma 2px (user-tuned). */\n margin-bottom: 5px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 16px;\n}\n\n.bau-title {\n margin: 0;\n font-size: 16px;\n line-height: 22px;\n font-weight: 500;\n}\n\n.bau-detail {\n margin: 0 2px 8px;\n}\n\n.bau-footerActions {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n}\n\n.bau-pager {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.bau-progress {\n padding: 0 4px;\n color: var(--dsw-alias-label-secondary);\n font-size: 14px;\n line-height: 24px;\n font-weight: 500;\n white-space: nowrap;\n /* Narrow the plain spaces around the slash without touching glyph tracking. */\n word-spacing: -2px;\n}\n\n.bau-iconButton {\n display: grid;\n place-items: center;\n width: 24px;\n height: 24px;\n padding: 0;\n border: none;\n border-radius: 999px;\n corner-shape: round;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n\n.bau-iconButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.bau-iconButton:disabled {\n color: var(--dsw-alias-label-dimmed);\n cursor: default;\n}\n\n.bau-body {\n display: flex;\n flex: 1 1 auto;\n flex-direction: column;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n.bau-options {\n display: flex;\n flex-direction: column;\n gap: 1px;\n margin: 8px 0 0;\n padding: 4px 12px;\n}\n\n.bau-option {\n display: flex;\n /* flex-start, not center: with a wrapped description the indicator must\n stay on the FIRST line (centering drifts it down the taller copy block).\n The 8px padding makes a single-line row 40px exactly, so nothing reads\n as top-heavy; .bau-number/.bau-checkbox re-center against the first line box. */\n align-items: flex-start;\n gap: 8px;\n width: 100%;\n min-height: 40px;\n /* Rows are the scroll content, never the slack absorber: a shrinkable row\n collapses to min-height while its wrapped copy keeps the taller\n intrinsic height, and centered content then paints outside the row box \u2014\n over the title and the next row. Overflow belongs to .bau-options. */\n flex-shrink: 0;\n padding: 8px 12px 8px 8px;\n border: 1px solid transparent;\n border-radius: var(--dsw-radius-md);\n background: transparent;\n color: inherit;\n text-align: left;\n cursor: pointer;\n transition: background-color 120ms ease, border-color 120ms ease;\n}\n\n.bau-option:hover:not(:disabled),\n.bau-optionSelected {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.bau-optionSelected {\n border-color: var(--dsw-alias-border-l2);\n}\n\n.bau-option:disabled {\n cursor: default;\n}\n\n/* Leading indicator (20\xD720): single-select shows the option\n number, multi-select swaps in a checkbox; the custom-answer row follows \u2014\n its checkbox mirrors the typed draft (styling only, exclusivity holds). */\n.bau-number {\n display: grid;\n place-items: center;\n flex: 0 0 20px;\n width: 20px;\n height: 20px;\n /* (24px first-line box \u2212 20px indicator) / 2: centers the indicator against\n the first text line under the row's flex-start alignment. */\n margin-top: 2px;\n border-radius: var(--dsw-radius-xs);\n background: var(--dsw-alias-bg-overlay);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n}\n\n/* Multi-select box (figma 1055:41594, user-tuned down to 14\xD714): a radius-4\n box centered in the 20px indicator seat; the box itself is the ::before\n layer so the check icon stacks over it in the same grid cell. */\n.bau-checkbox {\n display: grid;\n place-items: center;\n flex: 0 0 20px;\n width: 20px;\n height: 20px;\n /* Same first-line centering as .bau-number under flex-start alignment. */\n margin-top: 2px;\n}\n\n.bau-checkbox::before {\n content: '';\n grid-area: 1 / 1;\n width: 14px;\n height: 14px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-xs);\n transition: background-color 120ms ease, border-color 120ms ease;\n}\n\n.bau-checkbox > svg {\n grid-area: 1 / 1;\n}\n\n/* Checked: label-primary fill with a primary-foreground check \u2014 the pair\n inverts with the theme (dark fill in light mode, light fill in dark mode). */\n.bau-checkboxChecked {\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.bau-checkboxChecked::before {\n border-color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-label-primary);\n}\n\n.bau-optionCopy {\n min-width: 0;\n flex: 1;\n}\n\n.bau-optionLine {\n display: flex;\n align-items: baseline;\n flex-wrap: wrap;\n gap: 2px 6px;\n}\n\n.bau-optionLabel {\n font-size: 14px;\n line-height: 24px;\n font-weight: 500;\n}\n\n.bau-badge {\n padding: 0 4px;\n border-radius: var(--dsw-radius-xs);\n background: var(--dsw-specific-sidebar-nav-item-active-accent);\n color: var(--dsw-alias-button-info-fill);\n font-size: 11px;\n line-height: 18px;\n font-weight: 600;\n}\n\n.bau-description {\n color: var(--dsw-alias-label-tertiary);\n font-size: 14px;\n line-height: 24px;\n font-weight: 400;\n}\n\n/* Read-only note standing in for a question the user skipped: it takes the\n option rows' horizontal padding so it lines up with the choices above it. */\n.bau-reviewNote {\n margin: 0;\n padding: 8px 12px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 14px;\n line-height: 24px;\n}\n\n/* Custom answer row (figma 973:36427): an option-shaped row whose copy is an\n inline text input; focus or a typed draft gives it the selected look.\n While a single-select option is chosen, focus alone does not apply that\n look, so the radio group shows one selection; typing clears the option. */\n.bau-customRow {\n display: flex;\n /* Same first-line alignment as .bau-option \u2014 the indicator seat carries the\n 2px re-centering margin. */\n align-items: flex-start;\n gap: 8px;\n width: 100%;\n min-height: 40px;\n /* Same reason as .bau-option: the custom row is scroll content, and shrinking\n it pushes the inline input past the footer. */\n flex-shrink: 0;\n padding: 8px 12px 8px 8px;\n border: 1px solid transparent;\n border-radius: var(--dsw-radius-md);\n transition: background-color 120ms ease, border-color 120ms ease;\n}\n\n.bau-customRow:hover,\n.bau-customRow:focus-within:not(.bau-customRowYielded),\n.bau-customRowActive {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.bau-customRow:focus-within:not(.bau-customRowYielded),\n.bau-customRowActive {\n border-color: var(--dsw-alias-border-l2);\n}\n\n/* Auto-growing free-text answer (see AnswerField): mirror and textarea share\n one grid cell, the mirror sizes it, and the textarea stretches to it. The\n two layers MUST keep identical type, padding and wrapping \u2014 a mismatch\n makes the box the wrong height for the text the user is typing. */\n.bau-field {\n display: grid;\n min-width: 0;\n --dsh-answer-field-padding: 0;\n}\n\n.bau-field > * {\n grid-area: 1 / 1;\n min-width: 0;\n padding: var(--dsh-answer-field-padding);\n font: inherit;\n font-size: 14px;\n line-height: 24px;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n/* The height ruler, never painted. Growth stops at 6 lines: the card body is\n capped at 520px and still owes that budget to the title, the option rows and\n the footer actions, so a long answer scrolls in the textarea instead of\n pushing the choices it belongs to out of view.\n content-box overrides the card-wide border-box so the cap counts TEXT lines\n in both variants: under border-box the block variant's 16px of vertical\n padding eats two thirds of a line and the sixth one arrives as an 8px sliver.\n Width is unaffected \u2014 a stretched grid item's used width comes from the\n track, not from this box-sizing. */\n.bau-fieldMirror {\n box-sizing: content-box;\n max-height: 144px;\n overflow: hidden;\n visibility: hidden;\n}\n\n.bau-fieldInput {\n resize: none;\n /* The stack's only scrollport: past the mirror's cap the field stops growing\n and this scrolls. */\n overflow-y: auto;\n border: none;\n outline: none;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n caret-color: var(--dsw-alias-state-business-primary);\n}\n\n.bau-fieldInput::placeholder {\n color: var(--dsw-alias-label-caption);\n}\n\n/* Inline variant: the custom row's copy column, borrowing the row's chrome. */\n.bau-customInline {\n flex: 1;\n}\n\n/* Optionless question: the free-form answer is the whole body, so it carries\n its own frame. The 12px side margins add to the .bau-options 12px padding so both\n edges align with the title's 24px inset; two lines are reserved before the\n answer starts growing. */\n.bau-customBlock {\n min-height: 64px;\n flex-shrink: 0;\n margin: 0 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-alias-bg-module-platform);\n --dsh-answer-field-padding: 8px 12px;\n}\n\n.bau-customBlock:focus-within {\n border-color: var(--dsw-alias-state-business-primary);\n}\n\n.bau-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-shrink: 0;\n margin-top: 12px;\n padding: 0 10px 0 18px;\n}\n\n.bau-feedback {\n flex: 1;\n min-height: 16px;\n color: var(--dsw-alias-state-error-primary);\n font-size: 11px;\n line-height: 16px;\n text-align: right;\n}\n\n@media (max-width: 720px) {\n .bau-card {\n border-radius: var(--dsw-radius-xl);\n }\n\n .bau-header {\n padding: 10px 12px 0 18px;\n }\n\n .bau-options {\n padding: 4px 8px;\n }\n\n .bau-title {\n font-size: 15px;\n line-height: 21px;\n }\n\n .bau-option,\n .bau-customRow {\n padding: 8px 6px;\n }\n\n .bau-footer {\n align-items: flex-end;\n padding: 0 10px;\n }\n\n .bau-footerActions {\n flex-shrink: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .bau-option,\n .bau-customRow {\n transition: none;\n }\n}\n\n/* \u2500\u2500 Better ask-user adaptations: markdown / long text / narrow screens \u2500\u2500 */\n.bau-title,\n.bau-eyebrow,\n.bau-optionLabel,\n.bau-description {\n min-width: 0;\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n\n.bau-title {\n max-height: 30vh;\n overflow-y: auto;\n}\n\n.bau-title > div,\n.bau-eyebrow > div,\n.bau-optionLabel > div,\n.bau-description > div {\n margin: 0;\n}\n\n.bau-optionLabel {\n display: block;\n}\n\n.bau-description {\n display: block;\n}\n\n.bau-card {\n max-height: min(75vh, 640px);\n max-height: min(75dvh, 640px);\n}\n\n.bau-frame {\n padding-bottom: calc(10px + env(safe-area-inset-bottom));\n}\n\n@media (max-width: 720px) {\n .bau-header {\n flex-wrap: wrap;\n }\n\n .bau-headingBlock {\n flex: 1 1 100%;\n }\n\n .bau-headerActions {\n flex-wrap: wrap;\n justify-content: flex-end;\n margin-left: auto;\n }\n\n .bau-waitStatus {\n white-space: normal;\n }\n\n .bau-card {\n max-height: calc(100vh - 160px);\n max-height: calc(100dvh - 160px);\n }\n\n .bau-title {\n max-height: 24vh;\n max-height: 24dvh;\n font-size: 15px;\n line-height: 21px;\n }\n\n .bau-footer {\n flex-wrap: wrap;\n }\n\n .bau-feedback {\n flex: 1 1 100%;\n text-align: left;\n }\n\n .bau-footerActions {\n width: 100%;\n justify-content: flex-end;\n flex-wrap: wrap;\n }\n\n .bau-option,\n .bau-customRow {\n min-height: 44px;\n }\n}\n\n@media (max-width: 420px) {\n .bau-footer {\n align-items: stretch;\n flex-direction: column;\n }\n\n .bau-pager {\n justify-content: space-between;\n width: 100%;\n }\n\n .bau-footerActions {\n width: 100%;\n }\n\n .bau-footerActions > button {\n flex: 1 1 auto;\n }\n}\n";
|
|
712
|
+
var id3 = "dsh-better-ask-user/QuestionComposer.module.css";
|
|
713
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(id3) + "]") === null) {
|
|
601
714
|
const tag = document.createElement("style");
|
|
602
715
|
tag.dataset.plugin = "dsh-better-ask-user";
|
|
603
|
-
tag.dataset.pluginCss =
|
|
604
|
-
tag.textContent =
|
|
716
|
+
tag.dataset.pluginCss = id3;
|
|
717
|
+
tag.textContent = css3;
|
|
605
718
|
document.head.appendChild(tag);
|
|
606
719
|
}
|
|
607
720
|
var QuestionComposer_default = { "frame": "bau-frame", "card": "bau-card", "body": "bau-body", "css": "bau-css", "cardMinimized": "bau-cardMinimized", "header": "bau-header", "headerActions": "bau-headerActions", "waitButton": "bau-waitButton", "waitStatus": "bau-waitStatus", "headingBlock": "bau-headingBlock", "eyebrow": "bau-eyebrow", "title": "bau-title", "detail": "bau-detail", "footerActions": "bau-footerActions", "pager": "bau-pager", "progress": "bau-progress", "iconButton": "bau-iconButton", "options": "bau-options", "option": "bau-option", "number": "bau-number", "checkbox": "bau-checkbox", "optionSelected": "bau-optionSelected", "checkboxChecked": "bau-checkboxChecked", "optionCopy": "bau-optionCopy", "optionLine": "bau-optionLine", "optionLabel": "bau-optionLabel", "badge": "bau-badge", "description": "bau-description", "reviewNote": "bau-reviewNote", "customRow": "bau-customRow", "customRowYielded": "bau-customRowYielded", "customRowActive": "bau-customRowActive", "field": "bau-field", "fieldMirror": "bau-fieldMirror", "fieldInput": "bau-fieldInput", "customInline": "bau-customInline", "customBlock": "bau-customBlock", "footer": "bau-footer", "feedback": "bau-feedback" };
|
|
608
721
|
|
|
609
722
|
// src/client/QuestionComposer.tsx
|
|
610
|
-
var
|
|
723
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
611
724
|
var REMOVED_CARD = {
|
|
612
725
|
state: "open",
|
|
613
726
|
waitState: "counting",
|
|
@@ -637,10 +750,10 @@ function isComposing(event) {
|
|
|
637
750
|
return event.nativeEvent.isComposing || Reflect.get(event.nativeEvent, "keyCode") === 229;
|
|
638
751
|
}
|
|
639
752
|
function AnswerField(props) {
|
|
640
|
-
return /* @__PURE__ */ (0,
|
|
641
|
-
/* @__PURE__ */ (0,
|
|
753
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: clsx_default(QuestionComposer_default.field, props.variant === "inline" ? QuestionComposer_default.customInline : QuestionComposer_default.customBlock), children: [
|
|
754
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { "aria-hidden": true, className: QuestionComposer_default.fieldMirror, children: `${props.value}
|
|
642
755
|
` }),
|
|
643
|
-
/* @__PURE__ */ (0,
|
|
756
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
644
757
|
"textarea",
|
|
645
758
|
{
|
|
646
759
|
autoFocus: props.autoFocus,
|
|
@@ -659,7 +772,7 @@ function AnswerField(props) {
|
|
|
659
772
|
function QuestionComposer(props) {
|
|
660
773
|
const question = props.matched;
|
|
661
774
|
const review = (0, import_react2.useMemo)(() => planReviewOf(question.questions), [question]);
|
|
662
|
-
return review === void 0 ? /* @__PURE__ */ (0,
|
|
775
|
+
return review === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
663
776
|
QuestionFlow,
|
|
664
777
|
{
|
|
665
778
|
pending: question,
|
|
@@ -669,7 +782,7 @@ function QuestionComposer(props) {
|
|
|
669
782
|
actions: props.actions
|
|
670
783
|
},
|
|
671
784
|
question.key
|
|
672
|
-
) : /* @__PURE__ */ (0,
|
|
785
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PlanReviewPanel, { pending: question, review, t: props.t, renderSlot: props.renderSlot }, question.key);
|
|
673
786
|
}
|
|
674
787
|
function QuestionFlow({ pending, t, useStore, useQuestionCard, actions }) {
|
|
675
788
|
const questions = pending.questions;
|
|
@@ -878,36 +991,36 @@ function QuestionFlow({ pending, t, useStore, useQuestionCard, actions }) {
|
|
|
878
991
|
}
|
|
879
992
|
submitDrafts(nextDrafts);
|
|
880
993
|
};
|
|
881
|
-
return /* @__PURE__ */ (0,
|
|
994
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: QuestionComposer_default.frame, "data-question-key": pending.key, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
882
995
|
"section",
|
|
883
996
|
{
|
|
884
997
|
className: clsx_default(QuestionComposer_default.card, minimized && QuestionComposer_default.cardMinimized),
|
|
885
998
|
"aria-labelledby": `question-${pending.key}-${String(index)}`,
|
|
886
999
|
children: [
|
|
887
|
-
/* @__PURE__ */ (0,
|
|
888
|
-
/* @__PURE__ */ (0,
|
|
889
|
-
question.header !== void 0 && /* @__PURE__ */ (0,
|
|
890
|
-
/* @__PURE__ */ (0,
|
|
1000
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: QuestionComposer_default.header, children: [
|
|
1001
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: QuestionComposer_default.headingBlock, children: [
|
|
1002
|
+
question.header !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: QuestionComposer_default.eyebrow, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.MarkdownText, { text: question.header, variant: "compact", labels: markdownLabels }) }),
|
|
1003
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
891
1004
|
"div",
|
|
892
1005
|
{
|
|
893
1006
|
className: QuestionComposer_default.title,
|
|
894
1007
|
id: `question-${pending.key}-${String(index)}`,
|
|
895
1008
|
role: "heading",
|
|
896
1009
|
"aria-level": 2,
|
|
897
|
-
children: /* @__PURE__ */ (0,
|
|
1010
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.MarkdownText, { text: question.question, variant: "compact", labels: markdownLabels })
|
|
898
1011
|
}
|
|
899
1012
|
)
|
|
900
1013
|
] }),
|
|
901
|
-
/* @__PURE__ */ (0,
|
|
902
|
-
countdown !== void 0 && card.waitState !== "waiting" && card.waitState !== "editing" && card.waitState !== "continued" && /* @__PURE__ */ (0,
|
|
1014
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: QuestionComposer_default.headerActions, children: [
|
|
1015
|
+
countdown !== void 0 && card.waitState !== "waiting" && card.waitState !== "editing" && card.waitState !== "continued" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: QuestionComposer_default.waitStatus, children: t(countdown.running ? "wait.countdown" : "wait.paused", {
|
|
903
1016
|
seconds: Math.ceil(countdown.remainingMs / 1e3)
|
|
904
1017
|
}) }),
|
|
905
|
-
countdown !== void 0 && card.waitState !== "waiting" && card.waitState !== "editing" && card.waitState !== "continued" && /* @__PURE__ */ (0,
|
|
906
|
-
countdown !== void 0 && card.waitState !== "waiting" && card.waitState !== "editing" && card.waitState !== "continued" && /* @__PURE__ */ (0,
|
|
907
|
-
card.state === "continued" && /* @__PURE__ */ (0,
|
|
908
|
-
countdown !== void 0 && (card.waitState === "waiting" || card.waitState === "editing") && /* @__PURE__ */ (0,
|
|
909
|
-
review !== void 0 && /* @__PURE__ */ (0,
|
|
910
|
-
/* @__PURE__ */ (0,
|
|
1018
|
+
countdown !== void 0 && card.waitState !== "waiting" && card.waitState !== "editing" && card.waitState !== "continued" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: QuestionComposer_default.waitStatus, children: t(card.timeoutMode === "default" ? "wait.auto" : "wait.extend") }),
|
|
1019
|
+
countdown !== void 0 && card.waitState !== "waiting" && card.waitState !== "editing" && card.waitState !== "continued" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Button, { variant: "outline", className: QuestionComposer_default.waitButton, onClick: takeTime, children: t("wait.takeTime") }),
|
|
1020
|
+
card.state === "continued" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: QuestionComposer_default.waitStatus, children: t("wait.continued") }),
|
|
1021
|
+
countdown !== void 0 && (card.waitState === "waiting" || card.waitState === "editing") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: QuestionComposer_default.waitStatus, children: t("wait.held") }),
|
|
1022
|
+
review !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: QuestionComposer_default.waitStatus, children: t("review.status") }),
|
|
1023
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
911
1024
|
"button",
|
|
912
1025
|
{
|
|
913
1026
|
type: "button",
|
|
@@ -919,10 +1032,10 @@ function QuestionFlow({ pending, t, useStore, useQuestionCard, actions }) {
|
|
|
919
1032
|
onClick: () => {
|
|
920
1033
|
setMinimized((current) => !current);
|
|
921
1034
|
},
|
|
922
|
-
children: minimized ? /* @__PURE__ */ (0,
|
|
1035
|
+
children: minimized ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.IconChevronUpOutlineRegular, {}) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.IconChevronDownOutlineRegular, {})
|
|
923
1036
|
}
|
|
924
1037
|
),
|
|
925
|
-
/* @__PURE__ */ (0,
|
|
1038
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
926
1039
|
"button",
|
|
927
1040
|
{
|
|
928
1041
|
type: "button",
|
|
@@ -931,13 +1044,13 @@ function QuestionFlow({ pending, t, useStore, useQuestionCard, actions }) {
|
|
|
931
1044
|
title: t(pending.dismissal === "hide" ? "nav.close" : "nav.cancel"),
|
|
932
1045
|
disabled: busy !== null,
|
|
933
1046
|
onClick: dismissFlow,
|
|
934
|
-
children: /* @__PURE__ */ (0,
|
|
1047
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.IconCloseOutlineRegular, {})
|
|
935
1048
|
}
|
|
936
1049
|
)
|
|
937
1050
|
] })
|
|
938
1051
|
] }),
|
|
939
|
-
!minimized && /* @__PURE__ */ (0,
|
|
940
|
-
/* @__PURE__ */ (0,
|
|
1052
|
+
!minimized && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1053
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
941
1054
|
"div",
|
|
942
1055
|
{
|
|
943
1056
|
ref: answerSurface,
|
|
@@ -946,12 +1059,12 @@ function QuestionFlow({ pending, t, useStore, useQuestionCard, actions }) {
|
|
|
946
1059
|
onFocusCapture: focusAnswerSurface,
|
|
947
1060
|
onBlurCapture: blurAnswerSurface,
|
|
948
1061
|
children: [
|
|
949
|
-
question.detail !== void 0 && /* @__PURE__ */ (0,
|
|
950
|
-
/* @__PURE__ */ (0,
|
|
1062
|
+
question.detail !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: QuestionComposer_default.detail, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.MarkdownText, { text: question.detail, labels: markdownLabels }) }),
|
|
1063
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: QuestionComposer_default.options, role: question.multiSelect === true ? "group" : "radiogroup", children: [
|
|
951
1064
|
(question.options ?? []).map((option, optionIndex) => {
|
|
952
1065
|
const selected = draft.selected.includes(option.label);
|
|
953
1066
|
const display = parseRecommendedLabel(option.label);
|
|
954
|
-
return /* @__PURE__ */ (0,
|
|
1067
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
955
1068
|
"button",
|
|
956
1069
|
{
|
|
957
1070
|
type: "button",
|
|
@@ -969,19 +1082,19 @@ function QuestionFlow({ pending, t, useStore, useQuestionCard, actions }) {
|
|
|
969
1082
|
submitDrafts(drafts);
|
|
970
1083
|
},
|
|
971
1084
|
children: [
|
|
972
|
-
question.multiSelect === true ? /* @__PURE__ */ (0,
|
|
973
|
-
/* @__PURE__ */ (0,
|
|
974
|
-
/* @__PURE__ */ (0,
|
|
975
|
-
display.recommended && /* @__PURE__ */ (0,
|
|
976
|
-
option.description !== void 0 && /* @__PURE__ */ (0,
|
|
1085
|
+
question.multiSelect === true ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: clsx_default(QuestionComposer_default.checkbox, selected && QuestionComposer_default.checkboxChecked), "aria-hidden": "true", children: selected && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.IconCheckOutlineRegular, { size: 12 }) }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: QuestionComposer_default.number, children: optionIndex + 1 }),
|
|
1086
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: QuestionComposer_default.optionCopy, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: QuestionComposer_default.optionLine, children: [
|
|
1087
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: QuestionComposer_default.optionLabel, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.MarkdownText, { text: display.label, variant: "compact", labels: markdownLabels }) }),
|
|
1088
|
+
display.recommended && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: QuestionComposer_default.badge, children: t("option.recommended") }),
|
|
1089
|
+
option.description !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: QuestionComposer_default.description, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.MarkdownText, { text: option.description, variant: "compact", labels: markdownLabels }) })
|
|
977
1090
|
] }) })
|
|
978
1091
|
]
|
|
979
1092
|
},
|
|
980
1093
|
`${option.label}-${String(optionIndex)}`
|
|
981
1094
|
);
|
|
982
1095
|
}),
|
|
983
|
-
review !== void 0 && draft.skipped && /* @__PURE__ */ (0,
|
|
984
|
-
(review === void 0 || draft.custom !== "") && (hasOptions ? /* @__PURE__ */ (0,
|
|
1096
|
+
review !== void 0 && draft.skipped && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: QuestionComposer_default.reviewNote, children: t("review.skipped") }),
|
|
1097
|
+
(review === void 0 || draft.custom !== "") && (hasOptions ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
985
1098
|
"div",
|
|
986
1099
|
{
|
|
987
1100
|
className: clsx_default(
|
|
@@ -990,15 +1103,15 @@ function QuestionFlow({ pending, t, useStore, useQuestionCard, actions }) {
|
|
|
990
1103
|
question.multiSelect !== true && draft.selected.length > 0 && QuestionComposer_default.customRowYielded
|
|
991
1104
|
),
|
|
992
1105
|
children: [
|
|
993
|
-
question.multiSelect === true ? /* @__PURE__ */ (0,
|
|
1106
|
+
question.multiSelect === true ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
994
1107
|
"span",
|
|
995
1108
|
{
|
|
996
1109
|
className: clsx_default(QuestionComposer_default.checkbox, draft.custom !== "" && QuestionComposer_default.checkboxChecked),
|
|
997
1110
|
"aria-hidden": "true",
|
|
998
|
-
children: draft.custom !== "" && /* @__PURE__ */ (0,
|
|
1111
|
+
children: draft.custom !== "" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.IconCheckOutlineRegular, { size: 12 })
|
|
999
1112
|
}
|
|
1000
|
-
) : /* @__PURE__ */ (0,
|
|
1001
|
-
/* @__PURE__ */ (0,
|
|
1113
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: QuestionComposer_default.number, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.IconEditOutlineRegular, { size: 12 }) }),
|
|
1114
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1002
1115
|
AnswerField,
|
|
1003
1116
|
{
|
|
1004
1117
|
variant: "inline",
|
|
@@ -1011,7 +1124,7 @@ function QuestionFlow({ pending, t, useStore, useQuestionCard, actions }) {
|
|
|
1011
1124
|
)
|
|
1012
1125
|
]
|
|
1013
1126
|
}
|
|
1014
|
-
) : /* @__PURE__ */ (0,
|
|
1127
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1015
1128
|
AnswerField,
|
|
1016
1129
|
{
|
|
1017
1130
|
autoFocus: canSubmit && countdown === void 0 && !locked && !focusedQuestions.current.has(index),
|
|
@@ -1030,9 +1143,9 @@ function QuestionFlow({ pending, t, useStore, useQuestionCard, actions }) {
|
|
|
1030
1143
|
]
|
|
1031
1144
|
}
|
|
1032
1145
|
),
|
|
1033
|
-
/* @__PURE__ */ (0,
|
|
1034
|
-
/* @__PURE__ */ (0,
|
|
1035
|
-
/* @__PURE__ */ (0,
|
|
1146
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("footer", { className: QuestionComposer_default.footer, children: [
|
|
1147
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: QuestionComposer_default.pager, children: [
|
|
1148
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1036
1149
|
"button",
|
|
1037
1150
|
{
|
|
1038
1151
|
type: "button",
|
|
@@ -1043,15 +1156,15 @@ function QuestionFlow({ pending, t, useStore, useQuestionCard, actions }) {
|
|
|
1043
1156
|
replaceProgress(index - 1, drafts);
|
|
1044
1157
|
setError(null);
|
|
1045
1158
|
},
|
|
1046
|
-
children: /* @__PURE__ */ (0,
|
|
1159
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.IconChevronLeftOutlineRegular, {})
|
|
1047
1160
|
}
|
|
1048
1161
|
),
|
|
1049
|
-
/* @__PURE__ */ (0,
|
|
1162
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: QuestionComposer_default.progress, children: [
|
|
1050
1163
|
index + 1,
|
|
1051
1164
|
" / ",
|
|
1052
1165
|
questions.length
|
|
1053
1166
|
] }),
|
|
1054
|
-
/* @__PURE__ */ (0,
|
|
1167
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1055
1168
|
"button",
|
|
1056
1169
|
{
|
|
1057
1170
|
type: "button",
|
|
@@ -1062,15 +1175,15 @@ function QuestionFlow({ pending, t, useStore, useQuestionCard, actions }) {
|
|
|
1062
1175
|
replaceProgress(index + 1, drafts);
|
|
1063
1176
|
setError(null);
|
|
1064
1177
|
},
|
|
1065
|
-
children: /* @__PURE__ */ (0,
|
|
1178
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.IconChevronRightOutlineRegular, {})
|
|
1066
1179
|
}
|
|
1067
1180
|
)
|
|
1068
1181
|
] }),
|
|
1069
|
-
/* @__PURE__ */ (0,
|
|
1070
|
-
review === void 0 && /* @__PURE__ */ (0,
|
|
1071
|
-
/* @__PURE__ */ (0,
|
|
1072
|
-
/* @__PURE__ */ (0,
|
|
1073
|
-
|
|
1182
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: QuestionComposer_default.feedback, role: "status", children: error === null ? null : "key" in error ? t(error.key) : error.text }),
|
|
1183
|
+
review === void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: QuestionComposer_default.footerActions, children: [
|
|
1184
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Button, { variant: "outline", disabled: busy !== null, onClick: skipQuestion, children: t("action.skip") }),
|
|
1185
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1186
|
+
import_dsh_client_ui_primitives3.Button,
|
|
1074
1187
|
{
|
|
1075
1188
|
variant: "primary",
|
|
1076
1189
|
disabled: busy !== null || !answered(draft) || index === questions.length - 1 && !canSubmit,
|
|
@@ -1105,7 +1218,7 @@ function isAppendSurfaceEvent(event) {
|
|
|
1105
1218
|
}
|
|
1106
1219
|
|
|
1107
1220
|
// src/client/question-reply.ts
|
|
1108
|
-
function
|
|
1221
|
+
function isRecord2(value) {
|
|
1109
1222
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1110
1223
|
}
|
|
1111
1224
|
function replyPairsOf(text) {
|
|
@@ -1116,19 +1229,19 @@ function replyPairsOf(text) {
|
|
|
1116
1229
|
void error;
|
|
1117
1230
|
return { questions: [], answers: [] };
|
|
1118
1231
|
}
|
|
1119
|
-
if (!
|
|
1232
|
+
if (!isRecord2(value) || !Array.isArray(value.questions)) {
|
|
1120
1233
|
return { questions: [], answers: [] };
|
|
1121
1234
|
}
|
|
1122
1235
|
const questions = [];
|
|
1123
1236
|
for (const question of value.questions) {
|
|
1124
|
-
if (!
|
|
1237
|
+
if (!isRecord2(question) || typeof question.id !== "string" || typeof question.question !== "string") continue;
|
|
1125
1238
|
questions.push({
|
|
1126
1239
|
id: question.id,
|
|
1127
1240
|
question: question.question,
|
|
1128
1241
|
...typeof question.detail === "string" ? { detail: question.detail } : {},
|
|
1129
1242
|
...typeof question.header === "string" ? { header: question.header } : {},
|
|
1130
1243
|
...Array.isArray(question.options) ? { options: question.options.flatMap((option) => {
|
|
1131
|
-
if (!
|
|
1244
|
+
if (!isRecord2(option) || typeof option.label !== "string") return [];
|
|
1132
1245
|
return [{ label: option.label, ...typeof option.description === "string" ? { description: option.description } : {} }];
|
|
1133
1246
|
}) } : {},
|
|
1134
1247
|
...typeof question.multiSelect === "boolean" ? { multiSelect: question.multiSelect } : {}
|
|
@@ -1136,7 +1249,7 @@ function replyPairsOf(text) {
|
|
|
1136
1249
|
}
|
|
1137
1250
|
const answers = [];
|
|
1138
1251
|
for (const answer of Array.isArray(value.answers) ? value.answers : []) {
|
|
1139
|
-
if (!
|
|
1252
|
+
if (!isRecord2(answer) || typeof answer.id !== "string" || !Array.isArray(answer.selected)) continue;
|
|
1140
1253
|
answers.push({
|
|
1141
1254
|
id: answer.id,
|
|
1142
1255
|
selected: answer.selected.filter((item) => typeof item === "string"),
|
|
@@ -1145,8 +1258,8 @@ function replyPairsOf(text) {
|
|
|
1145
1258
|
}
|
|
1146
1259
|
return { questions, answers };
|
|
1147
1260
|
}
|
|
1148
|
-
function replyAnswerValues(data,
|
|
1149
|
-
const answer = data.answers.find((item) => item.id ===
|
|
1261
|
+
function replyAnswerValues(data, id5) {
|
|
1262
|
+
const answer = data.answers.find((item) => item.id === id5);
|
|
1150
1263
|
const custom = answer?.custom?.trim() ?? "";
|
|
1151
1264
|
return [...answer?.selected ?? [], ...custom === "" ? [] : [custom]];
|
|
1152
1265
|
}
|
|
@@ -1162,7 +1275,7 @@ ${answer}`;
|
|
|
1162
1275
|
}
|
|
1163
1276
|
function replySource(event) {
|
|
1164
1277
|
const source = event.data.source;
|
|
1165
|
-
return
|
|
1278
|
+
return isRecord2(source) && source.kind === "user-question-reply" && typeof source.callId === "string" && source.outcome === "answered" ? { callId: source.callId, outcome: "answered" } : null;
|
|
1166
1279
|
}
|
|
1167
1280
|
var questionReplyDefinition = {
|
|
1168
1281
|
kind: "user-question-reply",
|
|
@@ -1206,24 +1319,24 @@ var questionReplyDefinition = {
|
|
|
1206
1319
|
|
|
1207
1320
|
// src/client/QuestionReplyView.tsx
|
|
1208
1321
|
var import_react3 = require("react");
|
|
1209
|
-
var
|
|
1322
|
+
var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
1210
1323
|
|
|
1211
1324
|
// src/client/QuestionReplyView.module.css
|
|
1212
|
-
var
|
|
1213
|
-
var
|
|
1214
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(
|
|
1325
|
+
var css4 = ".bau-row {\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n align-items: flex-end;\n gap: 6px;\n padding: 4px 0;\n}\n\n.bau-bubble {\n max-width: 72%;\n padding: 10px 16px;\n border-radius: var(--dsw-radius-xl);\n background: var(--dsw-specific-bubble);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font-size: var(--dsh-content-font-size, 14px);\n line-height: calc(22px + var(--dsh-content-font-delta, 0px));\n text-align: left;\n overflow-wrap: anywhere;\n white-space: pre-wrap;\n}\n\n.bau-toggle {\n width: 100%;\n padding: 0;\n border: 0;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: inherit;\n text-align: left;\n}\n\n.bau-toggle:focus-visible {\n outline: 2px solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));\n outline-offset: 2px;\n}\n\n.bau-bubble:has(.bau-toggle:focus-visible) {\n box-shadow: 0 0 0 2px var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));\n}\n\n.bau-labelRow {\n display: flex;\n align-items: center;\n gap: 3px;\n}\n\n.bau-caret {\n display: inline-flex;\n color: var(--dsw-alias-label-secondary);\n}\n\n.bau-caret svg {\n width: 12px;\n height: 12px;\n}\n\n.bau-label {\n color: var(--dsw-alias-label-secondary);\n display: block;\n font-size: var(--dsh-content-font-size-secondary, 13px);\n line-height: calc(18px + var(--dsh-content-font-delta-secondary, 0px));\n}\n\n.bau-summary {\n display: block;\n margin-top: 3px;\n color: var(--dsw-alias-label-primary);\n font-size: var(--dsh-content-font-size, 14px);\n}\n\n.bau-text {\n margin: 8px 0 0;\n}\n\n.bau-details {\n margin: 8px 0 0;\n padding-top: 8px;\n border-top: 1px solid color-mix(in srgb, var(--dsw-alias-label-secondary) 24%, transparent);\n}\n\n.bau-details > div + div {\n margin-top: 12px;\n}\n\n.bau-details dt {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n\n.bau-question {\n display: grid;\n gap: 3px;\n}\n\n.bau-header,\n.bau-detail,\n.bau-options {\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n}\n\n.bau-questionText {\n color: var(--dsw-alias-label-primary);\n}\n\n.bau-options {\n margin: 0;\n padding-left: 16px;\n}\n\n.bau-details dd {\n margin: 4px 0 0;\n}\n\n.bau-answer {\n font-size: 14px;\n}\n\n.bau-answerLabel {\n margin-right: 4px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n\n.bau-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 28px;\n padding-right: 4px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.bau-time {\n padding-right: 4px;\n font-size: 13px;\n line-height: 24px;\n white-space: nowrap;\n}\n\n.bau-action {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 6px;\n border: none;\n border-radius: var(--dsw-radius-sm);\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n\n.bau-action svg {\n width: 15px;\n height: 15px;\n}\n\n.bau-action:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n/* Better ask-user: long reply text and narrow screens. */\n.bau-row,\n.bau-summary,\n.bau-text,\n.bau-question,\n.bau-questionText,\n.bau-answer,\n.bau-details {\n min-width: 0;\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n\n@media (max-width: 720px) {\n .bau-bubble {\n max-width: 100%;\n }\n\n .bau-labelRow {\n flex-wrap: wrap;\n }\n\n .bau-details {\n max-width: 100%;\n }\n}\n";
|
|
1326
|
+
var id4 = "dsh-better-ask-user/QuestionReplyView.module.css";
|
|
1327
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(id4) + "]") === null) {
|
|
1215
1328
|
const tag = document.createElement("style");
|
|
1216
1329
|
tag.dataset.plugin = "dsh-better-ask-user";
|
|
1217
|
-
tag.dataset.pluginCss =
|
|
1218
|
-
tag.textContent =
|
|
1330
|
+
tag.dataset.pluginCss = id4;
|
|
1331
|
+
tag.textContent = css4;
|
|
1219
1332
|
document.head.appendChild(tag);
|
|
1220
1333
|
}
|
|
1221
1334
|
var QuestionReplyView_default = { "row": "bau-row", "bubble": "bau-bubble", "toggle": "bau-toggle", "labelRow": "bau-labelRow", "caret": "bau-caret", "label": "bau-label", "summary": "bau-summary", "text": "bau-text", "details": "bau-details", "question": "bau-question", "header": "bau-header", "detail": "bau-detail", "options": "bau-options", "questionText": "bau-questionText", "answer": "bau-answer", "answerLabel": "bau-answerLabel", "actions": "bau-actions", "time": "bau-time", "action": "bau-action" };
|
|
1222
1335
|
|
|
1223
1336
|
// src/client/QuestionReplyView.tsx
|
|
1224
|
-
var
|
|
1337
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1225
1338
|
var QuestionReplyView = (0, import_react3.memo)(function QuestionReplyView2({ node, t }) {
|
|
1226
|
-
return /* @__PURE__ */ (0,
|
|
1339
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(QuestionReplyBubble, { data: node.data, t });
|
|
1227
1340
|
});
|
|
1228
1341
|
function QuestionReplyBubble({ data, t }) {
|
|
1229
1342
|
const label = t("reply.label");
|
|
@@ -1234,7 +1347,7 @@ function QuestionReplyBubble({ data, t }) {
|
|
|
1234
1347
|
const [copied, setCopied] = (0, import_react3.useState)(false);
|
|
1235
1348
|
const onCopy = (0, import_react3.useCallback)(() => {
|
|
1236
1349
|
if (copied) return;
|
|
1237
|
-
void (0,
|
|
1350
|
+
void (0, import_dsh_client_ui_primitives4.writeClipboard)(copyText).then((ok) => {
|
|
1238
1351
|
if (!ok) return;
|
|
1239
1352
|
setCopied(true);
|
|
1240
1353
|
window.setTimeout(() => {
|
|
@@ -1242,9 +1355,9 @@ function QuestionReplyBubble({ data, t }) {
|
|
|
1242
1355
|
}, 1e3);
|
|
1243
1356
|
});
|
|
1244
1357
|
}, [copied, copyText]);
|
|
1245
|
-
return /* @__PURE__ */ (0,
|
|
1246
|
-
/* @__PURE__ */ (0,
|
|
1247
|
-
/* @__PURE__ */ (0,
|
|
1358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: QuestionReplyView_default.row, "data-question-reply": data.callId, "data-reply-outcome": data.outcome, role: "group", "aria-label": label, children: [
|
|
1359
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: QuestionReplyView_default.bubble, children: [
|
|
1360
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1248
1361
|
"button",
|
|
1249
1362
|
{
|
|
1250
1363
|
type: "button",
|
|
@@ -1255,36 +1368,36 @@ function QuestionReplyBubble({ data, t }) {
|
|
|
1255
1368
|
setOpen((value) => !value);
|
|
1256
1369
|
},
|
|
1257
1370
|
children: [
|
|
1258
|
-
/* @__PURE__ */ (0,
|
|
1259
|
-
/* @__PURE__ */ (0,
|
|
1260
|
-
/* @__PURE__ */ (0,
|
|
1371
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: QuestionReplyView_default.labelRow, children: [
|
|
1372
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: QuestionReplyView_default.caret, "aria-hidden": "true", children: open ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconChevronDownOutlineRegular, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconChevronRightOutlineRegular, {}) }),
|
|
1373
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: QuestionReplyView_default.label, children: label })
|
|
1261
1374
|
] }),
|
|
1262
|
-
!open && /* @__PURE__ */ (0,
|
|
1375
|
+
!open && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: QuestionReplyView_default.summary, children: summary === "" ? t("reply.skipped") : summary })
|
|
1263
1376
|
]
|
|
1264
1377
|
}
|
|
1265
1378
|
),
|
|
1266
|
-
open && (data.questions.length === 0 ? /* @__PURE__ */ (0,
|
|
1379
|
+
open && (data.questions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: QuestionReplyView_default.text, children: data.text }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("dl", { className: QuestionReplyView_default.details, children: data.questions.map((question) => {
|
|
1267
1380
|
const values = replyAnswerValues(data, question.id);
|
|
1268
|
-
return /* @__PURE__ */ (0,
|
|
1269
|
-
/* @__PURE__ */ (0,
|
|
1270
|
-
question.header && question.header !== question.question && /* @__PURE__ */ (0,
|
|
1271
|
-
/* @__PURE__ */ (0,
|
|
1272
|
-
question.detail && /* @__PURE__ */ (0,
|
|
1273
|
-
question.options && question.options.length > 0 && /* @__PURE__ */ (0,
|
|
1381
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
|
|
1382
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("dt", { className: QuestionReplyView_default.question, children: [
|
|
1383
|
+
question.header && question.header !== question.question && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: QuestionReplyView_default.header, children: question.header }),
|
|
1384
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: QuestionReplyView_default.questionText, children: question.question }),
|
|
1385
|
+
question.detail && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: QuestionReplyView_default.detail, children: question.detail }),
|
|
1386
|
+
question.options && question.options.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: QuestionReplyView_default.options, children: question.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { children: [
|
|
1274
1387
|
option.label,
|
|
1275
1388
|
option.description && ` \u2014 ${option.description}`
|
|
1276
1389
|
] }, option.label)) })
|
|
1277
1390
|
] }),
|
|
1278
|
-
/* @__PURE__ */ (0,
|
|
1279
|
-
/* @__PURE__ */ (0,
|
|
1391
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("dd", { className: QuestionReplyView_default.answer, children: [
|
|
1392
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: QuestionReplyView_default.answerLabel, children: t("reply.answerLabel") }),
|
|
1280
1393
|
values.length === 0 ? t("reply.skipped") : values.join(", ")
|
|
1281
1394
|
] })
|
|
1282
1395
|
] }, question.id);
|
|
1283
1396
|
}) }))
|
|
1284
1397
|
] }),
|
|
1285
|
-
/* @__PURE__ */ (0,
|
|
1286
|
-
/* @__PURE__ */ (0,
|
|
1287
|
-
/* @__PURE__ */ (0,
|
|
1398
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: QuestionReplyView_default.actions, children: [
|
|
1399
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: QuestionReplyView_default.time, children: new Intl.DateTimeFormat(void 0, { hour: "2-digit", minute: "2-digit", hour12: false }).format(data.time) }),
|
|
1400
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.Tooltip, { label: copied ? t("copied") : t("copy"), side: "bottom", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: QuestionReplyView_default.action, "aria-label": copied ? t("copied") : t("copy"), onClick: onCopy, children: copied ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconCheckOutlineRegular, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconCopyOutlineRegular, {}) }) })
|
|
1288
1401
|
] })
|
|
1289
1402
|
] });
|
|
1290
1403
|
}
|
|
@@ -1296,6 +1409,9 @@ var zh = {
|
|
|
1296
1409
|
"error.unavailable": "\u5F53\u524D\u65E0\u6CD5\u63D0\u4EA4\uFF0C\u8BF7\u7A0D\u5019\u518D\u8BD5\u3002",
|
|
1297
1410
|
"error.resubmit": "\u56DE\u7B54\u672A\u9001\u8FBE\uFF0C\u5DE5\u4F5C\u5DF2\u7EE7\u7EED\uFF0C\u8BF7\u518D\u63D0\u4EA4\u4E00\u6B21\u3002",
|
|
1298
1411
|
"status.sent": "\u56DE\u7B54\u5DF2\u53D1\u9001\uFF1B\u9762\u677F\u672A\u80FD\u5173\u95ED\u3002",
|
|
1412
|
+
"history.title": "\u95EE\u9898",
|
|
1413
|
+
"history.review": "\u67E5\u770B",
|
|
1414
|
+
"history.reopen": "\u6253\u5F00",
|
|
1299
1415
|
"wait.takeTime": "\u6162\u6162\u56DE\u7B54",
|
|
1300
1416
|
"wait.countdown": "{seconds} \u79D2\u540E\u7EE7\u7EED\u5DE5\u4F5C",
|
|
1301
1417
|
"wait.paused": "\u5DF2\u6682\u505C \xB7 \u5269\u4F59 {seconds} \u79D2",
|
|
@@ -1331,6 +1447,9 @@ var en = {
|
|
|
1331
1447
|
"error.unavailable": "Cannot submit right now; try again in a moment.",
|
|
1332
1448
|
"error.resubmit": "The answer did not arrive before work continued; submit it again.",
|
|
1333
1449
|
"status.sent": "Reply sent; the panel could not close.",
|
|
1450
|
+
"history.title": "Question",
|
|
1451
|
+
"history.review": "Review",
|
|
1452
|
+
"history.reopen": "Open",
|
|
1334
1453
|
"wait.takeTime": "Take time",
|
|
1335
1454
|
"wait.countdown": "Continuing in {seconds}s",
|
|
1336
1455
|
"wait.paused": "Paused \xB7 {seconds}s remaining",
|
|
@@ -1415,7 +1534,7 @@ var settingsEn = {
|
|
|
1415
1534
|
};
|
|
1416
1535
|
|
|
1417
1536
|
// src/client/settings.tsx
|
|
1418
|
-
var
|
|
1537
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1419
1538
|
var DEFAULTS = { questionTimeoutSeconds: 120, timeoutBehavior: "native", goalTimeoutBehavior: "native" };
|
|
1420
1539
|
var MAX_QUESTION_TIMEOUT_SECONDS = 2147483;
|
|
1421
1540
|
var fallbackT = (key) => settingsEn[key];
|
|
@@ -1504,23 +1623,23 @@ function SettingsPage({ form, t = fallbackT }) {
|
|
|
1504
1623
|
}
|
|
1505
1624
|
}, [busy, dirty, form, host, parsed, revision, t, writable]);
|
|
1506
1625
|
if (state === void 0) {
|
|
1507
|
-
return /* @__PURE__ */ (0,
|
|
1626
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { padding: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: statusStyle, children: t("waiting") }) });
|
|
1508
1627
|
}
|
|
1509
1628
|
if (state.status === "loading") {
|
|
1510
|
-
return /* @__PURE__ */ (0,
|
|
1629
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { padding: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: statusStyle, children: t("loading") }) });
|
|
1511
1630
|
}
|
|
1512
1631
|
if (host === null || live === null) {
|
|
1513
|
-
return /* @__PURE__ */ (0,
|
|
1632
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { padding: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: statusStyle, children: t("unavailable") }) });
|
|
1514
1633
|
}
|
|
1515
1634
|
const invalid = parsed === void 0;
|
|
1516
|
-
const status = notice !== null ? /* @__PURE__ */ (0,
|
|
1517
|
-
return /* @__PURE__ */ (0,
|
|
1518
|
-
/* @__PURE__ */ (0,
|
|
1519
|
-
/* @__PURE__ */ (0,
|
|
1520
|
-
writable ? null : /* @__PURE__ */ (0,
|
|
1521
|
-
/* @__PURE__ */ (0,
|
|
1522
|
-
/* @__PURE__ */ (0,
|
|
1523
|
-
/* @__PURE__ */ (0,
|
|
1635
|
+
const status = notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { ...statusStyle, color: notice.tone === "ok" ? "#2f8f4e" : "#c0392b" }, children: notice.text }) : invalid ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { ...statusStyle, color: "#c0392b" }, children: t("invalidWait") }) : dirty ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: statusStyle, children: t("dirty") }) : null;
|
|
1636
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { padding: "4px 2px", maxWidth: 720 }, children: [
|
|
1637
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { style: { margin: "0 0 6px", fontSize: 16 }, children: t("title") }),
|
|
1638
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: { ...hintStyle, marginBottom: 18 }, children: t("intro") }),
|
|
1639
|
+
writable ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: { ...statusStyle, marginBottom: 14 }, children: t("readonly") }),
|
|
1640
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: fieldStyle, children: [
|
|
1641
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("label", { style: labelStyle, htmlFor: "better-ask-user-wait", children: t("waitLabel") }),
|
|
1642
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1524
1643
|
"input",
|
|
1525
1644
|
{
|
|
1526
1645
|
id: "better-ask-user-wait",
|
|
@@ -1537,11 +1656,11 @@ function SettingsPage({ form, t = fallbackT }) {
|
|
|
1537
1656
|
}
|
|
1538
1657
|
}
|
|
1539
1658
|
),
|
|
1540
|
-
/* @__PURE__ */ (0,
|
|
1659
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: hintStyle, children: t("waitHint") })
|
|
1541
1660
|
] }),
|
|
1542
|
-
/* @__PURE__ */ (0,
|
|
1543
|
-
/* @__PURE__ */ (0,
|
|
1544
|
-
/* @__PURE__ */ (0,
|
|
1661
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: fieldStyle, children: [
|
|
1662
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("label", { style: labelStyle, htmlFor: "better-ask-user-behavior", children: t("behaviorLabel") }),
|
|
1663
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1545
1664
|
"select",
|
|
1546
1665
|
{
|
|
1547
1666
|
id: "better-ask-user-behavior",
|
|
@@ -1553,16 +1672,16 @@ function SettingsPage({ form, t = fallbackT }) {
|
|
|
1553
1672
|
edit((current) => ({ ...current, timeoutBehavior: next }));
|
|
1554
1673
|
},
|
|
1555
1674
|
children: [
|
|
1556
|
-
/* @__PURE__ */ (0,
|
|
1557
|
-
/* @__PURE__ */ (0,
|
|
1675
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "native", children: t("native") }),
|
|
1676
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "default", children: t("default") })
|
|
1558
1677
|
]
|
|
1559
1678
|
}
|
|
1560
1679
|
),
|
|
1561
|
-
/* @__PURE__ */ (0,
|
|
1680
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: hintStyle, children: t(live.timeoutBehavior === "default" ? "defaultHint" : "nativeHint") })
|
|
1562
1681
|
] }),
|
|
1563
|
-
/* @__PURE__ */ (0,
|
|
1564
|
-
/* @__PURE__ */ (0,
|
|
1565
|
-
/* @__PURE__ */ (0,
|
|
1682
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: fieldStyle, children: [
|
|
1683
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("label", { style: labelStyle, htmlFor: "better-ask-user-goal-behavior", children: t("goalBehaviorLabel") }),
|
|
1684
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1566
1685
|
"select",
|
|
1567
1686
|
{
|
|
1568
1687
|
id: "better-ask-user-goal-behavior",
|
|
@@ -1574,15 +1693,15 @@ function SettingsPage({ form, t = fallbackT }) {
|
|
|
1574
1693
|
edit((current) => ({ ...current, goalTimeoutBehavior: next }));
|
|
1575
1694
|
},
|
|
1576
1695
|
children: [
|
|
1577
|
-
/* @__PURE__ */ (0,
|
|
1578
|
-
/* @__PURE__ */ (0,
|
|
1696
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "native", children: t("native") }),
|
|
1697
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "default", children: t("default") })
|
|
1579
1698
|
]
|
|
1580
1699
|
}
|
|
1581
1700
|
),
|
|
1582
|
-
/* @__PURE__ */ (0,
|
|
1701
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: hintStyle, children: t(live.goalTimeoutBehavior === "default" ? "defaultHint" : "nativeHint") })
|
|
1583
1702
|
] }),
|
|
1584
|
-
/* @__PURE__ */ (0,
|
|
1585
|
-
/* @__PURE__ */ (0,
|
|
1703
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
|
|
1704
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1586
1705
|
"button",
|
|
1587
1706
|
{
|
|
1588
1707
|
type: "button",
|
|
@@ -1600,8 +1719,8 @@ function SettingsPage({ form, t = fallbackT }) {
|
|
|
1600
1719
|
}
|
|
1601
1720
|
function SettingsEntry(props) {
|
|
1602
1721
|
const t = props.t ?? fallbackT;
|
|
1603
|
-
if (props.view === "summary") return /* @__PURE__ */ (0,
|
|
1604
|
-
return /* @__PURE__ */ (0,
|
|
1722
|
+
if (props.view === "summary") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: t("summary") });
|
|
1723
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SettingsPage, { form: props.form, t });
|
|
1605
1724
|
}
|
|
1606
1725
|
|
|
1607
1726
|
// src/client/index.ts
|
|
@@ -1894,6 +2013,15 @@ function apply(ctx) {
|
|
|
1894
2013
|
});
|
|
1895
2014
|
ctx.effect(() => disposePanels, "ui-user-questions: answer panels");
|
|
1896
2015
|
ctx.effect(() => publishContinuedQuestions(ctx, cards), "ui-user-questions: continued questions");
|
|
2016
|
+
ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
|
|
2017
|
+
name: "tool.call.toolview",
|
|
2018
|
+
key: "ask_user_question",
|
|
2019
|
+
locale: NS,
|
|
2020
|
+
inject: (sessionId) => ({
|
|
2021
|
+
revealPanel: (callId) => ctx.get("userQuestionPanels")?.reveal(sessionId, callId) ?? false,
|
|
2022
|
+
reviewPanel: (callId, record) => ctx.get("userQuestionPanels")?.review(sessionId, callId, record) ?? false
|
|
2023
|
+
})
|
|
2024
|
+
}, AskHistoryRow));
|
|
1897
2025
|
ctx.slots.inject("conversation.composer", () => ctx.slots.register(
|
|
1898
2026
|
{
|
|
1899
2027
|
name: "conversation.composer",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-better-ask-user",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Independent ask_user_question plugin: configurable wait, input-extended countdown, markdown/mobile card, native or default timeout behavior, and PTC deadline exemption.",
|
|
5
5
|
"license": "GPL-3.0",
|
|
6
6
|
"repository": {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
.row {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
gap: 8px;
|
|
5
|
+
min-height: 24px;
|
|
6
|
+
min-width: 0;
|
|
7
|
+
color: var(--dsw-alias-label-secondary);
|
|
8
|
+
}
|
|
9
|
+
.icon {
|
|
10
|
+
display: inline-flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
flex: none;
|
|
13
|
+
color: var(--dsw-alias-label-tertiary);
|
|
14
|
+
}
|
|
15
|
+
.title {
|
|
16
|
+
flex: none;
|
|
17
|
+
font: var(--dsw-font-xs-strong-13);
|
|
18
|
+
color: var(--dsw-alias-label-secondary);
|
|
19
|
+
}
|
|
20
|
+
.summary {
|
|
21
|
+
min-width: 0;
|
|
22
|
+
flex: 1;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
text-overflow: ellipsis;
|
|
25
|
+
white-space: nowrap;
|
|
26
|
+
font: var(--dsw-font-xs-13);
|
|
27
|
+
color: var(--dsw-alias-label-tertiary);
|
|
28
|
+
}
|
|
29
|
+
.open {
|
|
30
|
+
flex: none;
|
|
31
|
+
cursor: pointer;
|
|
32
|
+
border: .5px solid var(--dsw-alias-border-l4);
|
|
33
|
+
border-radius: 999px;
|
|
34
|
+
background: var(--dsw-alias-bg-base);
|
|
35
|
+
color: var(--dsw-alias-label-secondary);
|
|
36
|
+
padding: 1px 8px;
|
|
37
|
+
font: var(--dsw-font-xxs-12);
|
|
38
|
+
line-height: 16px;
|
|
39
|
+
}
|
|
40
|
+
.open:hover {
|
|
41
|
+
background: var(--dsw-alias-interactive-bg-hover-solid);
|
|
42
|
+
color: var(--dsw-alias-label-primary);
|
|
43
|
+
}
|
|
44
|
+
.open:focus-visible {
|
|
45
|
+
outline: var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));
|
|
46
|
+
outline-offset: 1px;
|
|
47
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/** History row for ask_user_question: compact summary plus a replay button. */
|
|
2
|
+
import { IconQuestionOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'
|
|
3
|
+
import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots'
|
|
4
|
+
import type { ToolCallViewProps, UserQuestionRecord } from '@deepseek-ai/dsh-client-ui-tool/client'
|
|
5
|
+
import type { AskUserQuestionItem } from '@deepseek-ai/dsh-user-questions/types'
|
|
6
|
+
import type { QuestionKey } from './locales.ts'
|
|
7
|
+
import css from './AskHistoryRow.module.css'
|
|
8
|
+
|
|
9
|
+
type AskHistoryRowProps = ToolCallViewProps & PropsLocale<'question'> & {
|
|
10
|
+
revealPanel: (callId: string) => boolean
|
|
11
|
+
reviewPanel: (callId: string, record: UserQuestionRecord) => boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface AnswerEntry {
|
|
15
|
+
id: string
|
|
16
|
+
selected: string[]
|
|
17
|
+
custom?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
21
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function parseJson(text: string): unknown {
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(text)
|
|
27
|
+
} catch {
|
|
28
|
+
return undefined
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resultText(content: readonly unknown[]): string | undefined {
|
|
33
|
+
const parts: string[] = []
|
|
34
|
+
for (const block of content) {
|
|
35
|
+
if (!isRecord(block) || block.type !== 'text' || typeof block.text !== 'string') continue
|
|
36
|
+
parts.push(block.text)
|
|
37
|
+
}
|
|
38
|
+
return parts.length === 0 ? undefined : parts.join('\n')
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function questionList(argsRaw: string): AskUserQuestionItem[] | undefined {
|
|
42
|
+
const parsed = parseJson(argsRaw)
|
|
43
|
+
if (!isRecord(parsed) || !Array.isArray(parsed.questions) || parsed.questions.length === 0) return undefined
|
|
44
|
+
const questions: AskUserQuestionItem[] = []
|
|
45
|
+
for (const candidate of parsed.questions) {
|
|
46
|
+
if (!isRecord(candidate) || typeof candidate.id !== 'string' || typeof candidate.question !== 'string') return undefined
|
|
47
|
+
questions.push({
|
|
48
|
+
id: candidate.id,
|
|
49
|
+
question: candidate.question,
|
|
50
|
+
...(typeof candidate.header === 'string' ? { header: candidate.header } : {}),
|
|
51
|
+
...(Array.isArray(candidate.options)
|
|
52
|
+
? {
|
|
53
|
+
options: candidate.options.flatMap(option => isRecord(option) && typeof option.label === 'string'
|
|
54
|
+
? [{
|
|
55
|
+
label: option.label,
|
|
56
|
+
...(typeof option.description === 'string' ? { description: option.description } : {}),
|
|
57
|
+
}]
|
|
58
|
+
: []),
|
|
59
|
+
}
|
|
60
|
+
: {}),
|
|
61
|
+
...(typeof candidate.multi_select === 'boolean' ? { multi_select: candidate.multi_select } : {}),
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
return questions
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function answerList(text: string | undefined): AnswerEntry[] | undefined {
|
|
68
|
+
if (text === undefined) return undefined
|
|
69
|
+
const parsed = parseJson(text)
|
|
70
|
+
if (!isRecord(parsed) || !Array.isArray(parsed.answers)) return undefined
|
|
71
|
+
const answers: AnswerEntry[] = []
|
|
72
|
+
for (const candidate of parsed.answers) {
|
|
73
|
+
if (!isRecord(candidate)
|
|
74
|
+
|| typeof candidate.id !== 'string'
|
|
75
|
+
|| !Array.isArray(candidate.selected)
|
|
76
|
+
|| !candidate.selected.every(value => typeof value === 'string')
|
|
77
|
+
|| (candidate.custom !== undefined && typeof candidate.custom !== 'string')) return undefined
|
|
78
|
+
answers.push({
|
|
79
|
+
id: candidate.id,
|
|
80
|
+
selected: candidate.selected,
|
|
81
|
+
...(candidate.custom === undefined ? {} : { custom: candidate.custom }),
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
return answers
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function isPending(text: string | undefined): boolean {
|
|
88
|
+
if (text === undefined) return false
|
|
89
|
+
const parsed = parseJson(text)
|
|
90
|
+
return isRecord(parsed) && parsed.pending === true
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The compact history re-entry for one ask call, top-level or nested. */
|
|
94
|
+
export function AskHistoryRow({
|
|
95
|
+
callId,
|
|
96
|
+
block,
|
|
97
|
+
phase,
|
|
98
|
+
revealPanel,
|
|
99
|
+
reviewPanel,
|
|
100
|
+
t,
|
|
101
|
+
}: AskHistoryRowProps): React.JSX.Element {
|
|
102
|
+
const argsRaw = 'kind' in block ? block.call?.argsRaw ?? '' : block.argsRaw
|
|
103
|
+
const output = 'kind' in block ? resultText(block.content) : undefined
|
|
104
|
+
const questions = questionList(argsRaw)
|
|
105
|
+
const answers = answerList(output)
|
|
106
|
+
const record: UserQuestionRecord | undefined = questions !== undefined && answers !== undefined
|
|
107
|
+
? { questions, answers }
|
|
108
|
+
: undefined
|
|
109
|
+
const summary = questions?.[0]?.question.split('\n').find(line => line.trim() !== '')?.trim() ?? t('history.title')
|
|
110
|
+
const review = record !== undefined
|
|
111
|
+
const action = review
|
|
112
|
+
? () => { reviewPanel(callId, record) }
|
|
113
|
+
: isPending(output) || phase === 'start'
|
|
114
|
+
? () => { revealPanel(callId) }
|
|
115
|
+
: undefined
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<div className={css.row}>
|
|
119
|
+
<span className={css.icon} aria-hidden="true"><IconQuestionOutline14 /></span>
|
|
120
|
+
<span className={css.title}>{t('history.title')}</span>
|
|
121
|
+
<span className={css.summary} title={summary}>{summary}</span>
|
|
122
|
+
{action !== undefined && (
|
|
123
|
+
<button
|
|
124
|
+
type="button"
|
|
125
|
+
className={css.open}
|
|
126
|
+
onClick={action}
|
|
127
|
+
aria-label={review ? t('history.review') : t('history.reopen')}
|
|
128
|
+
>
|
|
129
|
+
{review ? t('history.review') : t('history.reopen')}
|
|
130
|
+
</button>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
133
|
+
)
|
|
134
|
+
}
|
package/src/client/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ import type { ToolCallId } from '@deepseek-ai/dsh-llm'
|
|
|
27
27
|
import { brandString } from '@deepseek-ai/dsh-brand'
|
|
28
28
|
import { createWaterfallRequest, PendingQuestion, type BetterAskConfig, type QuestionRpcChannel } from './contract/slots.ts'
|
|
29
29
|
import { createQuestionDraftStore } from './draft-store.ts'
|
|
30
|
+
import { AskHistoryRow } from './AskHistoryRow.tsx'
|
|
30
31
|
import { QuestionComposer } from './QuestionComposer.tsx'
|
|
31
32
|
import { questionReplyDefinition } from './question-reply.ts'
|
|
32
33
|
import { QuestionReplyView } from './QuestionReplyView.tsx'
|
|
@@ -414,6 +415,15 @@ export function apply(ctx: ClientContext): void {
|
|
|
414
415
|
} satisfies UserQuestionPanels)
|
|
415
416
|
ctx.effect(() => disposePanels, 'ui-user-questions: answer panels')
|
|
416
417
|
ctx.effect(() => publishContinuedQuestions(ctx, cards), 'ui-user-questions: continued questions')
|
|
418
|
+
ctx.slots.inject('tool.call.toolview', () => ctx.slots.register({
|
|
419
|
+
name: 'tool.call.toolview',
|
|
420
|
+
key: 'ask_user_question',
|
|
421
|
+
locale: NS,
|
|
422
|
+
inject: (sessionId: SessionId) => ({
|
|
423
|
+
revealPanel: (callId: string) => ctx.get('userQuestionPanels')?.reveal(sessionId, callId) ?? false,
|
|
424
|
+
reviewPanel: (callId: string, record: UserQuestionRecord) => ctx.get('userQuestionPanels')?.review(sessionId, callId, record) ?? false,
|
|
425
|
+
}),
|
|
426
|
+
}, AskHistoryRow))
|
|
417
427
|
ctx.slots.inject('conversation.composer', () => ctx.slots.register(
|
|
418
428
|
{
|
|
419
429
|
name: 'conversation.composer',
|
package/src/client/locales.ts
CHANGED
|
@@ -7,6 +7,9 @@ export const zh = {
|
|
|
7
7
|
'error.unavailable': '当前无法提交,请稍候再试。',
|
|
8
8
|
'error.resubmit': '回答未送达,工作已继续,请再提交一次。',
|
|
9
9
|
'status.sent': '回答已发送;面板未能关闭。',
|
|
10
|
+
'history.title': '问题',
|
|
11
|
+
'history.review': '查看',
|
|
12
|
+
'history.reopen': '打开',
|
|
10
13
|
'wait.takeTime': '慢慢回答',
|
|
11
14
|
'wait.countdown': '{seconds} 秒后继续工作',
|
|
12
15
|
'wait.paused': '已暂停 · 剩余 {seconds} 秒',
|
|
@@ -47,6 +50,9 @@ export const en = {
|
|
|
47
50
|
'error.unavailable': 'Cannot submit right now; try again in a moment.',
|
|
48
51
|
'error.resubmit': 'The answer did not arrive before work continued; submit it again.',
|
|
49
52
|
'status.sent': 'Reply sent; the panel could not close.',
|
|
53
|
+
'history.title': 'Question',
|
|
54
|
+
'history.review': 'Review',
|
|
55
|
+
'history.reopen': 'Open',
|
|
50
56
|
'wait.takeTime': 'Take time',
|
|
51
57
|
'wait.countdown': 'Continuing in {seconds}s',
|
|
52
58
|
'wait.paused': 'Paused · {seconds}s remaining',
|