jotai-controller
Version:
A powerful state management library built on top of Jotai with controller pattern for React applications
1,608 lines (1,564 loc) • 2.7 MB
JavaScript
import { useStore, useAtom as useAtom$1, createStore as createStore$1, atom as atom$1 } from 'jotai';
import { useHydrateAtoms, createJSONStorage, atomWithStorage as atomWithStorage$1, RESET } from 'jotai/utils';
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
import * as React from 'react';
import React__default, { useCallback as useCallback$1, useState as useState$1, useRef as useRef$1, useLayoutEffect as useLayoutEffect$1, useEffect as useEffect$1, Fragment, createContext as createContext$1, useContext as useContext$1, useMemo as useMemo$1, useId as useId$3, forwardRef as forwardRef$1, cloneElement, Children, createElement as createElement$1, Component, memo, useReducer } from 'react';
import { atom, INTERNAL_overrideCreateStore, createStore } from 'jotai/vanilla';
import { INTERNAL_initializeStoreHooksRev2, INTERNAL_buildStoreRev2 } from 'jotai/vanilla/internals';
import { useSetAtom, useAtom, useAtomValue, Provider } from 'jotai/react';
import { atomWithStorage, atomWithDefault } from 'jotai/vanilla/utils';
import * as ReactDOM from 'react-dom';
import ReactDOM__default, { flushSync, createPortal } from 'react-dom';
function _mergeNamespaces(n, m) {
m.forEach(function (e) {
e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) {
if (k !== 'default' && !(k in n)) {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
});
return Object.freeze(n);
}
(undefined && undefined.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
/* eslint-disable @typescript-eslint/no-non-null-assertion */
const id = (x) => x;
const Left = (value) => ({
_tag: 'Left',
value,
});
const Right = (value) => ({
_tag: 'Right',
value,
});
const either = (mapLeft, mapRight, e) => (e._tag === 'Left' ? mapLeft(e.value) : mapRight(e.value));
const profunctorFn = {
dimap: (f, g, fn) => (x) => g(fn(f(x))),
first: (f) => ([x, y]) => [f(x), y],
right: (f) => (e) => e._tag === 'Left' ? e : Right(f(e.value)),
wander: (f) => (xs) => xs.map(f),
};
const monoidFirst = {
empty: () => undefined,
foldMap: (f, xs) => {
for (let i = 0; i < xs.length; i++) {
const x = f(xs[i]);
if (x != undefined)
return x;
}
return undefined;
},
};
const monoidArray = {
empty: () => [],
foldMap: (f, xs) => {
let acc = [];
xs.forEach((x) => {
acc = acc.concat(f(x));
});
return acc;
},
};
const profunctorConst = (monoid) => ({
dimap: (f, _g, toF) => (x) => toF(f(x)),
first: (toF) => ([x, _y]) => toF(x),
right: (toF) => (e) => e._tag === 'Left' ? monoid.empty() : toF(e.value),
wander: (toF) => (xs) => monoid.foldMap(toF, xs),
});
const compositionType = {
Equivalence: {
Equivalence: 'Equivalence',
Iso: 'Iso',
Lens: 'Lens',
Prism: 'Prism',
Traversal: 'Traversal',
Getter: 'Getter',
AffineFold: 'AffineFold',
Fold: 'Fold',
Setter: 'Setter',
},
Iso: {
Equivalence: 'Iso',
Iso: 'Iso',
Lens: 'Lens',
Prism: 'Prism',
Traversal: 'Traversal',
Getter: 'Getter',
AffineFold: 'AffineFold',
Fold: 'Fold',
Setter: 'Setter',
},
Lens: {
Equivalence: 'Lens',
Iso: 'Lens',
Lens: 'Lens',
Prism: 'Prism',
Traversal: 'Traversal',
Getter: 'Getter',
AffineFold: 'AffineFold',
Fold: 'Fold',
Setter: 'Setter',
},
Prism: {
Equivalence: 'Prism',
Iso: 'Prism',
Lens: 'Prism',
Prism: 'Prism',
Traversal: 'Traversal',
Getter: 'AffineFold',
AffineFold: 'AffineFold',
Fold: 'Fold',
Setter: 'Setter',
},
Traversal: {
Equivalence: 'Traversal',
Iso: 'Traversal',
Lens: 'Traversal',
Prism: 'Traversal',
Traversal: 'Traversal',
Getter: 'Fold',
AffineFold: 'Fold',
Fold: 'Fold',
Setter: 'Setter',
},
Getter: {
Equivalence: 'Getter',
Iso: 'Getter',
Lens: 'Getter',
Prism: 'AffineFold',
Traversal: 'Fold',
Getter: 'Getter',
AffineFold: 'AffineFold',
Fold: 'Fold',
Setter: undefined,
},
AffineFold: {
Equivalence: 'AffineFold',
Iso: 'AffineFold',
Lens: 'AffineFold',
Prism: 'AffineFold',
Traversal: 'Fold',
Getter: 'AffineFold',
AffineFold: 'AffineFold',
Fold: 'Fold',
Setter: undefined,
},
Fold: {
Equivalence: 'Fold',
Iso: 'Fold',
Lens: 'Fold',
Prism: 'Fold',
Traversal: 'Fold',
Getter: 'Fold',
AffineFold: 'Fold',
Fold: 'Fold',
Setter: undefined,
},
Setter: {
Equivalence: undefined,
Iso: undefined,
Lens: undefined,
Prism: undefined,
Traversal: undefined,
Getter: undefined,
AffineFold: undefined,
Fold: undefined,
Setter: undefined,
},
};
const withTag = (tag, optic) => {
const result = optic;
result._tag = tag;
return result;
};
const removable = (optic) => {
optic._removable = true;
return optic;
};
function compose(optic1, optic2, optic3) {
switch (arguments.length) {
case 2: {
const next = (P, optic) => optic1(P, optic2(P, optic));
next._tag = compositionType[optic1._tag][optic2._tag];
next._removable = optic2._removable || false;
return next;
}
default: {
const tag1 = compositionType[optic1._tag][optic2._tag];
const next = (P, optic) => optic1(P, optic2(P, optic3(P, optic)));
next._tag = compositionType[tag1][optic3._tag];
next._removable = optic3._removable || false;
return next;
}
}
}
const eq = /* @__PURE__ */ withTag('Equivalence', (_P, optic) => optic);
const iso = (there, back) => withTag('Iso', (P, optic) => P.dimap(there, back, optic));
const lens = (view, update) => withTag('Lens', (P, optic) => P.dimap((x) => [view(x), x], update, P.first(optic)));
const prism = (match, build) => withTag('Prism', (P, optic) => P.dimap(match, (x) => either(id, build, x), P.right(optic)));
const elems = /* @__PURE__ */ withTag('Traversal', (P, optic) => P.dimap(id, id, P.wander(optic)));
const to = (fn) => withTag('Getter', (P, optic) => P.dimap(fn, id, optic));
/////////////////////////////////////////////////////////////////////////////
const modify$1 = (optic, fn, source) => optic(profunctorFn, fn)(source);
const set$1 = (optic, value, source) => optic(profunctorFn, () => value)(source);
const get$1 = (optic, source) => optic(profunctorConst({}), id)(source);
const preview$1 = (optic, source) => optic(profunctorConst(monoidFirst), id)(source);
const collect$1 = (optic, source) => optic(profunctorConst(monoidArray), (x) => [x])(source);
/////////////////////////////////////////////////////////////////////////////
const indexed = /* @__PURE__ */ iso((value) => value.map((v, k) => [k, v]), (value) => {
const sorted = [...value].sort((a, b) => a[0] - b[0]);
const result = [];
for (let i = 0; i < sorted.length; ++i) {
if (i === sorted.length - 1 || sorted[i][0] !== sorted[i + 1][0]) {
result.push(sorted[i][1]);
}
}
return result;
});
const prop = (key) => lens((source) => source[key], ([value, source]) => (Object.assign(Object.assign({}, source), { [key]: value })));
const pick = (keys) => lens((source) => {
const value = {};
for (const key of keys) {
value[key] = source[key];
}
return value;
}, ([value, source]) => {
const result = Object.assign({}, source);
for (const key of keys) {
delete result[key];
}
return Object.assign(result, value);
});
const nth = (n) => lens((value) => value[n], ([value, source]) => {
const result = source.slice();
result[n] = value;
return result;
});
const fst = /* @__PURE__ */ nth(0);
const when = (pred) => prism((x) => (pred(x) ? Right(x) : Left(x)), id);
const noMatch = /* @__PURE__ */ Symbol('__no_match__');
const mustMatch = /* @__PURE__ */ when((source) => source !== noMatch);
const removeMe = /* @__PURE__ */ Symbol('__remove_me__');
const at = (i) => removable(compose(lens((source) => (0 <= i && i < source.length ? source[i] : noMatch), ([value, source]) => {
if (value === noMatch) {
return source;
}
if (value === removeMe) {
if (typeof source === 'string') {
return source.substring(0, i) + source.substring(i + 1);
}
else {
return [...source.slice(0, i), ...source.slice(i + 1)];
}
}
if (typeof source === 'string') {
if (i === 0) {
return value + source.substring(1);
}
if (i === source.length) {
return source.substring(0, i - 1) + value;
}
return source.substring(0, i) + value + source.substring(i + 1);
}
else {
const result = source.slice();
result[i] = value;
return result;
}
}), mustMatch));
const optional = /* @__PURE__ */ prism((source) => (source === undefined ? Left(undefined) : Right(source)), id);
const guard = (fn) => prism((source) => (fn(source) ? Right(source) : Left(source)), id);
const find = (predicate) => removable(compose(lens((source) => {
const index = source.findIndex(predicate);
if (index === -1) {
return [noMatch, -1];
}
return [source[index], index];
}, ([[value, index], source]) => {
if (value === noMatch) {
return source;
}
if (value === removeMe) {
return [...source.slice(0, index), ...source.slice(index + 1)];
}
const result = source.slice();
result[index] = value;
return result;
}), fst, mustMatch));
const filter = (predicate) => compose(lens((source) => {
const indexes = source
.map((item, index) => (predicate(item) ? index : null))
.filter((index) => index != null);
return [indexes.map((index) => source[index]), indexes];
}, ([[values, indexes], source]) => {
const sn = source.length, vn = values.length;
let si = 0, ii = 0, vi = 0;
const result = [];
while (si < sn) {
if (indexes[ii] === si) {
++ii;
if (vi < vn) {
result.push(values[vi]);
++vi;
}
}
else {
result.push(source[si]);
}
++si;
}
while (vi < vn) {
result.push(values[vi++]);
}
return result;
}), fst);
const valueOr = (defaultValue) => lens((source) => (source === undefined ? defaultValue : source), ([value, _source]) => value);
const partsOf = (traversal) => compose(lens((source) => {
const value = collect$1(traversal, source);
return [value, value.length];
}, ([[value, originalLength], source]) => {
if (value.length !== originalLength) {
throw new Error('cannot add/remove elements through partsOf');
}
let i = 0;
return modify$1(traversal, () => value[i++], source);
}), fst);
const reread = (fn) => lens((source) => fn(source), ([value, _]) => value);
const rewrite = (fn) => lens((source) => source, ([value, _]) => fn(value));
const prependTo = /* @__PURE__ */ lens((_source) => undefined, ([value, source]) => {
if (value === undefined)
return source;
return [value, ...source];
});
const appendTo = /* @__PURE__ */ lens((_source) => undefined, ([value, source]) => {
if (value === undefined)
return source;
return [...source, value];
});
const chars = /* @__PURE__ */ compose(iso((s) => s.split(''), (a) => a.join('')), elems);
const words = /* @__PURE__ */ compose(iso((s) => s.split(/\b/), (a) => a.join('')), elems, when((s) => !/\s+/.test(s)));
/////////////////////////////////////////////////////////////////////////////
class Optic {
constructor(_ref) {
this._ref = _ref;
}
get _tag() {
return this._ref._tag;
}
get _removable() {
return this._ref._removable;
}
compose(other) {
return new Optic(compose(this._ref, other._ref));
}
iso(there, back) {
return new Optic(compose(this._ref, iso(there, back)));
}
lens(view, set) {
return new Optic(compose(this._ref, lens(view, ([value, source]) => set(source, value))));
}
indexed() {
return new Optic(compose(this._ref, indexed));
}
prop(key) {
return new Optic(compose(this._ref, prop(key)));
}
path(...keys) {
if (keys.length === 1) {
keys = keys[0].split('.');
}
return new Optic(keys.reduce((ref, key) => compose(ref, prop(key)), this._ref));
}
pick(keys) {
return new Optic(compose(this._ref, pick(keys)));
}
nth(n) {
return new Optic(compose(this._ref, nth(n)));
}
filter(predicate) {
return new Optic(compose(this._ref, filter(predicate)));
}
valueOr(defaultValue) {
return new Optic(compose(this._ref, valueOr(defaultValue)));
}
partsOf(traversalOrFn) {
const traversal = typeof traversalOrFn === 'function' ? traversalOrFn(optic$1) : traversalOrFn;
return new Optic(compose(this._ref, partsOf(traversal._ref)));
}
reread(fn) {
return new Optic(compose(this._ref, reread(fn)));
}
rewrite(fn) {
return new Optic(compose(this._ref, rewrite(fn)));
}
optional() {
return new Optic(compose(this._ref, optional));
}
guard_() {
return (fn) => this.guard(fn);
}
guard(fn) {
return new Optic(compose(this._ref, guard(fn)));
}
at(i) {
return new Optic(compose(this._ref, at(i)));
}
head() {
return new Optic(compose(this._ref, at(0)));
}
index(i) {
return new Optic(compose(this._ref, at(i)));
}
find(predicate) {
return new Optic(compose(this._ref, find(predicate)));
}
elems() {
return new Optic(compose(this._ref, elems));
}
to(fn) {
return new Optic(compose(this._ref, to(fn)));
}
when(predicate) {
return new Optic(compose(this._ref, when(predicate)));
}
chars() {
return new Optic(compose(this._ref, chars));
}
words() {
return new Optic(compose(this._ref, words));
}
prependTo() {
return new Optic(compose(this._ref, prependTo));
}
appendTo() {
return new Optic(compose(this._ref, appendTo));
}
}
const optic$1 = /* @__PURE__ */ new Optic(eq);
/* eslint-disable @typescript-eslint/adjacent-overload-signatures, @typescript-eslint/no-unused-vars */
// This file is generated, do not edit! See ../scripts/generate-index.ts
function optic() {
return optic$1;
}
function get(optic) {
return (source) => get$1(optic._ref, source);
}
function preview(optic) {
return (source) => preview$1(optic._ref, source);
}
function collect(optic) {
return (source) => collect$1(optic._ref, source);
}
function modify(optic) {
return (f) => (source) => modify$1(optic._ref, f, source);
}
function set(optic) {
return (value) => (source) => set$1(optic._ref, value, source);
}
/* eslint-disable @typescript-eslint/no-explicit-any */
const getCached = (c, m, k) => (m.has(k) ? m : m.set(k, c())).get(k);
const cache1 = new WeakMap();
const memo2 = (create, dep1, dep2) => {
const cache2 = getCached(() => new WeakMap(), cache1, dep1);
return getCached(create, cache2, dep2);
};
const isFunction = (x) => typeof x === 'function';
// Implementation
function focusAtom(baseAtom, callback) {
return memo2(() => {
const focus = callback(optic());
const derivedAtom = atom((get) => {
const base = get(baseAtom);
return base instanceof Promise
? base.then((v) => getValueUsingOptic(focus, v))
: getValueUsingOptic(focus, base);
}, (get, set$1, update) => {
const newValueProducer = isFunction(update)
? modify(focus)(update)
: set(focus)(update);
const base = get(baseAtom);
return set$1(baseAtom, (base instanceof Promise
? base.then(newValueProducer)
: newValueProducer(base)));
});
return derivedAtom;
}, baseAtom, callback);
}
const getValueUsingOptic = (focus, bigValue) => {
if (focus._tag === 'Traversal') {
const values = collect(focus)(bigValue);
return values;
}
if (focus._tag === 'Prism') {
const value = preview(focus)(bigValue);
return value;
}
const value = get(focus)(bigValue);
return value;
};
// src/utils/useAtomsSnapshot.ts
var isDevToolsStore = (store) => {
return "subscribeStore" in store;
};
var __composeWithDevTools = (store) => {
const { sub, set, get } = store;
const storeListeners = /* @__PURE__ */ new Set();
const recentlySetAtomsMap = /* @__PURE__ */ new WeakMap();
const reduceCountOrRemoveRecentlySetAtom = (atom, onFound) => {
const foundCount = recentlySetAtomsMap.get(atom);
if (typeof foundCount === "number") {
if (foundCount > 1) {
recentlySetAtomsMap.set(atom, foundCount - 1);
} else {
recentlySetAtomsMap.delete(atom);
}
onFound?.();
}
};
const increaseCountRecentlySetAtom = (atom) => {
const foundCount = recentlySetAtomsMap.get(atom);
recentlySetAtomsMap.set(atom, (foundCount || 0) + 1);
};
store.sub = (...args) => {
const unsub = sub(...args);
storeListeners.forEach((l) => l({ type: "sub" }));
return () => {
unsub();
reduceCountOrRemoveRecentlySetAtom(args[0]);
storeListeners.forEach((l) => l({ type: "unsub" }));
};
};
store.get = (...args) => {
const value = get(...args);
reduceCountOrRemoveRecentlySetAtom(args[0], () => {
if (value instanceof Promise) {
value.finally(() => {
Promise.resolve().then(() => {
storeListeners.forEach((l) => l({ type: "async-get" }));
});
});
}
});
return value;
};
store.set = (...args) => {
const value = set(...args);
increaseCountRecentlySetAtom(args[0]);
storeListeners.forEach((l) => l({ type: "set" }));
return value;
};
store.subscribeStore = (l) => {
storeListeners.add(l);
return () => {
storeListeners.delete(l);
};
};
store.getMountedAtoms = () => {
return store.get_mounted_atoms();
};
store.getAtomState = (atom) => {
const aState = store.get_internal_weak_map().get(atom);
if (aState) {
return { v: aState.v, e: aState.e, d: new Set(aState.d.keys()) };
}
return void 0;
};
store.getMountedAtomState = (atom) => {
const aState = store.get_internal_weak_map().get(atom);
if (aState && "m" in aState) {
return {
l: aState.m.l,
t: aState.m.t
};
}
return void 0;
};
store.restoreAtoms = (values) => {
store.restore_atoms(values);
storeListeners.forEach((l) => l({ type: "restore" }));
};
return store;
};
var createDevStore = () => {
let inRestoreAtom = 0;
const storeHooks = INTERNAL_initializeStoreHooksRev2({});
const atomStateMap = /* @__PURE__ */ new WeakMap();
const mountedAtoms = /* @__PURE__ */ new WeakMap();
const store = INTERNAL_buildStoreRev2(
atomStateMap,
mountedAtoms,
void 0,
void 0,
void 0,
void 0,
storeHooks,
void 0,
(_store, atom, get, set, ...args) => {
if (inRestoreAtom) {
return set(atom, ...args);
}
return atom.write(get, set, ...args);
}
);
const debugMountedAtoms = /* @__PURE__ */ new Set();
storeHooks.m.add(void 0, (atom) => {
debugMountedAtoms.add(atom);
const atomState = atomStateMap.get(atom);
atomState.m = mountedAtoms.get(atom);
});
storeHooks.u.add(void 0, (atom) => {
debugMountedAtoms.delete(atom);
const atomState = atomStateMap.get(atom);
delete atomState.m;
});
const devStore = {
// store dev methods (these are tentative and subject to change without notice)
get_internal_weak_map: () => atomStateMap,
get_mounted_atoms: () => debugMountedAtoms,
restore_atoms: (values) => {
const restoreAtom = {
read: () => null,
write: (_get, set) => {
++inRestoreAtom;
try {
for (const [atom, value] of values) {
if ("init" in atom) {
set(atom, value);
}
}
} finally {
--inRestoreAtom;
}
}
};
store.set(restoreAtom);
}
};
return Object.assign(store, devStore);
};
var isDevStore = (store) => {
return "get_internal_weak_map" in store;
};
INTERNAL_overrideCreateStore((prev) => {
return createDevStore;
});
var composeWithDevTools = (store) => {
if (isDevToolsStore(store)) {
return store;
}
if (isDevStore(store)) {
return __composeWithDevTools(store);
}
return store;
};
// src/utils/hooks/useDevToolsStore.ts
var useDevToolsStore = (options) => {
const store = useStore(options);
return composeWithDevTools(store);
};
// src/utils/useAtomsSnapshot.ts
var isEqualAtomsValues = (left, right) => left.size === right.size && Array.from(left).every(([left2, v]) => Object.is(right.get(left2), v));
var isEqualAtomsDependents = (left, right) => left.size === right.size && Array.from(left).every(([a, dLeft]) => {
const dRight = right.get(a);
return dRight && dLeft.size === dRight.size && Array.from(dLeft).every((d) => dRight.has(d));
});
function useAtomsSnapshot({
shouldShowPrivateAtoms = false,
...options
} = {}) {
const store = useDevToolsStore(options);
const [atomsSnapshot, setAtomsSnapshot] = useState$1(() => ({
values: /* @__PURE__ */ new Map(),
dependents: /* @__PURE__ */ new Map()
}));
const duringReactRenderPhase = useRef$1(true);
duringReactRenderPhase.current = true;
useLayoutEffect$1(() => {
duringReactRenderPhase.current = false;
});
useEffect$1(() => {
if (!isDevToolsStore(store)) return;
let prevValues = /* @__PURE__ */ new Map();
let prevDependents = /* @__PURE__ */ new Map();
const callback = () => {
const values = /* @__PURE__ */ new Map();
const dependents = /* @__PURE__ */ new Map();
for (const atom of store.getMountedAtoms() || []) {
if (!shouldShowPrivateAtoms && atom.debugPrivate) {
continue;
}
const atomState = store.getAtomState(atom);
if (atomState) {
if ("v" in atomState) {
values.set(atom, atomState.v);
}
}
const mounted = store.getMountedAtomState(atom);
if (mounted) {
let atomDependents = mounted.t;
if (!shouldShowPrivateAtoms) {
atomDependents = new Set(
Array.from(atomDependents.values()).filter(
/* NOTE: This just removes private atoms from the dependents list,
instead of hiding them from the dependency chain and showing
the nested dependents of the private atoms. */
(dependent) => !dependent.debugPrivate
)
);
}
dependents.set(atom, atomDependents);
}
}
if (isEqualAtomsValues(prevValues, values) && isEqualAtomsDependents(prevDependents, dependents)) {
return;
}
prevValues = values;
prevDependents = dependents;
const deferrableAtomSetAction = () => setAtomsSnapshot({ values, dependents });
if (duringReactRenderPhase.current) {
Promise.resolve().then(deferrableAtomSetAction);
} else {
deferrableAtomSetAction();
}
};
const unsubscribe = store.subscribeStore(callback);
callback();
return unsubscribe;
}, [store, shouldShowPrivateAtoms]);
return atomsSnapshot;
}
function useGotoAtomsSnapshot(options) {
const store = useDevToolsStore(options);
return useCallback$1(
(snapshot) => {
if (isDevToolsStore(store)) {
store.restoreAtoms(snapshot.values);
}
},
[store]
);
}
function keys(object) {
return Object.keys(object);
}
function isObject(item) {
return item && typeof item === "object" && !Array.isArray(item);
}
function deepMerge(target, source) {
const result = { ...target };
const _source = source;
if (isObject(target) && isObject(source)) {
Object.keys(source).forEach((key) => {
if (isObject(_source[key])) {
if (!(key in target)) {
result[key] = _source[key];
} else {
result[key] = deepMerge(result[key], _source[key]);
}
} else {
result[key] = _source[key];
}
});
}
return result;
}
function camelToKebabCase(value) {
return value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
}
function getTransformedScaledValue(value) {
if (typeof value !== "string" || !value.includes("var(--mantine-scale)")) {
return value;
}
return value.match(/^calc\((.*?)\)$/)?.[1].split("*")[0].trim();
}
function px(value) {
const transformedValue = getTransformedScaledValue(value);
if (typeof transformedValue === "number") {
return transformedValue;
}
if (typeof transformedValue === "string") {
if (transformedValue.includes("calc") || transformedValue.includes("var")) {
return transformedValue;
}
if (transformedValue.includes("px")) {
return Number(transformedValue.replace("px", ""));
}
if (transformedValue.includes("rem")) {
return Number(transformedValue.replace("rem", "")) * 16;
}
if (transformedValue.includes("em")) {
return Number(transformedValue.replace("em", "")) * 16;
}
return Number(transformedValue);
}
return NaN;
}
function scaleRem(remValue) {
if (remValue === "0rem") {
return "0rem";
}
return `calc(${remValue} * var(--mantine-scale))`;
}
function createConverter(units, { shouldScale = false } = {}) {
function converter(value) {
if (value === 0 || value === "0") {
return `0${units}`;
}
if (typeof value === "number") {
const val = `${value / 16}${units}`;
return shouldScale ? scaleRem(val) : val;
}
if (typeof value === "string") {
if (value === "") {
return value;
}
if (value.startsWith("calc(") || value.startsWith("clamp(") || value.includes("rgba(")) {
return value;
}
if (value.includes(",")) {
return value.split(",").map((val) => converter(val)).join(",");
}
if (value.includes(" ")) {
return value.split(" ").map((val) => converter(val)).join(" ");
}
if (value.includes(units)) {
return shouldScale ? scaleRem(value) : value;
}
const replaced = value.replace("px", "");
if (!Number.isNaN(Number(replaced))) {
const val = `${Number(replaced) / 16}${units}`;
return shouldScale ? scaleRem(val) : val;
}
}
return value;
}
return converter;
}
const rem = createConverter("rem", { shouldScale: true });
const em = createConverter("em");
function filterProps(props) {
return Object.keys(props).reduce((acc, key) => {
if (props[key] !== void 0) {
acc[key] = props[key];
}
return acc;
}, {});
}
function isNumberLike(value) {
if (typeof value === "number") {
return true;
}
if (typeof value === "string") {
if (value.startsWith("calc(") || value.startsWith("var(") || value.includes(" ") && value.trim() !== "") {
return true;
}
const cssUnitsRegex = /^[+-]?[0-9]+(\.[0-9]+)?(px|em|rem|ex|ch|lh|rlh|vw|vh|vmin|vmax|vb|vi|svw|svh|lvw|lvh|dvw|dvh|cm|mm|in|pt|pc|q|cqw|cqh|cqi|cqb|cqmin|cqmax|%)?$/;
const values = value.trim().split(/\s+/);
return values.every((val) => cssUnitsRegex.test(val));
}
return false;
}
function isElement$1(value) {
if (Array.isArray(value) || value === null) {
return false;
}
if (typeof value === "object") {
if (value.type === Fragment) {
return false;
}
return true;
}
return false;
}
function createSafeContext(errorMessage) {
const Context = createContext$1(null);
const useSafeContext = () => {
const ctx = useContext$1(Context);
if (ctx === null) {
throw new Error(errorMessage);
}
return ctx;
};
const Provider = ({ children, value }) => /* @__PURE__ */ jsx(Context.Provider, { value, children });
return [Provider, useSafeContext];
}
function createOptionalContext(initialValue = null) {
const Context = createContext$1(initialValue);
const useOptionalContext = () => useContext$1(Context);
const Provider = ({ children, value }) => /* @__PURE__ */ jsx(Context.Provider, { value, children });
return [Provider, useOptionalContext];
}
function getSafeId(uid, errorMessage) {
return (value) => {
if (typeof value !== "string" || value.trim().length === 0) {
throw new Error(errorMessage);
}
return `${uid}-${value}`;
};
}
function findElementAncestor(element, selector) {
let _element = element;
while ((_element = _element.parentElement) && !_element.matches(selector)) {
}
return _element;
}
function getPreviousIndex$1(current, elements, loop) {
for (let i = current - 1; i >= 0; i -= 1) {
if (!elements[i].disabled) {
return i;
}
}
if (loop) {
for (let i = elements.length - 1; i > -1; i -= 1) {
if (!elements[i].disabled) {
return i;
}
}
}
return current;
}
function getNextIndex$1(current, elements, loop) {
for (let i = current + 1; i < elements.length; i += 1) {
if (!elements[i].disabled) {
return i;
}
}
if (loop) {
for (let i = 0; i < elements.length; i += 1) {
if (!elements[i].disabled) {
return i;
}
}
}
return current;
}
function onSameLevel(target, sibling, parentSelector) {
return findElementAncestor(target, parentSelector) === findElementAncestor(sibling, parentSelector);
}
function createScopedKeydownHandler({
parentSelector,
siblingSelector,
onKeyDown,
loop = true,
activateOnFocus = false,
dir = "rtl",
orientation
}) {
return (event) => {
onKeyDown?.(event);
const elements = Array.from(
findElementAncestor(event.currentTarget, parentSelector)?.querySelectorAll(
siblingSelector
) || []
).filter((node) => onSameLevel(event.currentTarget, node, parentSelector));
const current = elements.findIndex((el) => event.currentTarget === el);
const _nextIndex = getNextIndex$1(current, elements, loop);
const _previousIndex = getPreviousIndex$1(current, elements, loop);
const nextIndex = dir === "rtl" ? _previousIndex : _nextIndex;
const previousIndex = dir === "rtl" ? _nextIndex : _previousIndex;
switch (event.key) {
case "ArrowRight": {
if (orientation === "horizontal") {
event.stopPropagation();
event.preventDefault();
elements[nextIndex].focus();
activateOnFocus && elements[nextIndex].click();
}
break;
}
case "ArrowLeft": {
if (orientation === "horizontal") {
event.stopPropagation();
event.preventDefault();
elements[previousIndex].focus();
activateOnFocus && elements[previousIndex].click();
}
break;
}
case "ArrowUp": {
if (orientation === "vertical") {
event.stopPropagation();
event.preventDefault();
elements[_previousIndex].focus();
activateOnFocus && elements[_previousIndex].click();
}
break;
}
case "ArrowDown": {
if (orientation === "vertical") {
event.stopPropagation();
event.preventDefault();
elements[_nextIndex].focus();
activateOnFocus && elements[_nextIndex].click();
}
break;
}
case "Home": {
event.stopPropagation();
event.preventDefault();
!elements[0].disabled && elements[0].focus();
break;
}
case "End": {
event.stopPropagation();
event.preventDefault();
const last = elements.length - 1;
!elements[last].disabled && elements[last].focus();
break;
}
}
};
}
const elevations = {
app: 100,
modal: 200,
popover: 300,
overlay: 400,
max: 9999
};
function getDefaultZIndex(level) {
return elevations[level];
}
const noop$1 = () => {
};
function closeOnEscape(callback, options = { active: true }) {
if (typeof callback !== "function" || !options.active) {
return options.onKeyDown || noop$1;
}
return (event) => {
if (event.key === "Escape") {
callback(event);
options.onTrigger?.();
}
};
}
function getSize(size, prefix = "size", convertToRem = true) {
if (size === void 0) {
return void 0;
}
return isNumberLike(size) ? convertToRem ? rem(size) : size : `var(--${prefix}-${size})`;
}
function getSpacing(size) {
return getSize(size, "mantine-spacing");
}
function getRadius(size) {
if (size === void 0) {
return "var(--mantine-radius-default)";
}
return getSize(size, "mantine-radius");
}
function getFontSize(size) {
return getSize(size, "mantine-font-size");
}
function getLineHeight(size) {
return getSize(size, "mantine-line-height", false);
}
function getShadow(size) {
if (!size) {
return void 0;
}
return getSize(size, "mantine-shadow", false);
}
function clamp$2(value, min, max) {
if (min === void 0 && max === void 0) {
return value;
}
if (min !== void 0 && max === void 0) {
return Math.max(value, min);
}
if (min === void 0 && max !== void 0) {
return Math.min(value, max);
}
return Math.min(Math.max(value, min), max);
}
function randomId(prefix = "mantine-") {
return `${prefix}${Math.random().toString(36).slice(2, 11)}`;
}
function useCallbackRef(callback) {
const callbackRef = useRef$1(callback);
useEffect$1(() => {
callbackRef.current = callback;
});
return useMemo$1(() => (...args) => callbackRef.current?.(...args), []);
}
function useDebouncedCallback(callback, options) {
const delay = typeof options === "number" ? options : options.delay;
const flushOnUnmount = typeof options === "number" ? false : options.flushOnUnmount;
const handleCallback = useCallbackRef(callback);
const debounceTimerRef = useRef$1(0);
const flushRef = useRef$1(() => {
});
const lastCallback = Object.assign(
useCallback$1(
(...args) => {
window.clearTimeout(debounceTimerRef.current);
const flush = () => {
if (debounceTimerRef.current !== 0) {
debounceTimerRef.current = 0;
handleCallback(...args);
}
};
flushRef.current = flush;
lastCallback.flush = flush;
debounceTimerRef.current = window.setTimeout(flush, delay);
},
[handleCallback, delay]
),
{ flush: flushRef.current }
);
useEffect$1(
() => () => {
window.clearTimeout(debounceTimerRef.current);
if (flushOnUnmount) {
lastCallback.flush();
}
},
[lastCallback, flushOnUnmount]
);
return lastCallback;
}
const DEFAULT_EVENTS = ["mousedown", "touchstart"];
function useClickOutside(handler, events, nodes) {
const ref = useRef$1(null);
useEffect$1(() => {
const listener = (event) => {
const { target } = event ?? {};
if (Array.isArray(nodes)) {
const shouldIgnore = target?.hasAttribute("data-ignore-outside-clicks") || !document.body.contains(target) && target.tagName !== "HTML";
const shouldTrigger = nodes.every((node) => !!node && !event.composedPath().includes(node));
shouldTrigger && !shouldIgnore && handler();
} else if (ref.current && !ref.current.contains(target)) {
handler();
}
};
(events || DEFAULT_EVENTS).forEach((fn) => document.addEventListener(fn, listener));
return () => {
(events || DEFAULT_EVENTS).forEach((fn) => document.removeEventListener(fn, listener));
};
}, [ref, handler, nodes]);
return ref;
}
function useClipboard({ timeout = 2e3 } = {}) {
const [error, setError] = useState$1(null);
const [copied, setCopied] = useState$1(false);
const [copyTimeout, setCopyTimeout] = useState$1(null);
const handleCopyResult = (value) => {
window.clearTimeout(copyTimeout);
setCopyTimeout(window.setTimeout(() => setCopied(false), timeout));
setCopied(value);
};
const copy = (valueToCopy) => {
if ("clipboard" in navigator) {
navigator.clipboard.writeText(valueToCopy).then(() => handleCopyResult(true)).catch((err) => setError(err));
} else {
setError(new Error("useClipboard: navigator.clipboard is not supported"));
}
};
const reset = () => {
setCopied(false);
setError(null);
window.clearTimeout(copyTimeout);
};
return { copy, reset, error, copied };
}
function attachMediaListener(query, callback) {
try {
query.addEventListener("change", callback);
return () => query.removeEventListener("change", callback);
} catch (e) {
query.addListener(callback);
return () => query.removeListener(callback);
}
}
function getInitialValue(query, initialValue) {
if (typeof window !== "undefined" && "matchMedia" in window) {
return window.matchMedia(query).matches;
}
return false;
}
function useMediaQuery(query, initialValue, { getInitialValueInEffect } = {
getInitialValueInEffect: true
}) {
const [matches, setMatches] = useState$1(
getInitialValueInEffect ? initialValue : getInitialValue(query)
);
const queryRef = useRef$1(null);
useEffect$1(() => {
if ("matchMedia" in window) {
queryRef.current = window.matchMedia(query);
setMatches(queryRef.current.matches);
return attachMediaListener(queryRef.current, (event) => setMatches(event.matches));
}
return void 0;
}, [query]);
return matches;
}
function useColorScheme(initialValue, options) {
return useMediaQuery("(prefers-color-scheme: dark)", initialValue === "dark", options) ? "dark" : "light";
}
const useIsomorphicEffect = typeof document !== "undefined" ? useLayoutEffect$1 : useEffect$1;
function useDidUpdate(fn, dependencies) {
const mounted = useRef$1(false);
useEffect$1(
() => () => {
mounted.current = false;
},
[]
);
useEffect$1(() => {
if (mounted.current) {
return fn();
}
mounted.current = true;
return void 0;
}, dependencies);
}
function useFocusReturn({ opened, shouldReturnFocus = true }) {
const lastActiveElement = useRef$1(null);
const returnFocus = () => {
if (lastActiveElement.current && "focus" in lastActiveElement.current && typeof lastActiveElement.current.focus === "function") {
lastActiveElement.current?.focus({ preventScroll: true });
}
};
useDidUpdate(() => {
let timeout = -1;
const clearFocusTimeout = (event) => {
if (event.key === "Tab") {
window.clearTimeout(timeout);
}
};
document.addEventListener("keydown", clearFocusTimeout);
if (opened) {
lastActiveElement.current = document.activeElement;
} else if (shouldReturnFocus) {
timeout = window.setTimeout(returnFocus, 10);
}
return () => {
window.clearTimeout(timeout);
document.removeEventListener("keydown", clearFocusTimeout);
};
}, [opened, shouldReturnFocus]);
return returnFocus;
}
const TABBABLE_NODES = /input|select|textarea|button|object/;
const FOCUS_SELECTOR = "a, input, select, textarea, button, object, [tabindex]";
function hidden(element) {
if (process.env.NODE_ENV === "test") {
return false;
}
return element.style.display === "none";
}
function visible(element) {
const isHidden = element.getAttribute("aria-hidden") || element.getAttribute("hidden") || element.getAttribute("type") === "hidden";
if (isHidden) {
return false;
}
let parentElement = element;
while (parentElement) {
if (parentElement === document.body || parentElement.nodeType === 11) {
break;
}
if (hidden(parentElement)) {
return false;
}
parentElement = parentElement.parentNode;
}
return true;
}
function getElementTabIndex(element) {
let tabIndex = element.getAttribute("tabindex");
if (tabIndex === null) {
tabIndex = void 0;
}
return parseInt(tabIndex, 10);
}
function focusable(element) {
const nodeName = element.nodeName.toLowerCase();
const isTabIndexNotNaN = !Number.isNaN(getElementTabIndex(element));
const res = (
// @ts-expect-error function accepts any html element but if it is a button, it should not be disabled to trigger the condition
TABBABLE_NODES.test(nodeName) && !element.disabled || (element instanceof HTMLAnchorElement ? element.href || isTabIndexNotNaN : isTabIndexNotNaN)
);
return res && visible(element);
}
function tabbable(element) {
const tabIndex = getElementTabIndex(element);
const isTabIndexNaN = Number.isNaN(tabIndex);
return (isTabIndexNaN || tabIndex >= 0) && focusable(element);
}
function findTabbableDescendants(element) {
return Array.from(element.querySelectorAll(FOCUS_SELECTOR)).filter(tabbable);
}
function scopeTab(node, event) {
const tabbable = findTabbableDescendants(node);
if (!tabbable.length) {
event.preventDefault();
return;
}
const finalTabbable = tabbable[event.shiftKey ? 0 : tabbable.length - 1];
const root = node.getRootNode();
let leavingFinalTabbable = finalTabbable === root.activeElement || node === root.activeElement;
const activeElement = root.activeElement;
const activeElementIsRadio = activeElement.tagName === "INPUT" && activeElement.getAttribute("type") === "radio";
if (activeElementIsRadio) {
const activeRadioGroup = tabbable.filter(
(element) => element.getAttribute("type") === "radio" && element.getAttribute("name") === activeElement.getAttribute("name")
);
leavingFinalTabbable = activeRadioGroup.includes(finalTabbable);
}
if (!leavingFinalTabbable) {
return;
}
event.preventDefault();
const target = tabbable[event.shiftKey ? tabbable.length - 1 : 0];
if (target) {
target.focus();
}
}
function useFocusTrap(active = true) {
const ref = useRef$1(null);
const focusNode = (node) => {
let focusElement = node.querySelector("[data-autofocus]");
if (!focusElement) {
const children = Array.from(node.querySelectorAll(FOCUS_SELECTOR));
focusElement = children.find(tabbable) || children.find(focusable) || null;
if (!focusElement && focusable(node)) {
focusElement = node;
}
}
if (focusElement) {
focusElement.focus({ preventScroll: true });
} else if (process.env.NODE_ENV === "development") {
console.warn(
"[@mantine/hooks/use-focus-trap] Failed to find focusable element within provided node",
node
);
}
};
const setRef = useCallback$1(
(node) => {
if (!active) {
return;
}
if (node === null) {
return;
}
if (ref.current === node) {
return;
}
if (node) {
setTimeout(() => {
if (node.getRootNode()) {
focusNode(node);
} else if (process.env.NODE_ENV === "development") {
console.warn("[@mantine/hooks/use-focus-trap] Ref node is not part of the dom", node);
}
});
ref.current = node;
} else {
ref.current = null;
}
},
[active]
);
useEffect$1(() => {
if (!active) {
return void 0;
}
ref.current && setTimeout(() => focusNode(ref.current));
const handleKeyDown = (event) => {
if (event.key === "Tab" && ref.current) {
scopeTab(ref.current, event);
}
};
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, [active]);
return setRef;
}
const __useId = React__default["useId".toString()] || (() => void 0);
function useReactId$1() {
const id = __useId();
return id ? `mantine-${id.replace(/:/g, "")}` : "";
}
function useId$2(staticId) {
const reactId = useReactId$1();
const [uuid, setUuid] = useState$1(reactId);
useIsomorphicEffect(() => {
setUuid(randomId());
}, []);
if (typeof staticId === "string") {
return staticId;
}
if (typeof window === "undefined") {
return reactId;
}
return uuid;
}
function useInterval(fn, interval, { autoInvoke = false } = {}) {
const [active, setActive] = useState$1(false);
const intervalRef = useRef$1(null);
const fnRef = useRef$1(null);
const start = () => {
setActive((old) => {
if (!old && (!intervalRef.current || intervalRef.current === -1)) {
intervalRef.current = window.setInterval(fnRef.current, interval);
}
return true;
});
};
const stop = () => {
setActive(false);
window.clearInterval(intervalRef.current || -1);
intervalRef.current = -1;
};
const toggle = () => {
if (active) {
stop();
} else {
start();
}
};
useEffect$1(() => {
fnRef.current = fn;
active && start();
return stop;
}, [fn, active, interval]);
useEffect$1(() => {
if (autoInvoke) {
start();
}
}, []);
return { start, stop, toggle, active };
}
function useWindowEvent(type, listener, options) {
useEffect$1(() => {
window.addEventListener(type, listener, options);
return () => window.removeEventListener(type, listener, options);
}, [type, listener]);
}
function assignRef(ref, value) {
if (typeof ref === "function") {
return ref(value);
} else if (typeof ref === "object" && ref !== null && "current" in ref) {
ref.current = value;
}
}
function mergeRefs(...refs) {
const cleanupMap = /* @__PURE__ */ new Map();
return (node) => {
refs.forEach((ref) => {
const cleanup = assignRef(ref, node);
if (cleanup) {
cleanupMap.set(ref, cleanup);
}
});
if (cleanupMap.size > 0) {
return () => {
refs.forEach((ref) => {
const cleanup = cleanupMap.get(ref);
if (cleanup) {
cleanup();
} else {
assignRef(ref, null);
}
});
cleanupMap.clear();
};
}
};
}
function useMergedRef(...refs) {
return useCallback$1(mergeRefs(...refs), refs);
}
function useMove(onChange, handlers, dir = "ltr") {
const ref = useRef$1(null);
const mounted = useRef$1(false);
const isSliding = useRef$1(false);
const frame = useRef$1(0);
const [active, setActive] = useState$1(false);
useEffect$1(() => {
mounted.current = true;
}, []);
useEffect$1(() => {
const node = ref.current;
const onScrub = ({ x, y }) => {
cancelAnimationFrame(frame.current);
frame.current = requestAnimationFrame(() => {
if (mounted.current && node) {
node.style.userSelect = "none";
const rect = node.getBoundingClientRect();
if (rect.width && rect.height) {
const _x = clamp$2((x - rect.left) / rect.width, 0, 1);
onChange({
x: dir === "ltr" ? _x : 1 - _x,
y: clamp$2((y - rect.top) / rect.height, 0, 1)
});
}
}
});
};
const bindEvents = () => {
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", stopScrubbing);
document.addEventListener("touchmove", onTouchMove);
document.addEventListener("touchend", stopScrubbing);
};
const unbindEvents = () => {
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", stopScrubbing);
document.removeEventListener("touchmove", onTouchMove);
document.removeEventListener("touchend", stopScrubbing);
};
const startScrubbing = () => {
if (!isSliding.current && mounted.current) {
isSliding.current = true;
typeof handlers?.onScrubStart === "function" && handlers.onScrubStart();
setActive(true);
bindEvents();
}
};
const stopScrubbing = () => {
if (isSliding.current && mounted.current) {
isSliding.current = false;
setActive(false);
unbindEvents();
setTimeout(() => {
typeof handlers?.onScrubEnd === "function" && handlers.onScrubEnd();
}, 0);
}
};
const onMouseDown = (event) => {
startScrubbing();
event.preventDefault();
onMouseMove(event);
};
const onMouseMove = (event) => onScrub({ x: event.clientX, y: event.clientY });
const onTouchStart = (event) => {
if (event.cancelable) {
event.preventDefault();
}
startScrubbing();
onTouchMove(event);
};
const onTouchMove = (event) => {
if (event.cancelable) {
event.preventDefault();
}
onScrub({ x: event.changedTouches[0].clientX, y: event.changedTouches[0].clientY });
};
node?.addEventListener("mousedown", onMouseDown);
node?.addEventListener("touchstart", onTouchStart, { passive: fals