Compare commits
70 Commits
jazz-react
...
cojson@0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ae0b8df0d | ||
|
|
77dc51d466 | ||
|
|
bd645db4cc | ||
|
|
af46c68a4a | ||
|
|
fb58cb9299 | ||
|
|
63fb80e50d | ||
|
|
133b8abcbe | ||
|
|
6209bd2285 | ||
|
|
d8d1addf2b | ||
|
|
937a34c76e | ||
|
|
15996ced64 | ||
|
|
9fb98e2114 | ||
|
|
f55f779ea1 | ||
|
|
18c98fc3f5 | ||
|
|
41b286b672 | ||
|
|
ba944c20ed | ||
|
|
0b89fadfdd | ||
|
|
1e50cebf55 | ||
|
|
ca8c5c0b02 | ||
|
|
a0aa261cab | ||
|
|
5d3d11e87c | ||
|
|
4a9ed21ea2 | ||
|
|
2ddfc9d92b | ||
|
|
a032fda936 | ||
|
|
c6fb8dc845 | ||
|
|
69499e3965 | ||
|
|
d67ced14c4 | ||
|
|
95ae69ead2 | ||
|
|
4170f13858 | ||
|
|
45e4a77afb | ||
|
|
603538e255 | ||
|
|
afb49f3666 | ||
|
|
c6de2ce8b8 | ||
|
|
cdc4229df7 | ||
|
|
fa19f7471f | ||
|
|
75f3af2cc1 | ||
|
|
5ae77ee57e | ||
|
|
88ea30a6f8 | ||
|
|
f4cbe395d5 | ||
|
|
c59fb5dc1f | ||
|
|
c712ef28e8 | ||
|
|
c62a4a1c69 | ||
|
|
87a7cf202f | ||
|
|
9a9b424ff2 | ||
|
|
dfe6146aa3 | ||
|
|
8b26728914 | ||
|
|
f5003ac8ec | ||
|
|
ee71ba99e2 | ||
|
|
d28ce598e2 | ||
|
|
14475991c8 | ||
|
|
15d9ec4b38 | ||
|
|
f911545ae3 | ||
|
|
ad71530cc0 | ||
|
|
c33c02691f | ||
|
|
51c19770a8 | ||
|
|
5c2c7d4188 | ||
|
|
334d27d53d | ||
|
|
a5396a42ce | ||
|
|
5cfe38d547 | ||
|
|
3f7aa34726 | ||
|
|
008750d401 | ||
|
|
72708f82ea | ||
|
|
30f65f1c91 | ||
|
|
67d55ce0ee | ||
|
|
e887f37713 | ||
|
|
82a515d493 | ||
|
|
bd94012507 | ||
|
|
e1dbab1517 | ||
|
|
dafea6039b | ||
|
|
ccc5f89ed7 |
@@ -1,5 +1,38 @@
|
||||
# chat-rn-expo-clerk
|
||||
|
||||
## 1.0.109
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-expo@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
- jazz-react-native-media-images@0.13.17
|
||||
|
||||
## 1.0.108
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-expo@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
- jazz-react-native-media-images@0.13.16
|
||||
|
||||
## 1.0.107
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-expo@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
- jazz-react-native-media-images@0.13.15
|
||||
|
||||
## 1.0.106
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [bd94012]
|
||||
- jazz-expo@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
- jazz-react-native-media-images@0.13.14
|
||||
|
||||
## 1.0.105
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "chat-rn-expo-clerk",
|
||||
"main": "index.js",
|
||||
"version": "1.0.105",
|
||||
"version": "1.0.109",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
"start": "expo start",
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
# chat-rn-expo
|
||||
|
||||
## 1.0.96
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-expo@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 1.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-expo@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 1.0.94
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-expo@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 1.0.93
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [bd94012]
|
||||
- jazz-expo@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 1.0.92
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn-expo",
|
||||
"version": "1.0.92",
|
||||
"version": "1.0.96",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
|
||||
@@ -1,5 +1,46 @@
|
||||
# chat-rn
|
||||
|
||||
## 1.0.104
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9fb98e2]
|
||||
- Updated dependencies [0b89fad]
|
||||
- cojson@0.13.17
|
||||
- cojson-transport-ws@0.13.17
|
||||
- jazz-react-native@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 1.0.103
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c6fb8dc]
|
||||
- cojson@0.13.16
|
||||
- cojson-transport-ws@0.13.16
|
||||
- jazz-react-native@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 1.0.102
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c712ef2]
|
||||
- cojson@0.13.15
|
||||
- cojson-transport-ws@0.13.15
|
||||
- jazz-react-native@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 1.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5c2c7d4]
|
||||
- cojson@0.13.14
|
||||
- cojson-transport-ws@0.13.14
|
||||
- jazz-react-native@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 1.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn",
|
||||
"version": "1.0.100",
|
||||
"version": "1.0.104",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"android": "react-native run-android",
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# chat-vue
|
||||
|
||||
## 0.0.88
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
- jazz-vue@0.13.17
|
||||
|
||||
## 0.0.87
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
- jazz-vue@0.13.16
|
||||
|
||||
## 0.0.86
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
- jazz-vue@0.13.15
|
||||
|
||||
## 0.0.85
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
- jazz-vue@0.13.14
|
||||
|
||||
## 0.0.84
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-vue",
|
||||
"version": "0.0.84",
|
||||
"version": "0.0.88",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.186
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.17
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.185
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.16
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.184
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.15
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.183
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.14
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.182
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat",
|
||||
"private": true,
|
||||
"version": "0.0.182",
|
||||
"version": "0.0.186",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# minimal-auth-clerk
|
||||
|
||||
## 0.0.85
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-react-auth-clerk@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.84
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-react-auth-clerk@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.83
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-react-auth-clerk@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-react-auth-clerk@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.81
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "clerk",
|
||||
"private": true,
|
||||
"version": "0.0.81",
|
||||
"version": "0.0.85",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# file-share-svelte
|
||||
|
||||
## 0.0.68
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.67
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.66
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.65
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.64
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "file-share-svelte",
|
||||
"version": "0.0.64",
|
||||
"version": "0.0.68",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# jazz-tailwind-demo-auth-starter
|
||||
|
||||
## 0.0.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.17
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.24
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.16
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.23
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.15
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.22
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.14
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "filestream",
|
||||
"private": true,
|
||||
"version": "0.0.21",
|
||||
"version": "0.0.25",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# form
|
||||
|
||||
## 0.1.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.1.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.1.24
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.1.23
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.1.22
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "form",
|
||||
"private": true,
|
||||
"version": "0.1.22",
|
||||
"version": "0.1.26",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# image-upload
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.81
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.80
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.79
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.78
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "image-upload",
|
||||
"private": true,
|
||||
"version": "0.0.78",
|
||||
"version": "0.0.82",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,42 @@
|
||||
# jazz-example-inspector
|
||||
|
||||
## 0.0.136
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9fb98e2]
|
||||
- Updated dependencies [0b89fad]
|
||||
- cojson@0.13.17
|
||||
- cojson-transport-ws@0.13.17
|
||||
- jazz-inspector@0.13.17
|
||||
|
||||
## 0.0.135
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c6fb8dc]
|
||||
- cojson@0.13.16
|
||||
- cojson-transport-ws@0.13.16
|
||||
- jazz-inspector@0.13.16
|
||||
|
||||
## 0.0.134
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c712ef2]
|
||||
- cojson@0.13.15
|
||||
- cojson-transport-ws@0.13.15
|
||||
- jazz-inspector@0.13.15
|
||||
|
||||
## 0.0.133
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5c2c7d4]
|
||||
- cojson@0.13.14
|
||||
- cojson-transport-ws@0.13.14
|
||||
- jazz-inspector@0.13.14
|
||||
|
||||
## 0.0.132
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-inspector-app",
|
||||
"private": true,
|
||||
"version": "0.0.132",
|
||||
"version": "0.0.136",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
"dev:worker": "tsx --watch --env-file=.env ./src/worker.ts",
|
||||
"build": "vite build && tsc",
|
||||
"serve": "vite preview",
|
||||
"generate-env": "tsx generate-env.ts"
|
||||
"generate-env": "tsx generate-env.ts",
|
||||
"format-and-lint": "biome check .",
|
||||
"format-and-lint:fix": "biome check . --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-label": "^2.1.2",
|
||||
|
||||
1
examples/jazz-paper-scissors/src/apiKey.ts
Normal file
1
examples/jazz-paper-scissors/src/apiKey.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const apiKey = "jazz-paper-scissors@garden.co";
|
||||
@@ -3,6 +3,7 @@ import { StrictMode } from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
|
||||
import "./index.css";
|
||||
import { apiKey } from "@/apiKey.ts";
|
||||
import { JazzProvider } from "jazz-react";
|
||||
import { App } from "./app";
|
||||
|
||||
@@ -13,7 +14,7 @@ if (rootElement && !rootElement.innerHTML) {
|
||||
<StrictMode>
|
||||
<JazzProvider
|
||||
sync={{
|
||||
peer: "wss://cloud.jazz.tools/?key=jazz-paper-scissors@garden.co",
|
||||
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
||||
}}
|
||||
>
|
||||
<JazzInspector />
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
|
||||
import { Route as rootRoute } from "./routes/__root";
|
||||
import { Route as AuthenticatedImport } from "./routes/_authenticated";
|
||||
import { Route as IndexImport } from "./routes/index";
|
||||
import { Route as AuthenticatedWaitingRoomWaitingRoomIdImport } from "./routes/_authenticated/waiting-room.$waitingRoomId";
|
||||
import { Route as AuthenticatedGameGameIdImport } from "./routes/_authenticated/game.$gameId";
|
||||
import { Route as AuthenticatedWaitingRoomWaitingRoomIdImport } from "./routes/_authenticated/waiting-room.$waitingRoomId";
|
||||
import { Route as IndexImport } from "./routes/index";
|
||||
|
||||
// Create/Update Routes
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ export const Route = createFileRoute("/_authenticated/game/$gameId")({
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { gameId, me, loaderGame } = Route.useLoaderData();
|
||||
const { gameId, loaderGame } = Route.useLoaderData();
|
||||
|
||||
const isPlayer1 = loaderGame.player1?.account?.isMe;
|
||||
const player = isPlayer1 ? "player1" : "player2";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Account, CoMap, SchemaUnion, co } from "jazz-tools";
|
||||
import { Account, CoMap, co } from "jazz-tools";
|
||||
|
||||
export class Game extends CoMap {
|
||||
player1 = co.ref(Player);
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# multi-cursors
|
||||
|
||||
## 0.0.78
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.77
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.76
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.75
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.74
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "multi-cursors",
|
||||
"private": true,
|
||||
"version": "0.0.74",
|
||||
"version": "0.0.78",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# multiauth
|
||||
|
||||
## 0.0.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-react-auth-clerk@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-react-auth-clerk@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.24
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-react-auth-clerk@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.23
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-react-auth-clerk@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.22
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "multiauth",
|
||||
"private": true,
|
||||
"version": "0.0.22",
|
||||
"version": "0.0.26",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# jazz-example-musicplayer
|
||||
|
||||
## 0.0.107
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.17
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.106
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.16
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.105
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.15
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.104
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.14
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.103
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-music-player",
|
||||
"private": true,
|
||||
"version": "0.0.103",
|
||||
"version": "0.0.107",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# organization
|
||||
|
||||
## 0.0.78
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.77
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.76
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.75
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.74
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "organization",
|
||||
"private": true,
|
||||
"version": "0.0.74",
|
||||
"version": "0.0.78",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# passkey-svelte
|
||||
|
||||
## 0.0.72
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.71
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.70
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.69
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.68
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "passkey-svelte",
|
||||
"version": "0.0.68",
|
||||
"version": "0.0.72",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# minimal-auth-passkey
|
||||
|
||||
## 0.0.83
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.81
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.80
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.79
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passkey",
|
||||
"private": true,
|
||||
"version": "0.0.79",
|
||||
"version": "0.0.83",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# passphrase
|
||||
|
||||
## 0.0.80
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.79
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.78
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.77
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.76
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passphrase",
|
||||
"private": true,
|
||||
"version": "0.0.76",
|
||||
"version": "0.0.80",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# jazz-password-manager
|
||||
|
||||
## 0.0.104
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.103
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.102
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-password-manager",
|
||||
"private": true,
|
||||
"version": "0.0.100",
|
||||
"version": "0.0.104",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# jazz-example-pets
|
||||
|
||||
## 0.0.202
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.201
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.200
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.199
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.198
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-pets",
|
||||
"private": true,
|
||||
"version": "0.0.198",
|
||||
"version": "0.0.202",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# reactions
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.81
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.80
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.79
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.78
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "reactions",
|
||||
"private": true,
|
||||
"version": "0.0.78",
|
||||
"version": "0.0.82",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,38 @@
|
||||
# richtext
|
||||
|
||||
## 0.0.72
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [133b8ab]
|
||||
- jazz-richtext-prosemirror@0.1.6
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.71
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
- jazz-richtext-prosemirror@0.1.5
|
||||
|
||||
## 0.0.70
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
- jazz-richtext-prosemirror@0.1.4
|
||||
|
||||
## 0.0.69
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
- jazz-richtext-prosemirror@0.1.3
|
||||
|
||||
## 0.0.68
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
A demonstration of collaborative rich text editing with Jazz, React, and ProseMirror.
|
||||
|
||||
Live version: [https://richtext-demo.jazz.tools](https://richtext-demo.jazz.tools)
|
||||
|
||||
## Overview
|
||||
|
||||
This example shows how to implement collaborative rich text editing using:
|
||||
@@ -16,23 +18,52 @@ The example features:
|
||||
- Side-by-side plaintext and rich text editors
|
||||
- Real-time collaboration across devices
|
||||
- Persistent document storage
|
||||
## Getting started
|
||||
|
||||
## Running locally
|
||||
You can either
|
||||
1. Clone the jazz repository, and run the app within the monorepo.
|
||||
2. Or create a new Jazz project using this example as a template.
|
||||
|
||||
Install dependencies:
|
||||
|
||||
### Using the example as a template
|
||||
|
||||
Create a new Jazz project, and use this example as a template.
|
||||
```bash
|
||||
npm i
|
||||
# or
|
||||
yarn
|
||||
npx create-jazz-app@latest richtext-app --example richtext
|
||||
```
|
||||
|
||||
Then, run the development server:
|
||||
Go to the new project directory.
|
||||
```bash
|
||||
cd richtext-app
|
||||
```
|
||||
|
||||
Run the dev server.
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
```
|
||||
|
||||
### Using the monorepo
|
||||
|
||||
This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation).
|
||||
|
||||
Clone the jazz repository.
|
||||
```bash
|
||||
git clone https://github.com/garden-co/jazz.git
|
||||
```
|
||||
|
||||
Install and build dependencies.
|
||||
```bash
|
||||
pnpm i && npx turbo build
|
||||
```
|
||||
|
||||
Go to the example directory.
|
||||
```bash
|
||||
cd jazz/examples/richtext/
|
||||
```
|
||||
|
||||
Start the dev server.
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
Open [http://localhost:5173](http://localhost:5173) with your browser to see the result.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "richtext",
|
||||
"private": true,
|
||||
"version": "0.0.68",
|
||||
"version": "0.0.72",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -19,6 +19,7 @@
|
||||
"prosemirror-example-setup": "^1.2.3",
|
||||
"prosemirror-model": "^1.25.0",
|
||||
"prosemirror-schema-basic": "^1.2.4",
|
||||
"prosemirror-schema-list": "^1.5.1",
|
||||
"prosemirror-state": "^1.4.3",
|
||||
"prosemirror-view": "^1.39.1",
|
||||
"react": "18.3.1",
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { useAccount } from "jazz-react";
|
||||
import { createJazzPlugin } from "jazz-richtext-prosemirror";
|
||||
import { exampleSetup } from "prosemirror-example-setup";
|
||||
import { schema } from "prosemirror-schema-basic";
|
||||
import { Schema } from "prosemirror-model";
|
||||
import { schema as basicSchema } from "prosemirror-schema-basic";
|
||||
import { addListNodes } from "prosemirror-schema-list";
|
||||
import { EditorState } from "prosemirror-state";
|
||||
import { EditorView } from "prosemirror-view";
|
||||
import { useEffect, useRef } from "react";
|
||||
@@ -14,6 +16,11 @@ export function Editor() {
|
||||
useEffect(() => {
|
||||
if (!me || !editorRef.current || !me.profile.bio) return;
|
||||
|
||||
const schema = new Schema({
|
||||
nodes: addListNodes(basicSchema.spec.nodes, "paragraph block*", "block"),
|
||||
marks: basicSchema.spec.marks,
|
||||
});
|
||||
|
||||
const setupPlugins = exampleSetup({ schema });
|
||||
const jazzPlugin = createJazzPlugin(me.profile.bio);
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
.ProseMirror ul {
|
||||
@apply list-disc;
|
||||
}
|
||||
.ProseMirror ol {
|
||||
@apply list-decimal;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# todo-vue
|
||||
|
||||
## 0.0.86
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
- jazz-vue@0.13.17
|
||||
|
||||
## 0.0.85
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
- jazz-vue@0.13.16
|
||||
|
||||
## 0.0.84
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
- jazz-vue@0.13.15
|
||||
|
||||
## 0.0.83
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
- jazz-vue@0.13.14
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "todo-vue",
|
||||
"version": "0.0.82",
|
||||
"version": "0.0.86",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# jazz-example-todo
|
||||
|
||||
## 0.0.201
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.200
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.199
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.198
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.197
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-todo",
|
||||
"private": true,
|
||||
"version": "0.0.197",
|
||||
"version": "0.0.201",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# version-history
|
||||
|
||||
## 0.0.80
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.17
|
||||
- jazz-react@0.13.17
|
||||
- jazz-tools@0.13.17
|
||||
|
||||
## 0.0.79
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.16
|
||||
- jazz-react@0.13.16
|
||||
- jazz-tools@0.13.16
|
||||
|
||||
## 0.0.78
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.15
|
||||
- jazz-react@0.13.15
|
||||
- jazz-tools@0.13.15
|
||||
|
||||
## 0.0.77
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.14
|
||||
- jazz-react@0.13.14
|
||||
- jazz-tools@0.13.14
|
||||
|
||||
## 0.0.76
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "version-history",
|
||||
"private": true,
|
||||
"version": "0.0.76",
|
||||
"version": "0.0.80",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
AlertTriangleIcon,
|
||||
ArrowDownIcon,
|
||||
ArrowRightIcon,
|
||||
BoldIcon,
|
||||
BookTextIcon,
|
||||
BoxIcon,
|
||||
BracesIcon,
|
||||
@@ -20,6 +21,7 @@ import {
|
||||
HashIcon,
|
||||
ImageIcon,
|
||||
InfoIcon,
|
||||
ItalicIcon,
|
||||
LinkIcon,
|
||||
LockKeyholeIcon,
|
||||
type LucideIcon,
|
||||
@@ -87,6 +89,10 @@ const icons = {
|
||||
colist: Brackets,
|
||||
user: UserIcon,
|
||||
group: UsersIcon,
|
||||
|
||||
// text editor icons
|
||||
bold: BoldIcon,
|
||||
italic: ItalicIcon,
|
||||
};
|
||||
|
||||
// copied from tailwind line height https://tailwindcss.com/docs/font-size
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { clsx } from "clsx";
|
||||
import { useEffect, useId, useRef, useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { Icon } from "../atoms/Icon";
|
||||
|
||||
// TODO: add tabs feature, and remove CodeExampleTabs
|
||||
@@ -84,9 +84,25 @@ export function CodeGroup({
|
||||
}) {
|
||||
const textRef = useRef<HTMLPreElement | null>(null);
|
||||
const [code, setCode] = useState<string>();
|
||||
|
||||
const filterText = (node: Node): string => {
|
||||
if (
|
||||
node instanceof Element &&
|
||||
(node.classList.contains("twoslash-popup-container") ||
|
||||
node.classList.contains("twoslash-completion-cursor"))
|
||||
) {
|
||||
return "";
|
||||
}
|
||||
if (node.nodeType === Node.TEXT_NODE) {
|
||||
return node.textContent ?? "";
|
||||
}
|
||||
|
||||
return Array.from(node.childNodes).map(filterText).join("");
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (textRef.current) {
|
||||
setCode(textRef.current.innerText);
|
||||
setCode(filterText(textRef.current));
|
||||
}
|
||||
}, [children]);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { packages } from "@/content/packages";
|
||||
import { clsx } from "clsx";
|
||||
import { Icon } from "@garden-co/design-system/src/components/atoms/Icon";
|
||||
import { clsx } from "clsx";
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ import { ReactNativeLogo } from "@/components/icons/ReactNativeLogo";
|
||||
import { SvelteLogo } from "@/components/icons/SvelteLogo";
|
||||
import { VueLogo } from "@/components/icons/VueLogo";
|
||||
import { Example, features, tech } from "@/content/example";
|
||||
import { clsx } from "clsx";
|
||||
import { H2 } from "@garden-co/design-system/src/components/atoms/Headings";
|
||||
import { Icon } from "@garden-co/design-system/src/components/atoms/Icon";
|
||||
import { GappedGrid } from "@garden-co/design-system/src/components/molecules/GappedGrid";
|
||||
import { HeroHeader } from "@garden-co/design-system/src/components/molecules/HeroHeader";
|
||||
import { clsx } from "clsx";
|
||||
import type { Metadata } from "next";
|
||||
|
||||
const title = "Examples";
|
||||
@@ -198,6 +198,12 @@ const MusicIllustration = () => (
|
||||
</div>
|
||||
);
|
||||
|
||||
const JazzPaperScissorsIllustration = () => (
|
||||
<div className="flex flex-col items-center justify-center h-full p-8 text-4xl">
|
||||
✊ ✋ ✌️
|
||||
</div>
|
||||
);
|
||||
|
||||
const ImageUploadIllustration = () => (
|
||||
<div className="flex flex-col items-center justify-center h-full p-8">
|
||||
<div className="p-3 w-[12rem] h-[8rem] border border-dashed border-blue dark:border-blue-500 rounded-lg flex gap-2 flex-col items-center justify-center">
|
||||
@@ -255,21 +261,21 @@ const ReactionsIllustration = () => (
|
||||
|
||||
const MultiCursorIllustration = () => (
|
||||
<div className="flex bg-stone-100 h-full flex-col items-center justify-center dark:bg-transparent p-4">
|
||||
<div className=" bg-white md:aspect-[3/2] flex flex-col rounded-md shadow-xl shadow-stone-400/20 dark:shadow-none">
|
||||
<div className=" bg-white min-w-64 md:aspect-[3/2] flex flex-col rounded-md shadow-xl shadow-stone-400/20 dark:shadow-none">
|
||||
<div className="w-full py-2 flex items-center gap-1.5 px-2 border-b dark:border-b-stone-200">
|
||||
<span className="rounded-full size-2 bg-stone-200"></span>
|
||||
<span className="rounded-full size-2 bg-stone-200"></span>
|
||||
<span className="rounded-full size-2 bg-stone-200"></span>
|
||||
</div>
|
||||
|
||||
<div className="h-full mx-auto flex flex-col justify-center p-12 sm:p-16">
|
||||
<div className="h-full mx-auto flex flex-col justify-center p-12">
|
||||
<div className="inline-block relative px-1 ring-1 ring-blue-400">
|
||||
<div className="absolute size-2 bg-white border border-blue-400 -left-1 -top-1"></div>
|
||||
<div className="absolute size-2 bg-white border border-blue-400 -right-1 -top-1"></div>
|
||||
<div className="absolute size-2 bg-white border border-blue-400 -left-1 -bottom-1"></div>
|
||||
<div className="absolute size-2 bg-white border border-blue-400 -right-1 -bottom-1"></div>
|
||||
|
||||
<span className="text-lg font-semibold md:text-2xl md:font-bold text-stone-800 ">
|
||||
<span className="text-lg font-semibold md:text-2xl md:font-bold text-stone-800">
|
||||
Hello, world!
|
||||
</span>
|
||||
<div className="absolute -top-10 right-4 text-rose-600 flex items-end gap-1">
|
||||
@@ -285,6 +291,21 @@ const MultiCursorIllustration = () => (
|
||||
</div>
|
||||
);
|
||||
|
||||
const CoTextIllustration = () => (
|
||||
<div className="flex bg-stone-100 h-full flex-col items-center justify-center dark:bg-transparent p-4">
|
||||
<div className=" bg-white md:aspect-[3/2] min-w-64 flex flex-col rounded-md shadow-xl shadow-stone-400/20 dark:shadow-none">
|
||||
<div className="flex gap-2 p-3 border-b">
|
||||
<Icon name="bold" size="xs" />
|
||||
<Icon name="italic" size="xs" />
|
||||
<Icon name="code" size="xs" />
|
||||
</div>
|
||||
<div className="py-2 px-3 text-xl text-stone-800">
|
||||
<em>Hello</em>, <strong>world!</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const PetIllustration = () => (
|
||||
<div className="h-full p-4 bg-[url('/dog.jpg')] bg-cover bg-center p-4 flex items-end">
|
||||
<div className="inline-flex justify-center gap-1 mx-auto">
|
||||
@@ -434,9 +455,19 @@ const reactExamples: Example[] = [
|
||||
"Track user presence on a canvas with multiple cursors and out of bounds indicators.",
|
||||
tech: [tech.react],
|
||||
features: [features.coFeed],
|
||||
demoUrl: "https://jazz-multi-cursors.vercel.app",
|
||||
demoUrl: "https://multi-cursors-demo.jazz.tools",
|
||||
illustration: <MultiCursorIllustration />,
|
||||
},
|
||||
{
|
||||
name: "Collaborative rich text",
|
||||
slug: "richtext",
|
||||
description:
|
||||
"Handle multiple users editing the same text, integrated with a ProseMirror editor for rich text.",
|
||||
tech: [tech.react],
|
||||
features: [features.coRichText, features.coPlainText],
|
||||
demoUrl: "https://richtext-demo.jazz.tools",
|
||||
illustration: <CoTextIllustration />,
|
||||
},
|
||||
{
|
||||
name: "Rate my pet",
|
||||
slug: "pets",
|
||||
@@ -477,6 +508,16 @@ const reactExamples: Example[] = [
|
||||
demoUrl: "https://music-demo.jazz.tools",
|
||||
illustration: <MusicIllustration />,
|
||||
},
|
||||
{
|
||||
name: "Jazz paper scissors",
|
||||
slug: "jazz-paper-scissors",
|
||||
description:
|
||||
"A game that shows how to communicate with other accounts through the experimental Inbox API.",
|
||||
tech: [tech.react],
|
||||
features: [features.serverWorker, features.inbox],
|
||||
illustration: <JazzPaperScissorsIllustration />,
|
||||
demoUrl: "https://jazz-paper-scissors.vercel.app"
|
||||
},
|
||||
{
|
||||
name: "Clerk",
|
||||
slug: "clerk",
|
||||
@@ -511,6 +552,7 @@ const reactExamples: Example[] = [
|
||||
tech: [tech.react],
|
||||
features: [features.inviteLink],
|
||||
illustration: <OrganizationIllustration />,
|
||||
demoUrl: "https://jazz-organization.vercel.app"
|
||||
},
|
||||
{
|
||||
name: "Version history",
|
||||
@@ -519,6 +561,7 @@ const reactExamples: Example[] = [
|
||||
"Track and restore previous versions of your data, and see who made the changes.",
|
||||
tech: [tech.react],
|
||||
illustration: <VersionHistoryIllustration />,
|
||||
demoUrl: "https://jazz-version-history.vercel.app"
|
||||
},
|
||||
];
|
||||
|
||||
@@ -566,7 +609,6 @@ const vueExamples: Example[] = [
|
||||
description: "A todo list where you can collaborate with invited guests.",
|
||||
tech: [tech.vue],
|
||||
features: [features.inviteLink],
|
||||
demoUrl: "https://todo-demo.jazz.tools",
|
||||
illustration: (
|
||||
<div className="h-full w-full bg-cover bg-[url('/todo.jpg')] bg-left-bottom"></div>
|
||||
),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import LatencyChart from "@/components/LatencyChart";
|
||||
import { clsx } from "clsx";
|
||||
import { HeroHeader } from "@garden-co/design-system/src/components/molecules/HeroHeader";
|
||||
import { clsx } from "clsx";
|
||||
import type { Metadata } from "next";
|
||||
import { Fragment } from "react";
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import "./globals.css";
|
||||
import type { Metadata } from "next";
|
||||
import { fontClasses } from "@garden-co/design-system/src/fonts";
|
||||
import { ThemeProvider } from "@/components/ThemeProvider";
|
||||
import { JazzFooter } from "@/components/footer";
|
||||
import { marketingCopy } from "@/content/marketingCopy";
|
||||
import { fontClasses } from "@garden-co/design-system/src/fonts";
|
||||
import { Analytics } from "@vercel/analytics/react";
|
||||
import { SpeedInsights } from "@vercel/speed-insights/next";
|
||||
import type { Metadata } from "next";
|
||||
|
||||
const metaTags = {
|
||||
title: `Jazz - ${marketingCopy.headline}`,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { track } from "@vercel/analytics";
|
||||
import { Button } from "@garden-co/design-system/src/components/atoms/Button";
|
||||
import { track } from "@vercel/analytics";
|
||||
|
||||
export function FakeGetStartedButton({ tier }: { tier: "starter" | "indie" }) {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { clsx } from "clsx";
|
||||
import { Button } from "@garden-co/design-system/src/components/atoms/Button";
|
||||
import { clsx } from "clsx";
|
||||
import {
|
||||
CircleCheckIcon,
|
||||
LucideBuilding2,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { clsx } from "clsx";
|
||||
import { Icon } from "@garden-co/design-system/src/components/atoms/Icon";
|
||||
import { clsx } from "clsx";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { JazzNav } from "@/components/nav";
|
||||
import { clsx } from "clsx";
|
||||
import { NavSection } from "@garden-co/design-system/src/components/organisms/Nav";
|
||||
import { clsx } from "clsx";
|
||||
|
||||
export function SideNavLayout({
|
||||
children,
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
import { TableOfContents } from "@/components/docs/TableOfContents";
|
||||
import { JazzMobileNav } from "@/components/nav";
|
||||
import { TocEntry } from "@stefanprobst/rehype-extract-toc";
|
||||
import type { IconName } from "@garden-co/design-system/src/components/atoms/Icon";
|
||||
import { NavSection } from "@garden-co/design-system/src/components/organisms/Nav";
|
||||
import { TocEntry } from "@stefanprobst/rehype-extract-toc";
|
||||
|
||||
export default function DocsLayout({
|
||||
children,
|
||||
|
||||
10
homepage/homepage/components/docs/Framework.tsx
Normal file
10
homepage/homepage/components/docs/Framework.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import { frameworkNames } from "@/content/framework";
|
||||
import { useFramework } from "@/lib/use-framework";
|
||||
|
||||
export function Framework() {
|
||||
const framework = useFramework();
|
||||
|
||||
return <>{frameworkNames[framework].label}</>;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Framework } from "@/content/framework";
|
||||
import { Framework, frameworkNames } from "@/content/framework";
|
||||
import { useFramework } from "@/lib/use-framework";
|
||||
import { Button } from "@garden-co/design-system/src/components/atoms/Button";
|
||||
import { Icon } from "@garden-co/design-system/src/components/atoms/Icon";
|
||||
@@ -13,39 +13,6 @@ import {
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
const frameworks: Record<
|
||||
Framework,
|
||||
{
|
||||
label: string;
|
||||
experimental: boolean;
|
||||
}
|
||||
> = {
|
||||
[Framework.React]: {
|
||||
label: "React",
|
||||
experimental: false,
|
||||
},
|
||||
[Framework.ReactNative]: {
|
||||
label: "React Native",
|
||||
experimental: false,
|
||||
},
|
||||
[Framework.ReactNativeExpo]: {
|
||||
label: "React Native (Expo)",
|
||||
experimental: false,
|
||||
},
|
||||
[Framework.Vanilla]: {
|
||||
label: "VanillaJS",
|
||||
experimental: false,
|
||||
},
|
||||
[Framework.Svelte]: {
|
||||
label: "Svelte",
|
||||
experimental: true,
|
||||
},
|
||||
[Framework.Vue]: {
|
||||
label: "Vue",
|
||||
experimental: true,
|
||||
},
|
||||
};
|
||||
|
||||
export function FrameworkSelect() {
|
||||
const router = useRouter();
|
||||
const defaultFramework = useFramework();
|
||||
@@ -66,11 +33,11 @@ export function FrameworkSelect() {
|
||||
as={Button}
|
||||
variant="secondary"
|
||||
>
|
||||
{frameworks[selectedFramework].label}
|
||||
{frameworkNames[selectedFramework].label}
|
||||
<Icon name="chevronDown" size="sm" className="text-muted" />
|
||||
</DropdownButton>
|
||||
<DropdownMenu className="w-[--button-width] z-50" anchor="bottom start">
|
||||
{Object.entries(frameworks).map(([key, framework]) => (
|
||||
{Object.entries(frameworkNames).map(([key, framework]) => (
|
||||
<DropdownItem
|
||||
className="items-baseline"
|
||||
key={key}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import { Example } from "@/content/example";
|
||||
import { InterpolateInCode } from "@/mdx-components";
|
||||
import { DialogDescription } from "@headlessui/react";
|
||||
import { Button } from "@garden-co/design-system/src/components/atoms/Button";
|
||||
import { CodeGroup } from "@garden-co/design-system/src/components/molecules/CodeGroup";
|
||||
import {
|
||||
@@ -11,6 +10,7 @@ import {
|
||||
DialogBody,
|
||||
DialogTitle,
|
||||
} from "@garden-co/design-system/src/components/organisms/Dialog";
|
||||
import { DialogDescription } from "@headlessui/react";
|
||||
import { useState } from "react";
|
||||
import CreateJazzApp from "./CreateJazzApp.mdx";
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { CodeGroup as CodeGroupClient } from "@garden-co/design-system/src/compo
|
||||
import { AnchorHTMLAttributes, DetailedHTMLProps } from "react";
|
||||
import { FileDownloadLink as FileDownloadLinkClient } from "./FileDownloadLink";
|
||||
import { ComingSoon as ComingSoonClient } from "./docs/ComingSoon";
|
||||
import { Framework as FrameworkClient } from "./docs/Framework";
|
||||
import { IssueTrackerPreview as IssueTrackerPreviewClient } from "./docs/IssueTrackerPreview";
|
||||
|
||||
export function CodeExampleTabs(props: CodeExampleTabsProps) {
|
||||
@@ -46,3 +47,7 @@ export function FileDownloadLink(
|
||||
) {
|
||||
return <FileDownloadLinkClient {...props} />;
|
||||
}
|
||||
|
||||
export function Framework() {
|
||||
return <FrameworkClient />;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { clsx } from "clsx";
|
||||
import { Card } from "@garden-co/design-system/src/components/atoms/Card";
|
||||
import { H2 } from "@garden-co/design-system/src/components/atoms/Headings";
|
||||
import { Kicker } from "@garden-co/design-system/src/components/atoms/Kicker";
|
||||
import { GappedGrid } from "@garden-co/design-system/src/components/molecules/GappedGrid";
|
||||
import { clsx } from "clsx";
|
||||
import CodeStepAction from "./CodeStepAction.mdx";
|
||||
import CodeStepCloud from "./CodeStepCloud.mdx";
|
||||
import CodeStepRender from "./CodeStepRender.mdx";
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -134,9 +134,20 @@ export async function onAnonymousAccountDiscarded(
|
||||
|
||||
To see how this works, try uploading a song in the [music player demo](https://music-demo.jazz.tools/) and then log in with an existing account.
|
||||
|
||||
## Provider Configuration for Authentication
|
||||
|
||||
You can configure how authentication states work in your app with the [JazzProvider](/docs/project-setup/providers/). The provider offers several options that impact authentication behavior:
|
||||
|
||||
- `guestMode`: Enable/disable Guest Mode
|
||||
- `onAnonymousAccountDiscarded`: Handle data migration when switching accounts
|
||||
- `sync.when`: Control when data synchronization happens
|
||||
- `defaultProfileName`: Set default name for new user profiles
|
||||
|
||||
For detailed information on all provider options, see [Provider Configuration options](/docs/project-setup/providers/#additional-options).
|
||||
|
||||
## Controlling sync for different authentication states
|
||||
|
||||
You can control network sync with [Providers](/docs/project-setup/providers) based on authentication state:
|
||||
You can control network sync with [Providers](/docs/project-setup/providers/) based on authentication state:
|
||||
|
||||
- `when: "always"`: Sync is enabled for both Anonymous Authentication and Authenticated Account
|
||||
- `when: "signedUp"`: Sync is enabled when the user is authenticated
|
||||
@@ -197,7 +208,7 @@ function App() {
|
||||
|
||||
### Configuring Guest Mode Access
|
||||
|
||||
You can configure Guest Mode access with the `guestMode` prop for [Providers](/docs/project-setup/providers).
|
||||
You can configure Guest Mode access with the `guestMode` prop for [Providers](/docs/project-setup/providers/).
|
||||
|
||||
<ContentByFramework framework="react">
|
||||
<CodeGroup>
|
||||
|
||||
@@ -53,6 +53,7 @@ export const docNavigationItems = [
|
||||
name: "Providers",
|
||||
href: "/docs/project-setup/providers",
|
||||
done: {
|
||||
react: 100,
|
||||
"react-native": 100,
|
||||
"react-native-expo": 100,
|
||||
},
|
||||
@@ -168,6 +169,11 @@ export const docNavigationItems = [
|
||||
href: "/docs/using-covalues/cofeeds",
|
||||
done: 100,
|
||||
},
|
||||
{
|
||||
name: "CoTexts",
|
||||
href: "/docs/using-covalues/cotexts",
|
||||
done: 100,
|
||||
},
|
||||
{
|
||||
name: "FileStreams",
|
||||
href: "/docs/using-covalues/filestreams",
|
||||
|
||||
195
homepage/homepage/content/docs/project-setup/providers/react.mdx
Normal file
195
homepage/homepage/content/docs/project-setup/providers/react.mdx
Normal file
@@ -0,0 +1,195 @@
|
||||
export const metadata = { title: "Providers" };
|
||||
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
# Providers
|
||||
|
||||
## Introduction
|
||||
|
||||
`<JazzProvider />` is the core component that connects your React application to Jazz. It handles:
|
||||
|
||||
- **Data Synchronization**: Manages connections to peers and the Jazz cloud
|
||||
- **Local Storage**: Persists data locally between app sessions
|
||||
- **Schema Types**: Provides APIs for the [AccountSchema](/docs/schemas/accounts-and-migrations)
|
||||
- **Authentication**: Connects your authentication system to Jazz
|
||||
|
||||
Our [Chat example app](https://jazz.tools/examples#chat) provides a complete implementation of JazzProvider with authentication and real-time data sync.
|
||||
|
||||
## Setting up the Provider
|
||||
|
||||
The `<JazzProvider />` accepts several configuration options:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx twoslash
|
||||
// @filename: schema.ts
|
||||
import { Account, co } from "jazz-tools";
|
||||
|
||||
export class MyAppAccount extends Account {
|
||||
name = co.string;
|
||||
}
|
||||
|
||||
// @filename: app.tsx
|
||||
import * as React from "react";
|
||||
// ---cut---
|
||||
// App.tsx
|
||||
import { JazzProvider } from "jazz-react";
|
||||
import { MyAppAccount } from "./schema";
|
||||
|
||||
export function MyApp({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<JazzProvider
|
||||
sync={{
|
||||
peer: "wss://cloud.jazz.tools/?key=your-api-key",
|
||||
when: "always" // When to sync: "always", "never", or "signedUp"
|
||||
}}
|
||||
AccountSchema={MyAppAccount}
|
||||
>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
);
|
||||
}
|
||||
|
||||
// Register the Account schema so `useAccount` returns our custom `MyAppAccount`
|
||||
declare module "jazz-react" {
|
||||
interface Register {
|
||||
Account: MyAppAccount;
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Provider Options
|
||||
|
||||
### Sync Options
|
||||
|
||||
The `sync` property configures how your application connects to the Jazz network:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx twoslash
|
||||
import { type SyncConfig } from "jazz-tools";
|
||||
|
||||
const syncConfig: SyncConfig = {
|
||||
// Connection to Jazz Cloud or your own sync server
|
||||
peer: "wss://cloud.jazz.tools/?key=your-api-key",
|
||||
|
||||
// When to sync: "always" (default), "never", or "signedUp"
|
||||
when: "always",
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
See [Authentication States](/docs/authentication/authentication-states#controlling-sync-for-different-authentication-states) for more details on how the `when` property affects synchronization based on authentication state.
|
||||
|
||||
### Account Schema
|
||||
|
||||
The `AccountSchema` property defines your application's account structure:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx twoslash
|
||||
|
||||
// @filename: schema.ts
|
||||
import { Account, CoMap, co } from "jazz-tools";
|
||||
// schema.ts
|
||||
class Preferences extends CoMap {
|
||||
theme = co.string;
|
||||
notifications = co.boolean;
|
||||
}
|
||||
|
||||
// Define your custom account schema
|
||||
export class MyAppAccount extends Account {
|
||||
name = co.string;
|
||||
preferences = co.ref(Preferences);
|
||||
}
|
||||
|
||||
// @filename: app.tsx
|
||||
import * as React from "react";
|
||||
import { JazzProvider } from "jazz-react";
|
||||
import { SyncConfig } from "jazz-tools";
|
||||
|
||||
const syncConfig: SyncConfig = {
|
||||
peer: "wss://cloud.jazz.tools/?key=your-api-key",
|
||||
when: "always",
|
||||
}
|
||||
|
||||
// ---cut---
|
||||
// app.tsx
|
||||
import { MyAppAccount } from "./schema";
|
||||
|
||||
export function MyApp ({ children }: { children: React.ReactNode }) {
|
||||
// Use in provider
|
||||
return (
|
||||
<JazzProvider
|
||||
sync={syncConfig}
|
||||
|
||||
AccountSchema={MyAppAccount}
|
||||
>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
);
|
||||
}
|
||||
|
||||
// Register type for useAccount
|
||||
declare module "jazz-react" {
|
||||
interface Register {
|
||||
Account: MyAppAccount;
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Additional Options
|
||||
|
||||
The provider accepts these additional options:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx twoslash
|
||||
import * as React from "react";
|
||||
import { JazzProvider } from "jazz-react";
|
||||
import { SyncConfig } from "jazz-tools";
|
||||
|
||||
const syncConfig: SyncConfig = {
|
||||
peer: "wss://cloud.jazz.tools/?key=your-api-key",
|
||||
when: "always",
|
||||
}
|
||||
|
||||
// ---cut---
|
||||
// app.tsx
|
||||
export function MyApp ({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<JazzProvider
|
||||
sync={syncConfig}
|
||||
|
||||
// Enable guest mode for account-less access
|
||||
guestMode={false}
|
||||
|
||||
// Set default name for new user profiles
|
||||
defaultProfileName="New User"
|
||||
|
||||
// Handle user logout
|
||||
onLogOut={() => {
|
||||
console.log("User logged out");
|
||||
}}
|
||||
|
||||
// Handle anonymous account data when user logs in to existing account
|
||||
onAnonymousAccountDiscarded={(account) => {
|
||||
console.log("Anonymous account discarded", account.id);
|
||||
// Migrate data here
|
||||
return Promise.resolve();
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
See [Authentication States](/docs/authentication/authentication-states) for more information on authentication states, guest mode, and handling anonymous accounts.
|
||||
|
||||
## Authentication
|
||||
|
||||
`<JazzProvider />` works with various authentication methods to enable users to access their data across multiple devices. For a complete guide to authentication, see our [Authentication Overview](/docs/authentication/overview).
|
||||
|
||||
## Need Help?
|
||||
|
||||
If you have questions about configuring the Jazz Provider for your specific use case, [join our Discord community](https://discord.gg/utDMjHYg42) for help.
|
||||
@@ -70,7 +70,7 @@ If you are not working within a monorepo, create a new file `metro.config.js` in
|
||||
// @noErrors: 2304
|
||||
// metro.config.js
|
||||
const { getDefaultConfig } = require("expo/metro-config");
|
||||
const config = getDefaultConfig(projectRoot);
|
||||
const config = getDefaultConfig(__dirname);
|
||||
|
||||
config.resolver.sourceExts = ["mjs", "js", "json", "ts", "tsx"];
|
||||
config.resolver.requireCycleIgnorePatterns = [/(^|\/|\\)node_modules($|\/|\\)/];
|
||||
|
||||
@@ -33,7 +33,34 @@ const activityFeed = ActivityFeed.create([]);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Like other CoValues, you can specify [ownership](/docs/using-covalues/ownership) when creating CoFeeds.
|
||||
### Ownership
|
||||
|
||||
Like other CoValues, you can specify ownership when creating CoFeeds.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { Group, co, CoMap, CoFeed } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const colleagueAccount = await createJazzTestAccount();
|
||||
|
||||
class Activity extends CoMap {
|
||||
timestamp = co.Date;
|
||||
action = co.literal("watering", "planting", "harvesting", "maintenance");
|
||||
notes = co.optional.string;
|
||||
}
|
||||
|
||||
class ActivityFeed extends CoFeed.Of(co.ref(Activity)) {}
|
||||
|
||||
// ---cut---
|
||||
const teamGroup = Group.create();
|
||||
teamGroup.addMember(colleagueAccount, "writer");
|
||||
|
||||
const teamFeed = ActivityFeed.create([], { owner: teamGroup });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
See [Groups as permission scopes](/docs/groups/intro) for more information on how to use groups to control access to CoFeeds.
|
||||
|
||||
## Reading from CoFeeds
|
||||
|
||||
|
||||
@@ -33,7 +33,32 @@ const tasks = ListOfTasks.create([
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Like other CoValues, you can specify [ownership](/docs/using-covalues/ownership) when creating CoLists.
|
||||
### Ownership
|
||||
|
||||
Like other CoValues, you can specify ownership when creating CoLists.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { Group, co, CoMap, CoList } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const colleagueAccount = await createJazzTestAccount();
|
||||
class Task extends CoMap {
|
||||
title = co.string;
|
||||
status = co.string;
|
||||
}
|
||||
class ListOfTasks extends CoList.Of(co.ref(Task)) {}
|
||||
|
||||
// ---cut---
|
||||
// Create with shared ownership
|
||||
const teamGroup = Group.create();
|
||||
teamGroup.addMember(colleagueAccount, "writer");
|
||||
|
||||
const teamList = ListOfTasks.create([], { owner: teamGroup });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
See [Groups as permission scopes](/docs/groups/intro) for more information on how to use groups to control access to CoLists.
|
||||
|
||||
## Reading from CoLists
|
||||
|
||||
|
||||
@@ -52,7 +52,24 @@ const inventory = Inventory.create({
|
||||
When creating CoMaps, you can specify ownership to control access:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, CoMap } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const memberAccount = await createJazzTestAccount();
|
||||
|
||||
class Member extends CoMap {
|
||||
name = co.string;
|
||||
}
|
||||
|
||||
class Project extends CoMap {
|
||||
name = co.string;
|
||||
startDate = co.Date;
|
||||
status = co.literal("planning", "active", "completed");
|
||||
coordinator = co.optional.ref(Member);
|
||||
}
|
||||
|
||||
// ---cut---
|
||||
// Create with default owner (current user)
|
||||
const privateProject = Project.create({
|
||||
name: "My Herb Garden",
|
||||
@@ -75,6 +92,8 @@ const communityProject = Project.create(
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
See [Groups as permission scopes](/docs/groups/intro) for more information on how to use groups to control access to CoMaps.
|
||||
|
||||
## Reading from CoMaps
|
||||
|
||||
CoMaps can be accessed using familiar JavaScript object notation:
|
||||
|
||||
437
homepage/homepage/content/docs/using-covalues/cotexts.mdx
Normal file
437
homepage/homepage/content/docs/using-covalues/cotexts.mdx
Normal file
@@ -0,0 +1,437 @@
|
||||
import { CodeGroup, ContentByFramework } from "@/components/forMdx";
|
||||
|
||||
export const metadata = { title: "CoTexts" };
|
||||
|
||||
# CoTexts
|
||||
|
||||
Jazz provides two CoValue types for collaborative text editing, collectively referred to as "CoText" values:
|
||||
|
||||
- **CoPlainText** for simple text editing without formatting
|
||||
- **CoRichText** for rich text with HTML-based formatting (extends CoPlainText)
|
||||
|
||||
Both types enable real-time collaborative editing of text content while maintaining consistency across multiple users.
|
||||
|
||||
**Note:** If you're looking for a quick way to add rich text editing to your app, check out [jazz-richtext-prosemirror](#using-rich-text-with-prosemirror).
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { CoPlainText } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
// ---cut---
|
||||
const note = CoPlainText.create("Meeting notes", { owner: me });
|
||||
|
||||
// Update the text
|
||||
note.applyDiff("Meeting notes for Tuesday");
|
||||
|
||||
console.log(note.toString()); // "Meeting notes for Tuesday"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
For a full example of CoTexts in action, see [our Richtext example app](https://github.com/garden-co/jazz/tree/main/examples/richtext), which shows plain text and rich text editing.
|
||||
|
||||
## CoPlainText vs co.string
|
||||
|
||||
While `co.string` is perfect for simple text fields, `CoPlainText` is the right choice when you need:
|
||||
|
||||
- Multiple users editing the same text simultaneously
|
||||
- Fine-grained control over text edits (inserting, deleting at specific positions)
|
||||
- Character-by-character collaboration
|
||||
- Efficient merging of concurrent changes
|
||||
|
||||
Both support real-time updates, but `CoPlainText` provides specialized tools for collaborative editing scenarios.
|
||||
|
||||
## Creating CoText Values
|
||||
|
||||
CoText values are typically used as fields in your schemas:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { CoMap, CoPlainText, CoRichText, co } from "jazz-tools";
|
||||
|
||||
// ---cut---
|
||||
class Profile extends CoMap {
|
||||
name = co.string;
|
||||
bio = co.ref(CoPlainText); // Plain text field
|
||||
description = co.ref(CoRichText); // Rich text with formatting
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Create a CoText value with a simple string:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { CoPlainText, CoRichText, Account } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
// ---cut---
|
||||
// Create plaintext with default ownership (current user)
|
||||
const note = CoPlainText.create("Meeting notes", { owner: me });
|
||||
|
||||
// Create rich text with HTML content
|
||||
const document = CoRichText.create("<p>Project <strong>overview</strong></p>",
|
||||
{ owner: me }
|
||||
);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Ownership
|
||||
|
||||
Like other CoValues, you can specify ownership when creating CoTexts.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { CoPlainText, Group, Account } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const colleagueAccount = await createJazzTestAccount();
|
||||
|
||||
// ---cut---
|
||||
// Create with shared ownership
|
||||
const teamGroup = Group.create();
|
||||
teamGroup.addMember(colleagueAccount, "writer");
|
||||
|
||||
const teamNote = CoPlainText.create("Team updates", { owner: teamGroup });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
See [Groups as permission scopes](/docs/groups/intro) for more information on how to use groups to control access to CoText values.
|
||||
|
||||
## Reading Text
|
||||
|
||||
CoText values work like JavaScript strings:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { CoPlainText, Account } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const note = CoPlainText.create("Meeting notes", { owner: me });
|
||||
|
||||
// ---cut---
|
||||
// Get the text content
|
||||
console.log(note.toString()); // "Meeting notes"
|
||||
|
||||
// Check the text length
|
||||
console.log(note.length); // 14
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Making Edits
|
||||
|
||||
Insert and delete text with intuitive methods:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { CoPlainText, Account } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const note = CoPlainText.create("Meeting notes", { owner: me });
|
||||
|
||||
// ---cut---
|
||||
// Insert text at a specific position
|
||||
note.insertBefore(8, "weekly "); // "Meeting weekly notes"
|
||||
|
||||
// Insert after a position
|
||||
note.insertAfter(21, " for Monday"); // "Meeting weekly notes for Monday"
|
||||
|
||||
// Delete a range of text
|
||||
note.deleteRange({ from: 8, to: 15 }); // "Meeting notes for Monday"
|
||||
|
||||
// Apply a diff to update the entire text
|
||||
note.applyDiff("Team meeting notes for Tuesday");
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Applying Diffs
|
||||
|
||||
Use `applyDiff` to efficiently update text with minimal changes:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { CoPlainText, Account } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
// ---cut---
|
||||
// Original text: "Team status update"
|
||||
const minutes = CoPlainText.create("Team status update", { owner: me });
|
||||
|
||||
// Replace the entire text with a new version
|
||||
minutes.applyDiff("Weekly team status update for Project X");
|
||||
|
||||
// Make partial changes
|
||||
let text = minutes.toString();
|
||||
text = text.replace("Weekly", "Monday");
|
||||
minutes.applyDiff(text); // Efficiently updates only what changed
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Perfect for handling user input in form controls:
|
||||
|
||||
<ContentByFramework framework="react">
|
||||
<CodeGroup>
|
||||
```tsx twoslash
|
||||
import { CoPlainText, Account } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
import React, { useState } from "react";
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
// ---cut---
|
||||
function TextEditor() {
|
||||
const [note, setNote] = useState(CoPlainText.create("", { owner: me }));
|
||||
|
||||
return (
|
||||
<textarea
|
||||
value={note.toString()}
|
||||
onChange={(e) => {
|
||||
// Efficiently update only what the user changed
|
||||
note.applyDiff(e.target.value);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework="vanilla">
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { CoPlainText, Account } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
// ---cut---
|
||||
const note = CoPlainText.create("", { owner: me });
|
||||
|
||||
// Create and set up the textarea
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = note.toString();
|
||||
|
||||
// Add event listener for changes
|
||||
textarea.addEventListener('input', (e: Event) => {
|
||||
const target = e.target as HTMLTextAreaElement;
|
||||
// Efficiently update only what the user changed
|
||||
note.applyDiff(target.value);
|
||||
});
|
||||
|
||||
// Add the textarea to the document
|
||||
document.body.appendChild(textarea);
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework="vue">
|
||||
<CodeGroup>
|
||||
```vue twoslash
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { CoPlainText } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
|
||||
const note = ref(null);
|
||||
const textContent = ref("");
|
||||
|
||||
onMounted(async () => {
|
||||
const me = await createJazzTestAccount();
|
||||
note.value = CoPlainText.create("", { owner: me });
|
||||
textContent.value = note.value.toString();
|
||||
});
|
||||
|
||||
function updateText(e) {
|
||||
if (note.value) {
|
||||
note.value.applyDiff(e.target.value);
|
||||
textContent.value = note.value.toString();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<textarea
|
||||
:value="textContent"
|
||||
@input="updateText"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework="svelte">
|
||||
<CodeGroup>
|
||||
```svelte twoslash
|
||||
<script lang="ts">
|
||||
import { CoPlainText, Account } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const note = CoPlainText.create("", { owner: me });
|
||||
</script>
|
||||
|
||||
<textarea
|
||||
value={note.toString()}
|
||||
oninput={e => note.applyDiff(e.target.value)}
|
||||
/>
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
## Using Rich Text with ProseMirror
|
||||
|
||||
Jazz provides a dedicated plugin for integrating CoRichText with the popular ProseMirror editor. This plugin, [`jazz-richtext-prosemirror`](https://www.npmjs.com/package/jazz-richtext-prosemirror), enables bidirectional synchronization between your CoRichText instances and ProseMirror editors.
|
||||
|
||||
### ProseMirror Plugin Features
|
||||
|
||||
- **Bidirectional Sync**: Changes in the editor automatically update the CoRichText and vice versa
|
||||
- **Real-time Collaboration**: Multiple users can edit the same document simultaneously
|
||||
- **HTML Conversion**: Automatically converts between HTML (used by CoRichText) and ProseMirror's document model
|
||||
|
||||
### Installation
|
||||
|
||||
<CodeGroup>
|
||||
```bash
|
||||
pnpm add jazz-richtext-prosemirror \
|
||||
prosemirror-view \
|
||||
prosemirror-state \
|
||||
prosemirror-schema-basic
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Integration
|
||||
|
||||
<ContentByFramework framework="react-native">
|
||||
We don't currently have a React Native-specific example, but you need help you can [request one](https://github.com/garden-co/jazz/issues/new), or ask on [Discord](https://discord.gg/utDMjHYg42).
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework="react-native-expo">
|
||||
We don't currently have a React Native Expo-specific example, but you need help please [request one](https://github.com/garden-co/jazz/issues/new), or ask on [Discord](https://discord.gg/utDMjHYg42).
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework={["react", "react-native", "react-native-expo"]}>
|
||||
For use with React:
|
||||
<CodeGroup>
|
||||
```tsx twoslash
|
||||
class JazzProfile extends Profile {
|
||||
bio = co.ref(CoRichText);
|
||||
}
|
||||
|
||||
class JazzAccount extends Account {
|
||||
profile = co.ref(JazzProfile);
|
||||
}
|
||||
|
||||
declare module "jazz-react" {
|
||||
interface Register {
|
||||
Account: JazzAccount;
|
||||
}
|
||||
}
|
||||
|
||||
import { useAccount, useCoState } from "jazz-react";
|
||||
import { CoRichText, Account, Profile, co } from "jazz-tools";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
// ---cut---
|
||||
// RichTextEditor.tsx
|
||||
import { createJazzPlugin } from "jazz-richtext-prosemirror";
|
||||
import { exampleSetup } from "prosemirror-example-setup";
|
||||
import { schema } from "prosemirror-schema-basic";
|
||||
import { EditorState } from "prosemirror-state";
|
||||
import { EditorView } from "prosemirror-view";
|
||||
|
||||
function RichTextEditor() {
|
||||
const { me } = useAccount({ resolve: { profile: true } });
|
||||
const editorRef = useRef<HTMLDivElement>(null);
|
||||
const viewRef = useRef<EditorView | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!me?.profile.bio || !editorRef.current) return;
|
||||
|
||||
// Create the Jazz plugin for ProseMirror
|
||||
// Providing a CoRichText instance to the plugin to automatically sync changes
|
||||
const jazzPlugin = createJazzPlugin(me.profile.bio); // [!code ++]
|
||||
|
||||
// Set up ProseMirror with the Jazz plugin
|
||||
if (!viewRef.current) {
|
||||
viewRef.current = new EditorView(editorRef.current, {
|
||||
state: EditorState.create({
|
||||
schema,
|
||||
plugins: [
|
||||
...exampleSetup({ schema }),
|
||||
jazzPlugin, // [!code ++]
|
||||
],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (viewRef.current) {
|
||||
viewRef.current.destroy();
|
||||
viewRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [me?.profile.bio?.id]);
|
||||
|
||||
if (!me) return null;
|
||||
|
||||
return (
|
||||
<div className="border rounded">
|
||||
<div ref={editorRef} className="p-2" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework="svelte">
|
||||
We don't currently have a Svelte-specific example, but you need help you can [request one](https://github.com/garden-co/jazz/issues/new), or ask on [Discord](https://discord.gg/utDMjHYg42).
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework="vue">
|
||||
We don't currently have a Vue-specific example, but you need help you can [request one](https://github.com/garden-co/jazz/issues/new), or ask on [Discord](https://discord.gg/utDMjHYg42).
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework={["vanilla", "svelte", "vue", "react-native", "react-native-expo"]}>
|
||||
For use without a framework:
|
||||
<CodeGroup>
|
||||
```js twoslash
|
||||
import { CoRichText } from "jazz-tools";
|
||||
import { createJazzPlugin } from "jazz-richtext-prosemirror";
|
||||
import { exampleSetup } from "prosemirror-example-setup";
|
||||
import { schema } from "prosemirror-schema-basic";
|
||||
import { EditorState } from "prosemirror-state";
|
||||
import { EditorView } from "prosemirror-view";
|
||||
|
||||
function setupRichTextEditor(coRichText, container) {
|
||||
// Create the Jazz plugin for ProseMirror
|
||||
// Providing a CoRichText instance to the plugin to automatically sync changes
|
||||
const jazzPlugin = createJazzPlugin(coRichText); // [!code ++]
|
||||
|
||||
// Set up ProseMirror with Jazz plugin
|
||||
const view = new EditorView(container, {
|
||||
state: EditorState.create({
|
||||
schema,
|
||||
plugins: [
|
||||
...exampleSetup({ schema }),
|
||||
jazzPlugin, // [!code ++]
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
// Return cleanup function
|
||||
return () => {
|
||||
view.destroy();
|
||||
};
|
||||
}
|
||||
|
||||
// Usage
|
||||
const document = CoRichText.create("<p>Initial content</p>", { owner: me });
|
||||
const editorContainer = document.getElementById("editor");
|
||||
const cleanup = setupRichTextEditor(document, editorContainer);
|
||||
|
||||
// Later when done with the editor
|
||||
cleanup();
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
@@ -18,7 +18,8 @@ FileStreams provide automatic chunking when using the `createFromBlob` method, t
|
||||
In your schema, reference FileStreams like any other CoValue:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
// schema.ts
|
||||
import { CoMap, FileStream, co } from "jazz-tools";
|
||||
|
||||
class Document extends CoMap {
|
||||
@@ -37,25 +38,33 @@ There are two main ways to create FileStreams: creating empty ones for manual da
|
||||
For files from input elements or drag-and-drop interfaces, use `createFromBlob`:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
// @errors: 18047
|
||||
import { FileStream, Group } from "jazz-tools";
|
||||
const myGroup = Group.create();
|
||||
const progressBar: HTMLElement = document.querySelector('.progress-bar')!;
|
||||
|
||||
// ---cut---
|
||||
// From a file input
|
||||
const fileInput = document.querySelector('input[type="file"]');
|
||||
const fileInput = document.querySelector('input[type="file"]') as HTMLInputElement;
|
||||
|
||||
fileInput.addEventListener('change', async () => {
|
||||
const file = fileInput.files[0];
|
||||
if (file) {
|
||||
// Create FileStream from user-selected file
|
||||
const fileStream = await FileStream.createFromBlob(file);
|
||||
|
||||
// Or with progress tracking for better UX
|
||||
const fileWithProgress = await FileStream.createFromBlob(file, {
|
||||
onProgress: (progress) => {
|
||||
// progress is a value between 0 and 1
|
||||
const percent = Math.round(progress * 100);
|
||||
console.log(`Upload progress: ${percent}%`);
|
||||
progressBar.style.width = `${percent}%`;
|
||||
}
|
||||
});
|
||||
}
|
||||
const file = fileInput.files?.[0];
|
||||
if (!file) return;
|
||||
|
||||
// Create FileStream from user-selected file
|
||||
const fileStream = await FileStream.createFromBlob(file, { owner: myGroup });
|
||||
|
||||
// Or with progress tracking for better UX
|
||||
const fileWithProgress = await FileStream.createFromBlob(file, {
|
||||
onProgress: (progress) => {
|
||||
// progress is a value between 0 and 1
|
||||
const percent = Math.round(progress * 100);
|
||||
console.log(`Upload progress: ${percent}%`);
|
||||
progressBar.style.width = `${percent}%`;
|
||||
},
|
||||
owner: myGroup
|
||||
});
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -65,14 +74,38 @@ fileInput.addEventListener('change', async () => {
|
||||
Create an empty FileStream when you want to manually [add binary data in chunks](/docs/using-covalues/filestreams#writing-to-filestreams):
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
import { FileStream } from "jazz-tools";
|
||||
|
||||
```ts twoslash
|
||||
import { Group, FileStream } from "jazz-tools";
|
||||
const myGroup = Group.create();
|
||||
// ---cut---
|
||||
// Create a new empty FileStream
|
||||
const fileStream = FileStream.create();
|
||||
const fileStream = FileStream.create({ owner: myGroup } );
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Ownership
|
||||
|
||||
Like other CoValues, you can specify ownership when creating FileStreams.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { Group, FileStream } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const colleagueAccount = await createJazzTestAccount();
|
||||
|
||||
// ---cut---
|
||||
// Create a team group
|
||||
const teamGroup = Group.create();
|
||||
teamGroup.addMember(colleagueAccount, "writer");
|
||||
|
||||
// Create a FileStream with shared ownership
|
||||
const teamFileStream = FileStream.create({ owner: teamGroup });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
See [Groups as permission scopes](/docs/groups/intro) for more information on how to use groups to control access to FileStreams.
|
||||
|
||||
## Reading from FileStreams
|
||||
|
||||
`FileStream`s provide several ways to access their binary content, from raw chunks to convenient Blob objects.
|
||||
@@ -82,7 +115,10 @@ const fileStream = FileStream.create();
|
||||
To access the raw binary data and metadata:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
// Get all chunks and metadata
|
||||
const fileData = fileStream.getChunks();
|
||||
|
||||
@@ -104,7 +140,10 @@ if (fileData) {
|
||||
By default, `getChunks()` only returns data for completely synced `FileStream`s. To start using chunks from a `FileStream` that's currently still being synced use the `allowUnfinished` option:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
// Get data even if the stream isn't complete
|
||||
const partialData = fileStream.getChunks({ allowUnfinished: true });
|
||||
```
|
||||
@@ -115,10 +154,16 @@ const partialData = fileStream.getChunks({ allowUnfinished: true });
|
||||
For easier integration with web APIs, convert to a `Blob`:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
// Convert to a Blob
|
||||
const blob = fileStream.toBlob();
|
||||
|
||||
// Get the filename from the metadata
|
||||
const filename = fileStream.getChunks()?.fileName;
|
||||
|
||||
if (blob) {
|
||||
// Use with URL.createObjectURL
|
||||
const url = URL.createObjectURL(blob);
|
||||
@@ -126,7 +171,7 @@ if (blob) {
|
||||
// Create a download link
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = fileData?.fileName || 'document.pdf';
|
||||
link.download = filename || 'document.pdf';
|
||||
link.click();
|
||||
|
||||
// Clean up when done
|
||||
@@ -140,7 +185,10 @@ if (blob) {
|
||||
You can directly load a `FileStream` as a `Blob` when you only have its ID:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream, type ID } from "jazz-tools";
|
||||
const fileStreamId = "co_z123" as ID<FileStream>;
|
||||
// ---cut---
|
||||
// Load directly as a Blob when you have an ID
|
||||
const blob = await FileStream.loadAsBlob(fileStreamId);
|
||||
|
||||
@@ -157,7 +205,10 @@ const partialBlob = await FileStream.loadAsBlob(fileStreamId, {
|
||||
Check if a `FileStream` is fully synced:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
if (fileStream.isBinaryStreamEnded()) {
|
||||
console.log('File is completely synced');
|
||||
} else {
|
||||
@@ -183,9 +234,12 @@ When creating a `FileStream` manually (not using `createFromBlob`), you need to
|
||||
Begin by providing metadata about the file:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream, Group } from "jazz-tools";
|
||||
const myGroup = Group.create();
|
||||
// ---cut---
|
||||
// Create an empty FileStream
|
||||
const fileStream = FileStream.create();
|
||||
const fileStream = FileStream.create({ owner: myGroup });
|
||||
|
||||
// Initialize with metadata
|
||||
fileStream.start({
|
||||
@@ -201,9 +255,15 @@ fileStream.start({
|
||||
Add binary data in chunks - this helps with large files and progress tracking:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
// Create a sample Uint8Array (in real apps, this would be file data)
|
||||
const data = new Uint8Array([...]);
|
||||
```ts twoslash
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
const file = [0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64]; // "Hello World" in ASCII
|
||||
const bytes = new Uint8Array(file);
|
||||
const arrayBuffer = bytes.buffer;
|
||||
|
||||
// ---cut---
|
||||
const data = new Uint8Array(arrayBuffer);
|
||||
|
||||
// For large files, break into chunks (e.g., 100KB each)
|
||||
const chunkSize = 1024 * 100;
|
||||
@@ -226,7 +286,10 @@ for (let i = 0; i < data.length; i += chunkSize) {
|
||||
Once all chunks are pushed, mark the `FileStream` as complete:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
// Finalize the upload
|
||||
fileStream.end();
|
||||
|
||||
@@ -243,9 +306,12 @@ Like other CoValues, you can subscribe to `FileStream`s to get notified of chang
|
||||
Load a `FileStream` when you have its ID:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream, type ID } from "jazz-tools";
|
||||
const fileStreamId = "co_z123" as ID<FileStream>;
|
||||
// ---cut---
|
||||
// Load a FileStream by ID
|
||||
const fileStream = await FileStream.load(fileStreamId, []);
|
||||
const fileStream = await FileStream.load(fileStreamId);
|
||||
|
||||
if (fileStream) {
|
||||
console.log('FileStream loaded successfully');
|
||||
@@ -264,16 +330,20 @@ if (fileStream) {
|
||||
Subscribe to a `FileStream` to be notified when chunks are added or when the upload is complete:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream, type ID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const fileStreamId = "co_z123" as ID<FileStream>;
|
||||
// ---cut---
|
||||
// Subscribe to a FileStream by ID
|
||||
const unsubscribe = FileStream.subscribe(fileStreamId, [], (fileStream) => {
|
||||
const unsubscribe = FileStream.subscribe(fileStreamId, (fileStream: FileStream) => {
|
||||
// Called whenever the FileStream changes
|
||||
console.log('FileStream updated');
|
||||
|
||||
// Get current status
|
||||
const chunks = fileStream.getChunks({ allowUnfinished: true });
|
||||
if (chunks) {
|
||||
const uploadedBytes = chunks.chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
||||
const uploadedBytes = chunks.chunks.reduce((sum: number, chunk: Uint8Array) => sum + chunk.length, 0);
|
||||
const totalBytes = chunks.totalSizeBytes || 1;
|
||||
const progress = Math.min(100, Math.round(uploadedBytes * 100 / totalBytes));
|
||||
|
||||
@@ -297,7 +367,10 @@ const unsubscribe = FileStream.subscribe(fileStreamId, [], (fileStream) => {
|
||||
If you need to wait for a `FileStream` to be fully synchronized across devices:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
// Wait for the FileStream to be fully synced
|
||||
await fileStream.waitForSync({
|
||||
timeout: 5000 // Optional timeout in ms
|
||||
|
||||
@@ -66,6 +66,31 @@ const image = await createImage(file, options);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Ownership
|
||||
|
||||
Like other CoValues, you can specify ownership when creating image definitions.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const colleagueAccount = await createJazzTestAccount();
|
||||
|
||||
const file = new File([], "test.jpg", { type: "image/jpeg" });
|
||||
|
||||
// ---cut---
|
||||
const teamGroup = Group.create();
|
||||
teamGroup.addMember(colleagueAccount, "writer");
|
||||
|
||||
// Create an image with shared ownership
|
||||
const teamImage = await createImage(file, { owner: teamGroup });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
See [Groups as permission scopes](/docs/groups/intro) for more information on how to use groups to control access to images.
|
||||
|
||||
## Creating ImageDefinitions
|
||||
|
||||
Create an `ImageDefinition` by specifying the original dimensions and an optional placeholder:
|
||||
|
||||
@@ -67,6 +67,31 @@ const image = await createImage(file, options);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Ownership
|
||||
|
||||
Like other CoValues, you can specify ownership when creating image definitions.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const colleagueAccount = await createJazzTestAccount();
|
||||
|
||||
const file = new File([], "test.jpg", { type: "image/jpeg" });
|
||||
|
||||
// ---cut---
|
||||
const teamGroup = Group.create();
|
||||
teamGroup.addMember(colleagueAccount, "writer");
|
||||
|
||||
// Create an image with shared ownership
|
||||
const teamImage = await createImage(file, { owner: teamGroup });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
See [Groups as permission scopes](/docs/groups/intro) for more information on how to use groups to control access to images.
|
||||
|
||||
## Displaying Images with `ProgressiveImg`
|
||||
|
||||
For a complete progressive loading experience, use the `ProgressiveImg` component:
|
||||
|
||||
@@ -26,4 +26,8 @@ export const features = {
|
||||
clerk: "Clerk auth",
|
||||
inviteLink: "Invite link",
|
||||
coFeed: "CoFeed",
|
||||
coRichText: "CoRichText",
|
||||
coPlainText: "CoPlainText",
|
||||
serverWorker: "Server worker",
|
||||
inbox: "Inbox",
|
||||
};
|
||||
|
||||
@@ -8,6 +8,38 @@ export enum Framework {
|
||||
}
|
||||
|
||||
export const frameworks = Object.values(Framework);
|
||||
export const frameworkNames: Record<
|
||||
Framework,
|
||||
{
|
||||
label: string;
|
||||
experimental: boolean;
|
||||
}
|
||||
> = {
|
||||
[Framework.React]: {
|
||||
label: "React",
|
||||
experimental: false,
|
||||
},
|
||||
[Framework.ReactNative]: {
|
||||
label: "React Native",
|
||||
experimental: false,
|
||||
},
|
||||
[Framework.ReactNativeExpo]: {
|
||||
label: "React Native (Expo)",
|
||||
experimental: false,
|
||||
},
|
||||
[Framework.Vanilla]: {
|
||||
label: "VanillaJS",
|
||||
experimental: false,
|
||||
},
|
||||
[Framework.Svelte]: {
|
||||
label: "Svelte",
|
||||
experimental: true,
|
||||
},
|
||||
[Framework.Vue]: {
|
||||
label: "Vue",
|
||||
experimental: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const DEFAULT_FRAMEWORK = Framework.React;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import DocsLayout from "@/components/docs/DocsLayout";
|
||||
import { DocNav } from "@/components/docs/DocsNav";
|
||||
import { Toc } from "@stefanprobst/rehype-extract-toc";
|
||||
import { Prose } from "@garden-co/design-system/src/components/molecules/Prose";
|
||||
import { Toc } from "@stefanprobst/rehype-extract-toc";
|
||||
|
||||
export async function getMdxSource(framework: string, slugPath?: string) {
|
||||
// Try to import the framework-specific file first
|
||||
@@ -42,7 +42,7 @@ export async function getDocMetadata(framework: string, slug?: string[]) {
|
||||
|
||||
function DocProse({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<Prose className="overflow-x-visible lg:flex-1 pb-8 pt-[calc(61px+2rem)] md:pt-8 md:max-w-3xl mx-auto">
|
||||
<Prose className="overflow-x-hidden lg:overflow-x-visible lg:flex-1 pb-8 pt-[calc(61px+2rem)] md:pt-8 md:max-w-3xl mx-auto">
|
||||
{children}
|
||||
</Prose>
|
||||
);
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
"jazz-react": "link:../../packages/jazz-react",
|
||||
"jazz-react-auth-clerk": "link:../../packages/jazz-react-auth-clerk",
|
||||
"jazz-react-native": "link:../../packages/jazz-react-native",
|
||||
"jazz-richtext-prosemirror": "link:../../packages/jazz-richtext-prosemirror",
|
||||
"jazz-tools": "link:../../packages/jazz-tools",
|
||||
"lucide-react": "^0.436.0",
|
||||
"mdast-util-from-markdown": "^2.0.0",
|
||||
|
||||
3
homepage/pnpm-lock.yaml
generated
3
homepage/pnpm-lock.yaml
generated
@@ -265,6 +265,9 @@ importers:
|
||||
jazz-react-native:
|
||||
specifier: link:../../packages/jazz-react-native
|
||||
version: link:../../packages/jazz-react-native
|
||||
jazz-richtext-prosemirror:
|
||||
specifier: link:../../packages/jazz-richtext-prosemirror
|
||||
version: link:../../packages/jazz-richtext-prosemirror
|
||||
jazz-tools:
|
||||
specifier: link:../../packages/jazz-tools
|
||||
version: link:../../packages/jazz-tools
|
||||
|
||||
@@ -1,5 +1,38 @@
|
||||
# cojson-storage-indexeddb
|
||||
|
||||
## 0.13.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9fb98e2]
|
||||
- Updated dependencies [0b89fad]
|
||||
- cojson@0.13.17
|
||||
- cojson-storage@0.13.17
|
||||
|
||||
## 0.13.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c6fb8dc]
|
||||
- cojson@0.13.16
|
||||
- cojson-storage@0.13.16
|
||||
|
||||
## 0.13.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c712ef2]
|
||||
- cojson@0.13.15
|
||||
- cojson-storage@0.13.15
|
||||
|
||||
## 0.13.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5c2c7d4]
|
||||
- cojson@0.13.14
|
||||
- cojson-storage@0.13.14
|
||||
|
||||
## 0.13.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cojson-storage-indexeddb",
|
||||
"version": "0.13.13",
|
||||
"version": "0.13.17",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,38 @@
|
||||
# cojson-storage-sqlite
|
||||
|
||||
## 0.13.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9fb98e2]
|
||||
- Updated dependencies [0b89fad]
|
||||
- cojson@0.13.17
|
||||
- cojson-storage@0.13.17
|
||||
|
||||
## 0.13.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c6fb8dc]
|
||||
- cojson@0.13.16
|
||||
- cojson-storage@0.13.16
|
||||
|
||||
## 0.13.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c712ef2]
|
||||
- cojson@0.13.15
|
||||
- cojson-storage@0.13.15
|
||||
|
||||
## 0.13.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5c2c7d4]
|
||||
- cojson@0.13.14
|
||||
- cojson-storage@0.13.14
|
||||
|
||||
## 0.13.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "cojson-storage-sqlite",
|
||||
"type": "module",
|
||||
"version": "0.13.13",
|
||||
"version": "0.13.17",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^11.7.0",
|
||||
"cojson": "workspace:0.13.13",
|
||||
"cojson": "workspace:0.13.17",
|
||||
"cojson-storage": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -118,10 +118,9 @@ test("should sync and load data from storage", async () => {
|
||||
"client -> LOAD Map sessions: empty",
|
||||
"storage -> KNOWN Group sessions: header/3",
|
||||
"storage -> CONTENT Group header: true new: After: 0 New: 3",
|
||||
"client -> KNOWN Group sessions: header/3",
|
||||
"storage -> KNOWN Map sessions: header/1",
|
||||
"storage -> CONTENT Map header: true new: After: 0 New: 1",
|
||||
"client -> KNOWN Map sessions: header/1",
|
||||
"client -> KNOWN Group sessions: header/3",
|
||||
]
|
||||
`);
|
||||
|
||||
@@ -205,13 +204,12 @@ test("should load dependencies correctly (group inheritance)", async () => {
|
||||
"client -> LOAD Map sessions: empty",
|
||||
"storage -> KNOWN ParentGroup sessions: header/4",
|
||||
"storage -> CONTENT ParentGroup header: true new: After: 0 New: 4",
|
||||
"client -> KNOWN ParentGroup sessions: header/4",
|
||||
"storage -> KNOWN Group sessions: header/5",
|
||||
"storage -> CONTENT Group header: true new: After: 0 New: 5",
|
||||
"client -> KNOWN Group sessions: header/5",
|
||||
"client -> KNOWN ParentGroup sessions: header/4",
|
||||
"storage -> KNOWN Map sessions: header/1",
|
||||
"storage -> CONTENT Map header: true new: After: 0 New: 1",
|
||||
"client -> KNOWN Map sessions: header/1",
|
||||
"client -> KNOWN Group sessions: header/5",
|
||||
]
|
||||
`);
|
||||
});
|
||||
@@ -312,10 +310,9 @@ test("should recover from data loss", async () => {
|
||||
"client -> LOAD Map sessions: empty",
|
||||
"storage -> KNOWN Group sessions: header/3",
|
||||
"storage -> CONTENT Group header: true new: After: 0 New: 3",
|
||||
"client -> KNOWN Group sessions: header/3",
|
||||
"storage -> KNOWN Map sessions: header/4",
|
||||
"storage -> CONTENT Map header: true new: After: 0 New: 4",
|
||||
"client -> KNOWN Map sessions: header/4",
|
||||
"client -> KNOWN Group sessions: header/3",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
# cojson-storage
|
||||
|
||||
## 0.13.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9fb98e2]
|
||||
- Updated dependencies [0b89fad]
|
||||
- cojson@0.13.17
|
||||
|
||||
## 0.13.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c6fb8dc]
|
||||
- cojson@0.13.16
|
||||
|
||||
## 0.13.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c712ef2]
|
||||
- cojson@0.13.15
|
||||
|
||||
## 0.13.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5c2c7d4]
|
||||
- cojson@0.13.14
|
||||
|
||||
## 0.13.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cojson-storage",
|
||||
"version": "0.13.13",
|
||||
"version": "0.13.17",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
# cojson-transport-nodejs-ws
|
||||
|
||||
## 0.13.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9fb98e2]
|
||||
- Updated dependencies [0b89fad]
|
||||
- cojson@0.13.17
|
||||
|
||||
## 0.13.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c6fb8dc]
|
||||
- cojson@0.13.16
|
||||
|
||||
## 0.13.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [c712ef2]
|
||||
- cojson@0.13.15
|
||||
|
||||
## 0.13.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5c2c7d4]
|
||||
- cojson@0.13.14
|
||||
|
||||
## 0.13.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user