Compare commits

..

3 Commits

Author SHA1 Message Date
pax-k
849c2b9ffc fix(useCoState): requested changes 2025-03-10 16:30:07 +02:00
pax-k
56860d406b chore: changeset 2025-02-28 13:12:48 +02:00
pax-k
357d1b4c8d fix: useCoState stale data 2025-02-28 13:11:47 +02:00
303 changed files with 1320 additions and 12471 deletions

View File

@@ -9,15 +9,12 @@
"cojson-storage",
"cojson-storage-indexeddb",
"cojson-storage-sqlite",
"cojson-storage-rn-sqlite",
"cojson-transport-ws",
"jazz-browser",
"jazz-auth-clerk",
"jazz-browser-media-images",
"jazz-inspector",
"jazz-nodejs",
"jazz-react",
"jazz-react-core",
"jazz-react-auth-clerk",
"jazz-react-native",
"jazz-react-native-auth-clerk",

View File

@@ -0,0 +1,5 @@
---
"jazz-react-core": patch
---
Fix useCoState stale data

View File

@@ -0,0 +1,5 @@
---
"create-jazz-app": patch
---
Added Cursor docs to create-jazz-app

View File

@@ -25,9 +25,6 @@ jobs:
- name: Setup Source Code
uses: ./.github/actions/source-code/
- name: Build packages
run: pnpm exec turbo run build --filter='./packages/*'
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@v1

View File

@@ -1,79 +1,5 @@
# chat-rn-clerk
## 1.0.85
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react-native@0.11.4
- jazz-react-native-auth-clerk@0.11.4
- jazz-react-native-media-images@0.11.4
## 1.0.84
### Patch Changes
- jazz-react-native@0.11.3
- jazz-react-native-auth-clerk@0.11.3
- jazz-tools@0.11.3
- jazz-react-native-media-images@0.11.3
## 1.0.83
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react-native@0.11.2
- jazz-react-native-auth-clerk@0.11.2
- jazz-react-native-media-images@0.11.2
## 1.0.82
### Patch Changes
- jazz-react-native@0.11.1
- jazz-react-native-auth-clerk@0.11.1
## 1.0.81
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-react-native-media-images@0.11.0
- jazz-react-native-auth-clerk@0.11.0
- jazz-react-native@0.11.0
## 1.0.80
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react-native@0.10.15
- jazz-react-native-auth-clerk@0.10.15
- jazz-react-native-media-images@0.10.15
## 1.0.79
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react-native@0.10.14
- jazz-react-native-auth-clerk@0.10.14
- jazz-react-native-media-images@0.10.14
## 1.0.78
### Patch Changes

View File

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

View File

@@ -1,66 +1,5 @@
# chat-rn
## 1.0.81
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react-native@0.11.4
## 1.0.80
### Patch Changes
- jazz-react-native@0.11.3
- jazz-tools@0.11.3
## 1.0.79
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react-native@0.11.2
## 1.0.78
### Patch Changes
- jazz-react-native@0.11.1
## 1.0.77
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-react-native@0.11.0
## 1.0.76
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react-native@0.10.15
## 1.0.75
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react-native@0.10.14
## 1.0.74
### Patch Changes

View File

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

View File

@@ -25,8 +25,11 @@ appId: com.jazz.chatrn
- assertVisible: "Logout"
# send a message
- tapOn:
id: "message-input"
- runFlow:
label: "Erase existing message"
file: erase_text.yml
env:
id: "message-input"
- inputText: "bro, low key, it do be like that tho"
- tapOn:
id: "send-button"
@@ -41,10 +44,5 @@ appId: com.jazz.chatrn
# logout
- tapOn: "Logout"
- assertVisible: "Anonymous user"
# This doesn't work on CI, maybe because Android has a different alert dialog
# - tapOn: "Join chat"
# - inputText: "co_zFs6KFyhxPw4xtw83tcEMzeHUNv" # Use a static id because maestro doesn't have access to the system clipboard
# - pressKey: "enter"
# - assertVisible: "boorad"
# - assertVisible: "bro, low key, it do be like that tho"
- assertVisible: "boorad"
- assertVisible: "bro, low key, it do be like that tho"

View File

@@ -1,67 +1,5 @@
# chat-vue
## 0.0.66
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-browser@0.11.4
- jazz-vue@0.11.4
## 0.0.65
### Patch Changes
- jazz-browser@0.11.3
- jazz-tools@0.11.3
- jazz-vue@0.11.3
## 0.0.64
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-browser@0.11.2
- jazz-vue@0.11.2
## 0.0.63
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [18428ea]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-browser@0.11.0
- jazz-vue@0.11.0
## 0.0.62
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-browser@0.10.15
- jazz-vue@0.10.15
## 0.0.61
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-browser@0.10.14
- jazz-vue@0.10.14
## 0.0.60
### Patch Changes

View File

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

View File

@@ -1,73 +1,5 @@
# jazz-example-chat
## 0.0.163
### Patch Changes
- 2074e45: In the chat app example, show a "Message not readable" placeholder, if messages from a chat list are not readable by the user.
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-browser-media-images@0.11.4
- jazz-react@0.11.4
## 0.0.162
### Patch Changes
- jazz-react@0.11.3
- jazz-tools@0.11.3
- jazz-browser-media-images@0.11.3
## 0.0.161
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
- jazz-browser-media-images@0.11.2
## 0.0.160
### Patch Changes
- jazz-react@0.11.1
## 0.0.159
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-browser-media-images@0.11.0
- jazz-react@0.11.0
## 0.0.158
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-browser-media-images@0.10.15
- jazz-react@0.10.15
## 0.0.157
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
- jazz-browser-media-images@0.10.14
## 0.0.156
### Patch Changes

View File

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

View File

