1import type { PasswordPolicy } from "../shared/types";23export interface GeneratorState {4 currentLength: number;5 userHasAdjusted: boolean;6}78export interface PolicyResult {9 length: number;10 sliderMin: number;11 sliderMax: number;12 constraintNote: string;13}1415const DEFAULT_LENGTH = 64;16const DEFAULT_SLIDER_MIN = 8;17const DEFAULT_SLIDER_MAX = 256;1819export function initGeneratorState(): GeneratorState {20 return { currentLength: DEFAULT_LENGTH, userHasAdjusted: false };21}2223export function handleLengthChange(state: GeneratorState, length: number): GeneratorState {24 return { ...state, currentLength: length, userHasAdjusted: true };25}2627export function initFromPolicy(28 policy: PasswordPolicy | null,29 state: { currentLength: number; userHasAdjusted: boolean },30): PolicyResult {31 const sliderMin = policy?.minLength ? Math.max(1, policy.minLength) : DEFAULT_SLIDER_MIN;32 const sliderMax = policy?.maxLength ? Math.min(DEFAULT_SLIDER_MAX, policy.maxLength) : DEFAULT_SLIDER_MAX;3334 let length = state.currentLength;3536 if (policy) {37 if (policy.maxLength !== undefined && policy.minLength !== undefined) {38 39 length = Math.max(policy.minLength, Math.min(policy.maxLength, state.currentLength));40 } else if (policy.maxLength !== undefined) {41 if (!state.userHasAdjusted) {42 43 length = policy.maxLength;44 } else if (state.currentLength > policy.maxLength) {45 46 length = policy.maxLength;47 }48 } else if (policy.minLength !== undefined && state.currentLength < policy.minLength) {49 50 length = policy.minLength;51 }52 }5354 let constraintNote = "";55 if (policy) {56 if (policy.maxLength !== undefined && length >= policy.maxLength) {57 constraintNote = `This site allows max ${policy.maxLength} characters`;58 } else if (policy.minLength !== undefined && length <= policy.minLength) {59 constraintNote = `This site requires at least ${policy.minLength} characters`;60 }61 }6263 return { length, sliderMin, sliderMax, constraintNote };64}