feat(dict): таблица справочника — hide tail columns по умолчанию (без H-scroll)

This commit is contained in:
Александр Зимин
2026-06-02 12:14:00 +00:00
parent 071315b058
commit b6190713e4
2 changed files with 44 additions and 10 deletions
+24 -9
View File
@@ -28,11 +28,20 @@ const DEFAULT_STATE: DictTableState = { sort: null, hidden: [] }
const storageKey = (dictName: string): string => `ord-dict-table:${dictName}`
const readState = (dictName: string): DictTableState => {
if (typeof window === 'undefined') return DEFAULT_STATE
/**
* Прочитать persisted state. Если в storage пусто (юзер ни разу не
* взаимодействовал с этим dict) → используем `fallbackHidden` как initial
* visibility (для info-dense schemas: hide tail columns по умолчанию,
* чтобы таблица помещалась в viewport без H-scroll). Любой toggle/setHidden
* запишет state в storage → дальнейшие посещения respect юзерский выбор
* вне зависимости от fallback.
*/
const readState = (dictName: string, fallbackHidden: string[]): DictTableState => {
const fallback: DictTableState = { sort: null, hidden: fallbackHidden }
if (typeof window === 'undefined') return fallback
try {
const raw = window.localStorage.getItem(storageKey(dictName))
if (!raw) return DEFAULT_STATE
if (!raw) return fallback
const parsed = JSON.parse(raw) as Partial<DictTableState>
return {
sort:
@@ -46,7 +55,7 @@ const readState = (dictName: string): DictTableState => {
: [],
}
} catch {
return DEFAULT_STATE
return fallback
}
}
@@ -60,13 +69,19 @@ const writeState = (dictName: string, state: DictTableState): void => {
}
}
export function useDictTableState(dictName: string) {
const [state, setState] = useState<DictTableState>(() => readState(dictName))
export function useDictTableState(dictName: string, defaultHidden: string[] = []) {
// Stable key для defaultHidden чтобы useEffect не зацикливался на каждый
// render (массив literal каждый раз new reference). Caller обычно строит
// defaultHidden из useMemo, но guard всё равно нужен.
const defaultKey = defaultHidden.join(',')
const [state, setState] = useState<DictTableState>(() => readState(dictName, defaultHidden))
// Перечитать когда смена dictName (navigation между справочниками).
// Перечитать когда смена dictName (navigation между справочниками) или
// когда меняется набор defaultHidden (schema reload → новые extra columns).
useEffect(() => {
setState(readState(dictName))
}, [dictName])
setState(readState(dictName, defaultHidden))
// eslint-disable-next-line react-hooks/exhaustive-deps -- defaultKey stable
}, [dictName, defaultKey])
useEffect(() => {
writeState(dictName, state)