@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 +78 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.mjs +33 -0
- package/package.json +47 -0
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
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -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
|
+
}
|