@synnaxlabs/drift 0.5.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/LICENSE +4 -0
- package/README.md +162 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
Source code in this repository is licensed under the Business Source License 1.1 (BSL).
|
|
2
|
+
A copy of the license can be found in the licenses/BSL.txt file. Source code in a given
|
|
3
|
+
file is licensed under the BSL and the copyright belongs to Synnax Labs, Inc. unless
|
|
4
|
+
otherwise noted at the beginning of the file.
|
package/README.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Drift - Redux State Synchronization and Declarative Window Management
|
|
2
|
+
|
|
3
|
+
# Summary
|
|
4
|
+
|
|
5
|
+
Building multi-window applications with Tauri and Electron raises the challenge of
|
|
6
|
+
synchronizing state between windows. Communicating over IPC is unintuitive when used in
|
|
7
|
+
combination with stateful UI frameworks like React.
|
|
8
|
+
|
|
9
|
+
Drift is a simple Redux extension that tightly synchronizes state between windows.
|
|
10
|
+
It also allows you to create, delete, and alter windows by dispatching actions.
|
|
11
|
+
|
|
12
|
+
What's more, Drift can prerender windows in the background, allowing new windows to be
|
|
13
|
+
ready to display in a fraction of the typical time.
|
|
14
|
+
|
|
15
|
+
Drift was inspired by the now
|
|
16
|
+
unmaintained [Electron Redux](https://github.com/klarna/electron-redux),
|
|
17
|
+
and exposes a much simpler, more powerful API.
|
|
18
|
+
|
|
19
|
+
# Supported Runtimes
|
|
20
|
+
|
|
21
|
+
| Runtime | Supported | Import |
|
|
22
|
+
|----------|---------------------------------------------------------------------------|----------------------------------------------------------|
|
|
23
|
+
| Tauri | Yes | `import { TauriRuntime } from "@synnaxlabs/drift/tauri"` |
|
|
24
|
+
| Electron | No. We're looking for someone to add Electron support! Please contribute. | TBA |
|
|
25
|
+
|
|
26
|
+
# Installation
|
|
27
|
+
|
|
28
|
+
With NPM:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @synnaxlabs/drift
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
With Yarn:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
yarn add @synnaxlabs/drift
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
With PNPM:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pnpm add @synnaxlabs/drift
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
# Usage
|
|
47
|
+
|
|
48
|
+
## Configuration
|
|
49
|
+
|
|
50
|
+
The first step is to reconfigure your store to support Drift. Drift exposes a custom
|
|
51
|
+
`configureStore` function returns a **promise** that resolves to a Redux store. This
|
|
52
|
+
allows Drift to asynchronously fetch the initial state from the main process. In order
|
|
53
|
+
to add declarative window management, you also need to add Drift's custom `reducer`
|
|
54
|
+
to your store.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// store configuration file
|
|
58
|
+
|
|
59
|
+
import {
|
|
60
|
+
reducer as driftReducer,
|
|
61
|
+
configureStore,
|
|
62
|
+
DRIFT_SLICE_NAME,
|
|
63
|
+
TauriRuntime,
|
|
64
|
+
} from "@synnaxlabs/drift"
|
|
65
|
+
|
|
66
|
+
import {combineReducers} from "@reduxjs/toolkit"
|
|
67
|
+
|
|
68
|
+
const reducer = combineReducers({
|
|
69
|
+
[DRIFT_SLICE_NAME]: driftReducer,
|
|
70
|
+
// ... your other reducers
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
export const storePromise = configureStore({
|
|
74
|
+
runtime: new TauriRuntime(),
|
|
75
|
+
reducer,
|
|
76
|
+
enablePrerender: true,
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Next, we've created a custom `Provider` that automatically resolves the store promise
|
|
81
|
+
and works exactly like the standard Redux `Provider`.
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
// in your main application file
|
|
85
|
+
|
|
86
|
+
import {Provider} from "@synnaxlabs/drift/react"
|
|
87
|
+
import {storePromise} from "./store"
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<Provider store={storePromise}>
|
|
91
|
+
{/* Your stateful application code*/}
|
|
92
|
+
</Provider>
|
|
93
|
+
)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
State should now be synchronized between all of your Windows!
|
|
97
|
+
|
|
98
|
+
## Managing Windows
|
|
99
|
+
|
|
100
|
+
Creating a Window is as easy as dispatching a `createWindow` action.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import {useDispatch} from "react-redux";
|
|
104
|
+
import {createWindow} from "@synnaxlabs/drift"
|
|
105
|
+
import {useEffect} from "react";
|
|
106
|
+
|
|
107
|
+
export const MyReactComponent = () => {
|
|
108
|
+
const dispatch = useDispatch()
|
|
109
|
+
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
dispatch(createWindow({
|
|
112
|
+
key: "exampleWindow",
|
|
113
|
+
title: "Example Window",
|
|
114
|
+
width: 800,
|
|
115
|
+
height: 600,
|
|
116
|
+
}))
|
|
117
|
+
}, [dispatch])
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The `key` property is used to uniquely identify the window. If a window with the same
|
|
125
|
+
key already exists, Drift will focus that window instead of creating a new one.
|
|
126
|
+
|
|
127
|
+
You can also dispatch a `closeWindow` action to close a window.
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import {useDispatch} from "react-redux";
|
|
131
|
+
import {closeWindow} from "@synnaxlabs/drift"
|
|
132
|
+
import {useEffect} from "react";
|
|
133
|
+
|
|
134
|
+
export const MyReactComponent = () => {
|
|
135
|
+
const dispatch = useDispatch()
|
|
136
|
+
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
dispatch(closeWindow({key: "exampleWindow"}))
|
|
139
|
+
}, [dispatch])
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Accessing Window State
|
|
146
|
+
|
|
147
|
+
Drift also provides selectors for accessing Window state in React.
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
import {useEffect} from "react;
|
|
151
|
+
import {useSelectWindow} from "@synnaxlabs/drift";
|
|
152
|
+
|
|
153
|
+
export const MyReactComponent = () => {
|
|
154
|
+
// Providing a key is optional. If no key is provided, the current window is selected.
|
|
155
|
+
const window = useSelectWindow()
|
|
156
|
+
|
|
157
|
+
useEffect(() => {
|
|
158
|
+
console.log(window)
|
|
159
|
+
}, [window])
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@synnaxlabs/drift",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.5.0",
|
|
5
|
+
"description": "State synchronization and Redux state synchronization for Tauri Apps",
|
|
6
|
+
"repository": "https://github.com/synnaxlabs/synnax/tree/main/drift",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"synnax",
|
|
11
|
+
"tauri",
|
|
12
|
+
"redux",
|
|
13
|
+
"react",
|
|
14
|
+
"electron",
|
|
15
|
+
"application level state"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@synnaxlabs/x": "0.10.0"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"@reduxjs/toolkit": "^2.2.0",
|
|
25
|
+
"@tauri-apps/api": "^1.5.3",
|
|
26
|
+
"proxy-memoize": "1.2.0",
|
|
27
|
+
"react": "^18.2.0",
|
|
28
|
+
"react-dom": "^18.2.0",
|
|
29
|
+
"react-redux": "^9.1.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@reduxjs/toolkit": "^2.2.0",
|
|
33
|
+
"@tauri-apps/api": "^1.5.3",
|
|
34
|
+
"@types/react": "^18.2.48",
|
|
35
|
+
"@vitest/coverage-v8": "^1.2.2",
|
|
36
|
+
"proxy-memoize": "1.2.0",
|
|
37
|
+
"react": "^18.2.0",
|
|
38
|
+
"react-dom": "^18.2.0",
|
|
39
|
+
"react-redux": "^9.1.0",
|
|
40
|
+
"typescript": "^5.3.3",
|
|
41
|
+
"vite": "^5.1.2",
|
|
42
|
+
"vite-plugin-lib": "^2.0.6",
|
|
43
|
+
"vitest": "^1.2.1",
|
|
44
|
+
"eslint-config-synnaxlabs": "0.0.1",
|
|
45
|
+
"@synnaxlabs/vite-plugin": "0.0.1",
|
|
46
|
+
"@synnaxlabs/tsconfig": "0.0.2"
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
"dist"
|
|
50
|
+
],
|
|
51
|
+
"main": "./dist/drift.cjs.js",
|
|
52
|
+
"module": "./dist/drift.es.js",
|
|
53
|
+
"types": "./dist/index.d.ts",
|
|
54
|
+
"exports": {
|
|
55
|
+
".": {
|
|
56
|
+
"import": "./dist/index.js",
|
|
57
|
+
"require": "./dist/index.cjs",
|
|
58
|
+
"types": "./dist/index.d.ts"
|
|
59
|
+
},
|
|
60
|
+
"./react": {
|
|
61
|
+
"import": "./dist/react.js",
|
|
62
|
+
"require": "./dist/react.cjs",
|
|
63
|
+
"types": "./dist/react/index.d.ts"
|
|
64
|
+
},
|
|
65
|
+
"./tauri": {
|
|
66
|
+
"import": "./dist/tauri.js",
|
|
67
|
+
"require": "./dist/tauri.cjs",
|
|
68
|
+
"types": "./dist/tauri/index.d.ts"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"scripts": {
|
|
72
|
+
"build": "tsc --noEmit && vite build",
|
|
73
|
+
"watch": "tsc --noEmit && vite build --watch",
|
|
74
|
+
"test": "vitest",
|
|
75
|
+
"cov": "vitest --coverage",
|
|
76
|
+
"lint": "eslint \"src/**/*.ts*\"",
|
|
77
|
+
"fix": "eslint \"src/**/*.ts*\" --fix"
|
|
78
|
+
}
|
|
79
|
+
}
|