1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
import { LOG } from "@/utilities/console";
import { get, isNull, isUndefined, uniqBy } from "lodash";
import { useCallback, useMemo, useRef } from "react";
import {
HookType,
useFormActions,
useStagedValues,
} from "../utilities/FormValues";
import { useSettings } from "../utilities/SettingsProvider";
export interface BaseInput<T> {
disabled?: boolean;
settingKey: string;
settingOptions?: SettingValueOptions<T>;
}
export type SettingValueOptions<T> = {
original?: boolean;
defaultValue?: T;
onLoaded?: (settings: Settings) => T;
onSaved?: (value: T) => unknown;
onSubmit?: (value: T) => unknown;
};
export function useBaseInput<T, V>(props: T & BaseInput<V>) {
const { settingKey, settingOptions, ...rest } = props;
// TODO: Opti options
const value = useSettingValue<V>(settingKey, settingOptions);
const { setValue } = useFormActions();
const update = useCallback(
(newValue: V | null) => {
const moddedValue =
(newValue && settingOptions?.onSaved?.(newValue)) ?? newValue;
setValue(moddedValue, settingKey, settingOptions?.onSubmit);
},
[settingOptions, setValue, settingKey],
);
return { value, update, rest };
}
export function useSettingValue<T>(
key: string,
options?: SettingValueOptions<T>,
): Readonly<Nullable<T>> {
const settings = useSettings();
const optionsRef = useRef(options);
optionsRef.current = options;
const originalValue = useMemo(() => {
const onLoaded = optionsRef.current?.onLoaded;
const defaultValue = optionsRef.current?.defaultValue;
if (onLoaded && settings) {
LOG("info", `${key} is using custom loader`);
return onLoaded(settings);
}
const path = key.replaceAll("-", ".");
const value = get({ settings }, path, null) as Nullable<T>;
if (defaultValue && (isNull(value) || isUndefined(value))) {
LOG("info", `${key} is falling back to`, defaultValue);
return defaultValue;
}
return value;
}, [key, settings]);
const stagedValue = useStagedValues();
if (key in stagedValue && optionsRef.current?.original !== true) {
return stagedValue[key] as T;
} else {
return originalValue;
}
}
export function useUpdateArray<T>(
key: string,
current: Readonly<T[]>,
compare: keyof T,
) {
const { setValue } = useFormActions();
const stagedValue = useStagedValues();
const compareRef = useRef(compare);
compareRef.current = compare;
const staged: T[] = useMemo(() => {
if (key in stagedValue) {
return stagedValue[key];
} else {
return current;
}
}, [key, stagedValue, current]);
return useCallback(
(v: T, hook?: HookType) => {
const newArray = uniqBy([v, ...staged], compareRef.current);
setValue(newArray, key, hook);
},
[staged, setValue, key],
);
}
|