40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
/** Internal select value when respondent picks the configurable Other option. Never stored in submissions. */
|
|
export const SELECT_OTHER_VALUE = '__other__';
|
|
|
|
export type SelectOptionItem = string | { value: string; label: string };
|
|
|
|
export function normalizeSelectOptions(options: SelectOptionItem[] | undefined): { value: string; label: string }[] {
|
|
return (options ?? []).map((o) => (typeof o === 'string' ? { value: o, label: o } : o));
|
|
}
|
|
|
|
export function isCustomSelectValue(
|
|
value: unknown,
|
|
optionValues: string[],
|
|
allowOther?: boolean,
|
|
): boolean {
|
|
if (!allowOther) return false;
|
|
const stored = String(value ?? '').trim();
|
|
if (!stored) return false;
|
|
return !optionValues.includes(stored);
|
|
}
|
|
|
|
export function selectControlValue(
|
|
value: unknown,
|
|
optionValues: string[],
|
|
allowOther?: boolean,
|
|
otherValue = SELECT_OTHER_VALUE,
|
|
): string {
|
|
const stored = String(value ?? '');
|
|
if (isCustomSelectValue(stored, optionValues, allowOther)) return otherValue;
|
|
return stored;
|
|
}
|
|
|
|
export function otherTextFromValue(
|
|
value: unknown,
|
|
optionValues: string[],
|
|
allowOther?: boolean,
|
|
): string {
|
|
if (!isCustomSelectValue(value, optionValues, allowOther)) return '';
|
|
return String(value ?? '');
|
|
}
|