@leesf/legend-state-selector 0.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 ADDED
@@ -0,0 +1,78 @@
1
+ # @leesf/legend-state-selector
2
+
3
+ A small `createSelector` helper for [Legend State](https://legendapp.com/open-source/state/) v3.
4
+
5
+ It creates per-key computed observables for selection state, so only the previously selected key and the next selected key are invalidated when the source value changes.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pnpm add @leesf/legend-state-selector @legendapp/state
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```ts
16
+ import { observable } from "@legendapp/state";
17
+ import { createSelector } from "@leesf/legend-state-selector";
18
+
19
+ const selected = observable("inbox");
20
+ const isSelected = createSelector(selected);
21
+
22
+ const inbox = isSelected("inbox");
23
+ const archive = isSelected("archive");
24
+
25
+ inbox.get(); // true
26
+ archive.get(); // false
27
+
28
+ selected.set("archive");
29
+
30
+ inbox.get(); // false
31
+ archive.get(); // true
32
+ ```
33
+
34
+ ## Object Values
35
+
36
+ Pass a `getKey` function when the selected value is an object. The key is used for both map lookups and equality checks.
37
+
38
+ ```ts
39
+ import { observable } from "@legendapp/state";
40
+ import { createSelector } from "@leesf/legend-state-selector";
41
+
42
+ const selected = observable({ id: "inbox", label: "Inbox" });
43
+
44
+ const isSelected = createSelector(selected, (item) => item.id);
45
+
46
+ const inbox = isSelected({ id: "inbox", label: "Unread" });
47
+ const archive = isSelected({ id: "archive", label: "Archive" });
48
+
49
+ inbox.get(); // true
50
+ archive.get(); // false
51
+
52
+ selected.set({ id: "archive", label: "All archived" });
53
+
54
+ inbox.get(); // false
55
+ archive.get(); // true
56
+ ```
57
+
58
+ ## API
59
+
60
+ ```ts
61
+ createSelector<T>(
62
+ source: Observable<T>,
63
+ getKey?: (value: T) => unknown,
64
+ ): (key: T) => Observable<boolean>
65
+ ```
66
+
67
+ - `source`: The Legend State observable holding the current selected value.
68
+ - `getKey`: Optional function that converts a selected value into a stable key. Defaults to the value itself.
69
+ - Returns a function that creates a computed boolean observable for a key.
70
+
71
+ ## Development
72
+
73
+ ```bash
74
+ pnpm install
75
+ pnpm test
76
+ pnpm run typecheck
77
+ pnpm run build
78
+ ```
@@ -0,0 +1,6 @@
1
+ import { Observable } from "@legendapp/state";
2
+
3
+ //#region src/index.d.ts
4
+ declare function createSelector<T = null>(source: Observable<T>, getKey?: (value: T) => unknown): (key: T) => import("@legendapp/state").ObservableBoolean<boolean>;
5
+ //#endregion
6
+ export { createSelector };
package/dist/index.mjs ADDED
@@ -0,0 +1,33 @@
1
+ import { batch, observable, observe } from "@legendapp/state";
2
+ //#region src/index.ts
3
+ function createSelector(source, getKey = (value) => value) {
4
+ let current = source.get();
5
+ let currentKey = getKey(current);
6
+ const versionByKey = /* @__PURE__ */ new Map();
7
+ observe(() => {
8
+ const next = source.get();
9
+ const nextKey = getKey(next);
10
+ if (Object.is(currentKey, nextKey)) return;
11
+ const prevKey = currentKey;
12
+ current = next;
13
+ currentKey = nextKey;
14
+ batch(() => {
15
+ versionByKey.get(prevKey)?.set((v) => v + 1);
16
+ versionByKey.get(nextKey)?.set((v) => v + 1);
17
+ });
18
+ });
19
+ return (key) => {
20
+ const selectorKey = getKey(key);
21
+ let keyVersion = versionByKey.get(selectorKey);
22
+ if (!keyVersion) {
23
+ keyVersion = observable(0);
24
+ versionByKey.set(selectorKey, keyVersion);
25
+ }
26
+ return observable(() => {
27
+ keyVersion.get();
28
+ return Object.is(currentKey, selectorKey);
29
+ });
30
+ };
31
+ }
32
+ //#endregion
33
+ export { createSelector };
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@leesf/legend-state-selector",
3
+ "type": "module",
4
+ "version": "0.1.0",
5
+ "description": "A createSelector helper for Legend State.",
6
+ "keywords": [
7
+ "legend-state",
8
+ "selector",
9
+ "observable",
10
+ "state"
11
+ ],
12
+ "author": "Lee Shuen Fei",
13
+ "license": "MIT",
14
+ "homepage": "https://github.com/LeeSF03/legend-state-selector#readme",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/LeeSF03/legend-state-selector.git"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/LeeSF03/legend-state-selector/issues"
21
+ },
22
+ "exports": {
23
+ ".": "./dist/index.mjs",
24
+ "./package.json": "./package.json"
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "devDependencies": {
30
+ "@types/node": "^25.6.2",
31
+ "@typescript/native-preview": "7.0.0-dev.20260509.2",
32
+ "bumpp": "^11.1.0",
33
+ "tsdown": "^0.22.0",
34
+ "typescript": "^6.0.3",
35
+ "vitest": "^4.1.5"
36
+ },
37
+ "dependencies": {
38
+ "@legendapp/state": "3.0.0-beta.47"
39
+ },
40
+ "scripts": {
41
+ "build": "tsdown",
42
+ "dev": "tsdown --watch",
43
+ "test": "vitest",
44
+ "typecheck": "tsc --noEmit",
45
+ "release": "bumpp"
46
+ }
47
+ }