@@ -1,6 +1,6 @@
import { createImage } from "jazz-browser-media-images";
import { useAccount, useCoState } from "jazz-react";
import { Account, ID } from "jazz-tools";
import { useCoState } from "jazz-react";
import { ID } from "jazz-tools";
import { useState } from "react";
import { Chat, Message } from "./schema.ts";
import {
@@ -17,7 +17,6 @@ import {
} from "./ui.tsx";
export function ChatScreen(props: { chatID: ID<Chat> }) {
const account = useAccount();
const chat = useCoState(Chat, props.chatID, [{}]);
const [showNLastMessages, setShowNLastMessages] = useState(30);
@@ -48,7 +47,7 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
chat
.slice(-showNLastMessages)
.reverse() // this plus flex-col-reverse on ChatBody gives us scroll-to-bottom behavior
.map((msg) => <ChatBubble me={account.me} msg={msg} key={msg.id} />)
.map((msg) => <ChatBubble msg={msg} key={msg.id} />)
) : (
<EmptyChatMessage />
)}
@@ -75,20 +74,7 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
);
}
function ChatBubble(props: { me: Account; msg: Message }) {
if (!props.me.canRead(props.msg)) {
return (
<BubbleContainer fromMe={false}>
<BubbleBody fromMe={false}>
<BubbleText
text="Message not readable"
className="text-gray-500 italic"
/>
</BubbleBody>
</BubbleContainer>
);
}
function ChatBubble(props: { msg: Message }) {
const lastEdit = props.msg._edits.text;
const fromMe = lastEdit.by?.isMe;
const { text, image } = props.msg;

View File

@@ -70,12 +70,8 @@ export function BubbleBody(props: {
);
}
export function BubbleText(props: { text: string; className?: string }) {
return (
<p className={clsx("px-2 leading-relaxed", props.className)}>
{props.text}
</p>
);
export function BubbleText(props: { text: string }) {
return <p className="px-2 leading-relaxed">{props.text}</p>;
}
export function BubbleImage(props: { image: ImageDefinition }) {

View File

@@ -1,73 +1,5 @@
# minimal-auth-clerk
## 0.0.62
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react@0.11.4
- jazz-react-auth-clerk@0.11.4
## 0.0.61
### Patch Changes
- jazz-react@0.11.3
- jazz-react-auth-clerk@0.11.3
- jazz-tools@0.11.3
## 0.0.60
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
- jazz-react-auth-clerk@0.11.2
## 0.0.59
### Patch Changes
- jazz-react@0.11.1
- jazz-react-auth-clerk@0.11.1
## 0.0.58
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-react-auth-clerk@0.11.0
- jazz-react@0.11.0
## 0.0.57
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react@0.10.15
- jazz-react-auth-clerk@0.10.15
## 0.0.56
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
- jazz-react-auth-clerk@0.10.14
## 0.0.55
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "clerk",
"private": true,
"version": "0.0.62",
"version": "0.0.55",
"type": "module",
"scripts": {
"dev": "vite",
@@ -13,7 +13,7 @@
"dependencies": {
"@clerk/clerk-react": "^5.4.1",
"jazz-react": "workspace:*",
"jazz-react-auth-clerk": "workspace:0.11.4",
"jazz-react-auth-clerk": "workspace:0.10.13",
"jazz-tools": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1"

View File

@@ -1,60 +1,5 @@
# file-share-svelte
## 0.0.46
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-svelte@0.11.4
## 0.0.45
### Patch Changes
- jazz-svelte@0.11.3
- jazz-tools@0.11.3
## 0.0.44
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-svelte@0.11.2
## 0.0.43
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-svelte@0.11.0
## 0.0.42
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-svelte@0.10.15
## 0.0.41
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-svelte@0.10.14
## 0.0.40
### Patch Changes

View File

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

View File

@@ -1,28 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
/test-results/
/playwright-report/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
playwright-report

View File

@@ -1,277 +0,0 @@
# jazz-tailwind-demo-auth-starter
## 0.0.2
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react@0.11.4
## 0.0.52
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react@0.10.15
## 0.0.51
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
## 0.0.50
### Patch Changes
- Updated dependencies [07feedd]
- jazz-tools@0.10.13
- jazz-react@0.10.13
## 0.0.49
### Patch Changes
- Updated dependencies [4612e05]
- jazz-tools@0.10.12
- jazz-react@0.10.12
## 0.0.48
### Patch Changes
- jazz-react@0.10.9
## 0.0.47
### Patch Changes
- Updated dependencies [2fb6428]
- jazz-tools@0.10.8
- jazz-react@0.10.8
## 0.0.46
### Patch Changes
- Updated dependencies [1136d9b]
- Updated dependencies [0eed228]
- jazz-react@0.10.7
- jazz-tools@0.10.7
## 0.0.45
### Patch Changes
- Updated dependencies [1d71ca1]
- Updated dependencies [ada802b]
- jazz-react@0.10.6
- jazz-tools@0.10.6
## 0.0.44
### Patch Changes
- Updated dependencies [59ff77e]
- jazz-tools@0.10.5
- jazz-react@0.10.5
## 0.0.43
### Patch Changes
- jazz-react@0.10.4
- jazz-tools@0.10.4
## 0.0.42
### Patch Changes
- Updated dependencies [d8582fc]
- jazz-tools@0.10.3
- jazz-react@0.10.3
## 0.0.41
### Patch Changes
- jazz-react@0.10.2
- jazz-tools@0.10.2
## 0.0.40
### Patch Changes
- Updated dependencies [5a63cba]
- jazz-tools@0.10.1
- jazz-react@0.10.1
## 0.0.39
### Patch Changes
- Updated dependencies [498954f]
- Updated dependencies [d42c2aa]
- Updated dependencies [dd03464]
- Updated dependencies [b426342]
- jazz-react@0.10.0
- jazz-tools@0.10.0
## 0.0.38
### Patch Changes
- jazz-react@0.9.23
- jazz-tools@0.9.23
## 0.0.37
### Patch Changes
- jazz-react@0.9.22
## 0.0.36
### Patch Changes
- Updated dependencies [1be017d]
- jazz-tools@0.9.21
- jazz-react@0.9.21
## 0.0.35
### Patch Changes
- Updated dependencies [b01cc1f]
- jazz-tools@0.9.20
- jazz-react@0.9.20
## 0.0.34
### Patch Changes
- jazz-react@0.9.19
- jazz-tools@0.9.19
## 0.0.33
### Patch Changes
- jazz-react@0.9.18
- jazz-tools@0.9.18
## 0.0.32
### Patch Changes
- Updated dependencies [c2ca1fe]
- Updated dependencies [1227047]
- jazz-tools@0.9.17
- jazz-react@0.9.17
## 0.0.31
### Patch Changes
- Updated dependencies [24b3b6a]
- jazz-tools@0.9.16
- jazz-react@0.9.16
## 0.0.30
### Patch Changes
- Updated dependencies [7491711]
- jazz-tools@0.9.15
- jazz-react@0.9.15
## 0.0.29
### Patch Changes
- Updated dependencies [3df93cc]
- jazz-tools@0.9.14
- jazz-react@0.9.14
## 0.0.28
### Patch Changes
- jazz-react@0.9.13
- jazz-tools@0.9.13
## 0.0.27
### Patch Changes
- jazz-react@0.9.12
- jazz-tools@0.9.12
## 0.0.26
### Patch Changes
- jazz-react@0.9.11
- jazz-tools@0.9.11
## 0.0.25
### Patch Changes
- Updated dependencies [5e83864]
- jazz-react@0.9.10
- jazz-tools@0.9.10
## 0.0.24
### Patch Changes
- Updated dependencies [8eb9247]
- jazz-tools@0.9.9
- jazz-react@0.9.9
## 0.0.23
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
## 0.0.22
### Patch Changes
- jazz-react@0.9.4
## 0.0.21
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
## 0.0.20
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
## 0.0.19
### Patch Changes
- Updated dependencies [dc62b95]
- Updated dependencies [1de26f8]
- jazz-tools@0.8.51
- jazz-react@0.8.51

View File

@@ -1,66 +0,0 @@
# File upload example with Jazz and React
This is an example of how to upload and render images with Jazz.
Live version: https://file-upload-demo.jazz.tools
## Getting started
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.
### Using the example as a template
Create a new Jazz project, and use this example as a template.
```bash
npx create-jazz-app@latest --example file-upload --project-name file-upload
```
Go to the new project directory.
```bash
cd file-upload
```
Run the dev server.
```bash
npm run 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/file-upload/
```
Start the dev server.
```bash
pnpm dev
```
Open [http://localhost:5173](http://localhost:5173) with your browser to see the result.
## Questions / problems / feedback
If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or open an issue or PR to fix something that seems wrong.
## Configuration: sync server
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of `JazzProvider` component in [./src/main.tsx](./src/main.tsx).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,13 +0,0 @@
<!doctype html>
<html lang="en" class="h-full">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Jazz | React + Demo Auth + Tailwind</title>
</head>
<body class="h-full flex flex-col">
<div id="root" class="align-self-center flex-1"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

View File

@@ -1,32 +0,0 @@
{
"name": "filestream",
"private": true,
"version": "0.0.2",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"format-and-lint": "biome check .",
"format-and-lint:fix": "biome check . --write"
},
"dependencies": {
"jazz-react": "workspace:*",
"jazz-tools": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"autoprefixer": "^10.4.20",
"globals": "^15.11.0",
"is-ci": "^3.0.1",
"postcss": "^8.5.3",
"tailwindcss": "^3.4.17",
"typescript": "~5.6.2",
"vite": "^6.0.11"
}
}

View File

@@ -1,46 +0,0 @@
import { defineConfig, devices } from "@playwright/test";
import isCI from "is-ci";
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./tests",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: isCI,
/* Retry on CI only */
retries: isCI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: isCI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "http://localhost:5173/",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
permissions: ["clipboard-read", "clipboard-write"],
},
/* Configure projects for major browsers */
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
],
/* Run your local dev server before starting the tests */
webServer: [
{
command: "pnpm preview --port 5173",
url: "http://localhost:5173/",
reuseExistingServer: !isCI,
},
],
});

View File

@@ -1,6 +0,0 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@@ -1,37 +0,0 @@
import { FileWidget } from "./FileWidget.js";
import { Logo } from "./Logo.tsx";
function App() {
return (
<>
<main className="container mt-16 flex flex-col gap-8">
<Logo />
<FileWidget />
<p className="text-center">
Edit the form above,{" "}
<button
type="button"
onClick={() => window.location.reload()}
className="font-semibold underline"
>
refresh
</button>{" "}
this page, and see your changes persist.
</p>
<p className="text-center my-16">
Go to{" "}
<a
className="font-semibold underline"
href="https://jazz.tools/docs/react/guide"
>
jazz.tools/docs/react/guide
</a>{" "}
for a full tutorial.
</p>
</main>
</>
);
}
export default App;

View File

@@ -1,269 +0,0 @@
"use client";
import { useAccount } from "jazz-react";
import { FileStream } from "jazz-tools";
import { useRef, useState } from "react";
export function FileWidget() {
const inputRef = useRef<HTMLInputElement>(null);
const dragAndDropElementRef = useRef<HTMLDivElement>(null);
const [isUploading, setIsUploading] = useState(false);
const [progress, setProgress] = useState(0);
const [error, setError] = useState<string | null>(null);
const { me } = useAccount();
async function handleUpload(event: React.FormEvent) {
event.preventDefault();
setError(null);
if (!me?.profile) {
setError("User profile not found");
return;
}
setProgress(0);
const file = inputRef.current?.files?.[0];
if (!file) {
setError("Please select a file");
return;
}
try {
setIsUploading(true);
me.profile.file = await FileStream.createFromBlob(file, {
onProgress: (p) => setProgress(Math.round(p * 100)),
});
} catch (error) {
setError(
error instanceof Error ? error.message : "Failed to upload file",
);
console.error("Error uploading file:", error);
} finally {
setIsUploading(false);
}
}
function handleDelete() {
if (!me?.profile) return;
delete me.profile?.file;
}
async function handleDownload() {
if (!me?.profile) return;
const file = me.profile.file;
if (!file) return;
try {
const blob = file.toBlob();
const url = URL.createObjectURL(blob || new Blob());
const a = document.createElement("a");
a.href = url;
a.download = file.id || "download";
a.click();
URL.revokeObjectURL(url);
} catch (error) {
console.error("Error downloading file:", error);
}
}
function formatFileSize(bytes?: number): string {
if (!bytes) return "0 Bytes";
const k = 1024;
const sizes = ["Bytes", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
}
const onDragEnter = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
dragAndDropElementRef?.current?.classList.replace(
"border-stone-400",
"border-blue-700",
);
};
const onDragOver = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
dragAndDropElementRef?.current?.classList.replace(
"border-stone-400",
"border-blue-700",
);
};
const onDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
dragAndDropElementRef?.current?.classList.replace(
"border-blue-700",
"border-stone-400",
);
};
const onDrop = async (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
dragAndDropElementRef?.current?.classList.replace(
"border-blue-700",
"border-stone-400",
);
if (!me?.profile) {
setError("User profile not found");
return;
}
const droppedFiles = e.dataTransfer.files;
if (!droppedFiles || droppedFiles.length === 0) {
return;
}
const file = droppedFiles[0];
setProgress(0);
try {
setIsUploading(true);
me.profile.file = await FileStream.createFromBlob(file, {
onProgress: (p) => setProgress(Math.round(p * 100)),
});
} catch (error) {
setError(
error instanceof Error ? error.message : "Failed to upload file",
);
console.error("Error uploading file:", error);
} finally {
setIsUploading(false);
}
};
if (me?.profile?.file == null) {
return (
<div className="flex flex-col gap-4">
<div
className="flex flex-col border-2 border-dashed border-stone-400 h-48 items-center justify-center bg-stone-100 m-5 rounded-md"
ref={dragAndDropElementRef}
onDragEnter={onDragEnter}
onDragOver={onDragOver}
onDragLeave={onDragLeave}
onDrop={onDrop}
>
<p>Drag & drop your file here</p>
</div>
<form onSubmit={handleUpload} className="flex gap-2">
<input
className="bg-stone-100 py-1.5 px-2 text-sm rounded-md w-4/5"
ref={inputRef}
type="file"
accept="file"
onChange={() => setError(null)}
disabled={isUploading}
/>
<button
type="submit"
className="bg-stone-100 py-1.5 px-3 text-sm rounded-md disabled:opacity-50"
disabled={isUploading}
>
{isUploading ? `Uploading...` : "Upload file"}
</button>
</form>
{error && (
<div className="text-red-800 text-sm pl-4" role="alert">
{error}
</div>
)}
{isUploading && (
<div className="flex gap-2 items-center">
<div className="py-1.5 px-3 text-sm">Progress: {progress}%</div>
<div className="h-2 bg-stone-200 rounded-full flex-1">
<div
className="h-full bg-blue-500 rounded-full transition-all duration-300"
style={{ width: `${progress}%` }}
/>
</div>
</div>
)}
</div>
);
}
const fileData = me?.profile?.file?.getChunks();
const mimeType = fileData?.mimeType || "unknown";
return (
<div className="gap-2">
<div className="p-4">
<div className="space-y-2">
<div className="flex justify-between">
<span className="font-bold">File name</span>
<span>{fileData?.fileName}</span>
</div>
<div className="flex justify-between">
<span className="font-bold">Type</span>
<span>{mimeType}</span>
</div>
<div className="flex justify-between">
<span className="font-bold">Size</span>
<span>{formatFileSize(fileData?.totalSizeBytes)}</span>
</div>
</div>
</div>
<div className="flex gap-2 justify-end">
<button
className="bg-stone-100 py-1.5 px-3 text-sm rounded-md"
onClick={handleDelete}
>
Delete file
</button>
<button
className="bg-stone-100 py-1.5 px-3 text-sm rounded-md"
onClick={handleDownload}
>
Download file
</button>
</div>
<div className="w-full justify-center pt-8">
{fileData?.mimeType?.startsWith("image/") && (
<div className="flex justify-center">
<img
src={URL.createObjectURL(
me?.profile?.file?.toBlob() || new Blob(),
)}
alt="File preview"
className="max-w-xs mb-4"
/>
</div>
)}
{fileData?.mimeType?.startsWith("audio/") && (
<div className="flex justify-center">
<audio
src={URL.createObjectURL(
me?.profile?.file?.toBlob() || new Blob(),
)}
controls
className="w-full mb-4"
/>
</div>
)}
{fileData?.mimeType?.startsWith("video/") && (
<div className="flex justify-center">
<video
src={URL.createObjectURL(
me?.profile?.file?.toBlob() || new Blob(),
)}
controls
className="w-full mb-4"
/>
</div>
)}
</div>
</div>
);
}

