import { Arr, Cell, Fun, Obj, type Optional } from '@ephox/katamari'; import type { ItemDataTuple } from '../../ui/types/ItemTypes'; import { nuState } from '../common/BehaviourState'; import type { DatasetRepresentingState, ManualRepresentingState, MemoryRepresentingState, RepresentingConfig, RepresentingState } from './RepresentingTypes'; const memory = (): MemoryRepresentingState => { const data = Cell(null); const readState = () => ({ mode: 'memory', value: data.get() }); const isNotSet = () => data.get() === null; const clear = () => { data.set(null); }; return nuState({ set: data.set, get: data.get, isNotSet, clear, readState }); }; const manual = (): ManualRepresentingState => { const readState = Fun.noop; return nuState({ readState }); }; const dataset = (): DatasetRepresentingState => { const dataByValue = Cell({ }); const dataByText = Cell({ }); const readState = () => ({ mode: 'dataset', dataByValue: dataByValue.get(), dataByText: dataByText.get() }); const clear = (): void => { dataByValue.set({ }); dataByText.set({ }); }; // itemString can be matching value or text. // TODO: type problem - impossible to correctly return value when type parameter only exists in return type const lookup = (itemString: string): Optional => Obj.get(dataByValue.get(), itemString).orThunk(() => Obj.get(dataByText.get(), itemString)); const update = (items: T[]): void => { const currentDataByValue = dataByValue.get(); const currentDataByText = dataByText.get(); const newDataByValue: Record = { }; const newDataByText: Record = { }; Arr.each(items, (item) => { newDataByValue[item.value] = item; Obj.get(item, 'meta').each((meta) => { Obj.get(meta, 'text').each((text) => { newDataByText[text] = item; }); }); }); dataByValue.set({ ...currentDataByValue, ...newDataByValue }); dataByText.set({ ...currentDataByText, ...newDataByText }); }; return nuState({ readState, lookup, update, clear }); }; const init = (spec: RepresentingConfig): RepresentingState => spec.store.manager.state(spec); export { memory, dataset, manual, init };