();
if (presented !== question) {
setOutgoing(current.current);
setPresented(question);
if (immediately) setActive(question);
}
current.current = { children, question };
useEffect(() => {
if (active !== question) setActive(question);
}, [active, question]);
return (
{outgoing && (
setOutgoing(step => step?.question === outgoing.question ? undefined : step)}
>
{outgoing.children}
)}
{children}
);
}
function Undecided(
{ canEdit, connected, motion, value, wire, ...pointing }:
& {
canEdit: boolean;
connected: boolean;
motion?: QuestionStepMotion;
value: Questionnaire;
wire?: Transport;
}
& Pointing,
) {
let state = useQuestionnaire({
id: value.id,
bridge: wire,
connected,
definition: definition(value),
});
let answerable = connected && !!state.definition;
let editable = canEdit && answerable;
return (
person.handle)} />}
renderStep={motion
? ({ children, question }) => (
{children}
)
: undefined}
status="open"
submitting={state.submitting}
{...pointing}
/>
);
}
function Decided(
{ resolved, value, ...pointing }: { resolved: Answer[]; value: Questionnaire } & Pointing,
) {
return (
}
>
);
}
/**
* Whether a resolved decision is carried entirely by a margin marker.
*
* Only when every question has prose to sit beside. Pending, deliberately
* empty and orphaned decisions have nowhere to put a marker, so they keep a
* compact card rather than vanishing from the plan.
*/
export function carriedByMarkers(
value: Questionnaire,
places: { [question: string]: number } | undefined,
): boolean {
return !!places
&& value.questions.length > 0
&& value.questions.every(question =>
question.answer !== undefined && (places[question.id] ?? 0) > 0
);
}
function InlineQuestionnaire({ value }: { value: Questionnaire }) {
let options = useCellValue(widgets$);
// Re-render when anchors arrive: whether the card collapses depends on them.
useRelations(options.questions);
let places = options.questions?.counts(value.id);
if (carriedByMarkers(value, places)) {
return ;
}
return (
options.questions?.highlight(value.id, question)}
onQuestionLeave={() => options.questions?.clear()}
onQuestionSelect={question => options.questions?.reveal(value.id, question)}
places={places}
value={value}
wire={options.wire}
/>
);
}
export function renderQuestionnaire(node: QuestionnaireNode) {
// React renders decorators after Lexical's read transaction has ended.
return ;
}