View File

@@ -1,21 +0,0 @@
export function Logo() {
return (
<svg
viewBox="0 0 386 146"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="text-black w-48 mx-auto"
>
<path
d="M176.725 33.865H188.275V22.7H176.725V33.865ZM164.9 129.4H172.875C182.72 129.4 188.275 123.9 188.275 114.22V43.6H176.725V109.545C176.725 115.65 173.975 118.51 167.925 118.51H164.9V129.4ZM245.298 53.28C241.613 45.47 233.363 41.95 222.748 41.95C208.998 41.95 200.748 48.44 197.888 58.615L208.613 61.915C210.648 55.315 216.368 52.565 222.638 52.565C231.933 52.565 235.673 56.415 236.058 64.61C226.433 65.93 216.643 67.195 209.768 69.23C200.583 72.145 195.743 77.865 195.743 86.83C195.743 96.51 202.673 104.65 215.818 104.65C225.443 104.65 232.318 101.35 237.213 94.365V103H247.388V66.425C247.388 61.475 247.168 57.185 245.298 53.28ZM217.853 95.245C210.483 95.245 207.128 91.34 207.128 86.72C207.128 82.045 210.593 79.515 215.323 77.92C220.328 76.435 226.983 75.5 235.948 74.18C235.893 76.93 235.673 80.725 234.738 83.475C233.418 89.25 227.643 95.245 217.853 95.245ZM251.22 103H301.545V92.715H269.535L303.195 45.47V43.6H254.3V53.885H284.935L251.22 101.185V103ZM304.815 103H355.14V92.715H323.13L356.79 45.47V43.6H307.895V53.885H338.53L304.815 101.185V103Z"
fill="currentColor"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M136.179 44.8277C136.179 44.8277 136.179 44.8277 136.179 44.8276V21.168C117.931 28.5527 97.9854 32.6192 77.0897 32.6192C65.1466 32.6192 53.5138 31.2908 42.331 28.7737V51.4076C42.331 51.4076 42.331 51.4076 42.331 51.4076V81.1508C41.2955 80.4385 40.1568 79.8458 38.9405 79.3915C36.1732 78.358 33.128 78.0876 30.1902 78.6145C27.2524 79.1414 24.5539 80.4419 22.4358 82.3516C20.3178 84.2613 18.8754 86.6944 18.291 89.3433C17.7066 91.9921 18.0066 94.7377 19.1528 97.2329C20.2991 99.728 22.2403 101.861 24.7308 103.361C27.2214 104.862 30.1495 105.662 33.1448 105.662H33.1455C33.6061 105.662 33.8365 105.662 34.0314 105.659C44.5583 105.449 53.042 96.9656 53.2513 86.4386C53.2534 86.3306 53.2544 86.2116 53.2548 86.0486H53.2552V85.7149L53.2552 85.5521V82.0762L53.2552 53.1993C61.0533 54.2324 69.0092 54.7656 77.0897 54.7656C77.6696 54.7656 78.2489 54.7629 78.8276 54.7574V110.696C77.792 109.983 76.6533 109.391 75.437 108.936C72.6697 107.903 69.6246 107.632 66.6867 108.159C63.7489 108.686 61.0504 109.987 58.9323 111.896C56.8143 113.806 55.3719 116.239 54.7875 118.888C54.2032 121.537 54.5031 124.283 55.6494 126.778C56.7956 129.273 58.7368 131.405 61.2273 132.906C63.7179 134.406 66.646 135.207 69.6414 135.207C70.1024 135.207 70.3329 135.207 70.5279 135.203C81.0548 134.994 89.5385 126.51 89.7478 115.983C89.7517 115.788 89.7517 115.558 89.7517 115.097V111.621L89.7517 54.3266C101.962 53.4768 113.837 51.4075 125.255 48.2397V80.9017C124.219 80.1894 123.081 79.5966 121.864 79.1424C119.097 78.1089 116.052 77.8384 113.114 78.3653C110.176 78.8922 107.478 80.1927 105.36 82.1025C103.242 84.0122 101.799 86.4453 101.215 89.0941C100.631 91.743 100.931 94.4886 102.077 96.9837C103.223 99.4789 105.164 101.612 107.655 103.112C110.145 104.612 113.073 105.413 116.069 105.413C116.53 105.413 116.76 105.413 116.955 105.409C127.482 105.2 135.966 96.7164 136.175 86.1895C136.179 85.9945 136.179 85.764 136.179 85.3029V81.8271L136.179 44.8277Z"
fill="#3313F7"
/>
</svg>
);
}

