@promoboxx/use-filter 1.11.1 → 2.0.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.
Files changed (57) hide show
  1. package/.github/workflows/main.yml +38 -0
  2. package/.vscode/settings.json +3 -0
  3. package/CHANGELOG.md +185 -0
  4. package/Makefile +25 -0
  5. package/eslint.config.js +30 -0
  6. package/mise.toml +3 -0
  7. package/package.json +33 -43
  8. package/prettier.config.js +3 -0
  9. package/src/lib/buildDefaultFilterInfo.ts +36 -0
  10. package/src/lib/getOffsetFromPage.ts +5 -0
  11. package/src/lib/getPageFromOffset.ts +5 -0
  12. package/src/lib/shallowEqual.test.ts +71 -0
  13. package/src/lib/shallowEqual.ts +26 -0
  14. package/src/store/index.ts +30 -0
  15. package/src/store/localStorageStore.ts +36 -0
  16. package/src/store/memoryStore.ts +27 -0
  17. package/src/store/reduxHelpers/createActions.test.ts +32 -0
  18. package/src/store/reduxHelpers/createActions.ts +56 -0
  19. package/src/store/reduxHelpers/createReducer.test.ts +65 -0
  20. package/src/store/reduxHelpers/createReducer.ts +47 -0
  21. package/src/store/reduxStore.ts +78 -0
  22. package/src/store/urlParamStore.test.ts +131 -0
  23. package/src/store/urlParamStore.ts +85 -0
  24. package/src/useFilter.test.tsx +822 -0
  25. package/src/useFilter.ts +524 -0
  26. package/src/useSimpleFilter.test.tsx +676 -0
  27. package/src/useSimpleFilter.ts +397 -0
  28. package/src/vitest-env.d.ts +1 -0
  29. package/tsconfig.json +76 -0
  30. package/tsdown.config.ts +30 -0
  31. package/vite.config.ts +9 -0
  32. package/dist/lib/buildDefaultFilterInfo.d.ts +0 -3
  33. package/dist/lib/buildDefaultFilterInfo.js +0 -35
  34. package/dist/lib/getOffsetFromPage.d.ts +0 -2
  35. package/dist/lib/getOffsetFromPage.js +0 -6
  36. package/dist/lib/getPageFromOffset.d.ts +0 -2
  37. package/dist/lib/getPageFromOffset.js +0 -6
  38. package/dist/lib/shallowEqual.d.ts +0 -2
  39. package/dist/lib/shallowEqual.js +0 -23
  40. package/dist/store/index.d.ts +0 -10
  41. package/dist/store/index.js +0 -16
  42. package/dist/store/localStorageStore.d.ts +0 -3
  43. package/dist/store/localStorageStore.js +0 -31
  44. package/dist/store/memoryStore.d.ts +0 -3
  45. package/dist/store/memoryStore.js +0 -23
  46. package/dist/store/reduxHelpers/createActions.d.ts +0 -16
  47. package/dist/store/reduxHelpers/createActions.js +0 -27
  48. package/dist/store/reduxHelpers/createReducer.d.ts +0 -8
  49. package/dist/store/reduxHelpers/createReducer.js +0 -26
  50. package/dist/store/reduxStore.d.ts +0 -15
  51. package/dist/store/reduxStore.js +0 -67
  52. package/dist/store/urlParamStore.d.ts +0 -2
  53. package/dist/store/urlParamStore.js +0 -86
  54. package/dist/useFilter.d.ts +0 -103
  55. package/dist/useFilter.js +0 -254
  56. package/dist/useSimpleFilter.d.ts +0 -86
  57. package/dist/useSimpleFilter.js +0 -173
