UNPKG

@westacks/vortex

Version:

Server-based routing for SPAs

209 lines (208 loc) 6.72 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { b as signal, e as effect, i as isEqual } from "./page-ILOxo6kg.js"; import { a as axios } from "./router-CgFdQeyO.js"; class Form { constructor(initial, handler) { __publicField(this, "_defaults"); __publicField(this, "_transform"); __publicField(this, "_recentlySuccessfulTimeout", null); __publicField(this, "_handler"); __publicField(this, "wasSuccessful", false); __publicField(this, "recentlySuccessful", false); __publicField(this, "processing", false); __publicField(this, "errors", {}); this._defaults = initial; this._handler = handler; Object.defineProperty(this, "_defaults", { enumerable: false }); Object.defineProperty(this, "_transform", { enumerable: false }); Object.defineProperty(this, "_recentlySuccessfulTimeout", { enumerable: false }); Object.defineProperty(this, "_handler", { enumerable: false, writable: false, configurable: false }); this.reset(); } get hasErrors() { return Object.keys(this.errors).length > 0; } get isDirty() { return !isEqual(this.data(), this._defaults); } data() { const keys = Object.keys(this._defaults); return keys.reduce((acc, key) => { acc[key] = unwrap(this[key]); return acc; }, {}); } transform(fn) { this._transform = fn(this.data()); return this; } reset(...fields) { const data = fields.length > 0 ? Object.keys(this._defaults).filter((key) => fields.includes(key)).reduce((obj, key) => { obj[key] = this._defaults[key]; return obj; }, {}) : this._defaults; Object.assign(this, wrap(data, this._handler)); return this; } fill(data) { Object.assign(this, wrap(data, this._handler)); return this; } defaults(field, value) { if (typeof field === "string") { field = { [field]: value }; } if (!field) { field = unwrap(Object.keys(this._defaults).reduce((obj, key) => { obj[key] = this[key]; return obj; }, {})); } this._defaults = { ...this._defaults, ...field }; return this; } clearErrors(...fields) { if (fields.length === 0) { this.errors = {}; } else for (const field of fields) { delete this.errors[field]; } return this; } setError(field, message) { if (typeof field === "string") { field = { [field]: message }; } this.errors = { ...this.errors, ...field }; return this; } request(options) { if (this._recentlySuccessfulTimeout) { clearTimeout(this._recentlySuccessfulTimeout); } this.wasSuccessful = false; this.processing = true; let data = this._transform || this.data(); if (containsFile(data)) { data = objectToFormData(data); } return axios.request({ ...options, data }).catch((error) => { return Promise.reject(error); }).then((response) => { var _a, _b; this.errors = ((_b = (_a = response == null ? void 0 : response.data) == null ? void 0 : _a.props) == null ? void 0 : _b.errors) ?? {}; if (Object.keys(this.errors).length === 0) { this.wasSuccessful = true; this.recentlySuccessful = true; this._recentlySuccessfulTimeout = setTimeout(() => { this.recentlySuccessful = false; }, 2e3); } return response; }).finally(() => { this._transform = void 0; this.processing = false; }); } get(url, options) { return this.request({ ...options, url, method: "get" }); } post(url, options) { return this.request({ ...options, url, method: "post" }); } put(url, options) { return this.request({ ...options, url, method: "put" }); } patch(url, options) { return this.request({ ...options, url, method: "patch" }); } delete(url, options) { return this.request({ ...options, url, method: "delete" }); } } function useForm(data, rememberKey) { data = typeof data === "function" ? data() : data; const [get, set] = signal(void 0, isEqual); const subscribe = (fn) => effect(() => fn(get())); set(createProxy(data, set)); return { get, set, subscribe }; } function createProxy(data, set) { const handler = { set(target, key, value, receiver) { const changed = target[key] !== value; const result = Reflect.set(target, key, value, receiver); if (result && !key.startsWith("_")) { set(proxy, changed); } return result; } }; const form = new Form(data, handler); const proxy = new Proxy(form, handler); return proxy; } function wrap(data, handler) { if (typeof data !== "object" || data === null || data instanceof File || data instanceof Blob) { return data; } if (Array.isArray(data)) { return data.map((item) => wrap(item, handler)); } return Object.entries(data).reduce( (acc, [key, value]) => { acc[key] = typeof value !== "object" || value === null ? value : new Proxy(wrap(value, handler), handler); return acc; }, {} ); } function unwrap(data) { if (typeof data !== "object" || data === null || data instanceof File || data instanceof Blob) { return data; } if (Array.isArray(data)) { return data.map(unwrap); } return Object.keys(data).reduce((acc, key) => { acc[key] = unwrap(data[key]); return acc; }, {}); } function containsFile(obj) { if (typeof obj !== "object" || obj === null) { return false; } return Object.values(obj).some( (item) => item instanceof File || item instanceof Blob ? true : containsFile(item) ); } function objectToFormData(obj, form = new FormData(), namespace = "") { for (const key in obj) { if (!Object.hasOwn(obj, key)) continue; const value = obj[key]; const formKey = namespace ? `${namespace}[${key}]` : key; if (value instanceof File || value instanceof Blob) { form.append(formKey, value); } else if (Array.isArray(value)) { value.forEach((item, index) => { const arrayKey = `${formKey}[${index}]`; if (typeof item === "object" && item !== null) { objectToFormData(item, form, arrayKey); } else { form.append(arrayKey, item); } }); } else if (typeof value === "object" && value !== null) { objectToFormData(value, form, formKey); } else if (value !== void 0 && value !== null) { form.append(formKey, value); } } return form; } export { useForm as u };