View File

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

View File

@@ -1,3 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -1,29 +0,0 @@
import { JazzProvider } from "jazz-react";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import { apiKey } from "./apiKey.ts";
import "./index.css";
import { JazzAccount } from "./schema.ts";
// We use this to identify the app in the passkey auth
export const APPLICATION_NAME = "Jazz File Stream Example";
declare module "jazz-react" {
export interface Register {
Account: JazzAccount;
}
}
createRoot(document.getElementById("root")!).render(
<StrictMode>
<JazzProvider
sync={{
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
}}
AccountSchema={JazzAccount}
>
<App />
</JazzProvider>
</StrictMode>,
);

View File

@@ -1,14 +0,0 @@
import { Account, FileStream, Profile, co } from "jazz-tools";
export class JazzProfile extends Profile {
file = co.ref(FileStream, { optional: true });
}
export class JazzAccount extends Account {
profile = co.ref(JazzProfile);
/** The account migration is run on account creation and on every log-in.
* You can use it to set up the account root and any other initial CoValues you need.
*/
migrate(this: JazzAccount) {}
}

View File

@@ -1 +0,0 @@
/// <reference types="vite/client" />

View File

@@ -1,23 +0,0 @@
import type { Config } from "tailwindcss";
const config: Config = {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
container: {
center: true,
padding: {
DEFAULT: "0.75rem",
sm: "1rem",
},
screens: {
lg: "600px",
xl: "600px",
},
},
},
},
plugins: [],
} as const;
export default config;

View File

@@ -1,9 +0,0 @@
import { expect, test } from "@playwright/test";
test("home page loads", async ({ page }) => {
await page.goto("/");
await expect(page.getByText("Welcome!")).toBeVisible();
await page.getByLabel("Name").fill("Bob");
await expect(page.getByText("Welcome, Bob!")).toBeVisible();
});

View File

@@ -1,24 +0,0 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2023", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

View File

@@ -1,7 +0,0 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

View File

@@ -1,22 +0,0 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -1,8 +0,0 @@
{
"build": {
"env": {
"APP_NAME": "filestream"
}
},
"ignoreCommand": "node ../../ignore-vercel-build.js"
}

View File

@@ -1,7 +0,0 @@
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
});

View File

@@ -1,76 +1,5 @@
# form
## 0.1.4
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-browser-media-images@0.11.4
- jazz-react@0.11.4
## 0.1.3
### Patch Changes
- jazz-react@0.11.3
- jazz-tools@0.11.3
- jazz-browser-media-images@0.11.3
## 0.1.2
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
- jazz-browser-media-images@0.11.2
## 0.1.1
### Patch Changes
- jazz-react@0.11.1
## 0.1.0
### Minor Changes
- 18428ea: PasskeyAuth: Sets `profile.name` only if a non-empty username is passed to `signUp`
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-browser-media-images@0.11.0
- jazz-react@0.11.0
## 0.0.53
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-browser-media-images@0.10.15
- jazz-react@0.10.15
## 0.0.52
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
- jazz-browser-media-images@0.10.14
## 0.0.51
### Patch Changes

View File

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

View File

@@ -1,72 +1,5 @@
# image-upload
## 0.0.60
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-browser-media-images@0.11.4
- jazz-react@0.11.4
## 0.0.59
### Patch Changes
- jazz-react@0.11.3
- jazz-tools@0.11.3
- jazz-browser-media-images@0.11.3
## 0.0.58
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
- jazz-browser-media-images@0.11.2
## 0.0.57
### Patch Changes
- jazz-react@0.11.1
## 0.0.56
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-browser-media-images@0.11.0
- jazz-react@0.11.0
## 0.0.55
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-browser-media-images@0.10.15
- jazz-react@0.10.15
## 0.0.54
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
- jazz-browser-media-images@0.10.14
## 0.0.53
### Patch Changes

View File

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

View File

@@ -1,41 +1,5 @@
# jazz-example-inspector
## 0.0.113
### Patch Changes
- Updated dependencies [7f036c1]
- cojson@0.11.4
- cojson-transport-ws@0.11.4
## 0.0.112
### Patch Changes
- Updated dependencies [68b0242]
- cojson-transport-ws@0.11.3
- cojson@0.11.3
## 0.0.111
### Patch Changes
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [e22de9f]
- Updated dependencies [34cbdc3]
- Updated dependencies [0f67e0a]
- cojson@0.11.0
- cojson-transport-ws@0.11.0
## 0.0.110
### Patch Changes
- Updated dependencies [f86e278]
- cojson@0.10.15
- cojson-transport-ws@0.10.15
## 0.0.109
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-inspector-app",
"private": true,
"version": "0.0.113",
"version": "0.0.109",
"type": "module",
"scripts": {
"dev": "vite",
@@ -16,8 +16,8 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cojson": "workspace:0.11.4",
"cojson-transport-ws": "workspace:0.11.4",
"cojson": "workspace:0.10.8",
"cojson-transport-ws": "workspace:0.10.8",
"hash-slash": "workspace:0.2.2",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",

View File

@@ -83,10 +83,7 @@ export default function CoJsonViewerApp() {
const addAccount = (id: RawAccountID, secret: AgentSecret) => {
const newAccount = { id, secret };
const accountExists = accounts.some((account) => account.id === id);
if (!accountExists) {
setAccounts([...accounts, newAccount]);
}
setAccounts([...accounts, newAccount]);
setCurrentAccount(newAccount);
};

View File

@@ -1 +0,0 @@
VITE_CLERK_PUBLISHABLE_KEY=pk_test_ZXZpZGVudC1kYW5lLTg5LmNsZXJrLmFjY291bnRzLmRldiQ

View File

@@ -1,24 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -1,29 +0,0 @@
# multiauth
## 0.0.3
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react@0.11.4
- jazz-react-auth-clerk@0.11.4
## 0.0.2
### Patch Changes
- jazz-react@0.11.3
- jazz-react-auth-clerk@0.11.3
- jazz-tools@0.11.3
## 0.0.1
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
- jazz-react-auth-clerk@0.11.2

View File

@@ -1,43 +0,0 @@
# Multi-auth example with Jazz and React
This example demonstrates using Jazz with multiple authentication methods; in this case, Clerk and passphrases are able to be used.
## Getting started
To run this example, you may either:
* Clone the Jazz monorepo and run this example from within.
* Create a new Jazz project using this example as a template, and run that new project.
### Using this example as a template
1. Create a new Jazz project, and use this example as a template.
```bash
npx create-jazz-app@latest --example counter --project-name counter
```
2. Navigate to the new project and start the development server.
```bash
cd counter
npm run dev
```
### Using the monorepo
This requires `pnpm` to be installed; see [https://pnpm.io/installation](https://pnpm.io/installation).
1. Clone the `jazz` repository.
```bash
git clone https://github.com/garden-co/jazz.git
```
2. Install dependencies.
```bash
cd jazz
pnpm install
```
3. Navigate to the example and start the development server.
```bash
cd examples/counter
pnpm dev
```
The example should be running at [http://localhost:5173](http://localhost:5173) by default.

View File

@@ -1,28 +0,0 @@
import js from "@eslint/js";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import globals from "globals";
import tseslint from "typescript-eslint";
export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
],
},
},
);

