Give MultiSelect chips accessible names and start creation fields empty.
Catalog chips now announce Select or Deselect so they are named for assistive tech. Method and value modals open blank; Generate draft inserts the catalog copy that used to be prefilled, and Customize still keeps the section headings. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
fd9f82ea19
commit
20ea4a2f30
35 files changed
+498
-156
No files matched your search
@@ -14,11 +14,10 @@ import type {
|
||||
} from "../../app/(app)/create/types";
|
||||
|
||||
/**
|
||||
* Per-method preset defaults shipped in `messages/en/create/customRule/*.json`.
|
||||
* Used to seed the final-review edit modal when the user has no saved
|
||||
* override yet, and to merge onto overrides when emitting the published rule
|
||||
* document so every method carries a complete section payload even if the
|
||||
* author only edited a subset of fields.
|
||||
* Catalog copy for method/value sections. Generate draft inserts these into
|
||||
* empty creation-modal fields. Publish still merges them onto saved overrides
|
||||
* so every method carries a complete section payload when the author only
|
||||
* edited a subset of fields.
|
||||
*/
|
||||
type CustomRuleMethodRow = {
|
||||
id: string;
|
||||
@@ -96,6 +95,10 @@ export function communicationPresetFor(
|
||||
};
|
||||
}
|
||||
|
||||
export function emptyCommunicationDetails(): CommunicationMethodDetailEntry {
|
||||
return { corePrinciple: "", logisticsAdmin: "", codeOfConduct: "" };
|
||||
}
|
||||
|
||||
export function membershipPresetFor(id: string): MembershipMethodDetailEntry {
|
||||
const method = findMethod(membershipMessages, id);
|
||||
const s = method?.sections ?? {};
|
||||
@@ -106,6 +109,10 @@ export function membershipPresetFor(id: string): MembershipMethodDetailEntry {
|
||||
};
|
||||
}
|
||||
|
||||
export function emptyMembershipDetails(): MembershipMethodDetailEntry {
|
||||
return { eligibility: "", joiningProcess: "", expectations: "" };
|
||||
}
|
||||
|
||||
/** Default consensus level used when a **catalog** preset omits a value. */
|
||||
export const DECISION_CONSENSUS_LEVEL_DEFAULT = 75;
|
||||
|
||||
@@ -132,6 +139,20 @@ export function decisionApproachPresetFor(
|
||||
return entry;
|
||||
}
|
||||
|
||||
/** Catalog scopes/consensus kept; text fields start empty for Generate draft. */
|
||||
export function emptyDecisionApproachTextFields(
|
||||
preset: DecisionApproachDetailEntry,
|
||||
): DecisionApproachDetailEntry {
|
||||
return {
|
||||
...preset,
|
||||
corePrinciple: "",
|
||||
stepByStepInstructions: "",
|
||||
objectionsDeadlocks: "",
|
||||
applicableScope: [...preset.applicableScope],
|
||||
selectedApplicableScope: [...preset.selectedApplicableScope],
|
||||
};
|
||||
}
|
||||
|
||||
export function conflictManagementPresetFor(
|
||||
id: string,
|
||||
): ConflictManagementDetailEntry {
|
||||
@@ -146,11 +167,19 @@ export function conflictManagementPresetFor(
|
||||
};
|
||||
}
|
||||
|
||||
export function emptyConflictManagementDetails(): ConflictManagementDetailEntry {
|
||||
return {
|
||||
corePrinciple: "",
|
||||
applicableScope: [],
|
||||
selectedApplicableScope: [],
|
||||
processProtocol: "",
|
||||
restorationFallbacks: "",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Preset meaning/signals for a core value chip. Mirrors `CoreValuesSelectScreen`'s
|
||||
* `getInitialTexts` so the final-review edit modal opens with the same
|
||||
* preset copy the select screen would have shown — without requiring the
|
||||
* user to have opened the select-screen modal first.
|
||||
* Preset meaning/signals for a core value chip. Used by Generate draft and
|
||||
* by publish/display merge when the author has not saved an override.
|
||||
*
|
||||
* Lookup order:
|
||||
* 1. Numeric chip id → 1-based index into `coreValues.json` `values[]`
|
||||
|
||||
@@ -89,46 +89,6 @@ function clampPercent(n: number): number {
|
||||
return Math.min(100, Math.max(1, Math.round(n)));
|
||||
}
|
||||
|
||||
function facetPrefillHasContent(prefill: MethodCardWizardFacetPrefill): boolean {
|
||||
switch (prefill.group) {
|
||||
case "communication":
|
||||
return (
|
||||
hasTrimmedText(prefill.draft.corePrinciple) ||
|
||||
hasTrimmedText(prefill.draft.logisticsAdmin) ||
|
||||
hasTrimmedText(prefill.draft.codeOfConduct)
|
||||
);
|
||||
case "membership":
|
||||
return (
|
||||
hasTrimmedText(prefill.draft.eligibility) ||
|
||||
hasTrimmedText(prefill.draft.joiningProcess) ||
|
||||
hasTrimmedText(prefill.draft.expectations)
|
||||
);
|
||||
case "decisionApproaches":
|
||||
return (
|
||||
hasTrimmedText(prefill.draft.corePrinciple) ||
|
||||
hasTrimmedText(prefill.draft.stepByStepInstructions) ||
|
||||
hasTrimmedText(prefill.draft.objectionsDeadlocks) ||
|
||||
prefill.draft.applicableScope.length > 0 ||
|
||||
prefill.draft.selectedApplicableScope.length > 0
|
||||
);
|
||||
case "conflictManagement":
|
||||
return (
|
||||
hasTrimmedText(prefill.draft.corePrinciple) ||
|
||||
hasTrimmedText(prefill.draft.processProtocol) ||
|
||||
hasTrimmedText(prefill.draft.restorationFallbacks) ||
|
||||
formatConflictApplicableScopeForTextarea(
|
||||
prefill.draft.selectedApplicableScope,
|
||||
prefill.draft.applicableScope,
|
||||
).trim().length > 0
|
||||
);
|
||||
case "coreValues":
|
||||
return (
|
||||
hasTrimmedText(prefill.draft.meaning) ||
|
||||
hasTrimmedText(prefill.draft.signals)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapFacetPrefillToWizardFieldBlocks(
|
||||
prefill: MethodCardWizardFacetPrefill,
|
||||
): CustomMethodCardFieldBlock[] {
|
||||
@@ -198,7 +158,11 @@ function mapFacetPrefillToWizardFieldBlocks(
|
||||
);
|
||||
if (
|
||||
typeof prefill.draft.consensusLevel === "number" &&
|
||||
facetPrefillHasContent(prefill)
|
||||
(hasTrimmedText(prefill.draft.corePrinciple) ||
|
||||
hasTrimmedText(prefill.draft.stepByStepInstructions) ||
|
||||
hasTrimmedText(prefill.draft.objectionsDeadlocks) ||
|
||||
prefill.draft.applicableScope.length > 0 ||
|
||||
prefill.draft.selectedApplicableScope.length > 0)
|
||||
) {
|
||||
blocks.push({
|
||||
kind: "proportion",
|
||||
@@ -260,14 +224,12 @@ function mapFacetPrefillToWizardFieldBlocks(
|
||||
|
||||
/**
|
||||
* Map a method card's facet editors onto wizard field blocks so Customize
|
||||
* can show and edit the same sections on step 3.
|
||||
* can show and edit the same sections on step 3. Empty copy still yields
|
||||
* the catalog headings so authors can fill them in the wizard.
|
||||
*/
|
||||
export function facetDetailsToWizardFieldBlocks(
|
||||
prefill: MethodCardWizardFacetPrefill,
|
||||
): CustomMethodCardFieldBlock[] {
|
||||
if (!facetPrefillHasContent(prefill)) {
|
||||
return [];
|
||||
}
|
||||
return mapFacetPrefillToWizardFieldBlocks(prefill);
|
||||
}
|
||||
|
||||
|
||||
@@ -178,7 +178,11 @@ export type ToggleGroupPositionValue =
|
||||
export const LABEL_VARIANT_OPTIONS = ["default", "horizontal"] as const;
|
||||
export type LabelVariantValue = (typeof LABEL_VARIANT_OPTIONS)[number];
|
||||
|
||||
export const TEXT_AREA_APPEARANCE_OPTIONS = ["default", "embedded"] as const;
|
||||
export const TEXT_AREA_APPEARANCE_OPTIONS = [
|
||||
"default",
|
||||
"embedded",
|
||||
"compose",
|
||||
] as const;
|
||||
export type TextAreaAppearanceValue =
|
||||
(typeof TEXT_AREA_APPEARANCE_OPTIONS)[number];
|
||||
|
||||
|
||||
Reference in new issue
Block a user