@createstore/createstore 0.0.0 → 1.1.0
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 +30 -0
- package/dist/cjs/createStore.cjs +48 -9
- package/dist/cjs/createStore.cjs.map +1 -1
- package/dist/esm/createStore.js +48 -9
- package/dist/esm/createStore.js.map +1 -1
- package/package.json +23 -4
package/README.md
CHANGED
|
@@ -24,6 +24,28 @@ function Counter() {
|
|
|
24
24
|
Every component that reads `'count'` re-renders when any of them changes it. Outside React, use
|
|
25
25
|
`store.getState('count')` and `store.setState('count', 2)`.
|
|
26
26
|
|
|
27
|
+
### Share state between components
|
|
28
|
+
|
|
29
|
+
Take `useGlobalState` out of the store, and any component can read or change the same list. No provider, no props
|
|
30
|
+
passed down:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
const { useGlobalState } = createStore({ todos: [] as { text: string }[] });
|
|
34
|
+
|
|
35
|
+
function TodoCount() {
|
|
36
|
+
const [todos] = useGlobalState('todos');
|
|
37
|
+
return <p>{todos.length} todos</p>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function AddTodo() {
|
|
41
|
+
const [todos, setTodos] = useGlobalState('todos');
|
|
42
|
+
const add = (text: string) => setTodos([...todos, { text }]);
|
|
43
|
+
return <Form onAdd={add} />;
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`<Form>` stands for your own form component. When `AddTodo` adds a todo, `TodoCount` updates by itself.
|
|
48
|
+
|
|
27
49
|
Everything else stays off until you use it: computed values, server data with `query()`, persistence, offline
|
|
28
50
|
support, undo/redo, tab sync, events and server rendering.
|
|
29
51
|
|
|
@@ -33,6 +55,14 @@ support, undo/redo, tab sync, events and server rendering.
|
|
|
33
55
|
- Published with [npm provenance](https://docs.npmjs.com/generating-provenance-statements).
|
|
34
56
|
- Versioned with [semantic versioning](https://semver.org); see [CHANGELOG.md](./CHANGELOG.md) once a release exists.
|
|
35
57
|
|
|
58
|
+
## Links
|
|
59
|
+
|
|
60
|
+
- [GitHub repository](https://github.com/Gauravasawa/createstore): source code, issues and releases
|
|
61
|
+
- [npm package](https://www.npmjs.com/package/@createstore/createstore)
|
|
62
|
+
- [Documentation](https://createstore-docs.pages.dev)
|
|
63
|
+
- [Report a bug or request a feature](https://github.com/Gauravasawa/createstore/issues/new/choose)
|
|
64
|
+
- [Security policy](https://github.com/Gauravasawa/createstore/security/policy)
|
|
65
|
+
|
|
36
66
|
## License
|
|
37
67
|
|
|
38
68
|
[MIT](./LICENSE)
|
package/dist/cjs/createStore.cjs
CHANGED
|
@@ -29,6 +29,15 @@ __export(createStore_exports, {
|
|
|
29
29
|
module.exports = __toCommonJS(createStore_exports);
|
|
30
30
|
var import_react_bindings = require("./react-bindings.cjs");
|
|
31
31
|
const __SnapshotContext = import_react_bindings.RSC ? null : (0, import_react_bindings.createContext)(null);
|
|
32
|
+
let leavingPage = false;
|
|
33
|
+
if (typeof window !== "undefined" && typeof window.addEventListener === "function") {
|
|
34
|
+
window.addEventListener("pagehide", () => {
|
|
35
|
+
leavingPage = true;
|
|
36
|
+
});
|
|
37
|
+
window.addEventListener("pageshow", () => {
|
|
38
|
+
leavingPage = false;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
32
41
|
const storesByName = /* @__PURE__ */ new Map();
|
|
33
42
|
const MERGE = /* @__PURE__ */ Symbol("createStore.merge");
|
|
34
43
|
const QUIET = /* @__PURE__ */ Symbol("createStore.quiet");
|
|
@@ -163,12 +172,48 @@ function defineEvents() {
|
|
|
163
172
|
return void 0;
|
|
164
173
|
}
|
|
165
174
|
function createStore(initialState, options = {}) {
|
|
175
|
+
checkStoreOptions(options);
|
|
166
176
|
if ("queries" in options)
|
|
167
177
|
throw new Error(
|
|
168
178
|
`[${options.name ?? "store"}] the queries option was replaced: declare each query in the state with query(fetch, options), e.g. { product: query((id, signal) => api.product(id, signal)) }, and read it with useGlobalState('product', id).`
|
|
169
179
|
);
|
|
170
180
|
return withScopes(initialState, options, makeBase(initialState, options));
|
|
171
181
|
}
|
|
182
|
+
const STORE_OPTIONS = /* @__PURE__ */ new Set([
|
|
183
|
+
"name",
|
|
184
|
+
"persist",
|
|
185
|
+
"syncTabs",
|
|
186
|
+
"history",
|
|
187
|
+
"devtools",
|
|
188
|
+
"shared",
|
|
189
|
+
"ssr",
|
|
190
|
+
"logger",
|
|
191
|
+
"onChange",
|
|
192
|
+
"offline",
|
|
193
|
+
"validate",
|
|
194
|
+
"events",
|
|
195
|
+
"computed",
|
|
196
|
+
"keyActions",
|
|
197
|
+
"actions",
|
|
198
|
+
"queries"
|
|
199
|
+
]);
|
|
200
|
+
const warnedOptions = /* @__PURE__ */ new Set();
|
|
201
|
+
function checkStoreOptions(opts) {
|
|
202
|
+
const options = opts;
|
|
203
|
+
const warn = (message) => {
|
|
204
|
+
if (warnedOptions.has(message)) return;
|
|
205
|
+
warnedOptions.add(message);
|
|
206
|
+
console.warn(message);
|
|
207
|
+
};
|
|
208
|
+
const id = options.name ?? "store";
|
|
209
|
+
for (const k of Object.keys(options))
|
|
210
|
+
if (!STORE_OPTIONS.has(k))
|
|
211
|
+
warn(`[${id}] createStore() has no option "${k}", so it is ignored. Options: ${[...STORE_OPTIONS].filter((o) => o !== "queries").join(", ")}.`);
|
|
212
|
+
if (!options.name && (options.persist || options.syncTabs || options.offline || options.shared))
|
|
213
|
+
warn(
|
|
214
|
+
`[store] persist, syncTabs, offline and shared use the store's name to tell stores apart. Without { name: '...' }, every unnamed store uses "store", so two of them would overwrite each other's saved data and mix up their tabs. Give this one a name.`
|
|
215
|
+
);
|
|
216
|
+
}
|
|
172
217
|
const warnedSharedOnServer = /* @__PURE__ */ new Set();
|
|
173
218
|
const warnedShape = /* @__PURE__ */ new Set();
|
|
174
219
|
const SHAPE = /* @__PURE__ */ Symbol("createStore.shape");
|
|
@@ -1263,6 +1308,7 @@ function build(initialState, options, sharedDefinition) {
|
|
|
1263
1308
|
updateHistoryInfo();
|
|
1264
1309
|
}
|
|
1265
1310
|
function batch(fn) {
|
|
1311
|
+
if (typeof fn !== "function") throw new Error(`[${name}] batch() takes a function that makes the changes: store.batch(() => { store.setState('a', 1); store.setState('b', 2); }).`);
|
|
1266
1312
|
batchDepth++;
|
|
1267
1313
|
if (batchDepth === 1 && historyLimit) batchChanges = /* @__PURE__ */ Object.create(null);
|
|
1268
1314
|
let result;
|
|
@@ -1590,15 +1636,6 @@ function build(initialState, options, sharedDefinition) {
|
|
|
1590
1636
|
ownPromises.add(promise);
|
|
1591
1637
|
return promise;
|
|
1592
1638
|
}
|
|
1593
|
-
let leavingPage = false;
|
|
1594
|
-
if (isBrowser && typeof window.addEventListener === "function") {
|
|
1595
|
-
window.addEventListener("pagehide", () => {
|
|
1596
|
-
leavingPage = true;
|
|
1597
|
-
});
|
|
1598
|
-
window.addEventListener("pageshow", () => {
|
|
1599
|
-
leavingPage = false;
|
|
1600
|
-
});
|
|
1601
|
-
}
|
|
1602
1639
|
const SERVER_LOADING = Object.freeze({
|
|
1603
1640
|
state: "loading",
|
|
1604
1641
|
loading: true,
|
|
@@ -2242,6 +2279,8 @@ function build(initialState, options, sharedDefinition) {
|
|
|
2242
2279
|
};
|
|
2243
2280
|
const api = Object.assign(Object.create(setterProtoOf(def, API_NAMES, "apiProto")), apiMembers);
|
|
2244
2281
|
Object.defineProperty(api, SETTER_OF, { value: (k) => setterFor(k) });
|
|
2282
|
+
if (options.actions != null && typeof options.actions !== "function")
|
|
2283
|
+
throw new Error(`[${name}] actions must be a function that receives the store's api and returns your actions: createStore(state, { actions: (api) => ({ add(x) { api.setState('items', (i) => [...i, x]); } }) }).`);
|
|
2245
2284
|
const actions = options.actions?.(api) ?? {};
|
|
2246
2285
|
const keyActionDefs = options.keyActions ?? {};
|
|
2247
2286
|
const ssrCfg = options.ssr;
|