View File

@@ -1,12 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Jazz Multi-auth (React)</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

View File

@@ -1,30 +0,0 @@
{
"name": "multiauth",
"private": true,
"version": "0.0.3",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"format-and-lint": "biome check .",
"format-and-lint:fix": "biome check . --write"
},
"dependencies": {
"@clerk/clerk-react": "^5.4.1",
"jazz-react": "workspace:*",
"jazz-react-auth-clerk": "workspace:*",
"jazz-tools": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"globals": "^15.11.0",
"typescript": "~5.6.2",
"vite": "^6.0.11"
}
}

View File

@@ -1,12 +0,0 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.card {
padding: 2em;
display: flex;
flex-direction: column;
}

View File

@@ -1,12 +0,0 @@
import { Home } from "./components/Home.tsx";
import "./App.css";
export default function App() {
return (
<div className="card">
<h1>Jazz Multi-auth (React)</h1>
<Home />
</div>
);
}

View File

@@ -1 +0,0 @@
export const apiKey = "counter-example@garden.co";

View File

@@ -1,26 +0,0 @@
import { useAccount, useIsAuthenticated } from "jazz-react";
export function Home() {
const { me, logOut } = useAccount({ root: {} });
const isAuthenticated = useIsAuthenticated();
if (!me) return;
if (!isAuthenticated) return;
return (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "1rem",
}}
>
<div className="container">
<h1>You're logged in</h1>
<p>Welcome back, {me?.profile?.name}</p>
<button onClick={() => logOut()}>Logout</button>
</div>
</div>
);
}

View File

@@ -1,184 +0,0 @@
import { SignInButton } from "@clerk/clerk-react";
import { usePassphraseAuth } from "jazz-react";
import { JazzProviderProps, useIsAuthenticated } from "jazz-react";
import { useState } from "react";
import "../index.css";
import { useClerk } from "@clerk/clerk-react";
import { JazzProviderWithClerk } from "jazz-react-auth-clerk";
import { wordlist } from "../wordlist.ts";
export function OmniAuthContainer(props: {
appName: string;
wordlist: string[];
children?: React.ReactNode;
}) {
const isAuthenticated = useIsAuthenticated();
const passphraseAuth = usePassphraseAuth({
wordlist: props.wordlist,
});
const [step, setStep] = useState<
"initial" | "create" | "loginWithPassphrase" | "loginWithClerk"
>("initial");
const [loginPassphrase, setLoginPassphrase] = useState("");
const [isCopied, setIsCopied] = useState(false);
const [currentPassphrase, setCurrentPassphrase] = useState(() =>
passphraseAuth.generateRandomPassphrase(),
);
if (passphraseAuth.state === "signedIn" || isAuthenticated) {
return props.children ?? null;
}
const handleCreateAccount = async () => {
setStep("create");
};
const handleLoginWithPassphrase = () => {
setStep("loginWithPassphrase");
};
const handleLoginWithClerk = () => {
setStep("loginWithClerk");
};
const handleReroll = () => {
const newPassphrase = passphraseAuth.generateRandomPassphrase();
setCurrentPassphrase(newPassphrase);
setIsCopied(false);
};
const handleBack = () => {
setStep("initial");
setLoginPassphrase("");
};
const handleCopy = async () => {
await navigator.clipboard.writeText(passphraseAuth.passphrase);
setIsCopied(true);
};
const handleLoginSubmit = async () => {
await passphraseAuth.logIn(loginPassphrase);
setStep("initial");
setLoginPassphrase("");
};
const handleNext = async () => {
await passphraseAuth.registerNewAccount(currentPassphrase, "My Account");
setStep("initial");
setLoginPassphrase("");
};
return (
<div className="auth-container">
<div className="auth-card">
{step === "initial" && (
<div>
<h1 className="auth-heading">{props.appName}</h1>
<button
onClick={handleCreateAccount}
className="auth-button-primary"
>
Signup with passphrase
</button>
<button
onClick={handleLoginWithPassphrase}
className="auth-button-secondary"
>
Login with passphrase
</button>
<button
onClick={handleLoginWithClerk}
className="auth-button-secondary"
>
Login with Clerk
</button>
</div>
)}
{step === "create" && (
<>
<h1 className="auth-heading">Your Passphrase</h1>
<p className="auth-description">
Please copy and store this passphrase somewhere safe. You'll need
it to log in.
</p>
<textarea
readOnly
value={currentPassphrase}
className="auth-textarea"
rows={5}
/>
<button onClick={handleCopy} className="auth-button-primary">
{isCopied ? "Copied!" : "Copy"}
</button>
<div className="auth-button-group">
<button onClick={handleBack} className="auth-button-secondary">
Back
</button>
<button onClick={handleReroll} className="auth-button-secondary">
Generate New Passphrase
</button>
<button onClick={handleNext} className="auth-button-primary">
Register
</button>
</div>
</>
)}
{step === "loginWithPassphrase" && (
<div>
<h1 className="auth-heading">Log In</h1>
<textarea
value={loginPassphrase}
onChange={(e) => setLoginPassphrase(e.target.value)}
placeholder="Enter your passphrase"
className="auth-textarea"
rows={5}
/>
<div className="auth-button-group">
<button onClick={handleBack} className="auth-button-secondary">
Back
</button>
<button
onClick={handleLoginSubmit}
className="auth-button-primary"
>
Log In
</button>
</div>
</div>
)}
{step === "loginWithClerk" && <SignInButton />}
</div>
</div>
);
}
export function OmniAuth({
children,
AccountSchema,
sync,
}: {
children: React.ReactNode;
} & JazzProviderProps) {
const clerk = useClerk();
return (
<JazzProviderWithClerk
clerk={clerk}
sync={sync}
AccountSchema={AccountSchema}
>
<OmniAuthContainer
appName="Jazz Multi-Authentication Example"
wordlist={wordlist}
>
{children}
</OmniAuthContainer>
</JazzProviderWithClerk>
);
}

View File