@@ -0,0 +1,38 @@
1
+ name: CI
2
+ on: push
3
+
4
+ jobs:
5
+ ci:
6
+ runs-on: ubuntu-latest
7
+
8
+ steps:
9
+ - uses: actions/checkout@v2
10
+
11
+ - uses: jdx/mise-action@v2
12
+
13
+ - name: Get pnpm store directory
14
+ shell: bash
15
+ run: |
16
+ echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
17
+
18
+ - uses: actions/cache@v3
19
+ name: Setup pnpm cache
20
+ with:
21
+ path: ${{ env.STORE_PATH }}
22
+ key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
23
+ restore-keys: |
24
+ ${{ runner.os }}-pnpm-store-
25
+
26
+ # https://github.community/t/github-actions-bot-email-address/17204/5
27
+ - name: Prep for git push
28
+ run: |
29
+ git config --local user.name "github-actions[bot]"
30
+ git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
31
+
32
+ - name: Prep NPM
33
+ run: npm config set '//registry.npmjs.org/:_authToken' "${{secrets.NPM_TOKEN}}"
34
+
35
+ - run: make prepare-env
36
+ - run: make test
37
+ - run: make build
38
+ - run: make deploy
@@ -0,0 +1,3 @@
1
+ {
2
+ "typescript.tsdk": "node_modules/typescript/lib"
3
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,185 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+ ## 2.0.0 (2026-06-07)
6
+
7
+
8
+ ### ⚠ BREAKING CHANGES
9
+
10
+ * ESM + CJS and various upgrades (#23)
11
+
12
+ ### Features
13
+
14
+ * ESM + CJS and various upgrades ([#23](https://github.com/promoboxx/use-filter/issues/23)) ([e898ea7](https://github.com/promoboxx/use-filter/commit/e898ea782effbbaa21f3cfe71b44cd007a5c54d2))
15
+
16
+ ### 1.11.2 (2023-08-01)
17
+
18
+ ### 1.11.1 (2023-06-12)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * Handle partial persisted `FilterInfo` / `TFilter` ([#21](https://github.com/promoboxx/use-filter/issues/21)) ([45e54ae](https://github.com/promoboxx/use-filter/commit/45e54ae960fdc2df2b37f8a9b59c2cc9dc5bc277))
24
+
25
+ ## 1.11.0 (2023-05-25)
26
+
27
+
28
+ ### Features
29
+
30
+ * Add `store` to hooks ([#20](https://github.com/promoboxx/use-filter/issues/20)) ([d7232cd](https://github.com/promoboxx/use-filter/commit/d7232cdca3b660020acb8d82a7b2464e3237bd87))
31
+
32
+ ## 1.10.0 (2023-05-24)
33
+
34
+
35
+ ### Features
36
+
37
+ * DEV-7161: URL param store ([#19](https://github.com/promoboxx/use-filter/issues/19)) ([ea658f3](https://github.com/promoboxx/use-filter/commit/ea658f3eb6343ddca8bfaa23af5b5cf4335f0428))
38
+
39
+ ### 1.9.1 (2023-03-27)
40
+
41
+
42
+ ### Bug Fixes
43
+
44
+ * Better check for totalResults / nextCursor in onChange response ([#18](https://github.com/promoboxx/use-filter/issues/18)) ([3cecc45](https://github.com/promoboxx/use-filter/commit/3cecc45d12f36895498dbb9d38fdb0f1220ca3af))
45
+
46
+ ## 1.9.0 (2023-03-16)
47
+
48
+
49
+ ### Features
50
+
51
+ * DEV-6808: Add `onBeforeSaveFilter` ([#17](https://github.com/promoboxx/use-filter/issues/17)) ([f1f6f0b](https://github.com/promoboxx/use-filter/commit/f1f6f0b5e9befcf9fc001223bbf1ddd9d39b1fed))
52
+
53
+ ### 1.8.3 (2023-03-16)
54
+
55
+
56
+ ### Bug Fixes
57
+
58
+ * DEV-6994: Reset cursor when filters change ([#16](https://github.com/promoboxx/use-filter/issues/16)) ([9115b92](https://github.com/promoboxx/use-filter/commit/9115b9201d257afb9d1d0dcf7ddd7af23ad1abc9))
59
+
60
+ ### 1.8.2 (2022-12-07)
61
+
62
+ ### 1.8.1 (2022-12-04)
63
+
64
+ ## 1.8.0 (2022-11-25)
65
+
66
+
67
+ ### Features
68
+
69
+ * Concept of "update reason" ([#14](https://github.com/promoboxx/use-filter/issues/14)) ([0b34cd3](https://github.com/promoboxx/use-filter/commit/0b34cd3854b2d49128998cb5a0fff9c05627ff31))
70
+
71
+ ## 1.7.0 (2022-11-25)
72
+
73
+
74
+ ### Features
75
+
76
+ * Cursor Pagination ([#13](https://github.com/promoboxx/use-filter/issues/13)) ([4df58f6](https://github.com/promoboxx/use-filter/commit/4df58f6a24004a7655f1e5c4d97db4c05e0613d7))
77
+
78
+ ## 1.6.0 (2022-06-02)
79
+
80
+
81
+ ### Features
82
+
83
+ * `setPageSize` helper ([#12](https://github.com/promoboxx/use-filter/issues/12)) ([364b1b8](https://github.com/promoboxx/use-filter/commit/364b1b80acdeef3a6464a2b8fcb1c2bea30ad54a))
84
+
85
+ ### 1.5.4 (2022-05-25)
86
+
87
+
88
+ ### Bug Fixes
89
+
90
+ * When filter exists in useFilter, run immediately on mount ([#11](https://github.com/promoboxx/use-filter/issues/11)) ([50338e9](https://github.com/promoboxx/use-filter/commit/50338e91c0ddeff969e05a63450d90a368a63c08))
91
+
92
+ ### 1.5.3 (2022-05-21)
93
+
94
+
95
+ ### Bug Fixes
96
+
97
+ * Simple mode immediate on mount ([#10](https://github.com/promoboxx/use-filter/issues/10)) ([c5b7023](https://github.com/promoboxx/use-filter/commit/c5b7023ed5e7c80b2948048a32e195ec0f36eacd))
98
+
99
+ ### 1.5.2 (2022-05-21)
100
+
101
+
102
+ ### Bug Fixes
103
+
104
+ * "Advanced" mode is always immediate ([#9](https://github.com/promoboxx/use-filter/issues/9)) ([2a2fdad](https://github.com/promoboxx/use-filter/commit/2a2fdad8d80b9cf98a0729e8f360ed00f71b5e38))
105
+
106
+ ### 1.5.1 (2022-05-20)
107
+
108
+
109
+ ### Bug Fixes
110
+
111
+ * Update package files ([#8](https://github.com/promoboxx/use-filter/issues/8)) ([c06fc1e](https://github.com/promoboxx/use-filter/commit/c06fc1ef8fc9ff6faf177a7535a4a03984c5c750))
112
+
113
+ ## 1.5.0 (2022-05-19)
114
+
115
+
116
+ ### Features
117
+
118
+ * Add useSimpleFilter ([#7](https://github.com/promoboxx/use-filter/issues/7)) ([c103e8e](https://github.com/promoboxx/use-filter/commit/c103e8e675998099f0c990a2b062335e926fd869))
119
+
120
+ ## 1.4.0 (2022-05-16)
121
+
122
+
123
+ ### Features
124
+
125
+ * Add `shouldRunImmediately` and refactor ([#6](https://github.com/promoboxx/use-filter/issues/6)) ([9f6bf0b](https://github.com/promoboxx/use-filter/commit/9f6bf0bc1be7563a1b29920a09a5794c02d506fc))
126
+
127
+ ## 1.3.0 (2021-07-18)
128
+
129
+
130
+ ### Features
131
+
132
+ * Redux store ([#5](https://github.com/promoboxx/use-filter/issues/5)) ([f92bee6](https://github.com/promoboxx/use-filter/commit/f92bee6417f78117ab9ca4936c23b24647aac008))
133
+
134
+ ### 1.2.1 (2021-07-17)
135
+
136
+
137
+ ### Bug Fixes
138
+
139
+ * some git stuff is needed ([2bb0f21](https://github.com/promoboxx/use-filter/commit/2bb0f2117c79fd1ba0b6a309db4234caf162f57b))
140
+
141
+ ## 1.2.0 (2021-07-16)
142
+
143
+
144
+ ### Features
145
+
146
+ * Add localStorageStore ([#4](https://github.com/promoboxx/use-filter/issues/4)) ([a6087e2](https://github.com/promoboxx/use-filter/commit/a6087e2f07a3640799b840e128b96838cd8ef150))
147
+
148
+ ## 1.1.0 (2021-07-16)
149
+
150
+
151
+ ### Features
152
+
153
+ * Add concept of data to useFilter ([#2](https://github.com/promoboxx/use-filter/issues/2)) ([563c5a9](https://github.com/promoboxx/use-filter/commit/563c5a959cdc22a0f8eba9dbb3dde7802df02b46))
154
+
155
+ ### 1.0.6 (2021-07-16)
156
+
157
+
158
+ ### Bug Fixes
159
+
160
+ * dont deploy test files ([500151c](https://github.com/promoboxx/use-filter/commit/500151c04f75139c71baf29b2ad2dccefcd57db7))
161
+
162
+ ### 1.0.5 (2021-07-16)
163
+
164
+
165
+ ### Bug Fixes
166
+
167
+ * declaration files ([4ce29e4](https://github.com/promoboxx/use-filter/commit/4ce29e43469ad4ade2d222c3b09f38ad8f89ca4c))
168
+
169
+ ### 1.0.4 (2021-07-16)
170
+
171
+
172
+ ### Bug Fixes
173
+
174
+ * more release prep ([daf06ac](https://github.com/promoboxx/use-filter/commit/daf06acc94668fdc7f0905c120f5541b4b2d16e9))
175
+
176
+ ### 1.0.3 (2021-07-16)
177
+
178
+ ### 1.0.2 (2021-07-16)
179
+
180
+
181
+ ### Bug Fixes
182
+
183
+ * proper secrets syntax ([afc9fe9](https://github.com/promoboxx/use-filter/commit/afc9fe9b177dda2961d82858ef43cc481f762950))
184
+
185
+ ### 1.0.1 (2021-07-16)
package/Makefile ADDED
@@ -0,0 +1,25 @@
1
+ prepare-env:
2
+ pnpm install
3
+
4
+ prepare-when-local:
5
+ ifneq ($(CI),true)
6
+ $(MAKE) prepare-env
7
+ endif
8
+
9
+ start: test
10
+
11
+ build: prepare-when-local
12
+ rm -rf dist/
13
+ ./node_modules/.bin/tsc --noEmit
14
+ ./node_modules/.bin/eslint --max-warnings 0 --ext js,jsx,ts,tsx,mjs,cjs src/
15
+ ./node_modules/.bin/tsdown
16
+
17
+ test: prepare-when-local
18
+ ./node_modules/.bin/vitest
19
+
20
+ deploy:
21
+ ifeq ($(GITHUB_REF),refs/heads/main)
22
+ npx standard-version
23
+ git push origin --tags HEAD
24
+ npm publish
25
+ endif
@@ -0,0 +1,30 @@
1
+ import pbxxBase from '@promoboxx/eslint-config'
2
+ import pbxxPrettier from '@promoboxx/eslint-config/prettier'
3
+ import pbxxReact from '@promoboxx/eslint-config/react'
4
+
5
+ /** @type {import('eslint').Linter.Config[]} */
6
+ const config = [
7
+ ...pbxxBase,
8
+ ...pbxxPrettier,
9
+ ...pbxxReact,
10
+
11
+ {
12
+ files: ['**/*.test.{ts,tsx}'],
13
+ rules: {
14
+ '@typescript-eslint/no-non-null-assertion': 'off',
15
+ },
16
+ },
17
+
18
+ // TODO This project is old, and while it is a library, has way too many
19
+ // `any` and casts. Disabled for now, but should be re-enabled and fixed up
20
+ // over time.
21
+ {
22
+ files: ['**/*.{js,jsx,ts,tsx}'],
23
+ rules: {
24
+ '@typescript-eslint/no-explicit-any': 'off',
25
+ '@typescript-eslint/consistent-type-assertions': 'off',
26
+ },
27
+ },
28
+ ]
29
+
30
+ export default config
package/mise.toml ADDED
@@ -0,0 +1,3 @@
1
+ [tools]
2
+ node = "24.16.0"
3
+ pnpm = "11.5.0"
package/package.json CHANGED
@@ -1,55 +1,45 @@
1
1
  {
2
2
  "name": "@promoboxx/use-filter",
3
- "version": "1.11.1",
3
+ "version": "2.0.0",
4
4
  "description": "",
5
- "main": "dist/useFilter.js",
5
+ "main": "./dist/cjs/useFilter.js",
6
+ "module": "./dist/esm/useFilter.mjs",
6
7
  "keywords": [],
7
8
  "author": "",
8
9
  "license": "ISC",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/esm/useFilter.mjs",
13
+ "require": "./dist/cjs/useFilter.js"
14
+ },
15
+ "./store": {
16
+ "import": "./dist/esm/store/index.mjs",
17
+ "require": "./dist/cjs/store/index.js"
18
+ },
19
+ "./*": {
20
+ "import": "./dist/esm/*.mjs",
21
+ "require": "./dist/cjs/*.js"
22
+ }
23
+ },
9
24
  "devDependencies": {
10
- "@promoboxx/eslint-config": "^2.3.0",
11
- "@testing-library/react": "^12.0.0",
12
- "@types/jest": "^26.0.24",
13
- "@types/qs": "^6.9.7",
14
- "@types/react": "^17.0.14",
15
- "@types/redux": "^3.6.0",
16
- "eslint": "^7.30.0",
17
- "jest": "^27.0.6",
18
- "prettier": "^2.3.2",
19
- "react": "^17.0.2",
20
- "react-dom": "^17.0.2",
21
- "ts-jest": "^27.0.3",
22
- "typescript": "^4.3.5"
25
+ "@promoboxx/eslint-config": "^4.0.4",
26
+ "@testing-library/react": "^16.3.2",
27
+ "@types/qs": "^6.9.8",
28
+ "@types/react": "^19.2.15",
29
+ "eslint": "^9.39.4",
30
+ "jsdom": "^29.1.1",
31
+ "prettier": "^3.0.3",
32
+ "react": "^19.2.6",
33
+ "react-dom": "^19.2.6",
34
+ "redux": "^5.0.1",
35
+ "tsdown": "^0.22.1",
36
+ "typescript": "^6.0.3",
37
+ "vitest": "^4.1.7"
23
38
  },
24
- "files": [
25
- "dist/lib/getOffsetFromPage.d.ts",
26
- "dist/lib/getPageFromOffset.d.ts",
27
- "dist/lib/getPageFromOffset.js",
28
- "dist/lib/shallowEqual.d.ts",
29
- "dist/lib/shallowEqual.js",
30
- "dist/lib/buildDefaultFilterInfo.d.ts",
31
- "dist/lib/getOffsetFromPage.js",
32
- "dist/lib/buildDefaultFilterInfo.js",
33
- "dist/useFilter.d.ts",
34
- "dist/useFilter.js",
35
- "dist/useSimpleFilter.d.ts",
36
- "dist/useSimpleFilter.js",
37
- "dist/store/memoryStore.d.ts",
38
- "dist/store/reduxStore.d.ts",
39
- "dist/store/localStorageStore.d.ts",
40
- "dist/store/reduxHelpers/createReducer.d.ts",
41
- "dist/store/reduxHelpers/createActions.d.ts",
42
- "dist/store/reduxHelpers/createActions.js",
43
- "dist/store/reduxHelpers/createReducer.js",
44
- "dist/store/index.d.ts",
45
- "dist/store/index.js",
46
- "dist/store/localStorageStore.js",
47
- "dist/store/urlParamStore.d.ts",
48
- "dist/store/urlParamStore.js",
49
- "dist/store/memoryStore.js",
50
- "dist/store/reduxStore.js"
51
- ],
52
39
  "dependencies": {
53
40
  "qs": "^6.11.2"
41
+ },
42
+ "peerDependencies": {
43
+ "react": ">=16.8.0"
54
44
  }
55
45
  }
@@ -0,0 +1,3 @@
1
+ import config from '@promoboxx/eslint-config/prettier.config'
2
+
3
+ export default config
@@ -0,0 +1,36 @@
1
+ import type { FilterInfo } from '../useFilter'
2
+
3
+ import getOffsetFromPage from './getOffsetFromPage'
4
+ import getPageFromOffset from './getPageFromOffset'
5
+
6
+ function buildDefaultFilterInfo<T extends Record<string, unknown>>(
7
+ filterInfo: Partial<FilterInfo<T>> = {},
8
+ ): FilterInfo<T> {
9
+ const merged: FilterInfo<T> = {
10
+ // Cast here to work around "'T' could be instantiated with an arbitrary
11
+ // type which could be unrelated to '{}'"
12
+ filter: {} as T,
13
+
14
+ sort: undefined,
15
+ pageSize: 20,
16
+ lastRefreshAt: new Date().getTime(),
17
+ totalResults: 1,
18
+ totalPages: 1,
19
+ offset: 0,
20
+ page: 1,
21
+ shouldRunImmediately: false,
22
+ ...filterInfo,
23
+ }
24
+
25
+ // If there's a page but no offset, set the offset.
26
+ if (filterInfo.page != null && filterInfo.offset == null) {
27
+ merged.offset = getOffsetFromPage(filterInfo.page, merged.pageSize)
28
+ // If there's an offset but no page, set the page.
29
+ } else if (filterInfo.page == null && filterInfo.offset != null) {
30
+ merged.page = getPageFromOffset(filterInfo.offset, merged.pageSize)
31
+ }
32
+
33
+ return merged
34
+ }
35
+
36
+ export default buildDefaultFilterInfo
@@ -0,0 +1,5 @@
1
+ function getOffsetFromPage(page: number, pageSize: number) {
2
+ return pageSize * (page - 1)
3
+ }
4
+
5
+ export default getOffsetFromPage
@@ -0,0 +1,5 @@
1
+ function getPageFromOffset(offset: number, pageSize: number) {
2
+ return Math.floor(offset / pageSize) + 1
3
+ }
4
+
5
+ export default getPageFromOffset
@@ -0,0 +1,71 @@
1
+ import shallowEqual from './shallowEqual'
2
+
3
+ describe('shallowEqual', () => {
4
+ it('should return true if arguments fields are equal', () => {
5
+ expect(
6
+ shallowEqual({ a: 1, b: 2, c: undefined }, { a: 1, b: 2, c: undefined }),
7
+ ).toBe(true)
8
+
9
+ expect(shallowEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 })).toBe(true)
10
+
11
+ const o = {}
12
+ expect(shallowEqual({ a: 1, b: 2, c: o }, { a: 1, b: 2, c: o })).toBe(true)
13
+
14
+ const d = function () {
15
+ return 1
16
+ }
17
+ expect(shallowEqual({ a: 1, b: 2, c: o, d }, { a: 1, b: 2, c: o, d })).toBe(
18
+ true,
19
+ )
20
+ })
21
+
22
+ it('should return false if arguments fields are different function identities', () => {
23
+ expect(
24
+ shallowEqual(
25
+ {
26
+ a: 1,
27
+ b: 2,
28
+ d() {
29
+ return 1
30
+ },
31
+ },
32
+ {
33
+ a: 1,
34
+ b: 2,
35
+ d() {
36
+ return 1
37
+ },
38
+ },
39
+ ),
40
+ ).toBe(false)
41
+ })
42
+
43
+ it('should return false if first argument has too many keys', () => {
44
+ expect(shallowEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2 })).toBe(false)
45
+ })
46
+
47
+ it('should return false if second argument has too many keys', () => {
48
+ expect(shallowEqual({ a: 1, b: 2 }, { a: 1, b: 2, c: 3 })).toBe(false)
49
+ })
50
+
51
+ it('should return false if arguments have different keys', () => {
52
+ expect(
53
+ shallowEqual({ a: 1, b: 2, c: undefined }, { a: 1, bb: 2, c: undefined }),
54
+ ).toBe(false)
55
+ })
56
+
57
+ it('should compare two NaN values', () => {
58
+ expect(shallowEqual(NaN, NaN)).toBe(true)
59
+ })
60
+
61
+ it('should compare empty objects, with false', () => {
62
+ expect(shallowEqual({}, false)).toBe(false)
63
+ expect(shallowEqual(false, {})).toBe(false)
64
+ expect(shallowEqual([], false)).toBe(false)
65
+ expect(shallowEqual(false, [])).toBe(false)
66
+ })
67
+
68
+ it('should compare two zero values', () => {
69
+ expect(shallowEqual(0, 0)).toBe(true)
70
+ })
71
+ })
@@ -0,0 +1,26 @@
1
+ const shallowEqual = (objA: any, objB: any) => {
2
+ if (Object.is(objA, objB)) {
3
+ return true
4
+ }
5
+
6
+ if (typeof objA !== 'object' || !objA || typeof objB !== 'object' || !objB) {
7
+ return false
8
+ }
9
+
10
+ const keysA = Object.keys(objA)
11
+ const keysB = Object.keys(objB)
12
+
13
+ if (keysA.length !== keysB.length) {
14
+ return false
15
+ }
16
+
17
+ for (const key of keysA) {
18
+ if (!Object.is(objA[key], objB[key])) {
19
+ return false
20
+ }
21
+ }
22
+
23
+ return true
24
+ }
25
+
26
+ export default shallowEqual
@@ -0,0 +1,30 @@
1
+ import type { FilterInfo } from '../useFilter'
2
+
3
+ export interface FilterStore {
4
+ getFilter<TFilter extends Record<string, unknown>>(
5
+ namespace: string,
6
+ ): FilterInfo<TFilter> | null | undefined
7
+ saveFilter<TFilter extends Record<string, unknown>>(
8
+ namespace: string,
9
+ filter: FilterInfo<TFilter>,
10
+ ): void
11
+ getData<TResult = any>(namespace: string): TResult | null | undefined
12
+ saveData<TResult = any>(namespace: string, data: TResult): void
13
+ clear(): void
14
+ }
15
+
16
+ let globalStore: FilterStore | undefined
17
+
18
+ export function setFilterStore(newStore: FilterStore) {
19
+ globalStore = newStore
20
+ }
21
+
22
+ export function getFilterStore(optionalStore?: FilterStore) {
23
+ const resolvedStore = optionalStore || globalStore
24
+
25
+ if (!resolvedStore) {
26
+ throw new Error('A store must be set with setFilterStore')
27
+ }
28
+
29
+ return resolvedStore
30
+ }
@@ -0,0 +1,36 @@
1
+ import type { FilterStore } from '.'
2
+
3
+ const prefix = 'useFilter'
4
+
5
+ const localStorageStore: FilterStore = {
6
+ getFilter(namespace) {
7
+ const item = localStorage.getItem(`${prefix}/${namespace}/filter`)
8
+ if (item) {
9
+ return JSON.parse(item)
10
+ }
11
+ },
12
+ saveFilter(namespace, filter) {
13
+ localStorage.setItem(
14
+ `${prefix}/${namespace}/filter`,
15
+ JSON.stringify(filter),
16
+ )
17
+ },
18
+ getData(namespace) {
19
+ const item = localStorage.getItem(`${prefix}/${namespace}/data`)
20
+ if (item) {
21
+ return JSON.parse(item)
22
+ }
23
+ },
24
+ saveData(namespace, data) {
25
+ localStorage.setItem(`${prefix}/${namespace}/data`, JSON.stringify(data))
26
+ },
27
+ clear() {
28
+ for (const key in localStorage) {
29
+ if (key.startsWith(prefix)) {
30
+ localStorage.removeItem(key)
31
+ }
32
+ }
33
+ },
34
+ }
35
+
36
+ export default localStorageStore
@@ -0,0 +1,27 @@
1
+ import type { FilterInfo } from '../useFilter'
2
+
3
+ import type { FilterStore } from '.'
4
+
5
+ let cachedFilters: Record<string, FilterInfo<any>> = {}
6
+ let cachedData: Record<string, any> = {}
7
+
8
+ const memoryStore: FilterStore = {
9
+ getFilter(namespace) {
10
+ return cachedFilters[namespace]
11
+ },
12
+ saveFilter(namespace, filter) {
13
+ cachedFilters[namespace] = filter
14
+ },
15
+ getData(namespace) {
16
+ return cachedData[namespace]
17
+ },
18
+ saveData(namespace, data) {
19
+ cachedData[namespace] = data
20
+ },
21
+ clear() {
22
+ cachedFilters = {}
23
+ cachedData = {}
24
+ },
25
+ }
26
+
27
+ export default memoryStore
@@ -0,0 +1,32 @@
1
+ import createActions from './createActions'
2
+
3
+ describe('createActions', () => {
4
+ it('creates actions using payload builders', () => {
5
+ const actions = createActions('test', {
6
+ action1: () => undefined,
7
+ action2: () => 'asdf',
8
+ action3: (arg1: number, arg2: string) => ({ arg1, arg2 }),
9
+ })
10
+
11
+ expect(actions.action1.actionType).toEqual('test/action1')
12
+ expect(actions.action1()).toEqual({
13
+ type: 'test/action1',
14
+ payload: undefined,
15
+ })
16
+
17
+ expect(actions.action2.actionType).toEqual('test/action2')
18
+ expect(actions.action2()).toEqual({
19
+ type: 'test/action2',
20
+ payload: 'asdf',
21
+ })
22
+
23
+ expect(actions.action3.actionType).toEqual('test/action3')
24
+ expect(actions.action3(42, 'foo')).toEqual({
25
+ type: 'test/action3',
26
+ payload: {
27
+ arg1: 42,
28
+ arg2: 'foo',
29
+ },
30
+ })
31
+ })
32
+ })