Files
community-rule/lib/create/coreValueChipOptionsFromDraft.ts
T
2026-04-29 18:38:40 -06:00

97 lines
2.9 KiB
TypeScript

import type { ChipOption } from "../../app/components/controls/MultiSelect/MultiSelect.types";
import type {
CreateFlowState,
} from "../../app/(app)/create/types";
type CoreValuePreset = { label: string; meaning: string; signals: string };
function chipRowsFromPresets(presets: readonly CoreValuePreset[]): ChipOption[] {
return presets.map((row, i) => ({
id: String(i + 1),
label: row.label,
state: "unselected" as const,
}));
}
function applySavedSelectionToPresetsOnly(
options: ChipOption[],
saved: string[] | undefined,
): ChipOption[] {
const selected = new Set(saved ?? []);
return options.map((opt) =>
opt.state === "custom"
? opt
: {
...opt,
state: selected.has(opt.id)
? ("selected" as const)
: ("unselected" as const),
},
);
}
/** Valid MultiSelect chip state from snapshot JSON. */
function normalizeChipState(s: unknown): ChipOption["state"] | undefined {
return s === "selected" ||
s === "unselected" ||
s === "custom" ||
s === "error"
? (s as ChipOption["state"])
: undefined;
}
/**
* Build the core-values MultiSelect chip list shown in-create.
*
* The published-rule hydration path writes only **selected** rows into
* `coreValuesChipsSnapshot`. Editing must still show every preset ("1"..N) plus
* custom ids from the snapshot. Card-deck pin / ordering features do not apply
* here.
*/
export function buildCoreValueChipOptionsFromDraft(
presets: readonly CoreValuePreset[],
snapshot: CreateFlowState["coreValuesChipsSnapshot"],
selectedCoreValueIds: CreateFlowState["selectedCoreValueIds"],
): ChipOption[] {
const presetBase = chipRowsFromPresets(presets);
const presetIdSet = new Set(presetBase.map((p) => p.id));
const selected = new Set(selectedCoreValueIds ?? []);
if (!snapshot?.length) {
return applySavedSelectionToPresetsOnly(presetBase, selectedCoreValueIds);
}
const snapById = new Map(snapshot.map((r) => [r.id, r] as const));
const presetRows: ChipOption[] = presetBase.map((opt) => {
const row = snapById.get(opt.id);
if (!row) {
return {
...opt,
state: selected.has(opt.id) ? ("selected" as const) : ("unselected" as const),
};
}
const normalized = normalizeChipState(row.state);
const effectiveState =
normalized ??
(selected.has(opt.id) ? ("selected" as const) : ("unselected" as const));
const label =
typeof row.label === "string" && row.label.trim().length > 0
? row.label
: opt.label;
return { ...opt, label, state: effectiveState };
});
const customRows: ChipOption[] = snapshot
.filter((r) => !presetIdSet.has(r.id))
.map((r) => ({
id: r.id,
label: r.label,
state:
normalizeChipState(r.state) ??
(selected.has(r.id) ? ("selected" as const) : ("unselected" as const)),
}));
return [...presetRows, ...customRows];
}