@@ -1,151 +0,0 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: auto 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 2.2em;
line-height: 1.1;
font-weight: 500;
letter-spacing: 0.6px;
}
button {
border-radius: 6px;
border: 1px solid white;
color: inherit;
padding: 0.5rem 1rem;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: transparent;
cursor: pointer;
transition: all 0.05s ease, border-color 0.1s ease;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
button:hover {
background-color: #313131;
}
button:active {
border-color: #3313f7;
transform: translateY(2px);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
@media (prefers-color-scheme: light) {
:root {
color: rgb(21, 20, 20);
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
border-color: #e5e4e2;
}
button:hover {
border-color: rgb(47, 46, 46);
background-color: white;
}
button:active {
border-color: #3313f7;
}
}
.auth-container {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: #f3f4f6;
}
.auth-card {
background-color: white;
padding: 2rem;
border-radius: 0.5rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px
rgba(0, 0, 0, 0.06);
width: 28rem;
}
.auth-button-primary,
.auth-button-secondary {
width: 100%;
padding: 0.5rem 1rem;
border-radius: 0.25rem;
font-weight: bold;
cursor: pointer;
margin-bottom: 1rem;
}
.auth-button-primary {
background-color: black;
color: white;
border: none;
}
.auth-button-secondary {
background-color: white;
color: black;
border: 1px solid black;
}
.auth-heading {
color: black;
font-size: 1.5rem;
font-weight: bold;
text-align: center;
margin-bottom: 1rem;
}
.auth-textarea {
width: 100%;
padding: 0.5rem;
border: 1px solid #d1d5db;
border-radius: 0.25rem;
margin-bottom: 1rem;
box-sizing: border-box;
}
.auth-description {
font-size: 0.875rem;
color: #4b5563;
text-align: center;
margin-bottom: 1rem;
}
.auth-button-group {
display: flex;
justify-content: space-between;
gap: 1rem;
}

View File

@@ -1,29 +0,0 @@
import { ClerkProvider } from "@clerk/clerk-react";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import "./index.css";
import { apiKey } from "./apiKey.ts";
import { OmniAuth } from "./components/OmniAuth.tsx";
// Import your publishable key
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY;
if (!PUBLISHABLE_KEY) {
throw new Error("Add your Clerk publishable key to the .env.local file");
}
createRoot(document.getElementById("root")!).render(
<StrictMode>
<ClerkProvider publishableKey={PUBLISHABLE_KEY} afterSignOutUrl="/">
<OmniAuth
sync={{
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
when: "signedUp", // This makes the app work in local mode when the user is not authenticated
}}
>
<App />
</OmniAuth>
</ClerkProvider>
</StrictMode>,
);

View File

@@ -1 +0,0 @@
/// <reference types="vite/client" />

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +0,0 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2023", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

View File

@@ -1,7 +0,0 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

View File

@@ -1,22 +0,0 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -1,7 +0,0 @@
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
});

View File

