@hookform/lenses
Version:
Type-safe lenses for React Hook Form that enable precise control over nested form state. Build reusable form components with composable operations, array handling, and full TypeScript support.
168 lines (166 loc) • 5.4 kB
JavaScript
// src/LensCore.ts
import { get } from "react-hook-form";
var LensCore = class _LensCore {
constructor(control, cache, settings = {}) {
this.control = control;
this.settings = settings;
this.cache = cache;
}
static create(control, cache) {
return new _LensCore(control, cache);
}
focus(propPath) {
var _a, _b, _c, _d, _e, _f, _g;
let nestedPath = this.settings.propPath === void 0 ? propPath : `${this.settings.propPath}.${propPath}`;
if (this.settings.lensesMap) {
if (Array.isArray(this.settings.lensesMap)) {
const arrayReflectMapper = get(this.settings.lensesMap[0], propPath);
if (arrayReflectMapper) {
const reflectedPropPath = (_a = arrayReflectMapper.settings.propPath) == null ? void 0 : _a.slice(`${this.settings.restructureSourcePath}.`.length);
if (reflectedPropPath) {
nestedPath = `${this.settings.propPath}.${reflectedPropPath}`;
if (!((_b = this.cache) == null ? void 0 : _b.has(nestedPath))) {
const newLens = new _LensCore(arrayReflectMapper.control, arrayReflectMapper.cache, {
...arrayReflectMapper.settings,
propPath: nestedPath
});
(_c = this.cache) == null ? void 0 : _c.set(newLens, nestedPath);
}
const focusedLens2 = (_d = this.cache) == null ? void 0 : _d.get(nestedPath);
if (!focusedLens2) {
throw new Error(`There is no focused lens: ${nestedPath}`);
}
return focusedLens2;
}
}
} else {
const result = get(this.settings.lensesMap, propPath);
if (result) {
return result;
}
}
}
if (!((_e = this.cache) == null ? void 0 : _e.has(nestedPath))) {
const newLens = new _LensCore(this.control, this.cache, {
propPath: nestedPath,
lensesMap: this.settings.lensesMap,
restructureSourcePath: this.settings.restructureSourcePath
});
(_f = this.cache) == null ? void 0 : _f.set(newLens, nestedPath);
}
const focusedLens = (_g = this.cache) == null ? void 0 : _g.get(nestedPath);
if (!focusedLens) {
throw new Error(`There is no focused lens: ${nestedPath}`);
}
return focusedLens;
}
reflect(getter) {
var _a, _b, _c, _d;
const fromCache = (_b = this.cache) == null ? void 0 : _b.get((_a = this.settings.propPath) != null ? _a : "", getter);
if (fromCache) {
return fromCache;
}
const proxy = new Proxy(
{},
{
get: (target, prop) => {
if (typeof prop === "string") {
return this.focus(prop);
}
return target;
}
}
);
const focusContext = getter(proxy, this);
const newLens = new _LensCore(this.control, this.cache, {
lensesMap: focusContext,
propPath: this.settings.propPath,
restructureSourcePath: this.settings.propPath
});
(_d = this.cache) == null ? void 0 : _d.set(newLens, (_c = this.settings.propPath) != null ? _c : "", getter);
return newLens;
}
map(fields, mapper) {
if (!this.settings.propPath) {
throw new Error(`There is no prop name in this lens: ${this.settings.propPath}`);
}
return fields.map((value, index, array) => {
const item = this.focus(index.toString());
const res = mapper(value, item, index, array, this);
return res;
});
}
interop(cb) {
return cb ? cb(this.control, this.settings.propPath, this) : { control: this.control, name: this.settings.propPath, lens: this };
}
};
// src/LensesStorage.ts
var LensesStorage = class {
constructor(control) {
var _a, _b, _c;
this.cache = /* @__PURE__ */ new Map();
(_c = (_b = (_a = control == null ? void 0 : control._subjects) == null ? void 0 : _a.values) == null ? void 0 : _b.subscribe) == null ? void 0 : _c.call(_b, {
next: () => {
control._names.unMount.forEach((name) => {
this.delete(name);
});
}
});
}
get(propPath, complexKey) {
const cached = this.cache.get(propPath);
if (cached) {
if (complexKey) {
return cached.complex.get(complexKey);
}
return cached.plain;
}
return void 0;
}
set(lens, propPath, complexKey) {
let cached = this.cache.get(propPath);
if (!cached) {
cached = {
complex: /* @__PURE__ */ new WeakMap()
};
this.cache.set(propPath, cached);
}
if (complexKey) {
cached.complex.set(complexKey, lens);
} else {
cached.plain = lens;
}
}
has(propPath, complexKey) {
var _a, _b;
if (complexKey) {
return (_b = (_a = this.cache.get(propPath)) == null ? void 0 : _a.complex.has(complexKey)) != null ? _b : false;
}
return this.cache.has(propPath);
}
delete(propPath) {
for (const key of this.cache.keys()) {
if (key.startsWith(propPath)) {
this.cache.delete(key);
}
}
}
clear() {
this.cache.clear();
}
};
// src/useLens.ts
import { useMemo } from "react";
function useLens(props, deps = []) {
return useMemo(() => {
const cache = new LensesStorage(props.control);
const lens = LensCore.create(props.control, cache);
return lens;
}, [props.control, ...deps]);
}
export {
LensCore,
LensesStorage,
useLens
};
//# sourceMappingURL=index.js.map