@buildinams/core 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/chunk-SIU7SKJK.js +139 -0
- package/dist/chunk-SIU7SKJK.js.map +1 -0
- package/dist/index.d.ts +288 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/state-BnfG-Qk9.d.ts +32 -0
- package/dist/store/index.d.ts +161 -0
- package/dist/store/index.js +417 -0
- package/dist/store/index.js.map +1 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
|
|
3
|
+
// src/config/index.ts
|
|
4
|
+
var IS_DEVELOPMENT = process.env.NODE_ENV === "development";
|
|
5
|
+
var IS_BUILD = process.env.NODE_ENV === "production";
|
|
6
|
+
var IS_IN_BROWSER = (() => {
|
|
7
|
+
try {
|
|
8
|
+
return !!window && "document" in window && !!window.document?.createElement;
|
|
9
|
+
} catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
})();
|
|
13
|
+
|
|
14
|
+
// src/functions/apply-state.ts
|
|
15
|
+
function isUpdater(argument) {
|
|
16
|
+
return typeof argument === "function";
|
|
17
|
+
}
|
|
18
|
+
function isLazyValue(value) {
|
|
19
|
+
return typeof value === "function";
|
|
20
|
+
}
|
|
21
|
+
function applyState(argument, currentValue) {
|
|
22
|
+
if (isUpdater(argument)) {
|
|
23
|
+
const value = isLazyValue(currentValue) ? currentValue() : currentValue;
|
|
24
|
+
return argument(value);
|
|
25
|
+
}
|
|
26
|
+
return argument;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/functions/default-value.ts
|
|
30
|
+
function defaultValue(...values) {
|
|
31
|
+
for (const value of values) {
|
|
32
|
+
if (value !== void 0) return value;
|
|
33
|
+
}
|
|
34
|
+
return void 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/functions/identity.ts
|
|
38
|
+
function identity(value) {
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// src/functions/math.ts
|
|
43
|
+
var wrap = (value, [min, max]) => {
|
|
44
|
+
const range = max - min + 1;
|
|
45
|
+
return ((value - min) % range + range) % range + min;
|
|
46
|
+
};
|
|
47
|
+
var clamp = (value, [min, max]) => {
|
|
48
|
+
return Math.min(Math.max(value, min), max);
|
|
49
|
+
};
|
|
50
|
+
var transform = (value, originRange, targetRange) => {
|
|
51
|
+
const [oMin, oMax] = originRange;
|
|
52
|
+
const [tMin, tMax] = targetRange;
|
|
53
|
+
const ratio = (value - oMin) / (oMax - oMin);
|
|
54
|
+
const transformedValue = tMin + ratio * (tMax - tMin);
|
|
55
|
+
return transformedValue;
|
|
56
|
+
};
|
|
57
|
+
var round = (value, decimalPlaces = 0) => {
|
|
58
|
+
const factor = Math.pow(10, decimalPlaces);
|
|
59
|
+
return Math.round((value + Number.EPSILON) * factor) / factor;
|
|
60
|
+
};
|
|
61
|
+
var mergeClassNames = (...classNames) => {
|
|
62
|
+
try {
|
|
63
|
+
return clsx(...classNames);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
"mergeClassNames: Invalid input provided. Ensure all class names are strings, undefined, or null."
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// src/functions/platform.ts
|
|
72
|
+
var isTouchDevice = () => {
|
|
73
|
+
return IS_IN_BROWSER && !!navigator.maxTouchPoints;
|
|
74
|
+
};
|
|
75
|
+
var isApple = () => {
|
|
76
|
+
if (!IS_IN_BROWSER) return false;
|
|
77
|
+
return /mac|iphone|ipad|ipod/i.test(navigator.platform);
|
|
78
|
+
};
|
|
79
|
+
var isMac = () => {
|
|
80
|
+
return IS_IN_BROWSER && navigator.platform.startsWith("Mac") && !isTouchDevice();
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// src/functions/remove-undefined-values.ts
|
|
84
|
+
function removeUndefinedValues(obj) {
|
|
85
|
+
const result = {};
|
|
86
|
+
for (const key in obj) {
|
|
87
|
+
if (obj[key] !== void 0) {
|
|
88
|
+
result[key] = obj[key];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/functions/shallow-equal.ts
|
|
95
|
+
function shallowEqual(a, b) {
|
|
96
|
+
if (a === b) return true;
|
|
97
|
+
if (!a) return false;
|
|
98
|
+
if (!b) return false;
|
|
99
|
+
if (typeof a !== "object") return false;
|
|
100
|
+
if (typeof b !== "object") return false;
|
|
101
|
+
const aKeys = Object.keys(a);
|
|
102
|
+
const bKeys = Object.keys(b);
|
|
103
|
+
const { length } = aKeys;
|
|
104
|
+
if (bKeys.length !== length) return false;
|
|
105
|
+
for (const key of aKeys) {
|
|
106
|
+
if (a[key] !== b[key]) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/functions/type-guards.ts
|
|
114
|
+
var notEmpty = (value) => value !== null && value !== void 0;
|
|
115
|
+
var isHTMLElement = (node) => node instanceof HTMLElement;
|
|
116
|
+
var isInArray = (item, array) => array.includes(item);
|
|
117
|
+
var isObject = (object) => {
|
|
118
|
+
try {
|
|
119
|
+
return typeof object === "object" && object !== null && !Array.isArray(object);
|
|
120
|
+
} catch {
|
|
121
|
+
throw new Error("isObject: Invalid input");
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
var isTruthy = (value) => !!value;
|
|
125
|
+
function invariant(condition, message) {
|
|
126
|
+
if (condition) return;
|
|
127
|
+
if (typeof message !== "string") throw new Error("Invariant failed");
|
|
128
|
+
throw new Error(message);
|
|
129
|
+
}
|
|
130
|
+
var hasOwnProperty = (object, prop) => {
|
|
131
|
+
if (typeof Object.hasOwn === "function") {
|
|
132
|
+
return Object.hasOwn(object, prop);
|
|
133
|
+
}
|
|
134
|
+
return Object.prototype.hasOwnProperty.call(object, prop);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export { IS_BUILD, IS_DEVELOPMENT, IS_IN_BROWSER, applyState, clamp, defaultValue, hasOwnProperty, identity, invariant, isApple, isHTMLElement, isInArray, isMac, isObject, isTouchDevice, isTruthy, mergeClassNames, notEmpty, removeUndefinedValues, round, shallowEqual, transform, wrap };
|
|
138
|
+
//# sourceMappingURL=chunk-SIU7SKJK.js.map
|
|
139
|
+
//# sourceMappingURL=chunk-SIU7SKJK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config/index.ts","../src/functions/apply-state.ts","../src/functions/default-value.ts","../src/functions/identity.ts","../src/functions/math.ts","../src/functions/merge-class-names.ts","../src/functions/platform.ts","../src/functions/remove-undefined-values.ts","../src/functions/shallow-equal.ts","../src/functions/type-guards.ts"],"names":[],"mappings":";;;AAAO,IAAM,cAAA,GAAiB,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa;AAChD,IAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa;AAE1C,IAAM,iBAAiB,MAAM;AACnC,EAAA,IAAI;AACH,IAAA,OAAO,CAAC,CAAC,MAAA,IAAU,UAAA,IAAc,UAAU,CAAC,CAAC,OAAO,QAAA,EAAU,aAAA;AAAA,EAC/D,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO,KAAA;AAAA,EACR;AACD,CAAA;;;ACLA,SAAS,UACR,QAAA,EACqD;AACrD,EAAA,OAAO,OAAO,QAAA,KAAa,UAAA;AAC5B;AAEA,SAAS,YAAe,KAAA,EAA8B;AACrD,EAAA,OAAO,OAAO,KAAA,KAAU,UAAA;AACzB;AASO,SAAS,UAAA,CACf,UACA,YAAA,EACC;AACD,EAAA,IAAI,SAAA,CAAU,QAAQ,CAAA,EAAG;AACxB,IAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,YAAY,CAAA,GAAI,cAAa,GAAI,YAAA;AAC3D,IAAA,OAAO,SAAS,KAAK,CAAA;AAAA,EACtB;AACA,EAAA,OAAO,QAAA;AACR;;;ACtBO,SAAS,gBAAgB,MAAA,EAAmB;AAClD,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC3B,IAAA,IAAI,KAAA,KAAU,QAAW,OAAO,KAAA;AAAA,EACjC;AACA,EAAA,OAAO,MAAA;AACR;;;ACVO,SAAS,SAAY,KAAA,EAAU;AACrC,EAAA,OAAO,KAAA;AACR;;;ACQO,IAAM,OAAO,CAAC,KAAA,EAAe,CAAC,GAAA,EAAK,GAAG,CAAA,KAAkC;AAC9E,EAAA,MAAM,KAAA,GAAQ,MAAM,GAAA,GAAM,CAAA;AAC1B,EAAA,OAAA,CAAA,CAAW,KAAA,GAAQ,GAAA,IAAO,KAAA,GAAS,KAAA,IAAS,KAAA,GAAS,GAAA;AACtD;AAgBO,IAAM,QAAQ,CACpB,KAAA,EACA,CAAC,GAAA,EAAK,GAAG,CAAA,KACL;AACJ,EAAA,OAAO,KAAK,GAAA,CAAI,IAAA,CAAK,IAAI,KAAA,EAAO,GAAG,GAAG,GAAG,CAAA;AAC1C;AAcO,IAAM,SAAA,GAAY,CACxB,KAAA,EACA,WAAA,EACA,WAAA,KACI;AACJ,EAAA,MAAM,CAAC,IAAA,EAAM,IAAI,CAAA,GAAI,WAAA;AACrB,EAAA,MAAM,CAAC,IAAA,EAAM,IAAI,CAAA,GAAI,WAAA;AAErB,EAAA,MAAM,KAAA,GAAA,CAAS,KAAA,GAAQ,IAAA,KAAS,IAAA,GAAO,IAAA,CAAA;AACvC,EAAA,MAAM,gBAAA,GAAmB,IAAA,GAAO,KAAA,IAAS,IAAA,GAAO,IAAA,CAAA;AAEhD,EAAA,OAAO,gBAAA;AACR;AAQO,IAAM,KAAA,GAAQ,CAAC,KAAA,EAAe,aAAA,GAAwB,CAAA,KAAM;AAClE,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,aAAa,CAAA;AACzC,EAAA,OAAO,KAAK,KAAA,CAAA,CAAO,KAAA,GAAQ,MAAA,CAAO,OAAA,IAAW,MAAM,CAAA,GAAI,MAAA;AACxD;ACxEA,IAAM,eAAA,GAAkB,IAAI,UAAA,KAAkC;AAC7D,EAAA,IAAI;AACH,IAAA,OAAO,IAAA,CAAK,GAAG,UAAU,CAAA;AAAA,EAC1B,SAAS,KAAA,EAAO;AACf,IAAA,MAAM,IAAI,KAAA;AAAA,MACT;AAAA,KACD;AAAA,EACD;AACD;;;ACLO,IAAM,gBAAgB,MAAM;AAClC,EAAA,OAAO,aAAA,IAAiB,CAAC,CAAC,SAAA,CAAU,cAAA;AACrC;AAKO,IAAM,UAAU,MAAM;AAC5B,EAAA,IAAI,CAAC,eAAe,OAAO,KAAA;AAC3B,EAAA,OAAO,uBAAA,CAAwB,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA;AACvD;AAKO,IAAM,QAAQ,MAAM;AAC1B,EAAA,OACC,iBAAiB,SAAA,CAAU,QAAA,CAAS,WAAW,KAAK,CAAA,IAAK,CAAC,aAAA,EAAc;AAE1E;;;ACnBO,SAAS,sBAA2C,GAAA,EAAQ;AAClE,EAAA,MAAM,SAAS,EAAC;AAChB,EAAA,KAAA,MAAW,OAAO,GAAA,EAAK;AACtB,IAAA,IAAI,GAAA,CAAI,GAAG,CAAA,KAAM,MAAA,EAAW;AAC3B,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,GAAA,CAAI,GAAG,CAAA;AAAA,IACtB;AAAA,EACD;AACA,EAAA,OAAO,MAAA;AACR;;;ACHO,SAAS,YAAA,CAAa,GAAe,CAAA,EAAe;AAC1D,EAAA,IAAI,CAAA,KAAM,GAAG,OAAO,IAAA;AACpB,EAAA,IAAI,CAAC,GAAG,OAAO,KAAA;AACf,EAAA,IAAI,CAAC,GAAG,OAAO,KAAA;AACf,EAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,KAAA;AAClC,EAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,KAAA;AAElC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAC3B,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAC3B,EAAA,MAAM,EAAE,QAAO,GAAI,KAAA;AAEnB,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,MAAA,EAAQ,OAAO,KAAA;AAEpC,EAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACxB,IAAA,IAAI,CAAA,CAAE,GAAG,CAAA,KAAM,CAAA,CAAE,GAAG,CAAA,EAAG;AACtB,MAAA,OAAO,KAAA;AAAA,IACR;AAAA,EACD;AAEA,EAAA,OAAO,IAAA;AACR;;;ACdO,IAAM,QAAA,GAAW,CACvB,KAAA,KACqB,KAAA,KAAU,QAAQ,KAAA,KAAU;AAgB3C,IAAM,aAAA,GAAgB,CAAC,IAAA,KAC7B,IAAA,YAAgB;AA4BV,IAAM,YAAY,CACxB,IAAA,EACA,KAAA,KACe,KAAA,CAAM,SAAS,IAAS;AAkBjC,IAAM,QAAA,GAAW,CACvB,MAAA,KACuC;AACvC,EAAA,IAAI;AACH,IAAA,OACC,OAAO,WAAW,QAAA,IAAY,MAAA,KAAW,QAAQ,CAAC,KAAA,CAAM,QAAQ,MAAM,CAAA;AAAA,EAExE,CAAA,CAAA,MAAQ;AACP,IAAA,MAAM,IAAI,MAAM,yBAAyB,CAAA;AAAA,EAC1C;AACD;AAkBO,IAAM,QAAA,GAAW,CAAI,KAAA,KAC3B,CAAC,CAAC;AAWI,SAAS,SAAA,CAEf,WACA,OAAA,EACoB;AACpB,EAAA,IAAI,SAAA,EAAW;AACf,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,EAAU,MAAM,IAAI,MAAM,kBAAkB,CAAA;AACnE,EAAA,MAAM,IAAI,MAAM,OAAO,CAAA;AACxB;AASO,IAAM,cAAA,GAAiB,CAC7B,MAAA,EAEA,IAAA,KACqB;AACrB,EAAA,IAAI,OAAO,MAAA,CAAO,MAAA,KAAW,UAAA,EAAY;AACxC,IAAA,OAAO,MAAA,CAAO,MAAA,CAAO,MAAA,EAAQ,IAAI,CAAA;AAAA,EAClC;AACA,EAAA,OAAO,MAAA,CAAO,SAAA,CAAU,cAAA,CAAe,IAAA,CAAK,QAAQ,IAAI,CAAA;AACzD","file":"chunk-SIU7SKJK.js","sourcesContent":["export const IS_DEVELOPMENT = process.env.NODE_ENV === \"development\";\nexport const IS_BUILD = process.env.NODE_ENV === \"production\";\n\nexport const IS_IN_BROWSER = (() => {\n\ttry {\n\t\treturn !!window && \"document\" in window && !!window.document?.createElement;\n\t} catch {\n\t\treturn false;\n\t}\n})();\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { BivariantCallback, SetStateAction } from \"src/types\";\n\nfunction isUpdater<T>(\n\targument: SetStateAction<T>,\n): argument is BivariantCallback<(prevState: T) => T> {\n\treturn typeof argument === \"function\";\n}\n\nfunction isLazyValue<T>(value: any): value is () => T {\n\treturn typeof value === \"function\";\n}\n\n/**\n * Receives a `setState` argument and calls it with `currentValue` if it's a\n * function. Otherwise return the argument as the new value.\n * @example\n * applyState((value) => value + 1, 1); // 2\n * applyState(2, 1); // 2\n */\nexport function applyState<T>(\n\targument: SetStateAction<T>,\n\tcurrentValue: T | (() => T),\n) {\n\tif (isUpdater(argument)) {\n\t\tconst value = isLazyValue(currentValue) ? currentValue() : currentValue;\n\t\treturn argument(value);\n\t}\n\treturn argument;\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * Returns the first value that is not `undefined`.\n */\nexport function defaultValue<T extends readonly any[]>(\n\t...values: T\n): DefaultValue<T>;\n\nexport function defaultValue(...values: unknown[]) {\n\tfor (const value of values) {\n\t\tif (value !== undefined) return value;\n\t}\n\treturn undefined;\n}\n\ntype DefaultValue<T extends readonly any[], Other = never> = T extends [\n\tinfer Head,\n\t...infer Rest,\n]\n\t? Rest extends []\n\t\t? T[number] | Other\n\t\t: undefined extends Head\n\t\t\t? DefaultValue<Rest, Exclude<Other | Head, undefined>>\n\t\t\t: Exclude<T[number], undefined>\n\t: never;\n","/**\n * Returns the same argument.\n */\nexport function identity<T>(value: T) {\n\treturn value;\n}\n","/**\n * Wraps a number within a specified range.\n * @param value - The number to wrap.\n * @param min - The minimum value of the range (inclusive).\n * @param max - The maximum value of the range (inclusive).\n * @returns The wrapped number within the range [min, max].\n *\n * @example\n * wrap(5, [0, 3]); // Returns 1\n * wrap(-1, [0, 3]); // Returns 2\n * wrap(-3, [0, 3]); // Returns 1\n * wrap(7, [0, 3]); // Returns 3\n */\nexport const wrap = (value: number, [min, max]: [min: number, max: number]) => {\n\tconst range = max - min + 1;\n\treturn ((((value - min) % range) + range) % range) + min;\n};\n\n/**\n * Limits a value between a specified range.\n * @param value - The number to limit.\n * @param min - The minimum value of the range (inclusive).\n * @param max - The maximum value of the range (inclusive).\n * @returns The wrapped number within the range [min, max].\n *\n * @example\n * clamp(2, [0, 3]); // Returns 2\n * clamp(5, [0, 3]); // Returns 3\n * clamp(-1, [0, 3]); // Returns 0\n * clamp(-3, [0, 3]); // Returns 0\n * clamp(7, [0, 3]); // Returns 3\n */\nexport const clamp = (\n\tvalue: number,\n\t[min, max]: [min: number, max: number],\n) => {\n\treturn Math.min(Math.max(value, min), max);\n};\n\n/**\n * Maps a number from one range to another.\n * @param value The number to map.\n * @param originRange The original range of the number.\n * @param targetRange The target range to map the number to.\n * @returns The mapped number within the target range.\n *\n * @example\n * transform(5, [0, 10], [0, 100]); // Returns 50\n * transform(0.5, [0, 1], [0, 10]); // Returns 5\n * transform(-5, [-10, 0], [0, 100]); // Returns 50\n */\nexport const transform = (\n\tvalue: number,\n\toriginRange: [number, number],\n\ttargetRange: [number, number],\n) => {\n\tconst [oMin, oMax] = originRange;\n\tconst [tMin, tMax] = targetRange;\n\n\tconst ratio = (value - oMin) / (oMax - oMin);\n\tconst transformedValue = tMin + ratio * (tMax - tMin);\n\n\treturn transformedValue;\n};\n\n/**\n * Rounds a number to a specified number of decimal places.\n * @param value - The number to round.\n * @param decimalPlaces - The number of decimal places to round to. (default is 0)\n * @returns The rounded number.\n */\nexport const round = (value: number, decimalPlaces: number = 0) => {\n\tconst factor = Math.pow(10, decimalPlaces);\n\treturn Math.round((value + Number.EPSILON) * factor) / factor;\n};\n","import clsx from \"clsx\";\n\nconst mergeClassNames = (...classNames: clsx.ClassValue[]) => {\n\ttry {\n\t\treturn clsx(...classNames);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t\"mergeClassNames: Invalid input provided. Ensure all class names are strings, undefined, or null.\",\n\t\t);\n\t}\n};\n\n// Name isn't very memorable, so we export it in this file to alias it\nexport { mergeClassNames };\n","import { IS_IN_BROWSER } from \"src/config\";\n\n/**\n * Detects if the device has touch capabilities.\n */\nexport const isTouchDevice = () => {\n\treturn IS_IN_BROWSER && !!navigator.maxTouchPoints;\n};\n\n/**\n * Detects Apple device.\n */\nexport const isApple = () => {\n\tif (!IS_IN_BROWSER) return false;\n\treturn /mac|iphone|ipad|ipod/i.test(navigator.platform);\n};\n\n/**\n * Detects Mac computer.\n */\nexport const isMac = () => {\n\treturn (\n\t\tIS_IN_BROWSER && navigator.platform.startsWith(\"Mac\") && !isTouchDevice()\n\t);\n};\n","import { AnyObject } from \"../types\";\n\n/**\n * Removes undefined values from an object.\n */\nexport function removeUndefinedValues<T extends AnyObject>(obj: T) {\n\tconst result = {} as T;\n\tfor (const key in obj) {\n\t\tif (obj[key] !== undefined) {\n\t\t\tresult[key] = obj[key];\n\t\t}\n\t}\n\treturn result;\n}\n","import { AnyObject } from \"src/types\";\n\n/**\n * Compares two objects.\n * @example\n * shallowEqual({ a: \"a\" }, {}); // false\n * shallowEqual({ a: \"a\" }, { b: \"b\" }); // false\n * shallowEqual({ a: \"a\" }, { a: \"a\" }); // true\n * shallowEqual({ a: \"a\" }, { a: \"a\", b: \"b\" }); // false\n */\nexport function shallowEqual(a?: AnyObject, b?: AnyObject) {\n\tif (a === b) return true;\n\tif (!a) return false;\n\tif (!b) return false;\n\tif (typeof a !== \"object\") return false;\n\tif (typeof b !== \"object\") return false;\n\n\tconst aKeys = Object.keys(a);\n\tconst bKeys = Object.keys(b);\n\tconst { length } = aKeys;\n\n\tif (bKeys.length !== length) return false;\n\n\tfor (const key of aKeys) {\n\t\tif (a[key] !== b[key]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n","import { AnyObject } from \"src/types\";\n\n/**\n * @function notEmpty\n * @description Checks if a value is not null or undefined.\n *\n * @param value - The value to check.\n * @returns Whether the value is not null or undefined.\n *\n * @example\n * ```ts\n * notEmpty(\"Hello\"); // true\n * notEmpty(null); // false\n * notEmpty(undefined); // false\n * ```\n */\nexport const notEmpty = <TValue>(\n\tvalue: TValue | null | undefined,\n): value is TValue => value !== null && value !== undefined;\n\n/**\n * @function isHTMLElement\n * @description Checks if a value is an instance of HTMLElement.\n *\n * @param node - The value to check.\n * @returns Whether the value is an instance of HTMLElement.\n *\n * @example\n * ```ts\n * isHTMLElement(document.querySelector('body')); // true\n * isHTMLElement({}); // false\n * ```\n */\n\nexport const isHTMLElement = (node: unknown): node is HTMLElement =>\n\tnode instanceof HTMLElement;\n\n/**\n * @function isInArray\n * @description Typesafe check if an item is in an array without being explicit about const types\n *\n * @param item - The item to check.\n * @param array - The array to check against.\n *\n * @returns Whether the item is in the array.\n *\n * @example\n * ```ts\n * // Default situation in TS:\n * const arr = ['hello', 'world'] as const;\n *\n * let someString = 'something';\n *\n * arr.includes(someString); // Argument of type 'string' is not assignable to parameter of type '\"hello\" | \"world\"'\n *\n * // Using isInArray:\n * const arr = ['hello', 'world'] as const;\n *\n * let someString = 'something';\n *\n * isInArray(someString, arr); // false, but no type error\n * ```\n */\nexport const isInArray = <T, A extends T>(\n\titem: T,\n\tarray: ReadonlyArray<A>,\n): item is A => array.includes(item as A);\n\n/**\n * @function isObject\n * @description Checks if a value is an object (excluding arrays).\n *\n * @param object - The value to check.\n * @returns Whether the value is truthy.\n *\n * @example\n * ```ts\n * isObject({ hello: world }); // true\n * isObject({}); // true\n * isObject([]); // false\n * isObject(\"\"); // false\n * isObject(null); // false\n * ```\n */\nexport const isObject = (\n\tobject: unknown,\n): object is Record<string, unknown> => {\n\ttry {\n\t\treturn (\n\t\t\ttypeof object === \"object\" && object !== null && !Array.isArray(object)\n\t\t);\n\t} catch {\n\t\tthrow new Error(\"isObject: Invalid input\");\n\t}\n};\n\n/**\n * @function isTruthy\n * @description Checks if a value is truthy.\n *\n * @param value - The value to check.\n * @returns Whether the value is truthy.\n *\n * @example\n * ```ts\n * isTruthy(\"foo\"); // true\n * isTruthy(1); // true\n * isTruthy(0); // false\n * isTruthy(\"\"); // false\n * ```\n *\n */\nexport const isTruthy = <T>(value?: T | undefined | null | false): value is T =>\n\t!!value;\n\n/**\n * Asserts that a condition is true, otherwise throws an error.\n * @example\n * invariant(\n * condition,\n * process.env.NODE_ENV !== \"production\" && \"Invariant failed\"\n * );\n */\n// assert functions need to be an explicit function(){}\nexport function invariant(\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tcondition: any,\n\tmessage?: string | boolean,\n): asserts condition {\n\tif (condition) return;\n\tif (typeof message !== \"string\") throw new Error(\"Invariant failed\");\n\tthrow new Error(message);\n}\n\n/**\n * Checks if an object has a property as its own (not inherited) property.\n * @example\n * hasOwnProperty({ a: \"a\" }, \"a\"); // true\n * hasOwnProperty({ a: \"a\" }, \"b\"); // false\n * hasOwnProperty(Object.create({ a: \"a\" }), \"a\"); // false\n */\nexport const hasOwnProperty = <T extends AnyObject>(\n\tobject: T,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tprop: keyof any,\n): prop is keyof T => {\n\tif (typeof Object.hasOwn === \"function\") {\n\t\treturn Object.hasOwn(object, prop);\n\t}\n\treturn Object.prototype.hasOwnProperty.call(object, prop);\n};\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { S as SetStateAction, A as AnyObject } from './state-BnfG-Qk9.js';
|
|
2
|
+
export { a as AnyFunction, B as BivariantCallback, E as EmptyObject, L as LooseObject, b as SetState } from './state-BnfG-Qk9.js';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import { ImageProps } from 'next/image';
|
|
5
|
+
|
|
6
|
+
declare const IS_DEVELOPMENT: boolean;
|
|
7
|
+
declare const IS_BUILD: boolean;
|
|
8
|
+
declare const IS_IN_BROWSER: boolean;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Picks only the properties from a type that have a specific value.
|
|
12
|
+
* @template T The type to pick from.
|
|
13
|
+
* @template Value The value to pick.
|
|
14
|
+
*/
|
|
15
|
+
type PickByValue<T, Value> = {
|
|
16
|
+
[K in keyof T as [Value] extends [T[K]] ? T[K] extends Value | undefined ? K : never : never]: T[K];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Picks only the required properties from a type.
|
|
20
|
+
* @template T The type to pick from.
|
|
21
|
+
* @template P The properties to pick.
|
|
22
|
+
*/
|
|
23
|
+
type PickRequired<T, P extends keyof T> = T & {
|
|
24
|
+
[K in keyof T]: Pick<Required<T>, K>;
|
|
25
|
+
}[P];
|
|
26
|
+
/** Turn { a: 1 } | { b: 2 } into { a: 1 } & { b: 2 } */
|
|
27
|
+
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
28
|
+
/** Turn { a: 1 } & { b: 2 } into { a: 1, b: 2 } */
|
|
29
|
+
type MergeIntersection<T> = T extends object ? {
|
|
30
|
+
[P in keyof T]: MergeIntersection<T[P]>;
|
|
31
|
+
} : T;
|
|
32
|
+
|
|
33
|
+
type BreakpointKey = string | number | "default";
|
|
34
|
+
type AllSizes = Partial<Record<BreakpointKey, number | string>>;
|
|
35
|
+
/**
|
|
36
|
+
* Prettify a type. This is useful for printing out all the keys
|
|
37
|
+
* of an inheritance based inference.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* type A = { a: string; b: number };
|
|
42
|
+
* type B = Prettify<A>;
|
|
43
|
+
* // B = {
|
|
44
|
+
* // a: string;
|
|
45
|
+
* // b: number;
|
|
46
|
+
* // }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
type Prettify<Type> = {
|
|
50
|
+
[Key in keyof Type]: Type[Key];
|
|
51
|
+
} & {};
|
|
52
|
+
type SizesMap = Prettify<AllSizes & Required<Pick<AllSizes, "default">>>;
|
|
53
|
+
type TypeImageArgs = "src" | "alt";
|
|
54
|
+
type TypeImage = Pick<ImageProps, TypeImageArgs>;
|
|
55
|
+
type TypePictureImage = {
|
|
56
|
+
type: "image";
|
|
57
|
+
width: number | `${number}`;
|
|
58
|
+
height: number | `${number}`;
|
|
59
|
+
} & Omit<TypeImage, "type" | "width" | "height">;
|
|
60
|
+
type TypePicture = {
|
|
61
|
+
type: "picture";
|
|
62
|
+
sources: {
|
|
63
|
+
media: string;
|
|
64
|
+
image: TypePictureImage;
|
|
65
|
+
}[];
|
|
66
|
+
alt: TypeImage["alt"];
|
|
67
|
+
};
|
|
68
|
+
type TypeVideo = {
|
|
69
|
+
type: "video";
|
|
70
|
+
} & {
|
|
71
|
+
src: string;
|
|
72
|
+
width: number;
|
|
73
|
+
height: number;
|
|
74
|
+
poster?: TypePictureImage;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Receives a `setState` argument and calls it with `currentValue` if it's a
|
|
79
|
+
* function. Otherwise return the argument as the new value.
|
|
80
|
+
* @example
|
|
81
|
+
* applyState((value) => value + 1, 1); // 2
|
|
82
|
+
* applyState(2, 1); // 2
|
|
83
|
+
*/
|
|
84
|
+
declare function applyState<T>(argument: SetStateAction<T>, currentValue: T | (() => T)): T;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Returns the first value that is not `undefined`.
|
|
88
|
+
*/
|
|
89
|
+
declare function defaultValue<T extends readonly any[]>(...values: T): DefaultValue<T>;
|
|
90
|
+
type DefaultValue<T extends readonly any[], Other = never> = T extends [
|
|
91
|
+
infer Head,
|
|
92
|
+
...infer Rest
|
|
93
|
+
] ? Rest extends [] ? T[number] | Other : undefined extends Head ? DefaultValue<Rest, Exclude<Other | Head, undefined>> : Exclude<T[number], undefined> : never;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Returns the same argument.
|
|
97
|
+
*/
|
|
98
|
+
declare function identity<T>(value: T): T;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Wraps a number within a specified range.
|
|
102
|
+
* @param value - The number to wrap.
|
|
103
|
+
* @param min - The minimum value of the range (inclusive).
|
|
104
|
+
* @param max - The maximum value of the range (inclusive).
|
|
105
|
+
* @returns The wrapped number within the range [min, max].
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* wrap(5, [0, 3]); // Returns 1
|
|
109
|
+
* wrap(-1, [0, 3]); // Returns 2
|
|
110
|
+
* wrap(-3, [0, 3]); // Returns 1
|
|
111
|
+
* wrap(7, [0, 3]); // Returns 3
|
|
112
|
+
*/
|
|
113
|
+
declare const wrap: (value: number, [min, max]: [min: number, max: number]) => number;
|
|
114
|
+
/**
|
|
115
|
+
* Limits a value between a specified range.
|
|
116
|
+
* @param value - The number to limit.
|
|
117
|
+
* @param min - The minimum value of the range (inclusive).
|
|
118
|
+
* @param max - The maximum value of the range (inclusive).
|
|
119
|
+
* @returns The wrapped number within the range [min, max].
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* clamp(2, [0, 3]); // Returns 2
|
|
123
|
+
* clamp(5, [0, 3]); // Returns 3
|
|
124
|
+
* clamp(-1, [0, 3]); // Returns 0
|
|
125
|
+
* clamp(-3, [0, 3]); // Returns 0
|
|
126
|
+
* clamp(7, [0, 3]); // Returns 3
|
|
127
|
+
*/
|
|
128
|
+
declare const clamp: (value: number, [min, max]: [min: number, max: number]) => number;
|
|
129
|
+
/**
|
|
130
|
+
* Maps a number from one range to another.
|
|
131
|
+
* @param value The number to map.
|
|
132
|
+
* @param originRange The original range of the number.
|
|
133
|
+
* @param targetRange The target range to map the number to.
|
|
134
|
+
* @returns The mapped number within the target range.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* transform(5, [0, 10], [0, 100]); // Returns 50
|
|
138
|
+
* transform(0.5, [0, 1], [0, 10]); // Returns 5
|
|
139
|
+
* transform(-5, [-10, 0], [0, 100]); // Returns 50
|
|
140
|
+
*/
|
|
141
|
+
declare const transform: (value: number, originRange: [number, number], targetRange: [number, number]) => number;
|
|
142
|
+
/**
|
|
143
|
+
* Rounds a number to a specified number of decimal places.
|
|
144
|
+
* @param value - The number to round.
|
|
145
|
+
* @param decimalPlaces - The number of decimal places to round to. (default is 0)
|
|
146
|
+
* @returns The rounded number.
|
|
147
|
+
*/
|
|
148
|
+
declare const round: (value: number, decimalPlaces?: number) => number;
|
|
149
|
+
|
|
150
|
+
declare const mergeClassNames: (...classNames: clsx.ClassValue[]) => string;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Detects if the device has touch capabilities.
|
|
154
|
+
*/
|
|
155
|
+
declare const isTouchDevice: () => boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Detects Apple device.
|
|
158
|
+
*/
|
|
159
|
+
declare const isApple: () => boolean;
|
|
160
|
+
/**
|
|
161
|
+
* Detects Mac computer.
|
|
162
|
+
*/
|
|
163
|
+
declare const isMac: () => boolean;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Removes undefined values from an object.
|
|
167
|
+
*/
|
|
168
|
+
declare function removeUndefinedValues<T extends AnyObject>(obj: T): T;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Compares two objects.
|
|
172
|
+
* @example
|
|
173
|
+
* shallowEqual({ a: "a" }, {}); // false
|
|
174
|
+
* shallowEqual({ a: "a" }, { b: "b" }); // false
|
|
175
|
+
* shallowEqual({ a: "a" }, { a: "a" }); // true
|
|
176
|
+
* shallowEqual({ a: "a" }, { a: "a", b: "b" }); // false
|
|
177
|
+
*/
|
|
178
|
+
declare function shallowEqual(a?: AnyObject, b?: AnyObject): boolean;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @function notEmpty
|
|
182
|
+
* @description Checks if a value is not null or undefined.
|
|
183
|
+
*
|
|
184
|
+
* @param value - The value to check.
|
|
185
|
+
* @returns Whether the value is not null or undefined.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```ts
|
|
189
|
+
* notEmpty("Hello"); // true
|
|
190
|
+
* notEmpty(null); // false
|
|
191
|
+
* notEmpty(undefined); // false
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
declare const notEmpty: <TValue>(value: TValue | null | undefined) => value is TValue;
|
|
195
|
+
/**
|
|
196
|
+
* @function isHTMLElement
|
|
197
|
+
* @description Checks if a value is an instance of HTMLElement.
|
|
198
|
+
*
|
|
199
|
+
* @param node - The value to check.
|
|
200
|
+
* @returns Whether the value is an instance of HTMLElement.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```ts
|
|
204
|
+
* isHTMLElement(document.querySelector('body')); // true
|
|
205
|
+
* isHTMLElement({}); // false
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
declare const isHTMLElement: (node: unknown) => node is HTMLElement;
|
|
209
|
+
/**
|
|
210
|
+
* @function isInArray
|
|
211
|
+
* @description Typesafe check if an item is in an array without being explicit about const types
|
|
212
|
+
*
|
|
213
|
+
* @param item - The item to check.
|
|
214
|
+
* @param array - The array to check against.
|
|
215
|
+
*
|
|
216
|
+
* @returns Whether the item is in the array.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* // Default situation in TS:
|
|
221
|
+
* const arr = ['hello', 'world'] as const;
|
|
222
|
+
*
|
|
223
|
+
* let someString = 'something';
|
|
224
|
+
*
|
|
225
|
+
* arr.includes(someString); // Argument of type 'string' is not assignable to parameter of type '"hello" | "world"'
|
|
226
|
+
*
|
|
227
|
+
* // Using isInArray:
|
|
228
|
+
* const arr = ['hello', 'world'] as const;
|
|
229
|
+
*
|
|
230
|
+
* let someString = 'something';
|
|
231
|
+
*
|
|
232
|
+
* isInArray(someString, arr); // false, but no type error
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
declare const isInArray: <T, A extends T>(item: T, array: ReadonlyArray<A>) => item is A;
|
|
236
|
+
/**
|
|
237
|
+
* @function isObject
|
|
238
|
+
* @description Checks if a value is an object (excluding arrays).
|
|
239
|
+
*
|
|
240
|
+
* @param object - The value to check.
|
|
241
|
+
* @returns Whether the value is truthy.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* isObject({ hello: world }); // true
|
|
246
|
+
* isObject({}); // true
|
|
247
|
+
* isObject([]); // false
|
|
248
|
+
* isObject(""); // false
|
|
249
|
+
* isObject(null); // false
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
declare const isObject: (object: unknown) => object is Record<string, unknown>;
|
|
253
|
+
/**
|
|
254
|
+
* @function isTruthy
|
|
255
|
+
* @description Checks if a value is truthy.
|
|
256
|
+
*
|
|
257
|
+
* @param value - The value to check.
|
|
258
|
+
* @returns Whether the value is truthy.
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```ts
|
|
262
|
+
* isTruthy("foo"); // true
|
|
263
|
+
* isTruthy(1); // true
|
|
264
|
+
* isTruthy(0); // false
|
|
265
|
+
* isTruthy(""); // false
|
|
266
|
+
* ```
|
|
267
|
+
*
|
|
268
|
+
*/
|
|
269
|
+
declare const isTruthy: <T>(value?: T | undefined | null | false) => value is T;
|
|
270
|
+
/**
|
|
271
|
+
* Asserts that a condition is true, otherwise throws an error.
|
|
272
|
+
* @example
|
|
273
|
+
* invariant(
|
|
274
|
+
* condition,
|
|
275
|
+
* process.env.NODE_ENV !== "production" && "Invariant failed"
|
|
276
|
+
* );
|
|
277
|
+
*/
|
|
278
|
+
declare function invariant(condition: any, message?: string | boolean): asserts condition;
|
|
279
|
+
/**
|
|
280
|
+
* Checks if an object has a property as its own (not inherited) property.
|
|
281
|
+
* @example
|
|
282
|
+
* hasOwnProperty({ a: "a" }, "a"); // true
|
|
283
|
+
* hasOwnProperty({ a: "a" }, "b"); // false
|
|
284
|
+
* hasOwnProperty(Object.create({ a: "a" }), "a"); // false
|
|
285
|
+
*/
|
|
286
|
+
declare const hasOwnProperty: <T extends AnyObject>(object: T, prop: keyof any) => prop is keyof T;
|
|
287
|
+
|
|
288
|
+
export { AnyObject, type BreakpointKey, IS_BUILD, IS_DEVELOPMENT, IS_IN_BROWSER, type MergeIntersection, type PickByValue, type PickRequired, SetStateAction, type SizesMap, type TypeImage, type TypeImageArgs, type TypePicture, type TypePictureImage, type TypeVideo, type UnionToIntersection, applyState, clamp, defaultValue, hasOwnProperty, identity, invariant, isApple, isHTMLElement, isInArray, isMac, isObject, isTouchDevice, isTruthy, mergeClassNames, notEmpty, removeUndefinedValues, round, shallowEqual, transform, wrap };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { IS_BUILD, IS_DEVELOPMENT, IS_IN_BROWSER, applyState, clamp, defaultValue, hasOwnProperty, identity, invariant, isApple, isHTMLElement, isInArray, isMac, isObject, isTouchDevice, isTruthy, mergeClassNames, notEmpty, removeUndefinedValues, round, shallowEqual, transform, wrap } from './chunk-SIU7SKJK.js';
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
type LooseObject = Record<any, any>;
|
|
2
|
+
/**
|
|
3
|
+
* Any object.
|
|
4
|
+
*/
|
|
5
|
+
type AnyObject = Record<string, any>;
|
|
6
|
+
/**
|
|
7
|
+
* Empty object.
|
|
8
|
+
*/
|
|
9
|
+
type EmptyObject = Record<keyof any, never>;
|
|
10
|
+
/**
|
|
11
|
+
* Any function.
|
|
12
|
+
*/
|
|
13
|
+
type AnyFunction = (...args: any) => any;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Workaround for variance issues.
|
|
17
|
+
* @template T The type of the callback.
|
|
18
|
+
*/
|
|
19
|
+
type BivariantCallback<T extends AnyFunction> = {
|
|
20
|
+
bivarianceHack(...args: Parameters<T>): ReturnType<T>;
|
|
21
|
+
}["bivarianceHack"];
|
|
22
|
+
/**
|
|
23
|
+
* @template T The state type.
|
|
24
|
+
*/
|
|
25
|
+
type SetStateAction<T> = T | BivariantCallback<(prevState: T) => T>;
|
|
26
|
+
/**
|
|
27
|
+
* The type of the `setState` function in `[state, setState] = useState()`.
|
|
28
|
+
* @template T The type of the state.
|
|
29
|
+
*/
|
|
30
|
+
type SetState<T> = BivariantCallback<(value: SetStateAction<T>) => void>;
|
|
31
|
+
|
|
32
|
+
export type { AnyObject as A, BivariantCallback as B, EmptyObject as E, LooseObject as L, SetStateAction as S, AnyFunction as a, SetState as b };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { A as AnyObject, S as SetStateAction, B as BivariantCallback } from '../state-BnfG-Qk9.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ============================================================================
|
|
5
|
+
* STORE
|
|
6
|
+
* ============================================================================
|
|
7
|
+
*
|
|
8
|
+
* Implementation taken from AriaKit (https://ariakit.org/)
|
|
9
|
+
*
|
|
10
|
+
* https://github.com/ariakit/ariakit/blob/295118174512ee27b81822f7f16d7cdf9d0d0be6/packages/ariakit-core/src/utils/store.ts
|
|
11
|
+
*/
|
|
12
|
+
/** */
|
|
13
|
+
type Listener<S> = (state: S, prevState: S) => void | (() => void);
|
|
14
|
+
type Sync<S, K extends keyof S> = (keys: K[] | null, listener: Listener<Pick<S, K>>) => () => void;
|
|
15
|
+
type StoreSetup = (callback: () => void | (() => void)) => () => void;
|
|
16
|
+
type StoreInit = () => () => void;
|
|
17
|
+
type StoreSubscribe<S = State, K extends keyof S = keyof S> = Sync<S, K>;
|
|
18
|
+
type StoreSync<S = State, K extends keyof S = keyof S> = Sync<S, K>;
|
|
19
|
+
type StoreBatch<S = State, K extends keyof S = keyof S> = Sync<S, K>;
|
|
20
|
+
type StorePick<S = State, K extends ReadonlyArray<keyof S> = ReadonlyArray<keyof S>> = (keys: K) => Store<Pick<S, K[number]>>;
|
|
21
|
+
type StoreOmit<S = State, K extends ReadonlyArray<keyof S> = ReadonlyArray<keyof S>> = (keys: K) => Store<Omit<S, K[number]>>;
|
|
22
|
+
/**
|
|
23
|
+
* Creates a store.
|
|
24
|
+
* @param initialState Initial state.
|
|
25
|
+
* @param stores Stores to extend.
|
|
26
|
+
*/
|
|
27
|
+
declare function createStore<S extends State>(initialState: S, ...stores: Array<Store<Partial<S>> | undefined>): Store<S>;
|
|
28
|
+
declare function setup<T extends Store>(store?: T | null, ...args: Parameters<StoreSetup>): T extends Store ? ReturnType<StoreSetup> : void;
|
|
29
|
+
declare function init<T extends Store>(store?: T | null, ...args: Parameters<StoreInit>): T extends Store ? ReturnType<StoreInit> : void;
|
|
30
|
+
declare function subscribe<T extends Store, K extends keyof StoreState<T>>(store?: T | null, ...args: Parameters<StoreSubscribe<StoreState<T>, K>>): T extends Store ? ReturnType<StoreSubscribe<StoreState<T>, K>> : void;
|
|
31
|
+
declare function sync<T extends Store, K extends keyof StoreState<T>>(store?: T | null, ...args: Parameters<StoreSync<StoreState<T>, K>>): T extends Store ? ReturnType<StoreSync<StoreState<T>, K>> : void;
|
|
32
|
+
declare function batch<T extends Store, K extends keyof StoreState<T>>(store?: T | null, ...args: Parameters<StoreBatch<StoreState<T>, K>>): T extends Store ? ReturnType<StoreBatch<StoreState<T>, K>> : void;
|
|
33
|
+
declare function omit<T extends Store, K extends ReadonlyArray<keyof StoreState<T>>>(store?: T | null, ...args: Parameters<StoreOmit<StoreState<T>, K>>): T extends Store ? ReturnType<StoreOmit<StoreState<T>, K>> : void;
|
|
34
|
+
declare function pick<T extends Store, K extends ReadonlyArray<keyof StoreState<T>>>(store?: T | null, ...args: Parameters<StorePick<StoreState<T>, K>>): T extends Store ? ReturnType<StorePick<StoreState<T>, K>> : void;
|
|
35
|
+
/**
|
|
36
|
+
* Merges multiple stores into a single store.
|
|
37
|
+
*/
|
|
38
|
+
declare function mergeStore<S extends State>(...stores: Array<Store<S> | undefined>): Store<S>;
|
|
39
|
+
/**
|
|
40
|
+
* Throws when a store prop is passed in conjunction with a default state.
|
|
41
|
+
*/
|
|
42
|
+
declare function throwOnConflictingProps(props: AnyObject, store?: Store): void;
|
|
43
|
+
/**
|
|
44
|
+
* Store state type.
|
|
45
|
+
*/
|
|
46
|
+
type State = AnyObject;
|
|
47
|
+
/**
|
|
48
|
+
* Initial state that can be passed to a store creator function.
|
|
49
|
+
* @template S State type.
|
|
50
|
+
* @template K Key type.
|
|
51
|
+
*/
|
|
52
|
+
type StoreOptions<S extends State, K extends keyof S> = Partial<Pick<S, K>>;
|
|
53
|
+
/**
|
|
54
|
+
* Props that can be passed to a store creator function.
|
|
55
|
+
* @template S State type.
|
|
56
|
+
*/
|
|
57
|
+
type StoreProps<S extends State = State> = {
|
|
58
|
+
/**
|
|
59
|
+
* Another store object that will be kept in sync with the original store.
|
|
60
|
+
*
|
|
61
|
+
* Live examples:
|
|
62
|
+
* - [Navigation Menubar](https://ariakit.org/examples/menubar-navigation)
|
|
63
|
+
*/
|
|
64
|
+
store?: Store<Partial<S>>;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Extracts the state type from a store type.
|
|
68
|
+
* @template T Store type.
|
|
69
|
+
*/
|
|
70
|
+
type StoreState<T> = T extends Store<infer S> ? S : never;
|
|
71
|
+
/**
|
|
72
|
+
* Store.
|
|
73
|
+
* @template S State type.
|
|
74
|
+
*/
|
|
75
|
+
type Store<S = State> = {
|
|
76
|
+
/**
|
|
77
|
+
* Returns the current store state.
|
|
78
|
+
*/
|
|
79
|
+
getState(): S;
|
|
80
|
+
/**
|
|
81
|
+
* Sets a state value.
|
|
82
|
+
*/
|
|
83
|
+
setState<K extends keyof S>(key: K, value: SetStateAction<S[K]>): void;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Creates a collection store.
|
|
88
|
+
*/
|
|
89
|
+
declare function createCollectionStore<T extends CollectionStoreItem = CollectionStoreItem>(props?: CollectionStoreProps<T>): CollectionStore<T>;
|
|
90
|
+
type CollectionStoreItem = {
|
|
91
|
+
/**
|
|
92
|
+
* The id of the item.
|
|
93
|
+
*/
|
|
94
|
+
id: string;
|
|
95
|
+
/**
|
|
96
|
+
* The item HTML element. This is automatically set when the item is rendered.
|
|
97
|
+
*/
|
|
98
|
+
element?: HTMLElement | null;
|
|
99
|
+
};
|
|
100
|
+
type CollectionStoreState<T extends CollectionStoreItem = CollectionStoreItem> = {
|
|
101
|
+
/**
|
|
102
|
+
* Lists all items along with their metadata. This state is automatically
|
|
103
|
+
* updated when an item is registered or unregistered using the
|
|
104
|
+
* [`registerItem`](https://ariakit.org/reference/use-collection-store#registeritem)
|
|
105
|
+
* function.
|
|
106
|
+
*
|
|
107
|
+
* Live examples:
|
|
108
|
+
* - [Command Menu with
|
|
109
|
+
* Tabs](https://ariakit.org/examples/dialog-combobox-tab-command-menu)
|
|
110
|
+
*/
|
|
111
|
+
items: T[];
|
|
112
|
+
/**
|
|
113
|
+
* Lists all items, along with their metadata, in the exact order they appear in
|
|
114
|
+
* the DOM. This state is automatically updated when an item is rendered or
|
|
115
|
+
* unmounted using the
|
|
116
|
+
* [`renderItem`](https://ariakit.org/reference/use-collection-store#renderitem)
|
|
117
|
+
* function.
|
|
118
|
+
*/
|
|
119
|
+
renderedItems: T[];
|
|
120
|
+
};
|
|
121
|
+
type CollectionStoreFunctions<T extends CollectionStoreItem = CollectionStoreItem> = {
|
|
122
|
+
/**
|
|
123
|
+
* Registers an item in the collection. This function returns a cleanup
|
|
124
|
+
* function that unregisters the item.
|
|
125
|
+
* @example
|
|
126
|
+
* const unregisterItem = store.registerItem({ id: "item-1" });
|
|
127
|
+
* // on cleanup
|
|
128
|
+
* unregisterItem();
|
|
129
|
+
*/
|
|
130
|
+
registerItem: BivariantCallback<(item: T) => () => void>;
|
|
131
|
+
/**
|
|
132
|
+
* Renders an item in the collection. This function returns a cleanup function
|
|
133
|
+
* that unmounts the item.
|
|
134
|
+
* @example
|
|
135
|
+
* const unrenderItem = store.renderItem({ id: "item-1" });
|
|
136
|
+
* // on cleanup
|
|
137
|
+
* unrenderItem();
|
|
138
|
+
*/
|
|
139
|
+
renderItem: BivariantCallback<(item: T) => () => void>;
|
|
140
|
+
/**
|
|
141
|
+
* Gets an item by its id.
|
|
142
|
+
*
|
|
143
|
+
* Live examples:
|
|
144
|
+
* - [Animated TabPanel](https://ariakit.org/examples/tab-panel-animated)
|
|
145
|
+
* @example
|
|
146
|
+
* const item = store.item("item-1");
|
|
147
|
+
*/
|
|
148
|
+
item: (id: string | null | undefined) => T | null;
|
|
149
|
+
};
|
|
150
|
+
type CollectionStoreOptions<T extends CollectionStoreItem = CollectionStoreItem> = {
|
|
151
|
+
/**
|
|
152
|
+
* The defaut value for the
|
|
153
|
+
* [`items`](https://ariakit.org/reference/collection-provider#items) state.
|
|
154
|
+
* @default []
|
|
155
|
+
*/
|
|
156
|
+
defaultItems?: CollectionStoreState<T>["items"];
|
|
157
|
+
} & StoreOptions<CollectionStoreState<T>, "items">;
|
|
158
|
+
type CollectionStoreProps<T extends CollectionStoreItem = CollectionStoreItem> = {} & CollectionStoreOptions<T> & StoreProps<CollectionStoreState<T>>;
|
|
159
|
+
type CollectionStore<T extends CollectionStoreItem = CollectionStoreItem> = {} & CollectionStoreFunctions<T> & Store<CollectionStoreState<T>>;
|
|
160
|
+
|
|
161
|
+
export { type CollectionStore, type CollectionStoreFunctions, type CollectionStoreItem, type CollectionStoreOptions, type CollectionStoreProps, type CollectionStoreState, type State, type Store, type StoreOptions, type StoreProps, type StoreState, batch, createCollectionStore, createStore, init, mergeStore, omit, pick, setup, subscribe, sync, throwOnConflictingProps };
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import { hasOwnProperty, defaultValue, applyState, invariant } from '../chunk-SIU7SKJK.js';
|
|
2
|
+
|
|
3
|
+
// src/store/dom.ts
|
|
4
|
+
function getDocument(node) {
|
|
5
|
+
if (!node) return document;
|
|
6
|
+
if ("self" in node) return node.document;
|
|
7
|
+
return node.ownerDocument || document;
|
|
8
|
+
}
|
|
9
|
+
function sortBasedOnDOMPosition(items, getElement) {
|
|
10
|
+
const pairs = items.map((item, index) => [index, item]);
|
|
11
|
+
let isOrderDifferent = false;
|
|
12
|
+
pairs.sort(([indexA, a], [indexB, b]) => {
|
|
13
|
+
const elementA = getElement(a);
|
|
14
|
+
const elementB = getElement(b);
|
|
15
|
+
if (elementA === elementB) return 0;
|
|
16
|
+
if (!elementA || !elementB) return 0;
|
|
17
|
+
if (isElementPreceding(elementA, elementB)) {
|
|
18
|
+
if (indexA > indexB) {
|
|
19
|
+
isOrderDifferent = true;
|
|
20
|
+
}
|
|
21
|
+
return -1;
|
|
22
|
+
}
|
|
23
|
+
if (indexA < indexB) {
|
|
24
|
+
isOrderDifferent = true;
|
|
25
|
+
}
|
|
26
|
+
return 1;
|
|
27
|
+
});
|
|
28
|
+
if (isOrderDifferent) {
|
|
29
|
+
return pairs.map(([_, item]) => item);
|
|
30
|
+
}
|
|
31
|
+
return items;
|
|
32
|
+
}
|
|
33
|
+
function isElementPreceding(a, b) {
|
|
34
|
+
return Boolean(
|
|
35
|
+
b.compareDocumentPosition(a) & Node.DOCUMENT_POSITION_PRECEDING
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/store/utils.ts
|
|
40
|
+
function noop(..._) {
|
|
41
|
+
}
|
|
42
|
+
function chain(...fns) {
|
|
43
|
+
return (...args) => {
|
|
44
|
+
for (const fn of fns) {
|
|
45
|
+
if (typeof fn === "function") {
|
|
46
|
+
fn(...args);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function omit(object, keys) {
|
|
52
|
+
const result = { ...object };
|
|
53
|
+
for (const key of keys) {
|
|
54
|
+
if (hasOwnProperty(result, key)) {
|
|
55
|
+
delete result[key];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
function pick(object, paths) {
|
|
61
|
+
const result = {};
|
|
62
|
+
for (const key of paths) {
|
|
63
|
+
if (hasOwnProperty(object, key)) {
|
|
64
|
+
result[key] = object[key];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
function getKeys(obj) {
|
|
70
|
+
return Object.keys(obj);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/store/store.ts
|
|
74
|
+
function getInternal(store, key) {
|
|
75
|
+
const internals = store.__unstableInternals;
|
|
76
|
+
invariant(internals, "Invalid store");
|
|
77
|
+
return internals[key];
|
|
78
|
+
}
|
|
79
|
+
function createStore(initialState, ...stores) {
|
|
80
|
+
let state = initialState;
|
|
81
|
+
let prevStateBatch = state;
|
|
82
|
+
let lastUpdate = Symbol();
|
|
83
|
+
let destroy = noop;
|
|
84
|
+
const instances = /* @__PURE__ */ new Set();
|
|
85
|
+
const updatedKeys = /* @__PURE__ */ new Set();
|
|
86
|
+
const setups = /* @__PURE__ */ new Set();
|
|
87
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
88
|
+
const batchListeners = /* @__PURE__ */ new Set();
|
|
89
|
+
const disposables = /* @__PURE__ */ new WeakMap();
|
|
90
|
+
const listenerKeys = /* @__PURE__ */ new WeakMap();
|
|
91
|
+
const storeSetup = (callback) => {
|
|
92
|
+
setups.add(callback);
|
|
93
|
+
return () => setups.delete(callback);
|
|
94
|
+
};
|
|
95
|
+
const storeInit = () => {
|
|
96
|
+
const initialized = instances.size;
|
|
97
|
+
const instance = Symbol();
|
|
98
|
+
instances.add(instance);
|
|
99
|
+
const maybeDestroy = () => {
|
|
100
|
+
instances.delete(instance);
|
|
101
|
+
if (instances.size) return;
|
|
102
|
+
destroy();
|
|
103
|
+
};
|
|
104
|
+
if (initialized) return maybeDestroy;
|
|
105
|
+
const desyncs = getKeys(state).map(
|
|
106
|
+
(key) => chain(
|
|
107
|
+
...stores.map((store) => {
|
|
108
|
+
const storeState = store?.getState?.();
|
|
109
|
+
if (!storeState) return;
|
|
110
|
+
if (!hasOwnProperty(storeState, key)) return;
|
|
111
|
+
return sync(store, [key], (state2) => {
|
|
112
|
+
setState(
|
|
113
|
+
key,
|
|
114
|
+
state2[key],
|
|
115
|
+
// @ts-expect-error - Not public API. This is just to prevent
|
|
116
|
+
// infinite loops.
|
|
117
|
+
true
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
})
|
|
121
|
+
)
|
|
122
|
+
);
|
|
123
|
+
const teardowns = [];
|
|
124
|
+
for (const setup2 of setups) {
|
|
125
|
+
teardowns.push(setup2());
|
|
126
|
+
}
|
|
127
|
+
const cleanups = stores.map(init);
|
|
128
|
+
destroy = chain(...desyncs, ...teardowns, ...cleanups);
|
|
129
|
+
return maybeDestroy;
|
|
130
|
+
};
|
|
131
|
+
const sub = (keys, listener, set = listeners) => {
|
|
132
|
+
set.add(listener);
|
|
133
|
+
listenerKeys.set(listener, keys);
|
|
134
|
+
return () => {
|
|
135
|
+
disposables.get(listener)?.();
|
|
136
|
+
disposables.delete(listener);
|
|
137
|
+
listenerKeys.delete(listener);
|
|
138
|
+
set.delete(listener);
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
const storeSubscribe = (keys, listener) => sub(keys, listener);
|
|
142
|
+
const storeSync = (keys, listener) => {
|
|
143
|
+
disposables.set(listener, listener(state, state));
|
|
144
|
+
return sub(keys, listener);
|
|
145
|
+
};
|
|
146
|
+
const storeBatch = (keys, listener) => {
|
|
147
|
+
disposables.set(listener, listener(state, prevStateBatch));
|
|
148
|
+
return sub(keys, listener, batchListeners);
|
|
149
|
+
};
|
|
150
|
+
const storePick = (keys) => createStore(pick(state, keys), finalStore);
|
|
151
|
+
const storeOmit = (keys) => createStore(omit(state, keys), finalStore);
|
|
152
|
+
const getState = () => state;
|
|
153
|
+
const setState = (key, value, fromStores = false) => {
|
|
154
|
+
if (!hasOwnProperty(state, key)) return;
|
|
155
|
+
const nextValue = applyState(value, state[key]);
|
|
156
|
+
if (nextValue === state[key]) return;
|
|
157
|
+
if (!fromStores) {
|
|
158
|
+
for (const store of stores) {
|
|
159
|
+
store?.setState?.(key, nextValue);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const prevState = state;
|
|
163
|
+
state = { ...state, [key]: nextValue };
|
|
164
|
+
const thisUpdate = Symbol();
|
|
165
|
+
lastUpdate = thisUpdate;
|
|
166
|
+
updatedKeys.add(key);
|
|
167
|
+
const run = (listener, prev, uKeys) => {
|
|
168
|
+
const keys = listenerKeys.get(listener);
|
|
169
|
+
const updated = (k) => uKeys ? uKeys.has(k) : k === key;
|
|
170
|
+
if (!keys || keys.some(updated)) {
|
|
171
|
+
disposables.get(listener)?.();
|
|
172
|
+
disposables.set(listener, listener(state, prev));
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
for (const listener of listeners) {
|
|
176
|
+
run(listener, prevState);
|
|
177
|
+
}
|
|
178
|
+
queueMicrotask(() => {
|
|
179
|
+
if (lastUpdate !== thisUpdate) return;
|
|
180
|
+
const snapshot = state;
|
|
181
|
+
for (const listener of batchListeners) {
|
|
182
|
+
run(listener, prevStateBatch, updatedKeys);
|
|
183
|
+
}
|
|
184
|
+
prevStateBatch = snapshot;
|
|
185
|
+
updatedKeys.clear();
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
const finalStore = {
|
|
189
|
+
getState,
|
|
190
|
+
setState,
|
|
191
|
+
__unstableInternals: {
|
|
192
|
+
setup: storeSetup,
|
|
193
|
+
init: storeInit,
|
|
194
|
+
subscribe: storeSubscribe,
|
|
195
|
+
sync: storeSync,
|
|
196
|
+
batch: storeBatch,
|
|
197
|
+
pick: storePick,
|
|
198
|
+
omit: storeOmit
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
return finalStore;
|
|
202
|
+
}
|
|
203
|
+
function setup(store, ...args) {
|
|
204
|
+
if (!store) return;
|
|
205
|
+
return getInternal(store, "setup")(...args);
|
|
206
|
+
}
|
|
207
|
+
function init(store, ...args) {
|
|
208
|
+
if (!store) return;
|
|
209
|
+
return getInternal(store, "init")(...args);
|
|
210
|
+
}
|
|
211
|
+
function subscribe(store, ...args) {
|
|
212
|
+
if (!store) return;
|
|
213
|
+
return getInternal(store, "subscribe")(...args);
|
|
214
|
+
}
|
|
215
|
+
function sync(store, ...args) {
|
|
216
|
+
if (!store) return;
|
|
217
|
+
return getInternal(store, "sync")(...args);
|
|
218
|
+
}
|
|
219
|
+
function batch(store, ...args) {
|
|
220
|
+
if (!store) return;
|
|
221
|
+
return getInternal(store, "batch")(...args);
|
|
222
|
+
}
|
|
223
|
+
function omit2(store, ...args) {
|
|
224
|
+
if (!store) return;
|
|
225
|
+
return getInternal(store, "omit")(...args);
|
|
226
|
+
}
|
|
227
|
+
function pick2(store, ...args) {
|
|
228
|
+
if (!store) return;
|
|
229
|
+
return getInternal(store, "pick")(...args);
|
|
230
|
+
}
|
|
231
|
+
function mergeStore(...stores) {
|
|
232
|
+
const initialState = {};
|
|
233
|
+
for (const store2 of stores) {
|
|
234
|
+
const nextState = store2?.getState?.();
|
|
235
|
+
if (nextState) {
|
|
236
|
+
Object.assign(initialState, nextState);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const store = createStore(initialState, ...stores);
|
|
240
|
+
return Object.assign({}, ...stores, store);
|
|
241
|
+
}
|
|
242
|
+
function throwOnConflictingProps(props, store) {
|
|
243
|
+
if (process.env.NODE_ENV === "production") return;
|
|
244
|
+
if (!store) return;
|
|
245
|
+
const defaultKeys = Object.entries(props).filter(([key, value]) => key.startsWith("default") && value !== void 0).map(([key]) => {
|
|
246
|
+
const stateKey = key.replace("default", "");
|
|
247
|
+
return `${stateKey[0]?.toLowerCase() || ""}${stateKey.slice(1)}`;
|
|
248
|
+
});
|
|
249
|
+
if (!defaultKeys.length) return;
|
|
250
|
+
const storeState = store.getState();
|
|
251
|
+
const conflictingProps = defaultKeys.filter(
|
|
252
|
+
(key) => hasOwnProperty(storeState, key)
|
|
253
|
+
);
|
|
254
|
+
if (!conflictingProps.length) return;
|
|
255
|
+
throw new Error(
|
|
256
|
+
`Passing a store prop in conjunction with a default state is not supported.
|
|
257
|
+
|
|
258
|
+
const store = useSelectStore();
|
|
259
|
+
<SelectProvider store={store} defaultValue="Apple" />
|
|
260
|
+
^ ^
|
|
261
|
+
|
|
262
|
+
Instead, pass the default state to the topmost store:
|
|
263
|
+
|
|
264
|
+
const store = useSelectStore({ defaultValue: "Apple" });
|
|
265
|
+
<SelectProvider store={store} />
|
|
266
|
+
`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// src/store/collection-store.ts
|
|
271
|
+
function getCommonParent(items) {
|
|
272
|
+
const firstItem = items.find((item) => !!item.element);
|
|
273
|
+
const lastItem = [...items].reverse().find((item) => !!item.element);
|
|
274
|
+
let parentElement = firstItem?.element?.parentElement;
|
|
275
|
+
while (parentElement && lastItem?.element) {
|
|
276
|
+
const parent = parentElement;
|
|
277
|
+
if (lastItem && parent.contains(lastItem.element)) {
|
|
278
|
+
return parentElement;
|
|
279
|
+
}
|
|
280
|
+
parentElement = parentElement.parentElement;
|
|
281
|
+
}
|
|
282
|
+
return getDocument(parentElement).body;
|
|
283
|
+
}
|
|
284
|
+
function getPrivateStore(store) {
|
|
285
|
+
return store?.__unstablePrivateStore;
|
|
286
|
+
}
|
|
287
|
+
function createCollectionStore(props = {}) {
|
|
288
|
+
throwOnConflictingProps(props, props.store);
|
|
289
|
+
const syncState = props.store?.getState();
|
|
290
|
+
const items = defaultValue(
|
|
291
|
+
props.items,
|
|
292
|
+
syncState?.items,
|
|
293
|
+
props.defaultItems,
|
|
294
|
+
[]
|
|
295
|
+
);
|
|
296
|
+
const itemsMap = new Map(items.map((item) => [item.id, item]));
|
|
297
|
+
const initialState = {
|
|
298
|
+
items,
|
|
299
|
+
renderedItems: defaultValue(syncState?.renderedItems, [])
|
|
300
|
+
};
|
|
301
|
+
const syncPrivateStore = getPrivateStore(props.store);
|
|
302
|
+
const privateStore = createStore(
|
|
303
|
+
{ items, renderedItems: initialState.renderedItems },
|
|
304
|
+
syncPrivateStore
|
|
305
|
+
);
|
|
306
|
+
const collection = createStore(initialState, props.store);
|
|
307
|
+
const sortItems = (renderedItems) => {
|
|
308
|
+
const sortedItems = sortBasedOnDOMPosition(renderedItems, (i) => i.element);
|
|
309
|
+
privateStore.setState("renderedItems", sortedItems);
|
|
310
|
+
collection.setState("renderedItems", sortedItems);
|
|
311
|
+
};
|
|
312
|
+
setup(collection, () => init(privateStore));
|
|
313
|
+
setup(privateStore, () => {
|
|
314
|
+
return batch(privateStore, ["items"], (state) => {
|
|
315
|
+
collection.setState("items", state.items);
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
setup(privateStore, () => {
|
|
319
|
+
return batch(privateStore, ["renderedItems"], (state) => {
|
|
320
|
+
let firstRun = true;
|
|
321
|
+
let raf = requestAnimationFrame(() => {
|
|
322
|
+
const { renderedItems } = collection.getState();
|
|
323
|
+
if (state.renderedItems === renderedItems) return;
|
|
324
|
+
sortItems(state.renderedItems);
|
|
325
|
+
});
|
|
326
|
+
if (typeof IntersectionObserver !== "function") {
|
|
327
|
+
return () => cancelAnimationFrame(raf);
|
|
328
|
+
}
|
|
329
|
+
const ioCallback = () => {
|
|
330
|
+
if (firstRun) {
|
|
331
|
+
firstRun = false;
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
cancelAnimationFrame(raf);
|
|
335
|
+
raf = requestAnimationFrame(() => sortItems(state.renderedItems));
|
|
336
|
+
};
|
|
337
|
+
const root = getCommonParent(state.renderedItems);
|
|
338
|
+
const observer = new IntersectionObserver(ioCallback, { root });
|
|
339
|
+
for (const item of state.renderedItems) {
|
|
340
|
+
if (!item.element) continue;
|
|
341
|
+
observer.observe(item.element);
|
|
342
|
+
}
|
|
343
|
+
return () => {
|
|
344
|
+
cancelAnimationFrame(raf);
|
|
345
|
+
observer.disconnect();
|
|
346
|
+
};
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
const mergeItem = (item, setItems, canDeleteFromMap = false) => {
|
|
350
|
+
let prevItem;
|
|
351
|
+
setItems((items2) => {
|
|
352
|
+
const index = items2.findIndex(({ id }) => id === item.id);
|
|
353
|
+
const nextItems = items2.slice();
|
|
354
|
+
if (index !== -1) {
|
|
355
|
+
prevItem = items2[index];
|
|
356
|
+
const nextItem = { ...prevItem, ...item };
|
|
357
|
+
nextItems[index] = nextItem;
|
|
358
|
+
itemsMap.set(item.id, nextItem);
|
|
359
|
+
} else {
|
|
360
|
+
nextItems.push(item);
|
|
361
|
+
itemsMap.set(item.id, item);
|
|
362
|
+
}
|
|
363
|
+
return nextItems;
|
|
364
|
+
});
|
|
365
|
+
const unmergeItem = () => {
|
|
366
|
+
setItems((items2) => {
|
|
367
|
+
if (!prevItem) {
|
|
368
|
+
if (canDeleteFromMap) {
|
|
369
|
+
itemsMap.delete(item.id);
|
|
370
|
+
}
|
|
371
|
+
return items2.filter(({ id }) => id !== item.id);
|
|
372
|
+
}
|
|
373
|
+
const index = items2.findIndex(({ id }) => id === item.id);
|
|
374
|
+
if (index === -1) return items2;
|
|
375
|
+
const nextItems = items2.slice();
|
|
376
|
+
nextItems[index] = prevItem;
|
|
377
|
+
itemsMap.set(item.id, prevItem);
|
|
378
|
+
return nextItems;
|
|
379
|
+
});
|
|
380
|
+
};
|
|
381
|
+
return unmergeItem;
|
|
382
|
+
};
|
|
383
|
+
const registerItem = (item) => mergeItem(
|
|
384
|
+
item,
|
|
385
|
+
(getItems) => privateStore.setState("items", getItems),
|
|
386
|
+
true
|
|
387
|
+
);
|
|
388
|
+
return {
|
|
389
|
+
...collection,
|
|
390
|
+
registerItem,
|
|
391
|
+
renderItem: (item) => chain(
|
|
392
|
+
registerItem(item),
|
|
393
|
+
mergeItem(
|
|
394
|
+
item,
|
|
395
|
+
(getItems) => privateStore.setState("renderedItems", getItems)
|
|
396
|
+
)
|
|
397
|
+
),
|
|
398
|
+
item: (id) => {
|
|
399
|
+
if (!id) return null;
|
|
400
|
+
let item = itemsMap.get(id);
|
|
401
|
+
if (!item) {
|
|
402
|
+
const { items: items2 } = privateStore.getState();
|
|
403
|
+
item = items2.find((item2) => item2.id === id);
|
|
404
|
+
if (item) {
|
|
405
|
+
itemsMap.set(id, item);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return item || null;
|
|
409
|
+
},
|
|
410
|
+
// @ts-expect-error Internal
|
|
411
|
+
__unstablePrivateStore: privateStore
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export { batch, createCollectionStore, createStore, init, mergeStore, omit2 as omit, pick2 as pick, setup, subscribe, sync, throwOnConflictingProps };
|
|
416
|
+
//# sourceMappingURL=index.js.map
|
|
417
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/store/dom.ts","../../src/store/utils.ts","../../src/store/store.ts","../../src/store/collection-store.ts"],"names":["state","setup","omit","pick","store","items","item"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Returns `element.ownerDocument || document`.\n */\nexport function getDocument(node?: Window | Document | Node | null): Document {\n\tif (!node) return document;\n\tif (\"self\" in node) return node.document;\n\treturn node.ownerDocument || document;\n}\n\n/**\n * Sort the items based on their DOM position.\n */\nexport function sortBasedOnDOMPosition<T>(\n\titems: T[],\n\tgetElement: (item: T) => Element | null | undefined,\n) {\n\tconst pairs = items.map((item, index) => [index, item] as const);\n\tlet isOrderDifferent = false;\n\tpairs.sort(([indexA, a], [indexB, b]) => {\n\t\tconst elementA = getElement(a);\n\t\tconst elementB = getElement(b);\n\t\tif (elementA === elementB) return 0;\n\t\tif (!elementA || !elementB) return 0;\n\t\t// a before b\n\t\tif (isElementPreceding(elementA, elementB)) {\n\t\t\tif (indexA > indexB) {\n\t\t\t\tisOrderDifferent = true;\n\t\t\t}\n\t\t\treturn -1;\n\t\t}\n\t\t// a after b\n\t\tif (indexA < indexB) {\n\t\t\tisOrderDifferent = true;\n\t\t}\n\t\treturn 1;\n\t});\n\tif (isOrderDifferent) {\n\t\treturn pairs.map(([_, item]) => item);\n\t}\n\treturn items;\n}\n\nfunction isElementPreceding(a: Element, b: Element) {\n\treturn Boolean(\n\t\tb.compareDocumentPosition(a) & Node.DOCUMENT_POSITION_PRECEDING,\n\t);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { hasOwnProperty, isObject } from \"src/functions\";\nimport type { AnyFunction, AnyObject } from \"src/types\";\n\n/**\n * ============================================================================\n * STORE UTILITIES\n * ============================================================================\n *\n * Implementation taken from AriaKit (https://ariakit.org/)\n *\n * https://github.com/ariakit/ariakit/blob/295118174512ee27b81822f7f16d7cdf9d0d0be6/packages/ariakit-core/src/utils/misc.ts\n */\n/** */\n\n/**\n * Empty function.\n */\nexport function noop(..._: any[]): any {}\n\n/**\n * Checks whether `arg` is empty or not.\n * @example\n * isEmpty([]); // true\n * isEmpty([\"a\"]); // false\n * isEmpty({}); // true\n * isEmpty({ a: \"a\" }); // false\n * isEmpty(); // true\n * isEmpty(null); // true\n * isEmpty(undefined); // true\n * isEmpty(\"\"); // true\n */\nexport function isEmpty(arg: any): boolean {\n\tif (Array.isArray(arg)) return !arg.length;\n\tif (isObject(arg)) return !Object.keys(arg).length;\n\tif (arg == null) return true;\n\tif (arg === \"\") return true;\n\treturn false;\n}\n\n/**\n * Receives functions as arguments and returns a new function that calls all.\n */\nexport function chain<T>(...fns: T[]) {\n\treturn (...args: T extends AnyFunction ? Parameters<T> : never) => {\n\t\tfor (const fn of fns) {\n\t\t\tif (typeof fn === \"function\") {\n\t\t\t\tfn(...args);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Omits specific keys from an object.\n * @example\n * omit({ a: \"a\", b: \"b\" }, [\"a\"]); // { b: \"b\" }\n */\nexport function omit<T extends AnyObject, K extends keyof T>(\n\tobject: T,\n\tkeys: ReadonlyArray<K> | K[],\n) {\n\tconst result = { ...object } as Omit<T, K>;\n\tfor (const key of keys) {\n\t\tif (hasOwnProperty(result, key)) {\n\t\t\tdelete result[key];\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Picks specific keys from an object.\n * @example\n * pick({ a: \"a\", b: \"b\" }, [\"a\"]); // { a: \"a\" }\n */\nexport function pick<T extends AnyObject, K extends keyof T>(\n\tobject: T,\n\tpaths: ReadonlyArray<K> | K[],\n) {\n\tconst result = {} as Pick<T, K>;\n\tfor (const key of paths) {\n\t\tif (hasOwnProperty(object, key)) {\n\t\t\tresult[key] = object[key];\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Similar to `Object.keys` but returns a type-safe array of keys.\n */\nexport function getKeys<T extends object>(obj: T) {\n\treturn Object.keys(obj) as Array<keyof T>;\n}\n\n/**\n * Checks whether something is disabled or not based on its props.\n */\nexport function disabledFromProps(props: {\n\tdisabled?: boolean;\n\t\"aria-disabled\"?: boolean | \"true\" | \"false\";\n}) {\n\treturn (\n\t\tprops.disabled ||\n\t\tprops[\"aria-disabled\"] === true ||\n\t\tprops[\"aria-disabled\"] === \"true\"\n\t);\n}\n","import { applyState, hasOwnProperty, invariant } from \"src/functions\";\nimport type { AnyObject, SetStateAction } from \"src/types\";\n\nimport { chain, getKeys, noop, omit as _omit, pick as _pick } from \"./utils\";\n\n/**\n * ============================================================================\n * STORE\n * ============================================================================\n *\n * Implementation taken from AriaKit (https://ariakit.org/)\n *\n * https://github.com/ariakit/ariakit/blob/295118174512ee27b81822f7f16d7cdf9d0d0be6/packages/ariakit-core/src/utils/store.ts\n */\n/** */\n\ntype Listener<S> = (state: S, prevState: S) => void | (() => void);\n\ntype Sync<S, K extends keyof S> = (\n\tkeys: K[] | null,\n\tlistener: Listener<Pick<S, K>>,\n) => () => void;\n\ntype StoreSetup = (callback: () => void | (() => void)) => () => void;\ntype StoreInit = () => () => void;\ntype StoreSubscribe<S = State, K extends keyof S = keyof S> = Sync<S, K>;\ntype StoreSync<S = State, K extends keyof S = keyof S> = Sync<S, K>;\ntype StoreBatch<S = State, K extends keyof S = keyof S> = Sync<S, K>;\ntype StorePick<\n\tS = State,\n\tK extends ReadonlyArray<keyof S> = ReadonlyArray<keyof S>,\n> = (keys: K) => Store<Pick<S, K[number]>>;\ntype StoreOmit<\n\tS = State,\n\tK extends ReadonlyArray<keyof S> = ReadonlyArray<keyof S>,\n> = (keys: K) => Store<Omit<S, K[number]>>;\n\ntype StoreInternals<S = State> = {\n\tsetup: StoreSetup;\n\tinit: StoreInit;\n\tsubscribe: StoreSubscribe<S>;\n\tsync: StoreSync<S>;\n\tbatch: StoreBatch<S>;\n\tpick: StorePick<S>;\n\tomit: StoreOmit<S>;\n};\n\nfunction getInternal<K extends keyof StoreInternals>(\n\tstore: Store & { __unstableInternals?: StoreInternals },\n\tkey: K,\n): StoreInternals[K] {\n\tconst internals = store.__unstableInternals;\n\tinvariant(internals, \"Invalid store\");\n\treturn internals[key];\n}\n\n/**\n * Creates a store.\n * @param initialState Initial state.\n * @param stores Stores to extend.\n */\nexport function createStore<S extends State>(\n\tinitialState: S,\n\t...stores: Array<Store<Partial<S>> | undefined>\n): Store<S> {\n\tlet state = initialState;\n\tlet prevStateBatch = state;\n\tlet lastUpdate = Symbol();\n\tlet destroy = noop;\n\tconst instances = new Set<symbol>();\n\tconst updatedKeys = new Set<keyof S>();\n\n\tconst setups = new Set<() => void | (() => void)>();\n\tconst listeners = new Set<Listener<S>>();\n\tconst batchListeners = new Set<Listener<S>>();\n\tconst disposables = new WeakMap<Listener<S>, void | (() => void)>();\n\tconst listenerKeys = new WeakMap<Listener<S>, Array<keyof S> | null>();\n\n\tconst storeSetup: StoreSetup = (callback) => {\n\t\tsetups.add(callback);\n\t\treturn () => setups.delete(callback);\n\t};\n\n\tconst storeInit: StoreInit = () => {\n\t\t// Make sure we only initialize the store once, even when it's passed to\n\t\t// other stores. However, the store can't be destroyed until all instances\n\t\t// are unmounted. See https://github.com/ariakit/ariakit/issues/3147. See\n\t\t// select-default-open-controlled tests.\n\t\tconst initialized = instances.size;\n\t\tconst instance = Symbol();\n\t\tinstances.add(instance);\n\n\t\tconst maybeDestroy = () => {\n\t\t\tinstances.delete(instance);\n\t\t\tif (instances.size) return;\n\t\t\tdestroy();\n\t\t};\n\n\t\tif (initialized) return maybeDestroy;\n\n\t\tconst desyncs = getKeys(state).map((key) =>\n\t\t\tchain(\n\t\t\t\t...stores.map((store) => {\n\t\t\t\t\tconst storeState = store?.getState?.();\n\t\t\t\t\tif (!storeState) return;\n\t\t\t\t\tif (!hasOwnProperty(storeState, key)) return;\n\t\t\t\t\treturn sync(store, [key], (state) => {\n\t\t\t\t\t\tsetState(\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tstate[key]!,\n\t\t\t\t\t\t\t// @ts-expect-error - Not public API. This is just to prevent\n\t\t\t\t\t\t\t// infinite loops.\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\n\t\tconst teardowns: Array<void | (() => void)> = [];\n\t\tfor (const setup of setups) {\n\t\t\tteardowns.push(setup());\n\t\t}\n\n\t\tconst cleanups = stores.map(init);\n\n\t\tdestroy = chain(...desyncs, ...teardowns, ...cleanups);\n\n\t\treturn maybeDestroy;\n\t};\n\n\tconst sub = (\n\t\tkeys: Array<keyof S> | null,\n\t\tlistener: Listener<S>,\n\t\tset = listeners,\n\t) => {\n\t\tset.add(listener);\n\t\tlistenerKeys.set(listener, keys);\n\t\treturn () => {\n\t\t\tdisposables.get(listener)?.();\n\t\t\tdisposables.delete(listener);\n\t\t\tlistenerKeys.delete(listener);\n\t\t\tset.delete(listener);\n\t\t};\n\t};\n\n\tconst storeSubscribe: StoreSubscribe<S> = (keys, listener) =>\n\t\tsub(keys, listener);\n\n\tconst storeSync: StoreSync<S> = (keys, listener) => {\n\t\tdisposables.set(listener, listener(state, state));\n\t\treturn sub(keys, listener);\n\t};\n\n\tconst storeBatch: StoreBatch<S> = (keys, listener) => {\n\t\tdisposables.set(listener, listener(state, prevStateBatch));\n\t\treturn sub(keys, listener, batchListeners);\n\t};\n\n\tconst storePick: StorePick<S, ReadonlyArray<keyof S>> = (keys) =>\n\t\tcreateStore(_pick(state, keys), finalStore);\n\n\tconst storeOmit: StoreOmit<S, ReadonlyArray<keyof S>> = (keys) =>\n\t\tcreateStore(_omit(state, keys), finalStore);\n\n\tconst getState: Store<S>[\"getState\"] = () => state;\n\n\tconst setState: Store<S>[\"setState\"] = (key, value, fromStores = false) => {\n\t\tif (!hasOwnProperty(state, key)) return;\n\n\t\tconst nextValue = applyState(value, state[key]);\n\n\t\tif (nextValue === state[key]) return;\n\n\t\tif (!fromStores) {\n\t\t\tfor (const store of stores) {\n\t\t\t\tstore?.setState?.(key, nextValue);\n\t\t\t}\n\t\t}\n\n\t\tconst prevState = state;\n\t\tstate = { ...state, [key]: nextValue };\n\n\t\tconst thisUpdate = Symbol();\n\t\tlastUpdate = thisUpdate;\n\t\tupdatedKeys.add(key);\n\n\t\tconst run = (listener: Listener<S>, prev: S, uKeys?: Set<keyof S>) => {\n\t\t\tconst keys = listenerKeys.get(listener);\n\t\t\tconst updated = (k: keyof S) => (uKeys ? uKeys.has(k) : k === key);\n\t\t\tif (!keys || keys.some(updated)) {\n\t\t\t\tdisposables.get(listener)?.();\n\t\t\t\tdisposables.set(listener, listener(state, prev));\n\t\t\t}\n\t\t};\n\n\t\tfor (const listener of listeners) {\n\t\t\trun(listener, prevState);\n\t\t}\n\n\t\tqueueMicrotask(() => {\n\t\t\t// If setState is called again before this microtask runs, skip this\n\t\t\t// update. This is to prevent unnecessary updates when multiple keys are\n\t\t\t// updated in a single microtask.\n\t\t\tif (lastUpdate !== thisUpdate) return;\n\t\t\t// Take a snapshot of the state before running batch listeners. This is\n\t\t\t// necessary because batch listeners can setState.\n\t\t\tconst snapshot = state;\n\t\t\tfor (const listener of batchListeners) {\n\t\t\t\trun(listener, prevStateBatch, updatedKeys);\n\t\t\t}\n\t\t\tprevStateBatch = snapshot;\n\t\t\tupdatedKeys.clear();\n\t\t});\n\t};\n\n\tconst finalStore = {\n\t\tgetState,\n\t\tsetState,\n\t\t__unstableInternals: {\n\t\t\tsetup: storeSetup,\n\t\t\tinit: storeInit,\n\t\t\tsubscribe: storeSubscribe,\n\t\t\tsync: storeSync,\n\t\t\tbatch: storeBatch,\n\t\t\tpick: storePick,\n\t\t\tomit: storeOmit,\n\t\t},\n\t};\n\n\treturn finalStore;\n}\n\nexport function setup<T extends Store>(\n\tstore?: T | null,\n\t...args: Parameters<StoreSetup>\n): T extends Store ? ReturnType<StoreSetup> : void;\n\n/**\n * Register a callback function that's called when the store is initialized.\n */\nexport function setup(store?: Store, ...args: Parameters<StoreSetup>) {\n\tif (!store) return;\n\treturn getInternal(store, \"setup\")(...args);\n}\n\nexport function init<T extends Store>(\n\tstore?: T | null,\n\t...args: Parameters<StoreInit>\n): T extends Store ? ReturnType<StoreInit> : void;\n\n/**\n * Function that should be called when the store is initialized.\n */\nexport function init(store?: Store, ...args: Parameters<StoreInit>) {\n\tif (!store) return;\n\treturn getInternal(store, \"init\")(...args);\n}\n\nexport function subscribe<T extends Store, K extends keyof StoreState<T>>(\n\tstore?: T | null,\n\t...args: Parameters<StoreSubscribe<StoreState<T>, K>>\n): T extends Store ? ReturnType<StoreSubscribe<StoreState<T>, K>> : void;\n\n/**\n * Registers a listener function that's called after state changes in the store.\n */\nexport function subscribe(store?: Store, ...args: Parameters<StoreSubscribe>) {\n\tif (!store) return;\n\treturn getInternal(store, \"subscribe\")(...args);\n}\n\nexport function sync<T extends Store, K extends keyof StoreState<T>>(\n\tstore?: T | null,\n\t...args: Parameters<StoreSync<StoreState<T>, K>>\n): T extends Store ? ReturnType<StoreSync<StoreState<T>, K>> : void;\n\n/**\n * Registers a listener function that's called immediately and synchronously\n * whenever the store state changes.\n */\nexport function sync(store?: Store, ...args: Parameters<StoreSync>) {\n\tif (!store) return;\n\treturn getInternal(store, \"sync\")(...args);\n}\n\nexport function batch<T extends Store, K extends keyof StoreState<T>>(\n\tstore?: T | null,\n\t...args: Parameters<StoreBatch<StoreState<T>, K>>\n): T extends Store ? ReturnType<StoreBatch<StoreState<T>, K>> : void;\n\n/**\n * Registers a listener function that's called immediately and after a batch\n * of state changes in the store.\n */\nexport function batch(store?: Store, ...args: Parameters<StoreBatch>) {\n\tif (!store) return;\n\treturn getInternal(store, \"batch\")(...args);\n}\n\nexport function omit<\n\tT extends Store,\n\tK extends ReadonlyArray<keyof StoreState<T>>,\n>(\n\tstore?: T | null,\n\t...args: Parameters<StoreOmit<StoreState<T>, K>>\n): T extends Store ? ReturnType<StoreOmit<StoreState<T>, K>> : void;\n\n/**\n * Creates a new store with a subset of the current store state and keeps them\n * in sync.\n */\nexport function omit(store?: Store, ...args: Parameters<StoreOmit>) {\n\tif (!store) return;\n\treturn getInternal(store, \"omit\")(...args);\n}\n\nexport function pick<\n\tT extends Store,\n\tK extends ReadonlyArray<keyof StoreState<T>>,\n>(\n\tstore?: T | null,\n\t...args: Parameters<StorePick<StoreState<T>, K>>\n): T extends Store ? ReturnType<StorePick<StoreState<T>, K>> : void;\n\n/**\n * Creates a new store with a subset of the current store state and keeps them\n * in sync.\n */\nexport function pick(store: Store, ...args: Parameters<StorePick>) {\n\tif (!store) return;\n\treturn getInternal(store, \"pick\")(...args);\n}\n\n/**\n * Merges multiple stores into a single store.\n */\nexport function mergeStore<S extends State>(\n\t...stores: Array<Store<S> | undefined>\n): Store<S> {\n\tconst initialState = {} as S;\n\tfor (const store of stores) {\n\t\tconst nextState = store?.getState?.();\n\t\tif (nextState) {\n\t\t\tObject.assign(initialState, nextState);\n\t\t}\n\t}\n\tconst store = createStore(initialState, ...stores);\n\treturn Object.assign({}, ...stores, store);\n}\n\n/**\n * Throws when a store prop is passed in conjunction with a default state.\n */\nexport function throwOnConflictingProps(props: AnyObject, store?: Store) {\n\tif (process.env.NODE_ENV === \"production\") return;\n\tif (!store) return;\n\tconst defaultKeys = Object.entries(props)\n\t\t.filter(([key, value]) => key.startsWith(\"default\") && value !== undefined)\n\t\t.map(([key]) => {\n\t\t\tconst stateKey = key.replace(\"default\", \"\");\n\t\t\treturn `${stateKey[0]?.toLowerCase() || \"\"}${stateKey.slice(1)}`;\n\t\t});\n\tif (!defaultKeys.length) return;\n\tconst storeState = store.getState();\n\tconst conflictingProps = defaultKeys.filter((key) =>\n\t\thasOwnProperty(storeState, key),\n\t);\n\tif (!conflictingProps.length) return;\n\tthrow new Error(\n\t\t`Passing a store prop in conjunction with a default state is not supported.\n\nconst store = useSelectStore();\n<SelectProvider store={store} defaultValue=\"Apple\" />\n ^ ^\n\nInstead, pass the default state to the topmost store:\n\nconst store = useSelectStore({ defaultValue: \"Apple\" });\n<SelectProvider store={store} />\n`,\n\t);\n}\n\n/**\n * Store state type.\n */\nexport type State = AnyObject;\n\n/**\n * Initial state that can be passed to a store creator function.\n * @template S State type.\n * @template K Key type.\n */\nexport type StoreOptions<S extends State, K extends keyof S> = Partial<\n\tPick<S, K>\n>;\n\n/**\n * Props that can be passed to a store creator function.\n * @template S State type.\n */\nexport type StoreProps<S extends State = State> = {\n\t/**\n\t * Another store object that will be kept in sync with the original store.\n\t *\n\t * Live examples:\n\t * - [Navigation Menubar](https://ariakit.org/examples/menubar-navigation)\n\t */\n\tstore?: Store<Partial<S>>;\n};\n\n/**\n * Extracts the state type from a store type.\n * @template T Store type.\n */\nexport type StoreState<T> = T extends Store<infer S> ? S : never;\n\n/**\n * Store.\n * @template S State type.\n */\nexport type Store<S = State> = {\n\t/**\n\t * Returns the current store state.\n\t */\n\tgetState(): S;\n\t/**\n\t * Sets a state value.\n\t */\n\tsetState<K extends keyof S>(key: K, value: SetStateAction<S[K]>): void;\n};\n","import { defaultValue } from \"../functions/default-value\";\nimport type { BivariantCallback } from \"../types/state\";\nimport { getDocument, sortBasedOnDOMPosition } from \"./dom\";\nimport type { Store, StoreOptions, StoreProps } from \"./store\";\nimport {\n\tbatch,\n\tcreateStore,\n\tinit,\n\tsetup,\n\tthrowOnConflictingProps,\n} from \"./store\";\nimport { chain } from \"./utils\";\n\nfunction getCommonParent(items: CollectionStoreItem[]) {\n\tconst firstItem = items.find((item) => !!item.element);\n\tconst lastItem = [...items].reverse().find((item) => !!item.element);\n\tlet parentElement = firstItem?.element?.parentElement;\n\twhile (parentElement && lastItem?.element) {\n\t\tconst parent = parentElement;\n\t\tif (lastItem && parent.contains(lastItem.element)) {\n\t\t\treturn parentElement;\n\t\t}\n\t\tparentElement = parentElement.parentElement;\n\t}\n\treturn getDocument(parentElement).body;\n}\n\nfunction getPrivateStore<T extends CollectionStoreItem>(\n\tstore?: Store & {\n\t\t__unstablePrivateStore?: Store<{\n\t\t\trenderedItems: T[];\n\t\t}>;\n\t},\n) {\n\treturn store?.__unstablePrivateStore;\n}\n\n/**\n * Creates a collection store.\n */\nexport function createCollectionStore<\n\tT extends CollectionStoreItem = CollectionStoreItem,\n>(props: CollectionStoreProps<T> = {}): CollectionStore<T> {\n\tthrowOnConflictingProps(props, props.store);\n\n\tconst syncState = props.store?.getState();\n\n\tconst items = defaultValue(\n\t\tprops.items,\n\t\tsyncState?.items,\n\t\tprops.defaultItems,\n\t\t[],\n\t);\n\n\tconst itemsMap = new Map<string, T>(items.map((item) => [item.id, item]));\n\n\tconst initialState: CollectionStoreState<T> = {\n\t\titems,\n\t\trenderedItems: defaultValue(syncState?.renderedItems, []),\n\t};\n\n\tconst syncPrivateStore = getPrivateStore<T>(props.store);\n\n\tconst privateStore = createStore(\n\t\t{ items, renderedItems: initialState.renderedItems },\n\t\tsyncPrivateStore,\n\t);\n\n\tconst collection = createStore(initialState, props.store);\n\n\tconst sortItems = (renderedItems: T[]) => {\n\t\tconst sortedItems = sortBasedOnDOMPosition(renderedItems, (i) => i.element);\n\t\tprivateStore.setState(\"renderedItems\", sortedItems);\n\t\tcollection.setState(\"renderedItems\", sortedItems);\n\t};\n\n\tsetup(collection, () => init(privateStore));\n\n\t// Use the private store to register items and then batch the changes to the\n\t// public store so we don't trigger multiple updates on the store when adding\n\t// multiple items.\n\tsetup(privateStore, () => {\n\t\treturn batch(privateStore, [\"items\"], (state) => {\n\t\t\tcollection.setState(\"items\", state.items);\n\t\t});\n\t});\n\n\tsetup(privateStore, () => {\n\t\treturn batch(privateStore, [\"renderedItems\"], (state) => {\n\t\t\tlet firstRun = true;\n\n\t\t\tlet raf = requestAnimationFrame(() => {\n\t\t\t\tconst { renderedItems } = collection.getState();\n\t\t\t\t// Bail out if the rendered items haven't changed. This is important\n\t\t\t\t// because the following lines can cause this function to be called\n\t\t\t\t// again.\n\t\t\t\tif (state.renderedItems === renderedItems) return;\n\t\t\t\tsortItems(state.renderedItems);\n\t\t\t});\n\n\t\t\tif (typeof IntersectionObserver !== \"function\") {\n\t\t\t\treturn () => cancelAnimationFrame(raf);\n\t\t\t}\n\n\t\t\tconst ioCallback: IntersectionObserverCallback = () => {\n\t\t\t\tif (firstRun) {\n\t\t\t\t\t// The IntersectionObserver callback is called synchronously the first\n\t\t\t\t\t// time. We just ignore it.\n\t\t\t\t\tfirstRun = false;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcancelAnimationFrame(raf);\n\t\t\t\traf = requestAnimationFrame(() => sortItems(state.renderedItems));\n\t\t\t};\n\n\t\t\tconst root = getCommonParent(state.renderedItems);\n\t\t\tconst observer = new IntersectionObserver(ioCallback, { root });\n\n\t\t\tfor (const item of state.renderedItems) {\n\t\t\t\tif (!item.element) continue;\n\t\t\t\tobserver.observe(item.element);\n\t\t\t}\n\n\t\t\treturn () => {\n\t\t\t\tcancelAnimationFrame(raf);\n\t\t\t\tobserver.disconnect();\n\t\t\t};\n\t\t});\n\t});\n\n\tconst mergeItem = (\n\t\titem: T,\n\t\tsetItems: (getItems: (items: T[]) => T[]) => void,\n\t\tcanDeleteFromMap = false,\n\t) => {\n\t\tlet prevItem: T | undefined;\n\t\tsetItems((items) => {\n\t\t\tconst index = items.findIndex(({ id }) => id === item.id);\n\t\t\tconst nextItems = items.slice();\n\t\t\tif (index !== -1) {\n\t\t\t\tprevItem = items[index];\n\t\t\t\tconst nextItem = { ...prevItem, ...item };\n\t\t\t\tnextItems[index] = nextItem;\n\t\t\t\titemsMap.set(item.id, nextItem);\n\t\t\t} else {\n\t\t\t\tnextItems.push(item);\n\t\t\t\titemsMap.set(item.id, item);\n\t\t\t}\n\t\t\treturn nextItems;\n\t\t});\n\t\tconst unmergeItem = () => {\n\t\t\tsetItems((items) => {\n\t\t\t\tif (!prevItem) {\n\t\t\t\t\tif (canDeleteFromMap) {\n\t\t\t\t\t\titemsMap.delete(item.id);\n\t\t\t\t\t}\n\t\t\t\t\treturn items.filter(({ id }) => id !== item.id);\n\t\t\t\t}\n\t\t\t\tconst index = items.findIndex(({ id }) => id === item.id);\n\t\t\t\tif (index === -1) return items;\n\t\t\t\tconst nextItems = items.slice();\n\t\t\t\tnextItems[index] = prevItem;\n\t\t\t\titemsMap.set(item.id, prevItem);\n\t\t\t\treturn nextItems;\n\t\t\t});\n\t\t};\n\t\treturn unmergeItem;\n\t};\n\n\tconst registerItem: CollectionStore<T>[\"registerItem\"] = (item) =>\n\t\tmergeItem(\n\t\t\titem,\n\t\t\t(getItems) => privateStore.setState(\"items\", getItems),\n\t\t\ttrue,\n\t\t);\n\n\treturn {\n\t\t...collection,\n\n\t\tregisterItem,\n\t\trenderItem: (item) =>\n\t\t\tchain(\n\t\t\t\tregisterItem(item),\n\t\t\t\tmergeItem(item, (getItems) =>\n\t\t\t\t\tprivateStore.setState(\"renderedItems\", getItems),\n\t\t\t\t),\n\t\t\t),\n\n\t\titem: (id) => {\n\t\t\tif (!id) return null;\n\t\t\tlet item = itemsMap.get(id);\n\t\t\tif (!item) {\n\t\t\t\tconst { items } = privateStore.getState();\n\t\t\t\titem = items.find((item) => item.id === id);\n\t\t\t\tif (item) {\n\t\t\t\t\titemsMap.set(id, item);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn item || null;\n\t\t},\n\n\t\t// @ts-expect-error Internal\n\t\t__unstablePrivateStore: privateStore,\n\t};\n}\n\nexport type CollectionStoreItem = {\n\t/**\n\t * The id of the item.\n\t */\n\tid: string;\n\t/**\n\t * The item HTML element. This is automatically set when the item is rendered.\n\t */\n\telement?: HTMLElement | null;\n};\n\nexport type CollectionStoreState<\n\tT extends CollectionStoreItem = CollectionStoreItem,\n> = {\n\t/**\n\t * Lists all items along with their metadata. This state is automatically\n\t * updated when an item is registered or unregistered using the\n\t * [`registerItem`](https://ariakit.org/reference/use-collection-store#registeritem)\n\t * function.\n\t *\n\t * Live examples:\n\t * - [Command Menu with\n\t * Tabs](https://ariakit.org/examples/dialog-combobox-tab-command-menu)\n\t */\n\titems: T[];\n\t/**\n\t * Lists all items, along with their metadata, in the exact order they appear in\n\t * the DOM. This state is automatically updated when an item is rendered or\n\t * unmounted using the\n\t * [`renderItem`](https://ariakit.org/reference/use-collection-store#renderitem)\n\t * function.\n\t */\n\trenderedItems: T[];\n};\n\nexport type CollectionStoreFunctions<\n\tT extends CollectionStoreItem = CollectionStoreItem,\n> = {\n\t/**\n\t * Registers an item in the collection. This function returns a cleanup\n\t * function that unregisters the item.\n\t * @example\n\t * const unregisterItem = store.registerItem({ id: \"item-1\" });\n\t * // on cleanup\n\t * unregisterItem();\n\t */\n\tregisterItem: BivariantCallback<(item: T) => () => void>;\n\t/**\n\t * Renders an item in the collection. This function returns a cleanup function\n\t * that unmounts the item.\n\t * @example\n\t * const unrenderItem = store.renderItem({ id: \"item-1\" });\n\t * // on cleanup\n\t * unrenderItem();\n\t */\n\trenderItem: BivariantCallback<(item: T) => () => void>;\n\t/**\n\t * Gets an item by its id.\n\t *\n\t * Live examples:\n\t * - [Animated TabPanel](https://ariakit.org/examples/tab-panel-animated)\n\t * @example\n\t * const item = store.item(\"item-1\");\n\t */\n\titem: (id: string | null | undefined) => T | null;\n};\n\nexport type CollectionStoreOptions<\n\tT extends CollectionStoreItem = CollectionStoreItem,\n> = {\n\t/**\n\t * The defaut value for the\n\t * [`items`](https://ariakit.org/reference/collection-provider#items) state.\n\t * @default []\n\t */\n\tdefaultItems?: CollectionStoreState<T>[\"items\"];\n} & StoreOptions<CollectionStoreState<T>, \"items\">;\n\nexport type CollectionStoreProps<\n\tT extends CollectionStoreItem = CollectionStoreItem,\n\t// eslint-disable-next-line @typescript-eslint/ban-types\n> = {} & CollectionStoreOptions<T> & StoreProps<CollectionStoreState<T>>;\n\nexport type CollectionStore<\n\tT extends CollectionStoreItem = CollectionStoreItem,\n\t// eslint-disable-next-line @typescript-eslint/ban-types\n> = {} & CollectionStoreFunctions<T> & Store<CollectionStoreState<T>>;\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@buildinams/core",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": "Build in Amsterdam <development@buildinamsterdam.com> (https://www.buildinamsterdam.com/)",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/buildinamsterdam/bia-shared.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/buildinamsterdam/bia-shared/issues"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsup",
|
|
15
|
+
"dev": "tsup --watch",
|
|
16
|
+
"lint": "eslint .",
|
|
17
|
+
"test": "vitest watch",
|
|
18
|
+
"test:ci": "vitest run",
|
|
19
|
+
"lint:fix": "eslint . --fix"
|
|
20
|
+
},
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./store": {
|
|
29
|
+
"types": "./dist/store/index.d.ts",
|
|
30
|
+
"default": "./dist/store/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"typesVersions": {
|
|
34
|
+
"*": {
|
|
35
|
+
"*": [
|
|
36
|
+
"./dist/index.d.ts"
|
|
37
|
+
],
|
|
38
|
+
"./store": [
|
|
39
|
+
"./dist/store/index.d.ts"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"README.md"
|
|
46
|
+
],
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"registry": "https://npm.pkg.github.com",
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@buildinams/lint": "^0.4.0",
|
|
53
|
+
"tsup": "^8.0.1",
|
|
54
|
+
"typescript": "^5.4.5",
|
|
55
|
+
"vitest": "^3.2.4"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"clsx": "^2.1.1"
|
|
59
|
+
}
|
|
60
|
+
}
|