@@ -1,77 +1,5 @@
# jazz-example-musicplayer
## 0.0.84
### Patch Changes
- Updated dependencies [d133d47]
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- Updated dependencies [e902405]
- jazz-inspector@0.11.4
- jazz-tools@0.11.4
- jazz-react@0.11.4
## 0.0.83
### Patch Changes
- jazz-inspector@0.11.3
- jazz-react@0.11.3
- jazz-tools@0.11.3
## 0.0.82
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-inspector@0.11.2
- jazz-react@0.11.2
## 0.0.81
### Patch Changes
- Updated dependencies [7b00a81]
- jazz-inspector@0.11.1
- jazz-react@0.11.1
## 0.0.80
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [b7deb3c]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-react@0.11.0
- jazz-inspector@0.10.13
## 0.0.79
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-inspector@0.10.12
- jazz-react@0.10.15
## 0.0.78
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-inspector@0.10.11
- jazz-react@0.10.14
## 0.0.77
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-music-player",
"private": true,
"version": "0.0.84",
"version": "0.0.77",
"type": "module",
"scripts": {
"dev": "vite",
@@ -22,8 +22,8 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-inspector": "workspace:*",
"jazz-react": "workspace:0.11.4",
"jazz-tools": "workspace:0.11.4",
"jazz-react": "workspace:0.10.13",
"jazz-tools": "workspace:0.10.13",
"lucide-react": "^0.274.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",

View File

@@ -112,31 +112,34 @@ export async function addTrackToPlaylist(
playlist.tracks?.push(track);
return;
}
}
export async function removeTrackFromPlaylist(
playlist: Playlist,
track: MusicTrack,
) {
const notAdded = !playlist.tracks?.some(
(t) => t?.id === track.id || t?._refs.sourceTrack?.id === track.id,
/**
* Since musicTracks are created as private values (see uploadMusicTracks)
* to make them shareable as part of the playlist we are cloning them
* and setting the playlist group as owner of the clone
*
* Doing this for backwards compatibility for when the Group inheritance wasn't possible
*/
const blob = await FileStream.loadAsBlob(track._refs.file.id);
const waveform = await MusicTrackWaveform.load(track._refs.waveform.id, {});
if (!blob || !waveform) return;
const trackClone = MusicTrack.create(
{
file: await FileStream.createFromBlob(blob, playlist._owner),
duration: track.duration,
waveform: MusicTrackWaveform.create(
{ data: waveform.data },
playlist._owner,
),
title: track.title,
sourceTrack: track,
},
playlist._owner,
);
if (notAdded) return;
if (track._owner._type === "Group" && playlist._owner._type === "Group") {
const trackGroup = track._owner;
await trackGroup.revokeExtend(playlist._owner);
const index =
playlist.tracks?.findIndex(
(t) => t?.id === track.id || t?._refs.sourceTrack?.id === track.id,
) ?? -1;
if (index > -1) {
playlist.tracks?.splice(index, 1);
}
return;
}
playlist.tracks?.push(trackClone);
}
export async function updatePlaylistTitle(playlist: Playlist, title: string) {
@@ -194,16 +197,3 @@ export async function onAnonymousAccountDiscarded(
me.root.rootPlaylist.tracks.push(track);
}
}
export async function deletePlaylist(playlistId: string) {
const { root } = await MusicaAccount.getMe().ensureLoaded({
root: {
playlists: [],
},
});
const index = root.playlists.findIndex((p) => p?.id === playlistId);
if (index > -1) {
root.playlists.splice(index, 1);
}
}

View File

@@ -1,4 +1,4 @@
import { useAcceptInvite, useIsAuthenticated } from "jazz-react";
import { useAcceptInvite } from "jazz-react";
import { ID } from "jazz-tools";
import { useCallback } from "react";
import { useNavigate } from "react-router-dom";
@@ -7,8 +7,6 @@ import { MusicaAccount, Playlist } from "./1_schema";
export function InvitePage() {
const navigate = useNavigate();
const isAuthenticated = useIsAuthenticated();
useAcceptInvite({
invitedObjectSchema: Playlist,
onAccept: useCallback(
@@ -34,9 +32,5 @@ export function InvitePage() {
),
});
return isAuthenticated ? (
<p>Accepting invite....</p>
) : (
<p>Please sign in to accept the invite.</p>
);
return <p>Accepting invite....</p>;
}

View File

@@ -1,5 +1,5 @@
import { MusicTrack, Playlist } from "@/1_schema";
import { addTrackToPlaylist, removeTrackFromPlaylist } from "@/4_actions";
import { addTrackToPlaylist } from "@/4_actions";
import {
DropdownMenu,
DropdownMenuContent,
@@ -10,7 +10,6 @@ import { cn } from "@/lib/utils";
import { useAccount, useCoState } from "jazz-react";
import { ID } from "jazz-tools";
import { MoreHorizontal } from "lucide-react";
import { Fragment } from "react/jsx-runtime";
import { MusicTrackTitleInput } from "./MusicTrackTitleInput";
import { Button } from "./ui/button";
@@ -47,21 +46,6 @@ export function MusicTrackRow({
addTrackToPlaylist(playlist, track);
}
function handleRemoveFromPlaylist(playlist: Playlist) {
if (!track) return;
removeTrackFromPlaylist(playlist, track);
}
function deleteTrack() {
if (!me || !track) return;
const tracks = me.root.rootPlaylist?.tracks;
if (!tracks) return;
const index = tracks.findIndex((t) => t?.id === trackId);
if (index !== -1) {
tracks.splice(index, 1);
}
}
return (
<li
className={
@@ -100,30 +84,13 @@ export function MusicTrackRow({
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem
key={`delete`}
onSelect={async () => {
if (!track) return;
deleteTrack();
}}
>
Delete
</DropdownMenuItem>
{playlists.map((playlist, index) => (
<Fragment key={index}>
<DropdownMenuItem
key={`add-${index}`}
onSelect={() => handleAddToPlaylist(playlist)}
>
Add to {playlist.title}
</DropdownMenuItem>
<DropdownMenuItem
key={`remove-${index}`}
onSelect={() => handleRemoveFromPlaylist(playlist)}
>
Remove from {playlist.title}
</DropdownMenuItem>
</Fragment>
<DropdownMenuItem
key={index}
onSelect={() => handleAddToPlaylist(playlist)}
>
Add to {playlist.title}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>

View File

@@ -1,6 +1,4 @@
import { deletePlaylist } from "@/4_actions";
import { useAccount } from "jazz-react";
import { Trash2 } from "lucide-react";
import { useNavigate, useParams } from "react-router";
import { LocalOnlyTag } from "./LocalOnlyTag";
@@ -26,13 +24,6 @@ export function SidePanel() {
navigate(`/playlist/${playlistId}`);
}
async function handleDeletePlaylist(playlistId: string) {
if (confirm("Are you sure you want to delete this playlist?")) {
await deletePlaylist(playlistId);
navigate(`/`);
}
}
return (
<aside className="w-64 p-6 bg-white overflow-y-auto">
<div className="flex items-center mb-1">
@@ -74,28 +65,18 @@ export function SidePanel() {
</a>
</li>
{me?.root.playlists.map((playlist, index) => (
<li
key={index}
className={`px-2 py-1 flex transition-all duration-300 rounded items-center justify-between ${
playlist.id === playlistId ? "bg-blue-100" : ""
}`}
>
<li key={index}>
<a
href="#"
className={`w-full text-sm`}
className={`block px-2 py-1 text-sm rounded ${
playlist.id === playlistId
? "bg-blue-100 text-blue-600"
: "hover:bg-blue-100"
}`}
onClick={(evt) => handlePlaylistClick(evt, playlist.id)}
>
{playlist.title}
</a>
{playlist.id === playlistId && (
<button
onClick={() => handleDeletePlaylist(playlist.id)}
className="ml-2 text-red-600 hover:text-red-800 animate-in fade-in scale-in duration-200"
aria-label={`Delete ${playlist.title}`}
>
<Trash2 size={16} />
</button>
)}
</li>
))}
</ul>

View File

@@ -82,47 +82,3 @@ test("create a new playlist and share", async ({
await luigiHome.playMusicTrack("Super Mario World");
await luigiHome.expectActiveTrackPlaying();
});
test("create a new playlist, share, then remove track", async ({
page: marioPage,
browser,
}) => {
// Create playlist with a song and share
await marioPage.goto("/");
const marioHome = new HomePage(marioPage);
await marioHome.expectMusicTrack("Example song");
await marioHome.editTrackTitle("Example song", "Super Mario World");
await marioHome.createPlaylist();
await marioHome.editPlaylistTitle("Save the princess");
await marioHome.navigateToPlaylist("All tracks");
await marioHome.addTrackToPlaylist("Super Mario World", "Save the princess");
await marioHome.navigateToPlaylist("Save the princess");
await marioHome.expectMusicTrack("Super Mario World");
await marioHome.signUp("Mario");
const url = await marioHome.getShareLink();
await sleep(4000); // Wait for the sync to complete
// Retrieve shared playlist
const luigiContext = await browser.newContext();
await mockAuthenticator(luigiContext);
const luigiPage = await luigiContext.newPage();
await luigiPage.goto("/");
const luigiHome = new HomePage(luigiPage);
await luigiHome.signUp("Luigi");
await luigiPage.goto(url);
await luigiHome.expectMusicTrack("Super Mario World");
// Remove track from playlist
await marioHome.navigateToHome();
await marioHome.removeTrackFromPlaylist(
"Super Mario World",
"Save the princess",
);
await sleep(4000); // Wait for the sync to complete
// Expect that the track is removed from the playlist
await marioHome.navigateToPlaylist("Save the princess");
await marioHome.notExpectMusicTrack("Super Mario World");
await luigiHome.notExpectMusicTrack("Super Mario World");
});

View File

@@ -33,14 +33,6 @@ export class HomePage {
).toBeVisible();
}
async notExpectMusicTrack(trackName: string) {
await expect(
this.page.getByRole("button", {
name: `Play ${trackName}`,
}),
).not.toBeVisible();
}
async playMusicTrack(trackName: string) {
await this.page
.getByRole("button", {
@@ -73,14 +65,6 @@ export class HomePage {
.click();
}
async navigateToHome() {
await this.page
.getByRole("link", {
name: "All tracks",
})
.click();
}
async getShareLink() {
await this.page
.getByRole("button", {
@@ -111,20 +95,6 @@ export class HomePage {
.click();
}
async removeTrackFromPlaylist(trackTitle: string, playlistTitle: string) {
await this.page
.getByRole("button", {
name: `Open ${trackTitle} menu`,
})
.click();
await this.page
.getByRole("menuitem", {
name: `Remove from ${playlistTitle}`,
})
.click();
}
async signUp(name: string) {
await this.page.getByRole("button", { name: "Sign up" }).click();
await this.page.getByRole("textbox", { name: "Username" }).fill(name);

View File

@@ -1,66 +1,5 @@
# organization
## 0.0.56
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react@0.11.4
## 0.0.55
### Patch Changes
- jazz-react@0.11.3
- jazz-tools@0.11.3
## 0.0.54
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
## 0.0.53
### Patch Changes
- jazz-react@0.11.1
## 0.0.52
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-react@0.11.0
## 0.0.51
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react@0.10.15
## 0.0.50
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
## 0.0.49
### Patch Changes

View File

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

View File

@@ -23,7 +23,7 @@ export function CreateOrganization() {
return;
}
const group = Group.create();
const group = Group.create({ owner: me });
me.root.organizations.push(draft as Organization);

View File

@@ -1,4 +1,5 @@
import { Group } from "jazz-tools";
import { useCoState } from "jazz-react";
import { Account, Group, ID } from "jazz-tools";
import { Organization } from "../schema.ts";
export function OrganizationMembers({
@@ -9,13 +10,26 @@ export function OrganizationMembers({
return (
<>
{group.members.map((member) => (
<div key={member.id} className="px-4 py-5 sm:px-6">
<strong className="font-medium">
{member.account.profile?.name}
</strong>{" "}
({member.role})
</div>
<Member
key={member.id}
accountId={member.id as ID<Account>}
role={member.role}
/>
))}
</>
);
}
function Member({
accountId,
role,
}: { accountId: ID<Account>; role?: string }) {
const account = useCoState(Account, accountId, { profile: {} });
if (!account?.profile) return;
return (
<div className="px-4 py-5 sm:px-6">
<strong className="font-medium">{account.profile.name}</strong> ({role})
</div>
);
}

View File

@@ -1,41 +1,5 @@
# passkey-svelte
## 0.0.50
### Patch Changes
- jazz-svelte@0.11.4
## 0.0.49
### Patch Changes
- jazz-svelte@0.11.3
## 0.0.48
### Patch Changes
- jazz-svelte@0.11.2
## 0.0.47
### Patch Changes
- jazz-svelte@0.11.0
## 0.0.46
### Patch Changes
- jazz-svelte@0.10.15
## 0.0.45
### Patch Changes
- jazz-svelte@0.10.14
## 0.0.44
### Patch Changes

View File

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

View File

@@ -1,66 +1,5 @@
# minimal-auth-passkey
## 0.0.61
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react@0.11.4
## 0.0.60
### Patch Changes
- jazz-react@0.11.3
- jazz-tools@0.11.3
## 0.0.59
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
## 0.0.58
### Patch Changes
- jazz-react@0.11.1
## 0.0.57
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-react@0.11.0
## 0.0.56
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react@0.10.15
## 0.0.55
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
## 0.0.54
### Patch Changes

View File

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

View File

@@ -1,66 +1,5 @@
# passphrase
## 0.0.58
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react@0.11.4
## 0.0.57
### Patch Changes
- jazz-react@0.11.3
- jazz-tools@0.11.3
## 0.0.56
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
## 0.0.55
### Patch Changes
- jazz-react@0.11.1
## 0.0.54
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-react@0.11.0
## 0.0.53
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react@0.10.15
## 0.0.52
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
## 0.0.51
### Patch Changes

View File

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

View File

@@ -1,66 +1,5 @@
# jazz-password-manager
## 0.0.82
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react@0.11.4
## 0.0.81
### Patch Changes
- jazz-react@0.11.3
- jazz-tools@0.11.3
## 0.0.80
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
## 0.0.79
### Patch Changes
- jazz-react@0.11.1
## 0.0.78
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-react@0.11.0
## 0.0.77
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react@0.10.15
## 0.0.76
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
## 0.0.75
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-password-manager",
"private": true,
"version": "0.0.82",
"version": "0.0.75",
"type": "module",
"scripts": {
"dev": "vite",
@@ -12,8 +12,8 @@
"clean-install": "rm -rf node_modules pnpm-lock.yaml && pnpm install"
},
"dependencies": {
"jazz-react": "workspace:0.11.4",
"jazz-tools": "workspace:0.11.4",
"jazz-react": "workspace:0.10.13",
"jazz-tools": "workspace:0.10.13",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.41.5",

View File

@@ -6,7 +6,7 @@ import NewItemModal from "./components/new-item-modal";
import Table from "./components/table";
import { useAccount, useCoState } from "jazz-react";
import { CoMapInit, ID } from "jazz-tools";
import { CoMapInit, Group, ID } from "jazz-tools";
import { useNavigate, useParams } from "react-router-dom";
import { Folder, FolderList, PasswordItem } from "./1_schema";
import {
@@ -136,14 +136,20 @@ const VaultPage: React.FC = () => {
</Button>
<Button
onClick={() => setEditingItem(item)}
disabled={!me.canWrite(item)}
disabled={
item._owner.castAs(Group).myRole() !== "admin" &&
item._owner.castAs(Group).myRole() !== "writer"
}
>
Edit
</Button>
<Button
onClick={() => handleDeleteItem(item)}
variant="danger"
disabled={!me.canWrite(item)}
disabled={
item._owner.castAs(Group).myRole() !== "admin" &&
item._owner.castAs(Group).myRole() !== "writer"
}
>
Delete
</Button>
@@ -204,13 +210,21 @@ const VaultPage: React.FC = () => {
<div className="flex gap-2">
<Button
onClick={() => setIsNewItemModalOpen(true)}
disabled={!selectedFolder || !me.canWrite(selectedFolder)}
disabled={
!selectedFolder ||
(selectedFolder._owner.castAs(Group).myRole() !== "admin" &&
selectedFolder._owner.castAs(Group).myRole() !== "writer")
}
>
New Item
</Button>
<Button
onClick={() => setIsInviteModalOpen(true)}
disabled={!selectedFolder || !me.canWrite(selectedFolder)}
disabled={
!selectedFolder ||
(selectedFolder._owner.castAs(Group).myRole() !== "admin" &&
selectedFolder._owner.castAs(Group).myRole() !== "writer")
}
>
Share Folder
</Button>

View File

@@ -21,9 +21,11 @@ const InviteModal: React.FC<InviteModalProps> = ({
>("reader");
const [inviteLink, setInviteLink] = useState("");
const members = selectedFolder?._owner.members;
const members = selectedFolder?._owner.castAs(Group).members;
const invitedMembers = members
? members.filter((m) => !m.account?.isMe).map((m) => m.account)
? members
.filter((m) => !m.account?.isMe && m.role !== "revoked")
.map((m) => m.account)
: [];
const handleCreateInviteLink = () => {

View File

@@ -1,72 +1,5 @@
# jazz-example-pets
## 0.0.180
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-browser-media-images@0.11.4
- jazz-react@0.11.4
## 0.0.179
### Patch Changes
- jazz-react@0.11.3
- jazz-tools@0.11.3
- jazz-browser-media-images@0.11.3
## 0.0.178
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
- jazz-browser-media-images@0.11.2
## 0.0.177
### Patch Changes
- jazz-react@0.11.1
## 0.0.176
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-browser-media-images@0.11.0
- jazz-react@0.11.0
## 0.0.175
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-browser-media-images@0.10.15
- jazz-react@0.10.15
## 0.0.174
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
- jazz-browser-media-images@0.10.14
## 0.0.173
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-pets",
"private": true,
"version": "0.0.180",
"version": "0.0.173",
"type": "module",
"scripts": {
"dev": "vite",
@@ -19,9 +19,9 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-browser-media-images": "workspace:0.11.4",
"jazz-react": "workspace:0.11.4",
"jazz-tools": "workspace:0.11.4",
"jazz-browser-media-images": "workspace:0.10.13",
"jazz-react": "workspace:0.10.13",
"jazz-tools": "workspace:0.10.13",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.3.1",
@@ -41,7 +41,7 @@
"@vitejs/plugin-react-swc": "^3.3.2",
"autoprefixer": "^10.4.20",
"is-ci": "^3.0.1",
"jazz-run": "workspace:0.11.4",
"jazz-run": "workspace:0.10.13",
"postcss": "^8.4.27",
"tailwindcss": "^3.4.17",
"typescript": "~5.6.2",

View File

@@ -34,7 +34,7 @@ export function NewPetPostForm() {
if (newPetPost) {
newPetPost.name = name;
} else {
const petPostGroup = Group.create();
const petPostGroup = Group.create({ owner: me });
const petPost = PartialPetPost.create(
{
name,

View File

@@ -2,7 +2,7 @@ import { useParams } from "react-router";
import { PetPost, PetReactions, ReactionTypes } from "./1_schema";
import { ProgressiveImg, useAccount } from "jazz-react";
import { ProgressiveImg } from "jazz-react";
import { useCoState } from "jazz-react";
import { ID } from "jazz-tools";
import uniqolor from "uniqolor";
@@ -26,7 +26,6 @@ const reactionEmojiMap: {
export function RatePetPostUI() {
const petPostID = useParams<{ petPostId: ID<PetPost> }>().petPostId;
const { me } = useAccount();
const petPost = useCoState(PetPost, petPostID);
return (
@@ -61,7 +60,7 @@ export function RatePetPostUI() {
))}
</div>
{petPost && me.canAdmin(petPost) && petPost.reactions && (
{petPost?._owner.myRole() === "admin" && petPost.reactions && (
<ReactionOverview petReactions={petPost.reactions} />
)}
</div>

View File

@@ -2,7 +2,7 @@ import { useState } from "react";
import { PetPost } from "../1_schema";
import { createInviteLink, useAccount } from "jazz-react";
import { createInviteLink } from "jazz-react";
import QRCode from "qrcode";
import { Button, useToast } from "../basicComponents";
@@ -10,11 +10,9 @@ import { Button, useToast } from "../basicComponents";
export function ShareButton({ petPost }: { petPost?: PetPost | null }) {
const [existingInviteLink, setExistingInviteLink] = useState<string>();
const { toast } = useToast();
const { me } = useAccount();
return (
petPost &&
me.canAdmin(petPost) && (
petPost?._owner.myRole() === "admin" && (
<Button
size="sm"
className="py-0"

View File

@@ -1,72 +1,5 @@
# reactions
## 0.0.60
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-browser-media-images@0.11.4
- jazz-react@0.11.4
## 0.0.59
### Patch Changes
- jazz-react@0.11.3
- jazz-tools@0.11.3
- jazz-browser-media-images@0.11.3
## 0.0.58
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
- jazz-browser-media-images@0.11.2
## 0.0.57
### Patch Changes
- jazz-react@0.11.1
## 0.0.56
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-browser-media-images@0.11.0
- jazz-react@0.11.0
## 0.0.55
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-browser-media-images@0.10.15
- jazz-react@0.10.15
## 0.0.54
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
- jazz-browser-media-images@0.10.14
## 0.0.53
### Patch Changes

View File

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

View File

@@ -9,7 +9,8 @@ function App() {
const router = useIframeHashRouter();
const createReactions = () => {
const group = Group.create();
if (!me) return;
const group = Group.create({ owner: me });
group.addMember("everyone", "writer");
const chat = Reactions.create([], { owner: group });
router.navigate("/#/reactions/" + chat.id);

View File

@@ -1,67 +1,5 @@
# todo-vue
## 0.0.64
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-browser@0.11.4
- jazz-vue@0.11.4
## 0.0.63
### Patch Changes
- jazz-browser@0.11.3
- jazz-tools@0.11.3
- jazz-vue@0.11.3
## 0.0.62
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-browser@0.11.2
- jazz-vue@0.11.2
## 0.0.61
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [18428ea]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-browser@0.11.0
- jazz-vue@0.11.0
## 0.0.60
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-browser@0.10.15
- jazz-vue@0.10.15
## 0.0.59
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-browser@0.10.14
- jazz-vue@0.10.14
## 0.0.58
### Patch Changes

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