@agent-native/core 0.42.0 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -56
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +71 -10
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +13 -13
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.d.ts +2 -6
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +21 -79
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +76 -18
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/blocks/index.d.ts +9 -0
- package/dist/client/blocks/index.d.ts.map +1 -1
- package/dist/client/blocks/index.js +9 -0
- package/dist/client/blocks/index.js.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +3 -3
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.js +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -1
- package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/DiffBlock.js +128 -19
- package/dist/client/blocks/library/DiffBlock.js.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.js +31 -4
- package/dist/client/blocks/library/FileTreeBlock.js.map +1 -1
- package/dist/client/blocks/library/JsonExplorerBlock.js +1 -1
- package/dist/client/blocks/library/JsonExplorerBlock.js.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.js +1 -1
- package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
- package/dist/client/blocks/library/callout.config.d.ts +29 -0
- package/dist/client/blocks/library/callout.config.d.ts.map +1 -0
- package/dist/client/blocks/library/callout.config.js +33 -0
- package/dist/client/blocks/library/callout.config.js.map +1 -0
- package/dist/client/blocks/library/callout.d.ts +20 -0
- package/dist/client/blocks/library/callout.d.ts.map +1 -0
- package/dist/client/blocks/library/callout.js +61 -0
- package/dist/client/blocks/library/callout.js.map +1 -0
- package/dist/client/blocks/library/checklist.d.ts.map +1 -1
- package/dist/client/blocks/library/checklist.js +3 -3
- package/dist/client/blocks/library/checklist.js.map +1 -1
- package/dist/client/blocks/library/code-tabs.js +1 -1
- package/dist/client/blocks/library/code-tabs.js.map +1 -1
- package/dist/client/blocks/library/diagram.config.d.ts +64 -0
- package/dist/client/blocks/library/diagram.config.d.ts.map +1 -0
- package/dist/client/blocks/library/diagram.config.js +111 -0
- package/dist/client/blocks/library/diagram.config.js.map +1 -0
- package/dist/client/blocks/library/diagram.d.ts +16 -0
- package/dist/client/blocks/library/diagram.d.ts.map +1 -0
- package/dist/client/blocks/library/diagram.js +261 -0
- package/dist/client/blocks/library/diagram.js.map +1 -0
- package/dist/client/blocks/library/question-form.config.d.ts +69 -0
- package/dist/client/blocks/library/question-form.config.d.ts.map +1 -0
- package/dist/client/blocks/library/question-form.config.js +58 -0
- package/dist/client/blocks/library/question-form.config.js.map +1 -0
- package/dist/client/blocks/library/question-form.d.ts +20 -0
- package/dist/client/blocks/library/question-form.d.ts.map +1 -0
- package/dist/client/blocks/library/question-form.js +286 -0
- package/dist/client/blocks/library/question-form.js.map +1 -0
- package/dist/client/blocks/library/sanitize-html.d.ts +5 -0
- package/dist/client/blocks/library/sanitize-html.d.ts.map +1 -0
- package/dist/client/blocks/library/sanitize-html.js +240 -0
- package/dist/client/blocks/library/sanitize-html.js.map +1 -0
- package/dist/client/blocks/library/server-specs.d.ts.map +1 -1
- package/dist/client/blocks/library/server-specs.js +49 -0
- package/dist/client/blocks/library/server-specs.js.map +1 -1
- package/dist/client/blocks/library/specs.d.ts.map +1 -1
- package/dist/client/blocks/library/specs.js +9 -0
- package/dist/client/blocks/library/specs.js.map +1 -1
- package/dist/client/blocks/library/tabs.d.ts.map +1 -1
- package/dist/client/blocks/library/tabs.js +12 -12
- package/dist/client/blocks/library/tabs.js.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.d.ts +260 -0
- package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -0
- package/dist/client/blocks/library/wireframe-kit.js +920 -0
- package/dist/client/blocks/library/wireframe-kit.js.map +1 -0
- package/dist/client/blocks/library/wireframe.config.d.ts +123 -0
- package/dist/client/blocks/library/wireframe.config.d.ts.map +1 -0
- package/dist/client/blocks/library/wireframe.config.js +311 -0
- package/dist/client/blocks/library/wireframe.config.js.map +1 -0
- package/dist/client/blocks/library/wireframe.d.ts +15 -0
- package/dist/client/blocks/library/wireframe.d.ts.map +1 -0
- package/dist/client/blocks/library/wireframe.js +206 -0
- package/dist/client/blocks/library/wireframe.js.map +1 -0
- package/dist/client/blocks/mdx.d.ts.map +1 -1
- package/dist/client/blocks/mdx.js +11 -0
- package/dist/client/blocks/mdx.js.map +1 -1
- package/dist/client/blocks/registry.d.ts +9 -0
- package/dist/client/blocks/registry.d.ts.map +1 -1
- package/dist/client/blocks/registry.js +12 -5
- package/dist/client/blocks/registry.js.map +1 -1
- package/dist/client/blocks/server.d.ts +1 -0
- package/dist/client/blocks/server.d.ts.map +1 -1
- package/dist/client/blocks/server.js +1 -0
- package/dist/client/blocks/server.js.map +1 -1
- package/dist/client/blocks/types.d.ts +8 -0
- package/dist/client/blocks/types.d.ts.map +1 -1
- package/dist/client/blocks/types.js.map +1 -1
- package/dist/client/rich-markdown-editor/DragHandle.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/DragHandle.js +112 -84
- package/dist/client/rich-markdown-editor/DragHandle.js.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +9 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js +3 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
- package/dist/client/rich-markdown-editor/extensions.d.ts +13 -1
- package/dist/client/rich-markdown-editor/extensions.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/extensions.js +4 -2
- package/dist/client/rich-markdown-editor/extensions.js.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +11 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +30 -14
- package/dist/server/poll.js.map +1 -1
- package/dist/styles/agent-native.css +1 -0
- package/dist/styles/blocks.css +1388 -0
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +2 -0
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +141 -0
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +2 -0
- package/docs/content/plan-plugin.md +8 -8
- package/docs/content/pr-visual-recap.md +2 -2
- package/docs/content/template-plan.md +94 -17
- package/package.json +2 -1
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +2 -0
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +141 -0
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +2 -0
- package/docs/content/visual-plans.md +0 -82
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { IconCheck, IconChevronDown, IconClipboardText, IconPlus, IconSend, IconTrash, } from "@tabler/icons-react";
|
|
4
|
+
import { cn } from "../../utils.js";
|
|
5
|
+
import { defineBlock } from "../types.js";
|
|
6
|
+
import { questionFormSchema, questionFormMdx, visualQuestionsSchema, visualQuestionsMdx, } from "./question-form.config.js";
|
|
7
|
+
function isAnswered(question, answer) {
|
|
8
|
+
if (question.mode === "freeform")
|
|
9
|
+
return Boolean(answer?.text?.trim());
|
|
10
|
+
return Boolean(answer?.selected?.length || answer?.text?.trim());
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Build a readable, agent-ready summary string from the questions + collected
|
|
14
|
+
* answers. Generic replacement for the plan-specific `summarizeQuestionForm`.
|
|
15
|
+
*/
|
|
16
|
+
function summarizeAnswers(blockId, blockTitle, questions, answers) {
|
|
17
|
+
const lines = [
|
|
18
|
+
"Use these question answers to revise the plan:",
|
|
19
|
+
blockId ? `Question block: ${blockId}` : "",
|
|
20
|
+
blockTitle ? `Section: ${blockTitle}` : "",
|
|
21
|
+
"",
|
|
22
|
+
].filter((line) => line !== "");
|
|
23
|
+
for (const question of questions) {
|
|
24
|
+
const answer = answers[question.id];
|
|
25
|
+
const selectedLabels = question.options
|
|
26
|
+
?.filter((option) => answer?.selected?.includes(option.id))
|
|
27
|
+
.map((option) => option.label) ?? [];
|
|
28
|
+
const other = answer?.text?.trim();
|
|
29
|
+
const value = question.mode === "freeform"
|
|
30
|
+
? other
|
|
31
|
+
: [...selectedLabels, ...(other ? [`Other: ${other}`] : [])].join(", ");
|
|
32
|
+
lines.push(`- ${question.title}: ${value || "No answer yet"}`);
|
|
33
|
+
}
|
|
34
|
+
return lines.join("\n");
|
|
35
|
+
}
|
|
36
|
+
/** Render an inline preview (wireframe or diagram) through the app's dispatcher. */
|
|
37
|
+
function OptionVisual({ type, data, blockId, ctx, }) {
|
|
38
|
+
if (!data || !ctx.renderBlock)
|
|
39
|
+
return null;
|
|
40
|
+
const block = {
|
|
41
|
+
id: `${blockId}-${type}`,
|
|
42
|
+
type,
|
|
43
|
+
data,
|
|
44
|
+
};
|
|
45
|
+
return (_jsx(_Fragment, { children: ctx.renderBlock({ block, editing: false, compactVisuals: true }) }));
|
|
46
|
+
}
|
|
47
|
+
function QuestionView({ question, index, answer, blockId, ctx, onAnswer, }) {
|
|
48
|
+
const selected = answer?.selected ?? [];
|
|
49
|
+
const hasVisualOptions = Boolean(question.options?.some((option) => option.wireframe || option.diagram));
|
|
50
|
+
return (_jsxs("article", { className: "grid gap-4 sm:grid-cols-[36px_minmax(0,1fr)]", children: [_jsx("div", { className: "flex size-7 items-center justify-center rounded-full border border-border bg-card text-xs font-semibold text-muted-foreground", children: index + 1 }), _jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold leading-7 text-foreground", children: question.title }), question.subtitle && (_jsx("p", { className: "mt-1.5 max-w-3xl text-sm leading-6 text-muted-foreground", children: question.subtitle })), question.mode === "freeform" ? (_jsx("textarea", { value: answer?.text ?? "", onChange: (event) => onAnswer({ text: event.target.value }), className: "mt-4 min-h-28 w-full rounded-xl border border-border bg-card px-3 py-2 text-sm text-foreground outline-none transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring", "data-plan-interactive": true, placeholder: question.placeholder || "Add details..." })) : (_jsxs("div", { className: cn("mt-4", hasVisualOptions
|
|
51
|
+
? "grid gap-4 md:grid-cols-2"
|
|
52
|
+
: "grid max-w-4xl gap-3"), children: [question.options?.map((option) => {
|
|
53
|
+
const isSelected = selected.includes(option.id);
|
|
54
|
+
return (_jsxs("button", { type: "button", "data-plan-interactive": true, "aria-pressed": isSelected, className: cn(hasVisualOptions
|
|
55
|
+
? "grid gap-4 rounded-xl border border-border bg-card p-4 text-left transition-colors hover:bg-accent/30"
|
|
56
|
+
: "grid w-full gap-2 rounded-xl border border-border bg-card px-4 py-3 text-left text-foreground transition-colors hover:border-primary/40 hover:bg-accent/30", isSelected && "border-primary/40 bg-primary/10"), onClick: () => {
|
|
57
|
+
if (question.mode === "single") {
|
|
58
|
+
onAnswer({ ...answer, selected: [option.id] });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
onAnswer({
|
|
62
|
+
...answer,
|
|
63
|
+
selected: isSelected
|
|
64
|
+
? selected.filter((id) => id !== option.id)
|
|
65
|
+
: [...selected, option.id],
|
|
66
|
+
});
|
|
67
|
+
}, children: [_jsxs("div", { className: "flex min-w-0 items-start gap-3", children: [_jsx("span", { className: cn("mt-0.5 flex size-5 shrink-0 items-center justify-center border", question.mode === "single" ? "rounded-full" : "rounded", isSelected
|
|
68
|
+
? "border-primary bg-primary text-primary-foreground"
|
|
69
|
+
: "border-border"), children: isSelected && _jsx(IconCheck, { className: "size-3.5" }) }), _jsxs("span", { children: [_jsx("span", { className: "text-base font-semibold leading-6 text-foreground", children: option.label }), option.recommended && (_jsxs(_Fragment, { children: [" ", _jsx("span", { className: "ml-3 rounded-md border border-primary/30 px-2 py-0.5 align-middle text-[11px] font-medium uppercase tracking-[0.12em] text-primary", children: "Recommended" })] })), option.detail && (_jsx("span", { className: "mt-1 block max-w-2xl whitespace-pre-line text-sm font-normal leading-6 text-muted-foreground", children: option.detail }))] })] }), hasVisualOptions && (option.wireframe || option.diagram) && (_jsxs("div", { className: "ml-8 grid gap-4 lg:grid-cols-[minmax(0,1fr)_280px]", children: [option.wireframe != null && (_jsx(OptionVisual, { type: "wireframe", data: option.wireframe, blockId: `${blockId}-${option.id}`, ctx: ctx })), option.diagram != null && (_jsx(OptionVisual, { type: "diagram", data: option.diagram, blockId: `${blockId}-${option.id}`, ctx: ctx }))] }))] }, option.id));
|
|
70
|
+
}), question.allowOther !== false && (_jsx("input", { value: answer?.text ?? "", onChange: (event) => onAnswer({ ...answer, text: event.target.value }), className: cn("h-10 w-full rounded-lg border border-border bg-card px-4 text-sm text-foreground outline-none transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring", hasVisualOptions ? "md:col-span-2" : "sm:w-80"), "data-plan-interactive": true, placeholder: question.placeholder || "Other — type your own answer…" }))] }))] })] }));
|
|
71
|
+
}
|
|
72
|
+
/** The "Send to agent" affordance: a popover (via the app surface) when wired. */
|
|
73
|
+
function SubmitMenu({ blockId, ctx, onSubmit, buildSummary, }) {
|
|
74
|
+
const [open, setOpen] = useState(false);
|
|
75
|
+
const trigger = (_jsxs("button", { type: "button", "data-plan-interactive": true, className: "inline-flex h-9 shrink-0 items-center gap-1.5 rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90", children: ["Send to agent", _jsx(IconChevronDown, { className: "size-3.5 opacity-70" })] }));
|
|
76
|
+
const menu = (_jsxs("div", { className: "grid gap-1", children: [_jsx("div", { className: "px-1 py-1 text-xs font-semibold text-muted-foreground", children: "Send feedback" }), _jsxs("button", { type: "button", "data-plan-interactive": true, disabled: !onSubmit, onClick: () => {
|
|
77
|
+
onSubmit?.(buildSummary());
|
|
78
|
+
setOpen(false);
|
|
79
|
+
}, className: "grid grid-cols-[auto_1fr] items-start gap-2 rounded-md px-2 py-2 text-left text-sm text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50", children: [_jsx(IconSend, { className: "mt-0.5 size-4" }), _jsxs("span", { className: "grid gap-0.5", children: [_jsx("span", { children: "Send to inline agent" }), _jsx("span", { className: "text-xs font-normal leading-4 text-muted-foreground", children: "Posts answered questions into the app side agent." })] })] }), _jsxs("button", { type: "button", "data-plan-interactive": true, onClick: () => {
|
|
80
|
+
void navigator.clipboard.writeText(buildSummary());
|
|
81
|
+
setOpen(false);
|
|
82
|
+
}, className: "grid grid-cols-[auto_1fr] items-start gap-2 rounded-md px-2 py-2 text-left text-sm text-foreground transition-colors hover:bg-accent", children: [_jsx(IconClipboardText, { className: "mt-0.5 size-4" }), _jsxs("span", { className: "grid gap-0.5", children: [_jsx("span", { children: "Copy for your agent" }), _jsx("span", { className: "text-xs font-normal leading-4 text-muted-foreground", children: "Copies a prompt you can paste into chat." })] })] })] }));
|
|
83
|
+
// Prefer the app-provided popover surface (shadcn Popover in plan/content);
|
|
84
|
+
// core stays shadcn-free. Without a surface, fall back to a single button that
|
|
85
|
+
// submits directly so the form still works.
|
|
86
|
+
const surface = ctx.renderEditSurface?.({
|
|
87
|
+
title: "Send to agent",
|
|
88
|
+
open,
|
|
89
|
+
onOpenChange: setOpen,
|
|
90
|
+
blockId,
|
|
91
|
+
blockType: "question-form",
|
|
92
|
+
trigger,
|
|
93
|
+
children: menu,
|
|
94
|
+
});
|
|
95
|
+
if (surface)
|
|
96
|
+
return _jsx(_Fragment, { children: surface });
|
|
97
|
+
return (_jsx("button", { type: "button", "data-plan-interactive": true, disabled: !onSubmit, onClick: () => onSubmit?.(buildSummary()), className: "inline-flex h-9 shrink-0 items-center gap-1.5 rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50", children: "Send to agent" }));
|
|
98
|
+
}
|
|
99
|
+
/** Shared read renderer for both `question-form` and `visual-questions`. */
|
|
100
|
+
function QuestionFormReadInner({ data, blockId, title, ctx, }) {
|
|
101
|
+
const questions = data.questions;
|
|
102
|
+
const [answers, setAnswers] = useState({});
|
|
103
|
+
const submitCtx = ctx;
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
setAnswers({});
|
|
106
|
+
}, [blockId]);
|
|
107
|
+
const setAnswer = (questionId, next) => {
|
|
108
|
+
setAnswers((current) => ({ ...current, [questionId]: next }));
|
|
109
|
+
};
|
|
110
|
+
const answered = questions.filter((question) => isAnswered(question, answers[question.id])).length;
|
|
111
|
+
const buildSummary = () => summarizeAnswers(blockId, title, questions, answers);
|
|
112
|
+
return (_jsxs("section", { className: "an-questions-block plan-questions-block", "data-block-id": blockId, children: [title && (_jsx("h2", { className: "text-[1.45rem] font-semibold leading-tight text-foreground", children: title })), _jsx("div", { className: "mt-7 grid gap-8", children: questions.map((question, index) => (_jsx(QuestionView, { question: question, index: index, answer: answers[question.id], blockId: blockId, ctx: ctx, onAnswer: (next) => setAnswer(question.id, next) }, question.id))) }), _jsxs("div", { className: "sticky bottom-0 mt-10 flex items-center justify-between gap-4 border-t border-border bg-background py-4 backdrop-blur", children: [_jsxs("p", { className: "text-sm font-semibold text-muted-foreground", children: [answered, "/", questions.length, " answered"] }), _jsx("div", { "data-plan-interactive": true, children: _jsx(SubmitMenu, { blockId: blockId, ctx: ctx, onSubmit: submitCtx.onQuestionFormSubmit, buildSummary: buildSummary }) })] })] }));
|
|
113
|
+
}
|
|
114
|
+
export function QuestionFormRead(props) {
|
|
115
|
+
return _jsx(QuestionFormReadInner, { ...props });
|
|
116
|
+
}
|
|
117
|
+
export function VisualQuestionsRead(props) {
|
|
118
|
+
return _jsx(QuestionFormReadInner, { ...props });
|
|
119
|
+
}
|
|
120
|
+
const inlineInputClass = "w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground shadow-sm outline-none transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring";
|
|
121
|
+
const inlineTextareaClass = "w-full resize-y rounded-md border border-border bg-background px-3 py-2 text-sm leading-6 text-foreground shadow-sm outline-none transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring";
|
|
122
|
+
const inlineLabelClass = "text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground";
|
|
123
|
+
function newLocalId(prefix) {
|
|
124
|
+
return `${prefix}-${Math.random().toString(36).slice(2, 10)}`;
|
|
125
|
+
}
|
|
126
|
+
/** Shared editor for both `question-form` and `visual-questions`. */
|
|
127
|
+
export function QuestionFormEdit({ data, onChange, editable, }) {
|
|
128
|
+
const updateQuestion = (questionId, patch) => onChange({
|
|
129
|
+
...data,
|
|
130
|
+
questions: data.questions.map((question) => question.id === questionId ? { ...question, ...patch } : question),
|
|
131
|
+
});
|
|
132
|
+
const addQuestion = () => {
|
|
133
|
+
if (data.questions.length >= 40)
|
|
134
|
+
return;
|
|
135
|
+
onChange({
|
|
136
|
+
...data,
|
|
137
|
+
questions: [
|
|
138
|
+
...data.questions,
|
|
139
|
+
{
|
|
140
|
+
id: newLocalId("question"),
|
|
141
|
+
title: "New question",
|
|
142
|
+
mode: "freeform",
|
|
143
|
+
placeholder: "Type an answer...",
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
const removeQuestion = (questionId) => {
|
|
149
|
+
if (data.questions.length <= 1)
|
|
150
|
+
return;
|
|
151
|
+
onChange({
|
|
152
|
+
...data,
|
|
153
|
+
questions: data.questions.filter((question) => question.id !== questionId),
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
const setQuestionMode = (question, mode) => updateQuestion(question.id, {
|
|
157
|
+
mode,
|
|
158
|
+
options: mode === "freeform"
|
|
159
|
+
? question.options
|
|
160
|
+
: question.options && question.options.length > 0
|
|
161
|
+
? question.options
|
|
162
|
+
: [
|
|
163
|
+
{ id: newLocalId("option"), label: "Option A" },
|
|
164
|
+
{ id: newLocalId("option"), label: "Option B" },
|
|
165
|
+
],
|
|
166
|
+
});
|
|
167
|
+
const updateOption = (questionId, optionId, patch) => onChange({
|
|
168
|
+
...data,
|
|
169
|
+
questions: data.questions.map((question) => question.id === questionId
|
|
170
|
+
? {
|
|
171
|
+
...question,
|
|
172
|
+
options: (question.options ?? []).map((option) => option.id === optionId ? { ...option, ...patch } : option),
|
|
173
|
+
}
|
|
174
|
+
: question),
|
|
175
|
+
});
|
|
176
|
+
const addOption = (questionId) => onChange({
|
|
177
|
+
...data,
|
|
178
|
+
questions: data.questions.map((question) => question.id === questionId && (question.options?.length ?? 0) < 40
|
|
179
|
+
? {
|
|
180
|
+
...question,
|
|
181
|
+
options: [
|
|
182
|
+
...(question.options ?? []),
|
|
183
|
+
{ id: newLocalId("option"), label: "New option" },
|
|
184
|
+
],
|
|
185
|
+
}
|
|
186
|
+
: question),
|
|
187
|
+
});
|
|
188
|
+
const removeOption = (questionId, optionId) => onChange({
|
|
189
|
+
...data,
|
|
190
|
+
questions: data.questions.map((question) => {
|
|
191
|
+
if (question.id !== questionId)
|
|
192
|
+
return question;
|
|
193
|
+
const nextOptions = (question.options ?? []).filter((option) => option.id !== optionId);
|
|
194
|
+
return { ...question, options: nextOptions };
|
|
195
|
+
}),
|
|
196
|
+
});
|
|
197
|
+
return (_jsxs("div", { className: "grid gap-6", "data-plan-interactive": true, children: [_jsx("div", { className: "grid gap-4", children: data.questions.map((question, index) => {
|
|
198
|
+
const options = question.options ?? [];
|
|
199
|
+
return (_jsxs("article", { className: "rounded-lg border border-border bg-card p-4", children: [_jsxs("div", { className: "mb-4 flex items-center justify-between gap-3", children: [_jsxs("span", { className: inlineLabelClass, children: ["Question ", index + 1] }), data.questions.length > 1 && (_jsx("button", { type: "button", "aria-label": `Delete question ${index + 1}`, className: "inline-flex size-8 items-center justify-center rounded-md border border-border text-muted-foreground hover:bg-muted hover:text-foreground", disabled: !editable, onClick: () => removeQuestion(question.id), children: _jsx(IconTrash, { className: "size-4" }) }))] }), _jsxs("div", { className: "grid gap-3 md:grid-cols-[minmax(0,1fr)_12rem]", children: [_jsxs("label", { className: "grid gap-1.5", children: [_jsx("span", { className: inlineLabelClass, children: "Title" }), _jsx("input", { className: inlineInputClass, value: question.title, disabled: !editable, onChange: (event) => updateQuestion(question.id, {
|
|
200
|
+
title: event.target.value,
|
|
201
|
+
}) })] }), _jsxs("label", { className: "grid gap-1.5", children: [_jsx("span", { className: inlineLabelClass, children: "Mode" }), _jsxs("select", { className: inlineInputClass, value: question.mode, disabled: !editable, onChange: (event) => setQuestionMode(question, event.target.value), children: [_jsx("option", { value: "freeform", children: "Freeform" }), _jsx("option", { value: "single", children: "Single choice" }), _jsx("option", { value: "multi", children: "Multi choice" })] })] })] }), _jsxs("label", { className: "mt-3 grid gap-1.5", children: [_jsx("span", { className: inlineLabelClass, children: "Subtitle" }), _jsx("textarea", { className: inlineTextareaClass, rows: 2, value: question.subtitle ?? "", disabled: !editable, onChange: (event) => updateQuestion(question.id, {
|
|
202
|
+
subtitle: event.target.value || undefined,
|
|
203
|
+
}) })] }), _jsxs("div", { className: "mt-3 grid gap-3 md:grid-cols-[minmax(0,1fr)_auto_auto]", children: [_jsxs("label", { className: "grid gap-1.5", children: [_jsx("span", { className: inlineLabelClass, children: "Placeholder" }), _jsx("input", { className: inlineInputClass, value: question.placeholder ?? "", disabled: !editable, onChange: (event) => updateQuestion(question.id, {
|
|
204
|
+
placeholder: event.target.value || undefined,
|
|
205
|
+
}) })] }), _jsxs("label", { className: "flex items-end gap-2 text-sm font-semibold text-muted-foreground", children: [_jsx("input", { type: "checkbox", className: "mb-2 size-4", checked: Boolean(question.required), disabled: !editable, onChange: (event) => updateQuestion(question.id, {
|
|
206
|
+
required: event.target.checked || undefined,
|
|
207
|
+
}) }), "Required"] }), question.mode !== "freeform" && (_jsxs("label", { className: "flex items-end gap-2 text-sm font-semibold text-muted-foreground", children: [_jsx("input", { type: "checkbox", className: "mb-2 size-4", checked: question.allowOther !== false, disabled: !editable, onChange: (event) => updateQuestion(question.id, {
|
|
208
|
+
allowOther: event.target.checked ? undefined : false,
|
|
209
|
+
}) }), "Allow write-in"] }))] }), question.mode !== "freeform" && (_jsxs("div", { className: "mt-4 grid gap-3", children: [options.map((option) => (_jsxs("div", { className: "grid gap-3 rounded-md border border-border/80 bg-background p-3 md:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto]", children: [_jsxs("label", { className: "grid gap-1.5", children: [_jsx("span", { className: inlineLabelClass, children: "Option" }), _jsx("input", { className: inlineInputClass, value: option.label, disabled: !editable, onChange: (event) => updateOption(question.id, option.id, {
|
|
210
|
+
label: event.target.value,
|
|
211
|
+
}) })] }), _jsxs("label", { className: "grid gap-1.5", children: [_jsx("span", { className: inlineLabelClass, children: "Detail" }), _jsx("input", { className: inlineInputClass, value: option.detail ?? "", disabled: !editable, onChange: (event) => updateOption(question.id, option.id, {
|
|
212
|
+
detail: event.target.value || undefined,
|
|
213
|
+
}) })] }), _jsxs("div", { className: "flex items-end gap-2", children: [_jsxs("button", { type: "button", className: cn("inline-flex h-9 items-center gap-1.5 rounded-md border border-border px-3 text-sm font-semibold text-muted-foreground hover:bg-muted hover:text-foreground", option.recommended && "border-ring text-foreground"), disabled: !editable, onClick: () => updateOption(question.id, option.id, {
|
|
214
|
+
recommended: !option.recommended,
|
|
215
|
+
}), children: [option.recommended && (_jsx(IconCheck, { className: "size-4" })), "Recommended"] }), options.length > 1 && (_jsx("button", { type: "button", "aria-label": `Delete ${option.label}`, className: "inline-flex size-9 items-center justify-center rounded-md border border-border text-muted-foreground hover:bg-muted hover:text-foreground", disabled: !editable, onClick: () => removeOption(question.id, option.id), children: _jsx(IconTrash, { className: "size-4" }) }))] })] }, option.id))), _jsxs("button", { type: "button", className: "inline-flex h-9 w-fit items-center gap-1.5 rounded-md border border-border px-3 text-sm font-semibold text-muted-foreground hover:bg-muted hover:text-foreground", disabled: !editable || options.length >= 40, onClick: () => addOption(question.id), children: [_jsx(IconPlus, { className: "size-4" }), "Add option"] })] }))] }, question.id));
|
|
216
|
+
}) }), _jsxs("button", { type: "button", className: "inline-flex h-9 w-fit items-center gap-1.5 rounded-md border border-border px-3 text-sm font-semibold text-muted-foreground hover:bg-muted hover:text-foreground", disabled: !editable || data.questions.length >= 40, onClick: addQuestion, children: [_jsx(IconPlus, { className: "size-4" }), "Add question"] })] }));
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Full client spec for the shared `question-form` block. A respondent-facing
|
|
220
|
+
* intake form edited from the block panel (the schema-ish question shape lives
|
|
221
|
+
* behind the edit surface, not inline).
|
|
222
|
+
*/
|
|
223
|
+
export const questionFormBlock = defineBlock({
|
|
224
|
+
type: "question-form",
|
|
225
|
+
schema: questionFormSchema,
|
|
226
|
+
mdx: questionFormMdx,
|
|
227
|
+
Read: QuestionFormRead,
|
|
228
|
+
Edit: QuestionFormEdit,
|
|
229
|
+
placement: ["block"],
|
|
230
|
+
editSurface: "panel",
|
|
231
|
+
label: "Question form",
|
|
232
|
+
description: "An interactive respondent-facing form block for open questions, single-choice or multi-choice option rows, freeform answers, recommended options, and optional wireframe/diagram previews. Edit the question schema from the block panel.",
|
|
233
|
+
empty: () => ({
|
|
234
|
+
submitLabel: "Send to agent",
|
|
235
|
+
questions: [
|
|
236
|
+
{
|
|
237
|
+
id: "open-question",
|
|
238
|
+
title: "What should the agent clarify before revising this plan?",
|
|
239
|
+
mode: "freeform",
|
|
240
|
+
placeholder: "Add constraints, preferences, or a decision...",
|
|
241
|
+
},
|
|
242
|
+
],
|
|
243
|
+
}),
|
|
244
|
+
});
|
|
245
|
+
/**
|
|
246
|
+
* Full client spec for the shared `visual-questions` block — the same form UI
|
|
247
|
+
* and data shape as `question-form`, branded for explicit visual intake before a
|
|
248
|
+
* plan. Shares the Read/Edit internals; only the type, MDX tag, label, and seed
|
|
249
|
+
* differ.
|
|
250
|
+
*/
|
|
251
|
+
export const visualQuestionsBlock = defineBlock({
|
|
252
|
+
type: "visual-questions",
|
|
253
|
+
schema: visualQuestionsSchema,
|
|
254
|
+
mdx: visualQuestionsMdx,
|
|
255
|
+
Read: VisualQuestionsRead,
|
|
256
|
+
Edit: QuestionFormEdit,
|
|
257
|
+
placement: ["block"],
|
|
258
|
+
editSurface: "panel",
|
|
259
|
+
label: "Visual questions",
|
|
260
|
+
description: "A visual-intake question block that renders the respondent-facing question UI (single/multi/freeform, recommended options, inline wireframe/diagram previews) and keeps schema editing in the block panel.",
|
|
261
|
+
empty: () => ({
|
|
262
|
+
submitLabel: "Send to agent",
|
|
263
|
+
questions: [
|
|
264
|
+
{
|
|
265
|
+
id: "visual-question",
|
|
266
|
+
title: "Which direction should this plan take?",
|
|
267
|
+
mode: "single",
|
|
268
|
+
options: [
|
|
269
|
+
{
|
|
270
|
+
id: "option-a",
|
|
271
|
+
label: "Direction A",
|
|
272
|
+
detail: "Keep the current shape and refine it.",
|
|
273
|
+
recommended: true,
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
id: "option-b",
|
|
277
|
+
label: "Direction B",
|
|
278
|
+
detail: "Try a larger structural revision.",
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
allowOther: true,
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
}),
|
|
285
|
+
});
|
|
286
|
+
//# sourceMappingURL=question-form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"question-form.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/question-form.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EACL,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,SAAS,GACV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,kBAAkB,GAMnB,MAAM,2BAA2B,CAAC;AAyCnC,SAAS,UAAU,CACjB,QAA8B,EAC9B,MAAuB;IAEvB,IAAI,QAAQ,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACvE,OAAO,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACnE,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CACvB,OAA2B,EAC3B,UAA8B,EAC9B,SAAiC,EACjC,OAAwB;IAExB,MAAM,KAAK,GAAG;QACZ,gDAAgD;QAChD,OAAO,CAAC,CAAC,CAAC,mBAAmB,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE;QAC3C,UAAU,CAAC,CAAC,CAAC,YAAY,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE;QAC1C,EAAE;KACH,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;IAChC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACpC,MAAM,cAAc,GAClB,QAAQ,CAAC,OAAO;YACd,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;aAC1D,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACnC,MAAM,KAAK,GACT,QAAQ,CAAC,IAAI,KAAK,UAAU;YAC1B,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,CAAC,GAAG,cAAc,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5E,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,KAAK,KAAK,IAAI,eAAe,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,oFAAoF;AACpF,SAAS,YAAY,CAAC,EACpB,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,GAAG,GAMJ;IACC,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,KAAK,GAAgB;QACzB,EAAE,EAAE,GAAG,OAAO,IAAI,IAAI,EAAE;QACxB,IAAI;QACJ,IAAI;KACL,CAAC;IACF,OAAO,CACL,4BAAG,GAAG,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,GAAI,CACxE,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,EACpB,QAAQ,EACR,KAAK,EACL,MAAM,EACN,OAAO,EACP,GAAG,EACH,QAAQ,GAQT;IACC,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC;IACxC,MAAM,gBAAgB,GAAG,OAAO,CAC9B,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC,CACvE,CAAC;IACF,OAAO,CACL,mBAAS,SAAS,EAAC,8CAA8C,aAC/D,cAAK,SAAS,EAAC,+HAA+H,YAC3I,KAAK,GAAG,CAAC,GACN,EACN,0BACE,aAAI,SAAS,EAAC,iDAAiD,YAC5D,QAAQ,CAAC,KAAK,GACZ,EACJ,QAAQ,CAAC,QAAQ,IAAI,CACpB,YAAG,SAAS,EAAC,0DAA0D,YACpE,QAAQ,CAAC,QAAQ,GAChB,CACL,EACA,QAAQ,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAC9B,mBACE,KAAK,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,EACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,EAC3D,SAAS,EAAC,8MAA8M,iCAExN,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,gBAAgB,GACrD,CACH,CAAC,CAAC,CAAC,CACF,eACE,SAAS,EAAE,EAAE,CACX,MAAM,EACN,gBAAgB;4BACd,CAAC,CAAC,2BAA2B;4BAC7B,CAAC,CAAC,sBAAsB,CAC3B,aAEA,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;gCAChC,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gCAChD,OAAO,CACL,kBAEE,IAAI,EAAC,QAAQ,iDAEC,UAAU,EACxB,SAAS,EAAE,EAAE,CACX,gBAAgB;wCACd,CAAC,CAAC,uGAAuG;wCACzG,CAAC,CAAC,4JAA4J,EAChK,UAAU,IAAI,iCAAiC,CAChD,EACD,OAAO,EAAE,GAAG,EAAE;wCACZ,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;4CAC/B,QAAQ,CAAC,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;4CAC/C,OAAO;wCACT,CAAC;wCACD,QAAQ,CAAC;4CACP,GAAG,MAAM;4CACT,QAAQ,EAAE,UAAU;gDAClB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC;gDAC3C,CAAC,CAAC,CAAC,GAAG,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;yCAC7B,CAAC,CAAC;oCACL,CAAC,aAED,eAAK,SAAS,EAAC,gCAAgC,aAC7C,eACE,SAAS,EAAE,EAAE,CACX,gEAAgE,EAChE,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,EACvD,UAAU;wDACR,CAAC,CAAC,mDAAmD;wDACrD,CAAC,CAAC,eAAe,CACpB,YAEA,UAAU,IAAI,KAAC,SAAS,IAAC,SAAS,EAAC,UAAU,GAAG,GAC5C,EACP,2BACE,eAAM,SAAS,EAAC,mDAAmD,YAChE,MAAM,CAAC,KAAK,GACR,EACN,MAAM,CAAC,WAAW,IAAI,CACrB,8BACG,GAAG,EACJ,eAAM,SAAS,EAAC,oIAAoI,4BAE7I,IACN,CACJ,EACA,MAAM,CAAC,MAAM,IAAI,CAChB,eAAM,SAAS,EAAC,8FAA8F,YAC3G,MAAM,CAAC,MAAM,GACT,CACR,IACI,IACH,EACL,gBAAgB,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAC3D,eAAK,SAAS,EAAC,oDAAoD,aAChE,MAAM,CAAC,SAAS,IAAI,IAAI,IAAI,CAC3B,KAAC,YAAY,IACX,IAAI,EAAC,WAAW,EAChB,IAAI,EAAE,MAAM,CAAC,SAAS,EACtB,OAAO,EAAE,GAAG,OAAO,IAAI,MAAM,CAAC,EAAE,EAAE,EAClC,GAAG,EAAE,GAAG,GACR,CACH,EACA,MAAM,CAAC,OAAO,IAAI,IAAI,IAAI,CACzB,KAAC,YAAY,IACX,IAAI,EAAC,SAAS,EACd,IAAI,EAAE,MAAM,CAAC,OAAO,EACpB,OAAO,EAAE,GAAG,OAAO,IAAI,MAAM,CAAC,EAAE,EAAE,EAClC,GAAG,EAAE,GAAG,GACR,CACH,IACG,CACP,KAzEI,MAAM,CAAC,EAAE,CA0EP,CACV,CAAC;4BACJ,CAAC,CAAC,EAID,QAAQ,CAAC,UAAU,KAAK,KAAK,IAAI,CAChC,gBACE,KAAK,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,EACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,QAAQ,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,EAEnD,SAAS,EAAE,EAAE,CACX,gMAAgM,EAChM,gBAAgB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAC/C,iCAED,WAAW,EACT,QAAQ,CAAC,WAAW,IAAI,+BAA+B,GAEzD,CACH,IACG,CACP,IACG,IACE,CACX,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,SAAS,UAAU,CAAC,EAClB,OAAO,EACP,GAAG,EACH,QAAQ,EACR,YAAY,GAMb;IACC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,CACd,kBACE,IAAI,EAAC,QAAQ,iCAEb,SAAS,EAAC,4JAA4J,8BAGtK,KAAC,eAAe,IAAC,SAAS,EAAC,qBAAqB,GAAG,IAC5C,CACV,CAAC;IAEF,MAAM,IAAI,GAAG,CACX,eAAK,SAAS,EAAC,YAAY,aACzB,cAAK,SAAS,EAAC,uDAAuD,8BAEhE,EACN,kBACE,IAAI,EAAC,QAAQ,iCAEb,QAAQ,EAAE,CAAC,QAAQ,EACnB,OAAO,EAAE,GAAG,EAAE;oBACZ,QAAQ,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;oBAC3B,OAAO,CAAC,KAAK,CAAC,CAAC;gBACjB,CAAC,EACD,SAAS,EAAC,sLAAsL,aAEhM,KAAC,QAAQ,IAAC,SAAS,EAAC,eAAe,GAAG,EACtC,gBAAM,SAAS,EAAC,cAAc,aAC5B,kDAAiC,EACjC,eAAM,SAAS,EAAC,qDAAqD,kEAE9D,IACF,IACA,EACT,kBACE,IAAI,EAAC,QAAQ,iCAEb,OAAO,EAAE,GAAG,EAAE;oBACZ,KAAK,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;oBACnD,OAAO,CAAC,KAAK,CAAC,CAAC;gBACjB,CAAC,EACD,SAAS,EAAC,sIAAsI,aAEhJ,KAAC,iBAAiB,IAAC,SAAS,EAAC,eAAe,GAAG,EAC/C,gBAAM,SAAS,EAAC,cAAc,aAC5B,iDAAgC,EAChC,eAAM,SAAS,EAAC,qDAAqD,yDAE9D,IACF,IACA,IACL,CACP,CAAC;IAEF,4EAA4E;IAC5E,+EAA+E;IAC/E,4CAA4C;IAC5C,MAAM,OAAO,GAAG,GAAG,CAAC,iBAAiB,EAAE,CAAC;QACtC,KAAK,EAAE,eAAe;QACtB,IAAI;QACJ,YAAY,EAAE,OAAO;QACrB,OAAO;QACP,SAAS,EAAE,eAAe;QAC1B,OAAO;QACP,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;IACH,IAAI,OAAO;QAAE,OAAO,4BAAG,OAAO,GAAI,CAAC;IAEnC,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ,iCAEb,QAAQ,EAAE,CAAC,QAAQ,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,YAAY,EAAE,CAAC,EACzC,SAAS,EAAC,4MAA4M,8BAG/M,CACV,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,SAAS,qBAAqB,CAAC,EAC7B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,GAAG,GAC8B;IACjC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IACjC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAkB,EAAE,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,GAA4B,CAAC;IAE/C,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,MAAM,SAAS,GAAG,CAAC,UAAkB,EAAE,IAAoB,EAAE,EAAE;QAC7D,UAAU,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAC7C,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAC3C,CAAC,MAAM,CAAC;IACT,MAAM,YAAY,GAAG,GAAG,EAAE,CACxB,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAEvD,OAAO,CACL,mBACE,SAAS,EAAC,yCAAyC,mBACpC,OAAO,aAErB,KAAK,IAAI,CACR,aAAI,SAAS,EAAC,4DAA4D,YACvE,KAAK,GACH,CACN,EACD,cAAK,SAAS,EAAC,iBAAiB,YAC7B,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,CAClC,KAAC,YAAY,IAEX,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAC5B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,IAN3C,QAAQ,CAAC,EAAE,CAOhB,CACH,CAAC,GACE,EACN,eAAK,SAAS,EAAC,uHAAuH,aACpI,aAAG,SAAS,EAAC,6CAA6C,aACvD,QAAQ,OAAG,SAAS,CAAC,MAAM,iBAC1B,EACJ,uDACE,KAAC,UAAU,IACT,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,SAAS,CAAC,oBAAoB,EACxC,YAAY,EAAE,YAAY,GAC1B,GACE,IACF,IACE,CACX,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAuC;IACtE,OAAO,KAAC,qBAAqB,OAAK,KAAK,GAAI,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,KAA0C;IAE1C,OAAO,KAAC,qBAAqB,OAAK,KAAK,GAAI,CAAC;AAC9C,CAAC;AAED,MAAM,gBAAgB,GACpB,gNAAgN,CAAC;AACnN,MAAM,mBAAmB,GACvB,mOAAmO,CAAC;AACtO,MAAM,gBAAgB,GACpB,6EAA6E,CAAC;AAEhF,SAAS,UAAU,CAAC,MAAc;IAChC,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AAChE,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,gBAAgB,CAAC,EAC/B,IAAI,EACJ,QAAQ,EACR,QAAQ,GACyB;IACjC,MAAM,cAAc,GAAG,CACrB,UAAkB,EAClB,KAAoC,EACpC,EAAE,CACF,QAAQ,CAAC;QACP,GAAG,IAAI;QACP,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CACzC,QAAQ,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAClE;KACF,CAAC,CAAC;IAEL,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE;YAAE,OAAO;QACxC,QAAQ,CAAC;YACP,GAAG,IAAI;YACP,SAAS,EAAE;gBACT,GAAG,IAAI,CAAC,SAAS;gBACjB;oBACE,EAAE,EAAE,UAAU,CAAC,UAAU,CAAC;oBAC1B,KAAK,EAAE,cAAc;oBACrB,IAAI,EAAE,UAAU;oBAChB,WAAW,EAAE,mBAAmB;iBACjC;aACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,UAAkB,EAAE,EAAE;QAC5C,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC;YAAE,OAAO;QACvC,QAAQ,CAAC;YACP,GAAG,IAAI;YACP,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAC9B,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,UAAU,CACzC;SACF,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,CACtB,QAA8B,EAC9B,IAAkB,EAClB,EAAE,CACF,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE;QAC1B,IAAI;QACJ,OAAO,EACL,IAAI,KAAK,UAAU;YACjB,CAAC,CAAC,QAAQ,CAAC,OAAO;YAClB,CAAC,CAAC,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;gBAC/C,CAAC,CAAC,QAAQ,CAAC,OAAO;gBAClB,CAAC,CAAC;oBACE,EAAE,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE;oBAC/C,EAAE,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE;iBAChD;KACV,CAAC,CAAC;IAEL,MAAM,YAAY,GAAG,CACnB,UAAkB,EAClB,QAAgB,EAChB,KAAkC,EAClC,EAAE,CACF,QAAQ,CAAC;QACP,GAAG,IAAI;QACP,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CACzC,QAAQ,CAAC,EAAE,KAAK,UAAU;YACxB,CAAC,CAAC;gBACE,GAAG,QAAQ;gBACX,OAAO,EAAE,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAC/C,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAC1D;aACF;YACH,CAAC,CAAC,QAAQ,CACb;KACF,CAAC,CAAC;IAEL,MAAM,SAAS,GAAG,CAAC,UAAkB,EAAE,EAAE,CACvC,QAAQ,CAAC;QACP,GAAG,IAAI;QACP,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CACzC,QAAQ,CAAC,EAAE,KAAK,UAAU,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,EAAE;YAChE,CAAC,CAAC;gBACE,GAAG,QAAQ;gBACX,OAAO,EAAE;oBACP,GAAG,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC;oBAC3B,EAAE,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE;iBAClD;aACF;YACH,CAAC,CAAC,QAAQ,CACb;KACF,CAAC,CAAC;IAEL,MAAM,YAAY,GAAG,CAAC,UAAkB,EAAE,QAAgB,EAAE,EAAE,CAC5D,QAAQ,CAAC;QACP,GAAG,IAAI;QACP,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;YACzC,IAAI,QAAQ,CAAC,EAAE,KAAK,UAAU;gBAAE,OAAO,QAAQ,CAAC;YAChD,MAAM,WAAW,GAAG,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CACjD,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,QAAQ,CACnC,CAAC;YACF,OAAO,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;QAC/C,CAAC,CAAC;KACH,CAAC,CAAC;IAEL,OAAO,CACL,eAAK,SAAS,EAAC,YAAY,4CACzB,cAAK,SAAS,EAAC,YAAY,YACxB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE;oBACtC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC;oBACvC,OAAO,CACL,mBAEE,SAAS,EAAC,6CAA6C,aAEvD,eAAK,SAAS,EAAC,8CAA8C,aAC3D,gBAAM,SAAS,EAAE,gBAAgB,0BAAY,KAAK,GAAG,CAAC,IAAQ,EAC7D,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAC5B,iBACE,IAAI,EAAC,QAAQ,gBACD,mBAAmB,KAAK,GAAG,CAAC,EAAE,EAC1C,SAAS,EAAC,2IAA2I,EACrJ,QAAQ,EAAE,CAAC,QAAQ,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC,YAE1C,KAAC,SAAS,IAAC,SAAS,EAAC,QAAQ,GAAG,GACzB,CACV,IACG,EACN,eAAK,SAAS,EAAC,+CAA+C,aAC5D,iBAAO,SAAS,EAAC,cAAc,aAC7B,eAAM,SAAS,EAAE,gBAAgB,sBAAc,EAC/C,gBACE,SAAS,EAAE,gBAAgB,EAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK,EACrB,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE;oDAC1B,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK;iDAC1B,CAAC,GAEJ,IACI,EACR,iBAAO,SAAS,EAAC,cAAc,aAC7B,eAAM,SAAS,EAAE,gBAAgB,qBAAa,EAC9C,kBACE,SAAS,EAAE,gBAAgB,EAC3B,KAAK,EAAE,QAAQ,CAAC,IAAI,EACpB,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,eAAe,CACb,QAAQ,EACR,KAAK,CAAC,MAAM,CAAC,KAAqB,CACnC,aAGH,iBAAQ,KAAK,EAAC,UAAU,yBAAkB,EAC1C,iBAAQ,KAAK,EAAC,QAAQ,8BAAuB,EAC7C,iBAAQ,KAAK,EAAC,OAAO,6BAAsB,IACpC,IACH,IACJ,EACN,iBAAO,SAAS,EAAC,mBAAmB,aAClC,eAAM,SAAS,EAAE,gBAAgB,yBAAiB,EAClD,mBACE,SAAS,EAAE,mBAAmB,EAC9B,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,QAAQ,CAAC,QAAQ,IAAI,EAAE,EAC9B,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE;4CAC1B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS;yCAC1C,CAAC,GAEJ,IACI,EACR,eAAK,SAAS,EAAC,wDAAwD,aACrE,iBAAO,SAAS,EAAC,cAAc,aAC7B,eAAM,SAAS,EAAE,gBAAgB,4BAAoB,EACrD,gBACE,SAAS,EAAE,gBAAgB,EAC3B,KAAK,EAAE,QAAQ,CAAC,WAAW,IAAI,EAAE,EACjC,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE;oDAC1B,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS;iDAC7C,CAAC,GAEJ,IACI,EACR,iBAAO,SAAS,EAAC,kEAAkE,aACjF,gBACE,IAAI,EAAC,UAAU,EACf,SAAS,EAAC,aAAa,EACvB,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EACnC,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE;oDAC1B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,IAAI,SAAS;iDAC5C,CAAC,GAEJ,gBAEI,EACP,QAAQ,CAAC,IAAI,KAAK,UAAU,IAAI,CAC/B,iBAAO,SAAS,EAAC,kEAAkE,aACjF,gBACE,IAAI,EAAC,UAAU,EACf,SAAS,EAAC,aAAa,EACvB,OAAO,EAAE,QAAQ,CAAC,UAAU,KAAK,KAAK,EACtC,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE;oDAC1B,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK;iDACrD,CAAC,GAEJ,sBAEI,CACT,IACG,EACL,QAAQ,CAAC,IAAI,KAAK,UAAU,IAAI,CAC/B,eAAK,SAAS,EAAC,iBAAiB,aAC7B,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACvB,eAEE,SAAS,EAAC,iHAAiH,aAE3H,iBAAO,SAAS,EAAC,cAAc,aAC7B,eAAM,SAAS,EAAE,gBAAgB,uBAAe,EAChD,gBACE,SAAS,EAAE,gBAAgB,EAC3B,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,YAAY,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;4DACnC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK;yDAC1B,CAAC,GAEJ,IACI,EACR,iBAAO,SAAS,EAAC,cAAc,aAC7B,eAAM,SAAS,EAAE,gBAAgB,uBAAe,EAChD,gBACE,SAAS,EAAE,gBAAgB,EAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE,EAC1B,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,YAAY,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;4DACnC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS;yDACxC,CAAC,GAEJ,IACI,EACR,eAAK,SAAS,EAAC,sBAAsB,aACnC,kBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,EAAE,CACX,4JAA4J,EAC5J,MAAM,CAAC,WAAW,IAAI,6BAA6B,CACpD,EACD,QAAQ,EAAE,CAAC,QAAQ,EACnB,OAAO,EAAE,GAAG,EAAE,CACZ,YAAY,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;4DACnC,WAAW,EAAE,CAAC,MAAM,CAAC,WAAW;yDACjC,CAAC,aAGH,MAAM,CAAC,WAAW,IAAI,CACrB,KAAC,SAAS,IAAC,SAAS,EAAC,QAAQ,GAAG,CACjC,mBAEM,EACR,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CACrB,iBACE,IAAI,EAAC,QAAQ,gBACD,UAAU,MAAM,CAAC,KAAK,EAAE,EACpC,SAAS,EAAC,2IAA2I,EACrJ,QAAQ,EAAE,CAAC,QAAQ,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,YAEnD,KAAC,SAAS,IAAC,SAAS,EAAC,QAAQ,GAAG,GACzB,CACV,IACG,KA3DD,MAAM,CAAC,EAAE,CA4DV,CACP,CAAC,EACF,kBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,kKAAkK,EAC5K,QAAQ,EAAE,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE,EAC3C,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,aAErC,KAAC,QAAQ,IAAC,SAAS,EAAC,QAAQ,GAAG,kBAExB,IACL,CACP,KAzLI,QAAQ,CAAC,EAAE,CA0LR,CACX,CAAC;gBACJ,CAAC,CAAC,GACE,EACN,kBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,kKAAkK,EAC5K,QAAQ,EAAE,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE,EAClD,OAAO,EAAE,WAAW,aAEpB,KAAC,QAAQ,IAAC,SAAS,EAAC,QAAQ,GAAG,oBAExB,IACL,CACP,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAmB;IAC7D,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,kBAAkB;IAC1B,GAAG,EAAE,eAAe;IACpB,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,gBAAgB;IACtB,SAAS,EAAE,CAAC,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO;IACpB,KAAK,EAAE,eAAe;IACtB,WAAW,EACT,2OAA2O;IAC7O,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACZ,WAAW,EAAE,eAAe;QAC5B,SAAS,EAAE;YACT;gBACE,EAAE,EAAE,eAAe;gBACnB,KAAK,EAAE,0DAA0D;gBACjE,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,gDAAgD;aAC9D;SACF;KACF,CAAC;CACH,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,WAAW,CAAsB;IACnE,IAAI,EAAE,kBAAkB;IACxB,MAAM,EAAE,qBAAqB;IAC7B,GAAG,EAAE,kBAAkB;IACvB,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,gBAAgB;IACtB,SAAS,EAAE,CAAC,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO;IACpB,KAAK,EAAE,kBAAkB;IACzB,WAAW,EACT,4MAA4M;IAC9M,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACZ,WAAW,EAAE,eAAe;QAC5B,SAAS,EAAE;YACT;gBACE,EAAE,EAAE,iBAAiB;gBACrB,KAAK,EAAE,wCAAwC;gBAC/C,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE;oBACP;wBACE,EAAE,EAAE,UAAU;wBACd,KAAK,EAAE,aAAa;wBACpB,MAAM,EAAE,uCAAuC;wBAC/C,WAAW,EAAE,IAAI;qBAClB;oBACD;wBACE,EAAE,EAAE,UAAU;wBACd,KAAK,EAAE,aAAa;wBACpB,MAAM,EAAE,mCAAmC;qBAC5C;iBACF;gBACD,UAAU,EAAE,IAAI;aACjB;SACF;KACF,CAAC;CACH,CAAC,CAAC","sourcesContent":["import { useEffect, useState } from \"react\";\nimport {\n IconCheck,\n IconChevronDown,\n IconClipboardText,\n IconPlus,\n IconSend,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport { defineBlock } from \"../types.js\";\nimport type {\n BlockReadProps,\n BlockEditProps,\n BlockRenderContext,\n NestedBlock,\n} from \"../types.js\";\nimport {\n questionFormSchema,\n questionFormMdx,\n visualQuestionsSchema,\n visualQuestionsMdx,\n type QuestionFormData,\n type QuestionFormOption,\n type QuestionFormQuestion,\n type QuestionMode,\n type VisualQuestionsData,\n} from \"./question-form.config.js\";\n\n/**\n * Shared `question-form` and `visual-questions` blocks. A respondent-facing\n * intake form: single/multi/freeform questions, recommended options, optional\n * write-in answers, and optional inline wireframe/diagram previews per option.\n * Lives in core so any app can register it (it originated in the plan template).\n *\n * The block stays app-agnostic:\n * - It is shadcn-free. The \"Send to agent\" affordance uses `ctx.renderEditSurface`\n * (the app-provided popover primitive); when no surface is wired it falls back\n * to a plain button that submits directly.\n * - Submission routes through `ctx.onQuestionFormSubmit` so each app wires its own\n * destination (plan posts the summary into the side agent). The readable summary\n * string is built generically here from questions + collected answers.\n * - Per-option `wireframe`/`diagram` previews render through `ctx.renderBlock`\n * (the same nested-block seam tabs/columns use), so core never imports an app's\n * wireframe or diagram renderer.\n * - Colors map to shadcn theme tokens (`text-muted-foreground`, `border-border`,\n * `bg-background`, `bg-card`, `primary`). The root section carries BOTH the\n * app-neutral `an-questions-block` class and the legacy `plan-questions-block`\n * class so plan renders byte-identically while other apps get the theme treatment.\n */\n\n/**\n * `ctx.onQuestionFormSubmit` is the documented submit hook. It is read off the\n * render context as an optional extra so a host that has not yet added it to its\n * provider degrades to a no-op (the button disables) rather than throwing.\n */\ntype QuestionFormSubmitCtx = BlockRenderContext & {\n onQuestionFormSubmit?: (summary: string) => void;\n};\n\n/**\n * Reviewer answers are transient and never persisted on block data — they live\n * in local component state keyed by question id. `freeform` → a string;\n * `single`/`multi` → selected option ids (with an optional write-in `text`).\n */\ntype QuestionAnswer = { text?: string; selected?: string[] };\ntype QuestionAnswers = Record<string, QuestionAnswer>;\n\nfunction isAnswered(\n question: QuestionFormQuestion,\n answer?: QuestionAnswer,\n): boolean {\n if (question.mode === \"freeform\") return Boolean(answer?.text?.trim());\n return Boolean(answer?.selected?.length || answer?.text?.trim());\n}\n\n/**\n * Build a readable, agent-ready summary string from the questions + collected\n * answers. Generic replacement for the plan-specific `summarizeQuestionForm`.\n */\nfunction summarizeAnswers(\n blockId: string | undefined,\n blockTitle: string | undefined,\n questions: QuestionFormQuestion[],\n answers: QuestionAnswers,\n): string {\n const lines = [\n \"Use these question answers to revise the plan:\",\n blockId ? `Question block: ${blockId}` : \"\",\n blockTitle ? `Section: ${blockTitle}` : \"\",\n \"\",\n ].filter((line) => line !== \"\");\n for (const question of questions) {\n const answer = answers[question.id];\n const selectedLabels =\n question.options\n ?.filter((option) => answer?.selected?.includes(option.id))\n .map((option) => option.label) ?? [];\n const other = answer?.text?.trim();\n const value =\n question.mode === \"freeform\"\n ? other\n : [...selectedLabels, ...(other ? [`Other: ${other}`] : [])].join(\", \");\n lines.push(`- ${question.title}: ${value || \"No answer yet\"}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** Render an inline preview (wireframe or diagram) through the app's dispatcher. */\nfunction OptionVisual({\n type,\n data,\n blockId,\n ctx,\n}: {\n type: \"wireframe\" | \"diagram\";\n data: unknown;\n blockId: string;\n ctx: BlockRenderContext;\n}) {\n if (!data || !ctx.renderBlock) return null;\n const block: NestedBlock = {\n id: `${blockId}-${type}`,\n type,\n data,\n };\n return (\n <>{ctx.renderBlock({ block, editing: false, compactVisuals: true })}</>\n );\n}\n\nfunction QuestionView({\n question,\n index,\n answer,\n blockId,\n ctx,\n onAnswer,\n}: {\n question: QuestionFormQuestion;\n index: number;\n answer?: QuestionAnswer;\n blockId: string;\n ctx: BlockRenderContext;\n onAnswer: (answer: QuestionAnswer) => void;\n}) {\n const selected = answer?.selected ?? [];\n const hasVisualOptions = Boolean(\n question.options?.some((option) => option.wireframe || option.diagram),\n );\n return (\n <article className=\"grid gap-4 sm:grid-cols-[36px_minmax(0,1fr)]\">\n <div className=\"flex size-7 items-center justify-center rounded-full border border-border bg-card text-xs font-semibold text-muted-foreground\">\n {index + 1}\n </div>\n <div>\n <h3 className=\"text-lg font-semibold leading-7 text-foreground\">\n {question.title}\n </h3>\n {question.subtitle && (\n <p className=\"mt-1.5 max-w-3xl text-sm leading-6 text-muted-foreground\">\n {question.subtitle}\n </p>\n )}\n {question.mode === \"freeform\" ? (\n <textarea\n value={answer?.text ?? \"\"}\n onChange={(event) => onAnswer({ text: event.target.value })}\n className=\"mt-4 min-h-28 w-full rounded-xl border border-border bg-card px-3 py-2 text-sm text-foreground outline-none transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring\"\n data-plan-interactive\n placeholder={question.placeholder || \"Add details...\"}\n />\n ) : (\n <div\n className={cn(\n \"mt-4\",\n hasVisualOptions\n ? \"grid gap-4 md:grid-cols-2\"\n : \"grid max-w-4xl gap-3\",\n )}\n >\n {question.options?.map((option) => {\n const isSelected = selected.includes(option.id);\n return (\n <button\n key={option.id}\n type=\"button\"\n data-plan-interactive\n aria-pressed={isSelected}\n className={cn(\n hasVisualOptions\n ? \"grid gap-4 rounded-xl border border-border bg-card p-4 text-left transition-colors hover:bg-accent/30\"\n : \"grid w-full gap-2 rounded-xl border border-border bg-card px-4 py-3 text-left text-foreground transition-colors hover:border-primary/40 hover:bg-accent/30\",\n isSelected && \"border-primary/40 bg-primary/10\",\n )}\n onClick={() => {\n if (question.mode === \"single\") {\n onAnswer({ ...answer, selected: [option.id] });\n return;\n }\n onAnswer({\n ...answer,\n selected: isSelected\n ? selected.filter((id) => id !== option.id)\n : [...selected, option.id],\n });\n }}\n >\n <div className=\"flex min-w-0 items-start gap-3\">\n <span\n className={cn(\n \"mt-0.5 flex size-5 shrink-0 items-center justify-center border\",\n question.mode === \"single\" ? \"rounded-full\" : \"rounded\",\n isSelected\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-border\",\n )}\n >\n {isSelected && <IconCheck className=\"size-3.5\" />}\n </span>\n <span>\n <span className=\"text-base font-semibold leading-6 text-foreground\">\n {option.label}\n </span>\n {option.recommended && (\n <>\n {\" \"}\n <span className=\"ml-3 rounded-md border border-primary/30 px-2 py-0.5 align-middle text-[11px] font-medium uppercase tracking-[0.12em] text-primary\">\n Recommended\n </span>\n </>\n )}\n {option.detail && (\n <span className=\"mt-1 block max-w-2xl whitespace-pre-line text-sm font-normal leading-6 text-muted-foreground\">\n {option.detail}\n </span>\n )}\n </span>\n </div>\n {hasVisualOptions && (option.wireframe || option.diagram) && (\n <div className=\"ml-8 grid gap-4 lg:grid-cols-[minmax(0,1fr)_280px]\">\n {option.wireframe != null && (\n <OptionVisual\n type=\"wireframe\"\n data={option.wireframe}\n blockId={`${blockId}-${option.id}`}\n ctx={ctx}\n />\n )}\n {option.diagram != null && (\n <OptionVisual\n type=\"diagram\"\n data={option.diagram}\n blockId={`${blockId}-${option.id}`}\n ctx={ctx}\n />\n )}\n </div>\n )}\n </button>\n );\n })}\n {/* Multiple-choice questions always offer a write-in answer so a\n reviewer can give a custom response instead of the listed\n options. Authors opt out only by setting allowOther: false. */}\n {question.allowOther !== false && (\n <input\n value={answer?.text ?? \"\"}\n onChange={(event) =>\n onAnswer({ ...answer, text: event.target.value })\n }\n className={cn(\n \"h-10 w-full rounded-lg border border-border bg-card px-4 text-sm text-foreground outline-none transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring\",\n hasVisualOptions ? \"md:col-span-2\" : \"sm:w-80\",\n )}\n data-plan-interactive\n placeholder={\n question.placeholder || \"Other — type your own answer…\"\n }\n />\n )}\n </div>\n )}\n </div>\n </article>\n );\n}\n\n/** The \"Send to agent\" affordance: a popover (via the app surface) when wired. */\nfunction SubmitMenu({\n blockId,\n ctx,\n onSubmit,\n buildSummary,\n}: {\n blockId: string;\n ctx: BlockRenderContext;\n onSubmit?: (summary: string) => void;\n buildSummary: () => string;\n}) {\n const [open, setOpen] = useState(false);\n const trigger = (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"inline-flex h-9 shrink-0 items-center gap-1.5 rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90\"\n >\n Send to agent\n <IconChevronDown className=\"size-3.5 opacity-70\" />\n </button>\n );\n\n const menu = (\n <div className=\"grid gap-1\">\n <div className=\"px-1 py-1 text-xs font-semibold text-muted-foreground\">\n Send feedback\n </div>\n <button\n type=\"button\"\n data-plan-interactive\n disabled={!onSubmit}\n onClick={() => {\n onSubmit?.(buildSummary());\n setOpen(false);\n }}\n className=\"grid grid-cols-[auto_1fr] items-start gap-2 rounded-md px-2 py-2 text-left text-sm text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <IconSend className=\"mt-0.5 size-4\" />\n <span className=\"grid gap-0.5\">\n <span>Send to inline agent</span>\n <span className=\"text-xs font-normal leading-4 text-muted-foreground\">\n Posts answered questions into the app side agent.\n </span>\n </span>\n </button>\n <button\n type=\"button\"\n data-plan-interactive\n onClick={() => {\n void navigator.clipboard.writeText(buildSummary());\n setOpen(false);\n }}\n className=\"grid grid-cols-[auto_1fr] items-start gap-2 rounded-md px-2 py-2 text-left text-sm text-foreground transition-colors hover:bg-accent\"\n >\n <IconClipboardText className=\"mt-0.5 size-4\" />\n <span className=\"grid gap-0.5\">\n <span>Copy for your agent</span>\n <span className=\"text-xs font-normal leading-4 text-muted-foreground\">\n Copies a prompt you can paste into chat.\n </span>\n </span>\n </button>\n </div>\n );\n\n // Prefer the app-provided popover surface (shadcn Popover in plan/content);\n // core stays shadcn-free. Without a surface, fall back to a single button that\n // submits directly so the form still works.\n const surface = ctx.renderEditSurface?.({\n title: \"Send to agent\",\n open,\n onOpenChange: setOpen,\n blockId,\n blockType: \"question-form\",\n trigger,\n children: menu,\n });\n if (surface) return <>{surface}</>;\n\n return (\n <button\n type=\"button\"\n data-plan-interactive\n disabled={!onSubmit}\n onClick={() => onSubmit?.(buildSummary())}\n className=\"inline-flex h-9 shrink-0 items-center gap-1.5 rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n Send to agent\n </button>\n );\n}\n\n/** Shared read renderer for both `question-form` and `visual-questions`. */\nfunction QuestionFormReadInner({\n data,\n blockId,\n title,\n ctx,\n}: BlockReadProps<QuestionFormData>) {\n const questions = data.questions;\n const [answers, setAnswers] = useState<QuestionAnswers>({});\n const submitCtx = ctx as QuestionFormSubmitCtx;\n\n useEffect(() => {\n setAnswers({});\n }, [blockId]);\n\n const setAnswer = (questionId: string, next: QuestionAnswer) => {\n setAnswers((current) => ({ ...current, [questionId]: next }));\n };\n\n const answered = questions.filter((question) =>\n isAnswered(question, answers[question.id]),\n ).length;\n const buildSummary = () =>\n summarizeAnswers(blockId, title, questions, answers);\n\n return (\n <section\n className=\"an-questions-block plan-questions-block\"\n data-block-id={blockId}\n >\n {title && (\n <h2 className=\"text-[1.45rem] font-semibold leading-tight text-foreground\">\n {title}\n </h2>\n )}\n <div className=\"mt-7 grid gap-8\">\n {questions.map((question, index) => (\n <QuestionView\n key={question.id}\n question={question}\n index={index}\n answer={answers[question.id]}\n blockId={blockId}\n ctx={ctx}\n onAnswer={(next) => setAnswer(question.id, next)}\n />\n ))}\n </div>\n <div className=\"sticky bottom-0 mt-10 flex items-center justify-between gap-4 border-t border-border bg-background py-4 backdrop-blur\">\n <p className=\"text-sm font-semibold text-muted-foreground\">\n {answered}/{questions.length} answered\n </p>\n <div data-plan-interactive>\n <SubmitMenu\n blockId={blockId}\n ctx={ctx}\n onSubmit={submitCtx.onQuestionFormSubmit}\n buildSummary={buildSummary}\n />\n </div>\n </div>\n </section>\n );\n}\n\nexport function QuestionFormRead(props: BlockReadProps<QuestionFormData>) {\n return <QuestionFormReadInner {...props} />;\n}\n\nexport function VisualQuestionsRead(\n props: BlockReadProps<VisualQuestionsData>,\n) {\n return <QuestionFormReadInner {...props} />;\n}\n\nconst inlineInputClass =\n \"w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground shadow-sm outline-none transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring\";\nconst inlineTextareaClass =\n \"w-full resize-y rounded-md border border-border bg-background px-3 py-2 text-sm leading-6 text-foreground shadow-sm outline-none transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring\";\nconst inlineLabelClass =\n \"text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground\";\n\nfunction newLocalId(prefix: string): string {\n return `${prefix}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/** Shared editor for both `question-form` and `visual-questions`. */\nexport function QuestionFormEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<QuestionFormData>) {\n const updateQuestion = (\n questionId: string,\n patch: Partial<QuestionFormQuestion>,\n ) =>\n onChange({\n ...data,\n questions: data.questions.map((question) =>\n question.id === questionId ? { ...question, ...patch } : question,\n ),\n });\n\n const addQuestion = () => {\n if (data.questions.length >= 40) return;\n onChange({\n ...data,\n questions: [\n ...data.questions,\n {\n id: newLocalId(\"question\"),\n title: \"New question\",\n mode: \"freeform\",\n placeholder: \"Type an answer...\",\n },\n ],\n });\n };\n\n const removeQuestion = (questionId: string) => {\n if (data.questions.length <= 1) return;\n onChange({\n ...data,\n questions: data.questions.filter(\n (question) => question.id !== questionId,\n ),\n });\n };\n\n const setQuestionMode = (\n question: QuestionFormQuestion,\n mode: QuestionMode,\n ) =>\n updateQuestion(question.id, {\n mode,\n options:\n mode === \"freeform\"\n ? question.options\n : question.options && question.options.length > 0\n ? question.options\n : [\n { id: newLocalId(\"option\"), label: \"Option A\" },\n { id: newLocalId(\"option\"), label: \"Option B\" },\n ],\n });\n\n const updateOption = (\n questionId: string,\n optionId: string,\n patch: Partial<QuestionFormOption>,\n ) =>\n onChange({\n ...data,\n questions: data.questions.map((question) =>\n question.id === questionId\n ? {\n ...question,\n options: (question.options ?? []).map((option) =>\n option.id === optionId ? { ...option, ...patch } : option,\n ),\n }\n : question,\n ),\n });\n\n const addOption = (questionId: string) =>\n onChange({\n ...data,\n questions: data.questions.map((question) =>\n question.id === questionId && (question.options?.length ?? 0) < 40\n ? {\n ...question,\n options: [\n ...(question.options ?? []),\n { id: newLocalId(\"option\"), label: \"New option\" },\n ],\n }\n : question,\n ),\n });\n\n const removeOption = (questionId: string, optionId: string) =>\n onChange({\n ...data,\n questions: data.questions.map((question) => {\n if (question.id !== questionId) return question;\n const nextOptions = (question.options ?? []).filter(\n (option) => option.id !== optionId,\n );\n return { ...question, options: nextOptions };\n }),\n });\n\n return (\n <div className=\"grid gap-6\" data-plan-interactive>\n <div className=\"grid gap-4\">\n {data.questions.map((question, index) => {\n const options = question.options ?? [];\n return (\n <article\n key={question.id}\n className=\"rounded-lg border border-border bg-card p-4\"\n >\n <div className=\"mb-4 flex items-center justify-between gap-3\">\n <span className={inlineLabelClass}>Question {index + 1}</span>\n {data.questions.length > 1 && (\n <button\n type=\"button\"\n aria-label={`Delete question ${index + 1}`}\n className=\"inline-flex size-8 items-center justify-center rounded-md border border-border text-muted-foreground hover:bg-muted hover:text-foreground\"\n disabled={!editable}\n onClick={() => removeQuestion(question.id)}\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n <div className=\"grid gap-3 md:grid-cols-[minmax(0,1fr)_12rem]\">\n <label className=\"grid gap-1.5\">\n <span className={inlineLabelClass}>Title</span>\n <input\n className={inlineInputClass}\n value={question.title}\n disabled={!editable}\n onChange={(event) =>\n updateQuestion(question.id, {\n title: event.target.value,\n })\n }\n />\n </label>\n <label className=\"grid gap-1.5\">\n <span className={inlineLabelClass}>Mode</span>\n <select\n className={inlineInputClass}\n value={question.mode}\n disabled={!editable}\n onChange={(event) =>\n setQuestionMode(\n question,\n event.target.value as QuestionMode,\n )\n }\n >\n <option value=\"freeform\">Freeform</option>\n <option value=\"single\">Single choice</option>\n <option value=\"multi\">Multi choice</option>\n </select>\n </label>\n </div>\n <label className=\"mt-3 grid gap-1.5\">\n <span className={inlineLabelClass}>Subtitle</span>\n <textarea\n className={inlineTextareaClass}\n rows={2}\n value={question.subtitle ?? \"\"}\n disabled={!editable}\n onChange={(event) =>\n updateQuestion(question.id, {\n subtitle: event.target.value || undefined,\n })\n }\n />\n </label>\n <div className=\"mt-3 grid gap-3 md:grid-cols-[minmax(0,1fr)_auto_auto]\">\n <label className=\"grid gap-1.5\">\n <span className={inlineLabelClass}>Placeholder</span>\n <input\n className={inlineInputClass}\n value={question.placeholder ?? \"\"}\n disabled={!editable}\n onChange={(event) =>\n updateQuestion(question.id, {\n placeholder: event.target.value || undefined,\n })\n }\n />\n </label>\n <label className=\"flex items-end gap-2 text-sm font-semibold text-muted-foreground\">\n <input\n type=\"checkbox\"\n className=\"mb-2 size-4\"\n checked={Boolean(question.required)}\n disabled={!editable}\n onChange={(event) =>\n updateQuestion(question.id, {\n required: event.target.checked || undefined,\n })\n }\n />\n Required\n </label>\n {question.mode !== \"freeform\" && (\n <label className=\"flex items-end gap-2 text-sm font-semibold text-muted-foreground\">\n <input\n type=\"checkbox\"\n className=\"mb-2 size-4\"\n checked={question.allowOther !== false}\n disabled={!editable}\n onChange={(event) =>\n updateQuestion(question.id, {\n allowOther: event.target.checked ? undefined : false,\n })\n }\n />\n Allow write-in\n </label>\n )}\n </div>\n {question.mode !== \"freeform\" && (\n <div className=\"mt-4 grid gap-3\">\n {options.map((option) => (\n <div\n key={option.id}\n className=\"grid gap-3 rounded-md border border-border/80 bg-background p-3 md:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto]\"\n >\n <label className=\"grid gap-1.5\">\n <span className={inlineLabelClass}>Option</span>\n <input\n className={inlineInputClass}\n value={option.label}\n disabled={!editable}\n onChange={(event) =>\n updateOption(question.id, option.id, {\n label: event.target.value,\n })\n }\n />\n </label>\n <label className=\"grid gap-1.5\">\n <span className={inlineLabelClass}>Detail</span>\n <input\n className={inlineInputClass}\n value={option.detail ?? \"\"}\n disabled={!editable}\n onChange={(event) =>\n updateOption(question.id, option.id, {\n detail: event.target.value || undefined,\n })\n }\n />\n </label>\n <div className=\"flex items-end gap-2\">\n <button\n type=\"button\"\n className={cn(\n \"inline-flex h-9 items-center gap-1.5 rounded-md border border-border px-3 text-sm font-semibold text-muted-foreground hover:bg-muted hover:text-foreground\",\n option.recommended && \"border-ring text-foreground\",\n )}\n disabled={!editable}\n onClick={() =>\n updateOption(question.id, option.id, {\n recommended: !option.recommended,\n })\n }\n >\n {option.recommended && (\n <IconCheck className=\"size-4\" />\n )}\n Recommended\n </button>\n {options.length > 1 && (\n <button\n type=\"button\"\n aria-label={`Delete ${option.label}`}\n className=\"inline-flex size-9 items-center justify-center rounded-md border border-border text-muted-foreground hover:bg-muted hover:text-foreground\"\n disabled={!editable}\n onClick={() => removeOption(question.id, option.id)}\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n </div>\n ))}\n <button\n type=\"button\"\n className=\"inline-flex h-9 w-fit items-center gap-1.5 rounded-md border border-border px-3 text-sm font-semibold text-muted-foreground hover:bg-muted hover:text-foreground\"\n disabled={!editable || options.length >= 40}\n onClick={() => addOption(question.id)}\n >\n <IconPlus className=\"size-4\" />\n Add option\n </button>\n </div>\n )}\n </article>\n );\n })}\n </div>\n <button\n type=\"button\"\n className=\"inline-flex h-9 w-fit items-center gap-1.5 rounded-md border border-border px-3 text-sm font-semibold text-muted-foreground hover:bg-muted hover:text-foreground\"\n disabled={!editable || data.questions.length >= 40}\n onClick={addQuestion}\n >\n <IconPlus className=\"size-4\" />\n Add question\n </button>\n </div>\n );\n}\n\n/**\n * Full client spec for the shared `question-form` block. A respondent-facing\n * intake form edited from the block panel (the schema-ish question shape lives\n * behind the edit surface, not inline).\n */\nexport const questionFormBlock = defineBlock<QuestionFormData>({\n type: \"question-form\",\n schema: questionFormSchema,\n mdx: questionFormMdx,\n Read: QuestionFormRead,\n Edit: QuestionFormEdit,\n placement: [\"block\"],\n editSurface: \"panel\",\n label: \"Question form\",\n description:\n \"An interactive respondent-facing form block for open questions, single-choice or multi-choice option rows, freeform answers, recommended options, and optional wireframe/diagram previews. Edit the question schema from the block panel.\",\n empty: () => ({\n submitLabel: \"Send to agent\",\n questions: [\n {\n id: \"open-question\",\n title: \"What should the agent clarify before revising this plan?\",\n mode: \"freeform\",\n placeholder: \"Add constraints, preferences, or a decision...\",\n },\n ],\n }),\n});\n\n/**\n * Full client spec for the shared `visual-questions` block — the same form UI\n * and data shape as `question-form`, branded for explicit visual intake before a\n * plan. Shares the Read/Edit internals; only the type, MDX tag, label, and seed\n * differ.\n */\nexport const visualQuestionsBlock = defineBlock<VisualQuestionsData>({\n type: \"visual-questions\",\n schema: visualQuestionsSchema,\n mdx: visualQuestionsMdx,\n Read: VisualQuestionsRead,\n Edit: QuestionFormEdit,\n placement: [\"block\"],\n editSurface: \"panel\",\n label: \"Visual questions\",\n description:\n \"A visual-intake question block that renders the respondent-facing question UI (single/multi/freeform, recommended options, inline wireframe/diagram previews) and keeps schema editing in the block panel.\",\n empty: () => ({\n submitLabel: \"Send to agent\",\n questions: [\n {\n id: \"visual-question\",\n title: \"Which direction should this plan take?\",\n mode: \"single\",\n options: [\n {\n id: \"option-a\",\n label: \"Direction A\",\n detail: \"Keep the current shape and refine it.\",\n recommended: true,\n },\n {\n id: \"option-b\",\n label: \"Direction B\",\n detail: \"Try a larger structural revision.\",\n },\n ],\n allowOther: true,\n },\n ],\n }),\n});\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function sanitizeWireframeHtml(html: string | undefined): string;
|
|
2
|
+
export declare function sanitizeDiagramHtml(html: string | undefined): string;
|
|
3
|
+
export declare function sanitizeWireframeCss(css: string | undefined): string;
|
|
4
|
+
export declare function scopeDesignCss(css: string, scopeSelector: string): string;
|
|
5
|
+
//# sourceMappingURL=sanitize-html.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize-html.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/sanitize-html.ts"],"names":[],"mappings":"AAqHA,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAStE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAcpE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAoBpE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAsBzE"}
|