Compare commits

..

73 Commits

Author SHA1 Message Date
pax
2ae0b8df0d Merge pull request #2055 from garden-co/changeset-release/main
Version Packages
2025-05-01 16:23:16 +03:00
github-actions[bot]
77dc51d466 Version Packages 2025-05-01 13:19:08 +00:00
pax
bd645db4cc Merge pull request #2071 from garden-co/create-jazz-app-git-flag
create-jazz-app --git flag
2025-05-01 16:17:01 +03:00
pax-k
af46c68a4a chore: changest 2025-05-01 16:15:06 +03:00
pax-k
fb58cb9299 feat(create-jazz-app): option to pass git init boolean flag 2025-05-01 16:11:32 +03:00
James Vickery
63fb80e50d Merge pull request #2069 from garden-co/jmsv/jazz-richtext-prosemirror-custom-schema
createJazzPlugin support custom ProseMirror schema
2025-05-01 11:56:35 +01:00
James Vickery
133b8abcbe createJazzPlugin support custom ProseMirror schema 2025-05-01 10:35:16 +01:00
Guido D'Orsi
6209bd2285 Merge pull request #2057 from garden-co/feat/resolve-load-earlier
feat: resolve load earlier and move the retry in LocalNode
2025-04-30 16:25:53 +02:00
Benjamin S. Leveritt
d8d1addf2b Merge pull request #2056 from garden-co/2049-show-how-to-supply-owner-in-filestream-docs
2049-show-how-to-supply-owner-in-filestream-docs
2025-04-30 15:13:49 +01:00
Guido D'Orsi
937a34c76e test(prosemirror): skip failing test 2025-04-30 16:13:42 +02:00
Guido D'Orsi
15996ced64 Merge remote-tracking branch 'origin/main' into feat/resolve-load-earlier 2025-04-30 15:57:38 +02:00
Guido D'Orsi
9fb98e2114 feat: resolve load earlier and move the retry in LocalNode 2025-04-30 15:45:52 +02:00
Benjamin S. Leveritt
f55f779ea1 Adds owner to FileStream examples
Adds twoslash too
2025-04-30 14:36:26 +01:00
Benjamin S. Leveritt
18c98fc3f5 Merge pull request #2053 from garden-co/2052-match-filestreamsubscribe-signatures-with-other-covalues
Update FileStream.subscribe signature to allow omitting options
2025-04-30 14:05:57 +01:00
Guido D'Orsi
41b286b672 Merge pull request #2051 from garden-co/feat/incremental-processing
feat(colist): re-introduce incremental processing
2025-04-30 14:51:25 +02:00
Benjamin S. Leveritt
ba944c20ed Update subscribe signature + tests 2025-04-30 13:28:07 +01:00
Guido D'Orsi
0b89fadfdd feat(colist): re-introduce incremental processing 2025-04-30 13:12:43 +02:00
Guido D'Orsi
1e50cebf55 test(coList): add failing tests on the append operation 2025-04-30 11:33:52 +02:00
Trisha Lim
ca8c5c0b02 Merge pull request #2010 from garden-co/docs/update-examples-page
update examples page
2025-04-30 09:33:15 +01:00
Benjamin S. Leveritt
a0aa261cab Merge pull request #1998 from garden-co/1962-add-cotext-docs
Adds CoText doc
2025-04-30 08:16:11 +01:00
Benjamin S. Leveritt
5d3d11e87c Merge pull request #2016 from garden-co/1862-react-provider-doc
1862-react-provider-doc
2025-04-30 07:01:09 +01:00
Benjamin S. Leveritt
4a9ed21ea2 Fix links 2025-04-29 20:11:22 +01:00
Guido D'Orsi
2ddfc9d92b Merge pull request #2017 from garden-co/changeset-release/main
Version Packages
2025-04-29 18:43:06 +02:00
github-actions[bot]
a032fda936 Version Packages 2025-04-29 16:34:56 +00:00
Guido D'Orsi
c6fb8dc845 fix: handle null values on msg.id 2025-04-29 18:32:08 +02:00
Trisha Lim
69499e3965 lint 2025-04-29 11:56:01 +01:00
Trisha Lim
d67ced14c4 Merge pull request #1988 from garden-co/tobiaslins-patch-1
[expo] Fix CSS import when using `create-jazz-app`
2025-04-29 11:01:16 +01:00
Trisha Lim
95ae69ead2 add coplaintext to rich text example card 2025-04-29 10:07:44 +01:00
Trisha Lim
4170f13858 jazz-paper-scissors: move api key, add lint, change demo url 2025-04-29 10:07:44 +01:00
Trisha Lim
45e4a77afb lint fix 2025-04-29 10:07:44 +01:00
Trisha Lim
603538e255 add jazz-paper-scissors to examples page 2025-04-29 10:07:44 +01:00
Trisha Lim
afb49f3666 update richtext readme 2025-04-29 10:07:44 +01:00
Trisha Lim
c6de2ce8b8 add richtext example to examples page 2025-04-29 10:07:44 +01:00
Benjamin S. Leveritt
cdc4229df7 Add example app 2025-04-28 22:36:09 +01:00
Benjamin S. Leveritt
fa19f7471f Fix component name 2025-04-28 21:54:18 +01:00
Benjamin S. Leveritt
75f3af2cc1 Adds more config options 2025-04-28 21:48:32 +01:00
Benjamin S. Leveritt
5ae77ee57e Adds React Provider doc 2025-04-28 17:39:35 +01:00
Guido D'Orsi
88ea30a6f8 Merge pull request #2013 from garden-co/changeset-release/main
Version Packages
2025-04-28 14:12:53 +02:00
github-actions[bot]
f4cbe395d5 Version Packages 2025-04-28 12:09:21 +00:00
Guido D'Orsi
c59fb5dc1f fix: complete the incremental view revert 2025-04-28 14:07:15 +02:00
Guido D'Orsi
c712ef28e8 fix(coList): revert incremental processing 2025-04-28 13:20:09 +02:00
Guido D'Orsi
c62a4a1c69 Revert "perf(colist): process the content incrementally"
This reverts commit e05dff9c32.
2025-04-28 13:15:56 +02:00
Benjamin S. Leveritt
87a7cf202f Tweak copy 2025-04-28 11:39:27 +01:00
Benjamin S. Leveritt
9a9b424ff2 Add note about co.strings 2025-04-28 11:39:27 +01:00
Benjamin S. Leveritt
dfe6146aa3 Add Vue example 2025-04-28 11:39:27 +01:00
Benjamin S. Leveritt
8b26728914 Refinements 2025-04-28 11:39:27 +01:00
Benjamin S. Leveritt
f5003ac8ec Add more examples 2025-04-28 11:39:26 +01:00
Benjamin S. Leveritt
ee71ba99e2 Adds CoText doc
Closes #1962
2025-04-28 11:39:26 +01:00
Guido D'Orsi
d28ce598e2 Merge pull request #2003 from garden-co/changeset-release/main
Version Packages
2025-04-26 10:24:45 +02:00
github-actions[bot]
14475991c8 Version Packages 2025-04-25 12:39:39 +00:00
Guido D'Orsi
15d9ec4b38 chore: small cleanup on startPeerReconciliation 2025-04-25 14:37:34 +02:00
Guido D'Orsi
f911545ae3 Merge pull request #2006 from garden-co/chore/simplify-coValue-sync
chore: clean up syncCoValue code and remove the peer role
2025-04-25 13:55:00 +02:00
Guido D'Orsi
ad71530cc0 Merge pull request #2005 from garden-co/feat/no-sync-promises
feat(sync): make the incoming messages handling in the sync manager syncronous
2025-04-25 13:54:35 +02:00
Guido D'Orsi
c33c02691f chore: clean up syncCoValue code and remove the peer role 2025-04-25 13:22:02 +02:00
Guido D'Orsi
51c19770a8 feat: remove unused promises in PeerState outgoing queue 2025-04-25 13:08:20 +02:00
Guido D'Orsi
5c2c7d4188 feat(sync): make the incoming messages handling in the sync manager syncronous 2025-04-25 12:36:31 +02:00
Benjamin S. Leveritt
334d27d53d Merge pull request #2002 from garden-co/2001-fix-unused-vars-in-jazz-paper-scissors
Removes unused vars
2025-04-25 08:19:17 +01:00
Benjamin S. Leveritt
a5396a42ce Merge pull request #1989 from garden-co/fix-rn-metro-docs
docs(metro): fix RN docs for metro config
2025-04-24 15:31:12 +01:00
Benjamin S. Leveritt
5cfe38d547 Removes unused vars 2025-04-24 13:43:25 +01:00
Benjamin S. Leveritt
3f7aa34726 Merge pull request #1996 from garden-co/1995-add-ownership-sections-to-all-the-covalue-docs
Add Ownership sections to CoValue docs
2025-04-24 13:11:52 +01:00
Trisha Lim
008750d401 Merge pull request #1997 from garden-co/docs/framework-component
add Framework component to show framework name
2025-04-24 12:27:54 +01:00
Trisha Lim
72708f82ea add Framework component to show framework name 2025-04-24 12:18:24 +01:00
Benjamin S. Leveritt
30f65f1c91 Add Ownership sections to CoValue docs 2025-04-24 12:06:52 +01:00
Meg Culotta
67d55ce0ee update styles to handle mobile devices (#1944)
* update styles to handle mobile devices

* handle twoslash overflow

---------

Co-authored-by: Margaret Culotta <mculotta@Margarets-MacBook-Air.local>
Co-authored-by: Trisha Lim <hello@trishalim.com>
2025-04-24 09:11:36 +01:00
Trisha Lim
e887f37713 Merge pull request #1994 from garden-co/fix/code-copy
fix(docs): exclude twoslash popovers from getting copied
2025-04-24 09:08:55 +01:00
Trisha Lim
82a515d493 fix(docs): exclude twoslash popovers from getting copied 2025-04-24 08:57:00 +01:00
pax-k
bd94012507 chore: changeset 2025-04-23 23:00:22 +03:00
pax-k
e1dbab1517 chore: changeset 2025-04-23 22:58:11 +03:00
Guido D'Orsi
b675249960 Merge pull request #1990 from garden-co/changeset-release/main
Version Packages
2025-04-23 21:49:44 +02:00
github-actions[bot]
05198e4181 Version Packages 2025-04-23 19:48:47 +00:00
Guido D'Orsi
ec9cb40fa4 fix: remove .every() call on iterator to fix compat issues with React Native 2025-04-23 21:46:27 +02:00
pax-k
dafea6039b docs(metro): fix RN docs for metro config 2025-04-23 22:31:50 +03:00
Tobias Lins
ccc5f89ed7 Fix css path 2025-04-23 21:18:22 +02:00
177 changed files with 4584 additions and 1086 deletions

View File

@@ -1,5 +1,46 @@
# 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
- jazz-expo@0.13.13
- jazz-tools@0.13.13
- jazz-react-native-media-images@0.13.13
## 1.0.104
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "chat-rn-expo-clerk",
"main": "index.js",
"version": "1.0.104",
"version": "1.0.109",
"scripts": {
"build": "expo export -p ios",
"start": "expo start",

View File

@@ -1,5 +1,41 @@
# 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
- jazz-expo@0.13.13
- jazz-tools@0.13.13
## 1.0.91
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-rn-expo",
"version": "1.0.91",
"version": "1.0.96",
"main": "index.js",
"scripts": {
"build": "expo export -p ios",

View File

@@ -1,5 +1,56 @@
# 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
- Updated dependencies [ec9cb40]
- cojson@0.13.13
- cojson-transport-ws@0.13.13
- jazz-react-native@0.13.13
- jazz-tools@0.13.13
## 1.0.99
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-rn",
"version": "1.0.99",
"version": "1.0.104",
"main": "index.js",
"scripts": {
"android": "react-native run-android",

View File

@@ -1,5 +1,45 @@
# 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
- jazz-browser@0.13.13
- jazz-tools@0.13.13
- jazz-vue@0.13.13
## 0.0.83
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-vue",
"version": "0.0.83",
"version": "0.0.88",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,5 +1,45 @@
# 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
- jazz-inspector@0.13.13
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.181
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-chat",
"private": true,
"version": "0.0.181",
"version": "0.0.186",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,45 @@
# 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
- jazz-react@0.13.13
- jazz-react-auth-clerk@0.13.13
- jazz-tools@0.13.13
## 0.0.80
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "clerk",
"private": true,
"version": "0.0.80",
"version": "0.0.85",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,40 @@
# 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
- jazz-svelte@0.13.13
- jazz-tools@0.13.13
## 0.0.63
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "file-share-svelte",
"version": "0.0.63",
"version": "0.0.68",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,5 +1,45 @@
# 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
- jazz-inspector@0.13.13
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.20
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "filestream",
"private": true,
"version": "0.0.20",
"version": "0.0.25",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,40 @@
# 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
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.1.21
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "form",
"private": true,
"version": "0.1.21",
"version": "0.1.26",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,40 @@
# 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
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.77
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "image-upload",
"private": true,
"version": "0.0.77",
"version": "0.0.82",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,51 @@
# 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
- Updated dependencies [ec9cb40]
- cojson@0.13.13
- cojson-transport-ws@0.13.13
- jazz-inspector@0.13.13
## 0.0.131
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-inspector-app",
"private": true,
"version": "0.0.131",
"version": "0.0.136",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -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",

View File

@@ -0,0 +1 @@
export const apiKey = "jazz-paper-scissors@garden.co";

View File

@@ -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 />

View File

@@ -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

View File

@@ -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";

View File

@@ -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);

View File

@@ -1,5 +1,40 @@
# 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
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.73
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "multi-cursors",
"private": true,
"version": "0.0.73",
"version": "0.0.78",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,45 @@
# 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
- jazz-react@0.13.13
- jazz-react-auth-clerk@0.13.13
- jazz-tools@0.13.13
## 0.0.21
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "multiauth",
"private": true,
"version": "0.0.21",
"version": "0.0.26",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,45 @@
# 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
- jazz-inspector@0.13.13
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.102
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-music-player",
"private": true,
"version": "0.0.102",
"version": "0.0.107",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,40 @@
# 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
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.73
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "organization",
"private": true,
"version": "0.0.73",
"version": "0.0.78",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,40 @@
# 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
- jazz-svelte@0.13.13
- jazz-tools@0.13.13
## 0.0.67
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "passkey-svelte",
"version": "0.0.67",
"version": "0.0.72",
"type": "module",
"private": true,
"scripts": {

View File

@@ -1,5 +1,40 @@
# 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
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.78
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "passkey",
"private": true,
"version": "0.0.78",
"version": "0.0.83",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,40 @@
# 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
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.75
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "passphrase",
"private": true,
"version": "0.0.75",
"version": "0.0.80",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,40 @@
# 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
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.99
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-password-manager",
"private": true,
"version": "0.0.99",
"version": "0.0.104",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,40 @@
# 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
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.197
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-pets",
"private": true,
"version": "0.0.197",
"version": "0.0.202",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,40 @@
# 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
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.77
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "reactions",
"private": true,
"version": "0.0.77",
"version": "0.0.82",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,46 @@
# 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
- jazz-react@0.13.13
- jazz-tools@0.13.13
- jazz-richtext-prosemirror@0.1.2
## 0.0.67
### Patch Changes

View File

@@ -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.

View File

@@ -1,7 +1,7 @@
{
"name": "richtext",
"private": true,
"version": "0.0.67",
"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",

View File

@@ -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);

View File

@@ -1,3 +1,10 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
.ProseMirror ul {
@apply list-disc;
}
.ProseMirror ol {
@apply list-decimal;
}

View File

@@ -1,5 +1,45 @@
# 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
- jazz-browser@0.13.13
- jazz-tools@0.13.13
- jazz-vue@0.13.13
## 0.0.81
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "todo-vue",
"version": "0.0.81",
"version": "0.0.86",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,5 +1,40 @@
# 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
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.196
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-todo",
"private": true,
"version": "0.0.196",
"version": "0.0.201",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,45 @@
# 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
- jazz-inspector@0.13.13
- jazz-react@0.13.13
- jazz-tools@0.13.13
## 0.0.75
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "version-history",
"private": true,
"version": "0.0.75",
"version": "0.0.80",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -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

View File

@@ -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]);

View File

@@ -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";

View File

@@ -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>
),

View File

@@ -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";

View File

@@ -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}`,

View File

@@ -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 (

View File

@@ -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,

View File

@@ -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";

View File

@@ -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,

View File

@@ -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,

View 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}</>;
}

View File

@@ -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}

View File

@@ -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";

View File

@@ -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 />;
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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",

View 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.

View File

@@ -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($|\/|\\)/];

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View 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>

View File

@@ -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

View File

@@ -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:

View File

@@ -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:

View File

@@ -26,4 +26,8 @@ export const features = {
clerk: "Clerk auth",
inviteLink: "Invite link",
coFeed: "CoFeed",
coRichText: "CoRichText",
coPlainText: "CoPlainText",
serverWorker: "Server worker",
inbox: "Inbox",
};

View File

@@ -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;

View File

@@ -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>
);

View File

@@ -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",

View File

@@ -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

View File

@@ -1,5 +1,46 @@
# 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
- Updated dependencies [ec9cb40]
- cojson@0.13.13
- cojson-storage@0.13.13
## 0.13.12
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "cojson-storage-indexeddb",
"version": "0.13.12",
"version": "0.13.17",
"main": "dist/index.js",
"type": "module",
"types": "dist/index.d.ts",

View File

@@ -1,5 +1,46 @@
# 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
- Updated dependencies [ec9cb40]
- cojson@0.13.13
- cojson-storage@0.13.13
## 0.13.12
### Patch Changes

View File

@@ -1,13 +1,13 @@
{
"name": "cojson-storage-sqlite",
"type": "module",
"version": "0.13.12",
"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.12",
"cojson": "workspace:0.13.17",
"cojson-storage": "workspace:*"
},
"devDependencies": {

View File

@@ -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",
]
`);
});

View File

@@ -1,5 +1,41 @@
# 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
- Updated dependencies [ec9cb40]
- cojson@0.13.13
## 0.13.12
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "cojson-storage",
"version": "0.13.12",
"version": "0.13.17",
"main": "dist/index.js",
"type": "module",
"types": "dist/index.d.ts",

View File

@@ -1,5 +1,41 @@
# 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
- Updated dependencies [ec9cb40]
- cojson@0.13.13
## 0.13.12
### Patch Changes

Some files were not shown because too many files have changed in this diff Show More