UNPKG

checkbox-tree-sync

Version:
197 lines (196 loc) 4.91 kB
import { useRef as u, useState as C, useCallback as k } from "react"; var i = /* @__PURE__ */ ((h) => (h.Indeterminate = "indeterminate", h.Checked = "checked", h))(i || {}); class b { constructor(e) { this.params = e, this.flattenData = this.makeDataFlat(e.data), this.state = e.state ?? {}; } flattenData; variant = {}; state = {}; getCheckboxesModel() { return { checkboxes: this.createSubCheckboxesModel(this.params.data) }; } pickAll() { const e = {}; Object.keys(this.flattenData).forEach((t) => { e[t] = !0; }), this.handleChangeState(e); } /** * make data flat so we can easily find parent and children and retrieve data */ makeDataFlat(e, t) { const { getCheckboxId: a, getSubCheckboxes: s } = this.params, n = {}; return e.forEach((c) => { const r = s(c) ?? [], o = a(c), l = r.map(a); if (n[o] = { id: o, data: c, children: l, parentId: t }, r.length > 0) { const d = this.makeDataFlat(r, o); Object.assign(n, d); } }), n; } pickCheckboxParents(e) { const t = {}; let a = e; for (; a && this.flattenData[a]?.parentId; ) a = this.flattenData[a].parentId, t[a] = !0; return t; } getCheckboxChildren(e) { let t = this.flattenData[e]?.children ?? []; const a = t.flatMap( (s) => this.getCheckboxChildren(s) ); return t.concat(a); } pickCheckboxChildren(e) { const t = {}; return this.getCheckboxChildren(e).forEach((s) => { t[s] = !0; }), t; } removeCheckboxParents(e, t) { const a = { ...t }; let s = this.flattenData[e].parentId; for (; s; ) { const n = this.flattenData[s]; n.children.some((r) => a[r]) ? s = void 0 : (delete a[s], s = n.parentId); } return a; } removeCheckboxChildren(e, t) { const a = { ...t }; return this.getCheckboxChildren(e).forEach((n) => { delete a[n]; }), a; } toggleCheckbox(e, t) { const a = { ...this.state }; if (t) return Object.assign( a, this.pickCheckboxParents(e), this.pickCheckboxChildren(e), { [e]: !0 } ), a; delete a[e]; const s = this.removeCheckboxParents(e, a); return this.removeCheckboxChildren(e, s); } /** * checkbox model for rendering */ createCheckboxModel(e) { const t = this.params.getCheckboxId(e); return { id: t, getIsChecked: () => !!this?.state?.[t], getVariant: () => this.variant[t]?.type ?? i.Checked, getToggleHandler: () => () => { const a = this.state?.[t], s = this.toggleCheckbox(t, !a); this.handleChangeState(s); } }; } /** * checkbox model for rendering */ createSubCheckboxesModel(e) { return e.map((t) => { const a = this.createCheckboxModel(t), s = this.params.getSubCheckboxes(t) ?? [], n = this.createSubCheckboxesModel(s); return { ...a, subCheckboxes: n }; }); } handleChangeState(e) { this.params?.onStateChange ? this.params.onStateChange?.(e) : this.updateState(e); } updateVariant(e) { this.variant = this.params?.getCheckboxVariantModel?.({ data: this.params.data, state: e, getCheckboxId: this.params.getCheckboxId, getSubCheckboxes: this.params.getSubCheckboxes }) ?? {}; } updateParams(e) { e.data && this.params?.data !== e.data && (this.flattenData = this.makeDataFlat(e.data)), this.params = e; } updateState(e) { e !== void 0 && this.params.state !== e && (this.updateVariant(e), this.state = e); } } const g = () => ({ data: h, state: e, getSubCheckboxes: t, getCheckboxId: a }) => { const s = {}; return h.forEach((n) => { const c = t(n) ?? [], r = a(n); if (c && c.length) { const o = g()({ data: c, state: e, getCheckboxId: a, getSubCheckboxes: t }); Object.assign(s, o); const l = Object.values(o).every((d) => d.checked); r && (s[r] = { checked: l, type: l ? i.Checked : i.Indeterminate }); } else r && (s[r] = { checked: e[r], type: i.Checked }); }), s; }, x = ({ controlled: h, default: e }) => { const { current: t } = u(h !== void 0), [a, s] = C(e), n = t ? h : a, c = k( (r) => { t || s(r); }, [t] ); return [n, c]; }, f = ({ state: h, ...e }) => { const [t, a] = x({ controlled: h, default: {} }), s = u(); return s.current ? (s.current.updateParams(e), s.current.updateState(t)) : s.current = new b({ ...e, state: t, onStateChange: (n) => { e.onStateChange?.(n), a(n); } }), { checkBoxTreeSync: s.current }; }; export { b as CheckboxTreeSync, i as CheckboxVariantEnum, g as getCheckboxVariantModel, f as useCheckboxTreeSync };