Compare commits
49 Commits
chat-rn@1.
...
chat-rn@1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e410823087 | ||
|
|
dcc11e5b60 | ||
|
|
1b05fe5b55 | ||
|
|
de8f896bf9 | ||
|
|
d63716a827 | ||
|
|
a1e7fce3b9 | ||
|
|
d5edad7ba5 | ||
|
|
559a4a223b | ||
|
|
16d5553ccd | ||
|
|
ef76c586cc | ||
|
|
8ea4b9761c | ||
|
|
a81f281079 | ||
|
|
3ecb602459 | ||
|
|
ea69ea1f67 | ||
|
|
e430bd061e | ||
|
|
a957485172 | ||
|
|
9060975dfb | ||
|
|
753ec83fdd | ||
|
|
44a9785e93 | ||
|
|
d9b390e538 | ||
|
|
b194f7831b | ||
|
|
b60be9405d | ||
|
|
84588e0798 | ||
|
|
e5b170f25e | ||
|
|
cfbf3aa51e | ||
|
|
b1e00d2b18 | ||
|
|
ec330eaa14 | ||
|
|
07dd2c5e69 | ||
|
|
862386c19b | ||
|
|
30df1098e1 | ||
|
|
dad4394eed | ||
|
|
9b70336a38 | ||
|
|
75328ac49d | ||
|
|
63d0b0673e | ||
|
|
2b456b5e07 | ||
|
|
e20809d314 | ||
|
|
9472347b57 | ||
|
|
b43395d8ed | ||
|
|
b6de11e125 | ||
|
|
1ab839bd59 | ||
|
|
af3b13428c | ||
|
|
fe241e7e7c | ||
|
|
d23c71d511 | ||
|
|
b24071cf33 | ||
|
|
a5c88c08de | ||
|
|
906932db1e | ||
|
|
2033e35a41 | ||
|
|
5a2a12ccbb | ||
|
|
d288cb6954 |
@@ -12,6 +12,10 @@
|
||||
"cojson-transport-ws",
|
||||
"jazz-browser",
|
||||
"jazz-auth-clerk",
|
||||
"jazz-auth-betterauth",
|
||||
"jazz-betterauth-client-plugin",
|
||||
"jazz-betterauth-server-plugin",
|
||||
"jazz-react-auth-betterauth",
|
||||
"jazz-browser-media-images",
|
||||
"jazz-expo",
|
||||
"jazz-inspector",
|
||||
|
||||
2
.github/workflows/playwright.yml
vendored
2
.github/workflows/playwright.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
project: ["tests/e2e", "examples/chat", "examples/clerk", "examples/betterauth", "examples/file-share-svelte", "examples/form", "examples/music-player", "examples/pets", "starters/react-passkey-auth"]
|
||||
project: ["tests/e2e", "examples/chat", "examples/clerk", "examples/betterauth", "examples/file-share-svelte", "examples/form", "examples/music-player", "examples/organization", "examples/pets", "starters/react-passkey-auth"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -29,3 +29,5 @@ test-results
|
||||
|
||||
.cursorrules
|
||||
.windsurfrules
|
||||
|
||||
playwright-report
|
||||
@@ -1,5 +1,28 @@
|
||||
# betterauth
|
||||
|
||||
## 0.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-betterauth-server-plugin@0.13.31
|
||||
- jazz-inspector@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
- jazz-react-auth-betterauth@0.13.31
|
||||
- jazz-betterauth-client-plugin@0.13.31
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-betterauth-server-plugin@0.13.30
|
||||
- jazz-inspector@0.13.30
|
||||
- jazz-react@0.13.30
|
||||
- jazz-react-auth-betterauth@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
- jazz-betterauth-client-plugin@0.13.30
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "betterauth",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.3",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# chat-rn-expo-clerk
|
||||
|
||||
## 1.0.122
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-expo@0.13.31
|
||||
- jazz-react-native-media-images@0.13.31
|
||||
|
||||
## 1.0.121
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-expo@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
- jazz-react-native-media-images@0.13.30
|
||||
|
||||
## 1.0.120
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "chat-rn-expo-clerk",
|
||||
"main": "index.js",
|
||||
"version": "1.0.120",
|
||||
"version": "1.0.122",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
"start": "expo start",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# chat-rn-expo
|
||||
|
||||
## 1.0.109
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-expo@0.13.31
|
||||
|
||||
## 1.0.108
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-expo@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 1.0.107
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn-expo",
|
||||
"version": "1.0.107",
|
||||
"version": "1.0.109",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
# chat-rn
|
||||
|
||||
## 1.0.117
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- Updated dependencies [d63716a]
|
||||
- Updated dependencies [d5edad7]
|
||||
- jazz-tools@0.13.31
|
||||
- cojson@0.13.31
|
||||
- jazz-react-native@0.13.31
|
||||
- cojson-transport-ws@0.13.31
|
||||
|
||||
## 1.0.116
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [07dd2c5]
|
||||
- cojson@0.13.30
|
||||
- cojson-transport-ws@0.13.30
|
||||
- jazz-react-native@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 1.0.115
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn",
|
||||
"version": "1.0.115",
|
||||
"version": "1.0.117",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"android": "react-native run-android",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# chat-vue
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-browser@0.13.31
|
||||
- jazz-vue@0.13.31
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
- jazz-vue@0.13.30
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-vue",
|
||||
"version": "0.0.98",
|
||||
"version": "0.0.100",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.198
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-inspector@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.197
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.30
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.196
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat",
|
||||
"private": true,
|
||||
"version": "0.0.196",
|
||||
"version": "0.0.198",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# minimal-auth-clerk
|
||||
|
||||
## 0.0.97
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
- jazz-react-auth-clerk@0.13.31
|
||||
|
||||
## 0.0.96
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-react-auth-clerk@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "clerk",
|
||||
"private": true,
|
||||
"version": "0.0.95",
|
||||
"version": "0.0.97",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# file-share-svelte
|
||||
|
||||
## 0.0.81
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-inspector-element@0.13.31
|
||||
- jazz-svelte@0.13.31
|
||||
|
||||
## 0.0.80
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
- jazz-inspector-element@0.13.30
|
||||
|
||||
## 0.0.79
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "file-share-svelte",
|
||||
"version": "0.0.79",
|
||||
"version": "0.0.81",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-tailwind-demo-auth-starter
|
||||
|
||||
## 0.0.37
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-inspector@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.30
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "filestream",
|
||||
"private": true,
|
||||
"version": "0.0.35",
|
||||
"version": "0.0.37",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# form
|
||||
|
||||
## 0.1.38
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.1.37
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.1.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "form",
|
||||
"private": true,
|
||||
"version": "0.1.36",
|
||||
"version": "0.1.38",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# image-upload
|
||||
|
||||
## 0.0.94
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.93
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.92
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "image-upload",
|
||||
"private": true,
|
||||
"version": "0.0.92",
|
||||
"version": "0.0.94",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# jazz-example-inspector
|
||||
|
||||
## 0.0.148
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [d63716a]
|
||||
- Updated dependencies [d5edad7]
|
||||
- cojson@0.13.31
|
||||
- jazz-inspector@0.13.31
|
||||
- cojson-transport-ws@0.13.31
|
||||
|
||||
## 0.0.147
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [07dd2c5]
|
||||
- cojson@0.13.30
|
||||
- cojson-transport-ws@0.13.30
|
||||
- jazz-inspector@0.13.30
|
||||
|
||||
## 0.0.146
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-inspector-app",
|
||||
"private": true,
|
||||
"version": "0.0.146",
|
||||
"version": "0.0.148",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# multi-cursors
|
||||
|
||||
## 0.0.90
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.89
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.88
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "multi-cursors",
|
||||
"private": true,
|
||||
"version": "0.0.88",
|
||||
"version": "0.0.90",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# multiauth
|
||||
|
||||
## 0.0.38
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
- jazz-react-auth-clerk@0.13.31
|
||||
|
||||
## 0.0.37
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-react-auth-clerk@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "multiauth",
|
||||
"private": true,
|
||||
"version": "0.0.36",
|
||||
"version": "0.0.38",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-example-musicplayer
|
||||
|
||||
## 0.0.119
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-inspector@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.118
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.30
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.117
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-music-player",
|
||||
"private": true,
|
||||
"version": "0.0.117",
|
||||
"version": "0.0.119",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
2
examples/organization/.gitignore
vendored
2
examples/organization/.gitignore
vendored
@@ -22,3 +22,5 @@ dist-ssr
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
playwright-report
|
||||
@@ -1,5 +1,20 @@
|
||||
# organization
|
||||
|
||||
## 0.0.90
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.89
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.88
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
{
|
||||
"name": "organization",
|
||||
"private": true,
|
||||
"version": "0.0.88",
|
||||
"version": "0.0.90",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"format-and-lint": "biome check .",
|
||||
"format-and-lint:fix": "biome check . --write"
|
||||
"format-and-lint:fix": "biome check . --write",
|
||||
"test:e2e": "playwright test",
|
||||
"test:e2e:ui": "playwright test --ui"
|
||||
},
|
||||
"dependencies": {
|
||||
"jazz-react": "workspace:*",
|
||||
@@ -20,6 +22,7 @@
|
||||
"react-router-dom": "^6.16.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.50.1",
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@tailwindcss/forms": "^0.5.9",
|
||||
"@types/react": "^18.3.12",
|
||||
|
||||
53
examples/organization/playwright.config.ts
Normal file
53
examples/organization/playwright.config.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { defineConfig, devices } from "@playwright/test";
|
||||
import isCI from "is-ci";
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
* https://github.com/motdotla/dotenv
|
||||
*/
|
||||
// import dotenv from 'dotenv';
|
||||
// dotenv.config({ path: path.resolve(__dirname, '.env') });
|
||||
|
||||
/**
|
||||
* 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,
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -5,7 +5,13 @@ import { Heading } from "./components/Heading.tsx";
|
||||
|
||||
export function HomePage() {
|
||||
const { me } = useAccount({
|
||||
resolve: { root: { organizations: true } },
|
||||
resolve: {
|
||||
root: {
|
||||
organizations: {
|
||||
$each: { $onError: null },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!me?.root.organizations) return;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { UserIcon } from "lucide-react";
|
||||
|
||||
export function Layout({ children }: { children: React.ReactNode }) {
|
||||
const { me, logOut } = useAccount({
|
||||
resolve: { root: { draftOrganization: true } },
|
||||
resolve: { profile: true },
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -16,7 +16,20 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
||||
<span className="bg-stone-500 pt-1 size-6 flex items-center justify-center rounded-full">
|
||||
<UserIcon size={20} className="stroke-white" />
|
||||
</span>
|
||||
{me?.profile?.name}
|
||||
<label htmlFor="profile-name" className="sr-only">
|
||||
Profile name
|
||||
</label>
|
||||
<input
|
||||
id="profile-name"
|
||||
type="text"
|
||||
value={me?.profile.name ?? ""}
|
||||
className="rounded-md shadow-sm dark:bg-transparent text-sm py-1.5 px-3"
|
||||
onChange={(e) => {
|
||||
if (me) {
|
||||
me.profile.name = e.target.value;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
|
||||
<button
|
||||
|
||||
@@ -16,7 +16,21 @@ export function OrganizationPage() {
|
||||
resolve: { projects: true },
|
||||
});
|
||||
|
||||
if (!organization) return <p>Loading organization...</p>;
|
||||
if (organization === undefined) return <p>Loading organization...</p>;
|
||||
if (organization === null) {
|
||||
return (
|
||||
<div className="h-full flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<h1 className="text-2xl font-bold">
|
||||
You don't have access to this organization
|
||||
</h1>
|
||||
<a href="/#" className="text-blue-500">
|
||||
Go back to home
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
|
||||
@@ -27,7 +27,7 @@ export function OrganizationForm({
|
||||
type="submit"
|
||||
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
|
||||
>
|
||||
Submit
|
||||
Create
|
||||
</button>
|
||||
)}
|
||||
</form>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Group } from "jazz-tools";
|
||||
import { useAccount, useCoState } from "jazz-react";
|
||||
import { Account, Group, ID } from "jazz-tools";
|
||||
import { Organization } from "../schema.ts";
|
||||
|
||||
export function OrganizationMembers({
|
||||
@@ -9,13 +10,51 @@ 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>
|
||||
<MemberItem
|
||||
key={member.id}
|
||||
accountId={member.account.id}
|
||||
role={member.role}
|
||||
group={group}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function MemberItem({
|
||||
accountId,
|
||||
role,
|
||||
group,
|
||||
}: { accountId: ID<Account>; role: string; group: Group }) {
|
||||
const account = useCoState(Account, accountId, {
|
||||
resolve: {
|
||||
profile: true,
|
||||
},
|
||||
});
|
||||
const { me } = useAccount();
|
||||
|
||||
const canRemoveMember = group.myRole() === "admin" && accountId !== me?.id;
|
||||
|
||||
function handleRemoveMember() {
|
||||
if (canRemoveMember && account) {
|
||||
group.removeMember(account);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="px-4 py-5 sm:px-6 flex justify-between items-center">
|
||||
<div>
|
||||
<strong className="font-medium">{account?.profile.name}</strong> ({role}
|
||||
)
|
||||
</div>
|
||||
{canRemoveMember && (
|
||||
<button
|
||||
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
|
||||
onClick={handleRemoveMember}
|
||||
>
|
||||
Remove member
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Organization } from "../schema.ts";
|
||||
|
||||
export function OrganizationSelector({ className }: { className?: string }) {
|
||||
const { me } = useAccount({
|
||||
resolve: { root: { organizations: { $each: true } } },
|
||||
resolve: { root: { organizations: { $each: { $onError: null } } } },
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
@@ -48,6 +48,10 @@ export function OrganizationSelector({ className }: { className?: string }) {
|
||||
className="rounded-md shadow-sm dark:bg-transparent w-full"
|
||||
>
|
||||
{me?.root.organizations.map((organization) => {
|
||||
if (!organization) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<option key={organization.id} value={organization.id}>
|
||||
{organization.name}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Account, CoList, CoMap, Group, co } from "jazz-tools";
|
||||
import { Account, CoList, CoMap, Group, Profile, co } from "jazz-tools";
|
||||
import { getRandomUsername } from "./util";
|
||||
|
||||
export class Project extends CoMap {
|
||||
name = co.string;
|
||||
@@ -38,43 +39,49 @@ export class JazzAccountRoot extends CoMap {
|
||||
export class JazzAccount extends Account {
|
||||
root = co.ref(JazzAccountRoot);
|
||||
|
||||
async migrate() {
|
||||
if (!this._refs.root) {
|
||||
const draftOrganizationOwnership = {
|
||||
owner: Group.create({ owner: this }),
|
||||
};
|
||||
async migrate(this: JazzAccount) {
|
||||
if (this.profile === undefined) {
|
||||
const group = Group.create();
|
||||
this.profile = Profile.create(
|
||||
{
|
||||
name: getRandomUsername(),
|
||||
},
|
||||
group,
|
||||
);
|
||||
group.addMember("everyone", "reader");
|
||||
}
|
||||
|
||||
if (this.root === undefined) {
|
||||
const draftOrgGroup = Group.create();
|
||||
const draftOrganization = DraftOrganization.create(
|
||||
{
|
||||
projects: ListOfProjects.create([], draftOrganizationOwnership),
|
||||
projects: ListOfProjects.create([], draftOrgGroup),
|
||||
},
|
||||
draftOrganizationOwnership,
|
||||
draftOrgGroup,
|
||||
);
|
||||
|
||||
const initialOrganizationOwnership = {
|
||||
owner: Group.create({ owner: this }),
|
||||
};
|
||||
const organizations = ListOfOrganizations.create(
|
||||
[
|
||||
Organization.create(
|
||||
{
|
||||
name: this.profile?.name
|
||||
? `${this.profile.name}'s projects`
|
||||
: "Your projects",
|
||||
projects: ListOfProjects.create([], initialOrganizationOwnership),
|
||||
},
|
||||
initialOrganizationOwnership,
|
||||
),
|
||||
],
|
||||
{ owner: this },
|
||||
);
|
||||
const defaultOrgGroup = Group.create();
|
||||
|
||||
this.root = JazzAccountRoot.create(
|
||||
{
|
||||
draftOrganization,
|
||||
organizations,
|
||||
const { profile } = await this.ensureLoaded({
|
||||
resolve: {
|
||||
profile: true,
|
||||
},
|
||||
{ owner: this },
|
||||
);
|
||||
});
|
||||
|
||||
const organizations = ListOfOrganizations.create([
|
||||
Organization.create(
|
||||
{
|
||||
name: profile.name ? `${profile.name}'s projects` : "Your projects",
|
||||
projects: ListOfProjects.create([], defaultOrgGroup),
|
||||
},
|
||||
defaultOrgGroup,
|
||||
),
|
||||
]);
|
||||
|
||||
this.root = JazzAccountRoot.create({
|
||||
draftOrganization,
|
||||
organizations,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
examples/organization/src/util.ts
Normal file
16
examples/organization/src/util.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
const animals = [
|
||||
"elephant",
|
||||
"penguin",
|
||||
"giraffe",
|
||||
"octopus",
|
||||
"kangaroo",
|
||||
"dolphin",
|
||||
"cheetah",
|
||||
"koala",
|
||||
"platypus",
|
||||
"pangolin",
|
||||
];
|
||||
|
||||
export function getRandomUsername() {
|
||||
return `Anonymous ${animals[Math.floor(Math.random() * animals.length)]}`;
|
||||
}
|
||||
65
examples/organization/tests/createAndShare.spec.ts
Normal file
65
examples/organization/tests/createAndShare.spec.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { BrowserContext, expect, test } from "@playwright/test";
|
||||
|
||||
test("create a new organization and share", async ({
|
||||
page: marioPage,
|
||||
browser,
|
||||
}) => {
|
||||
await marioPage.goto("/");
|
||||
|
||||
const luigiContext = await browser.newContext();
|
||||
const luigiPage = await luigiContext.newPage();
|
||||
await luigiPage.goto("/");
|
||||
|
||||
await test.step("Set the profile names", async () => {
|
||||
await marioPage
|
||||
.getByRole("textbox", { name: "Profile name" })
|
||||
.fill("Mario");
|
||||
await luigiPage
|
||||
.getByRole("textbox", { name: "Profile name" })
|
||||
.fill("Luigi");
|
||||
});
|
||||
|
||||
await test.step("Create a new organization", async () => {
|
||||
await marioPage
|
||||
.getByRole("textbox", { name: "Organization name" })
|
||||
.fill("Mario's organization");
|
||||
await marioPage.getByRole("button", { name: "Create" }).click();
|
||||
|
||||
await expect(
|
||||
marioPage.getByRole("heading", { name: "Mario's organization" }),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step("Invite Luigi to the organization", async () => {
|
||||
await marioPage.getByRole("button", { name: "Copy invite link" }).click();
|
||||
|
||||
const inviteUrl = await marioPage.evaluate(() =>
|
||||
navigator.clipboard.readText(),
|
||||
);
|
||||
|
||||
await luigiPage.goto(inviteUrl);
|
||||
|
||||
await expect(
|
||||
luigiPage.getByRole("heading", { name: "Mario's organization" }),
|
||||
).toBeVisible();
|
||||
await expect(marioPage.getByText("Luigi")).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step("Kick out Luigi from the organization", async () => {
|
||||
await marioPage.getByRole("button", { name: "Remove" }).click();
|
||||
|
||||
await expect(marioPage.getByText("Luigi")).not.toBeVisible();
|
||||
|
||||
await expect(
|
||||
luigiPage.getByRole("heading", {
|
||||
name: "You don't have access to this organization",
|
||||
}),
|
||||
).toBeVisible();
|
||||
|
||||
await luigiPage.getByRole("link", { name: "Go back to home" }).click();
|
||||
|
||||
await expect(
|
||||
luigiPage.getByRole("heading", { name: "Organizations example app" }),
|
||||
).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,20 @@
|
||||
# passkey-svelte
|
||||
|
||||
## 0.0.85
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-svelte@0.13.31
|
||||
|
||||
## 0.0.84
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.83
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "passkey-svelte",
|
||||
"version": "0.0.83",
|
||||
"version": "0.0.85",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# minimal-auth-passkey
|
||||
|
||||
## 0.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.94
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.93
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passkey",
|
||||
"private": true,
|
||||
"version": "0.0.93",
|
||||
"version": "0.0.95",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# passphrase
|
||||
|
||||
## 0.0.92
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.91
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.90
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passphrase",
|
||||
"private": true,
|
||||
"version": "0.0.90",
|
||||
"version": "0.0.92",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# jazz-password-manager
|
||||
|
||||
## 0.0.116
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.115
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.114
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-password-manager",
|
||||
"private": true,
|
||||
"version": "0.0.114",
|
||||
"version": "0.0.116",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# jazz-example-pets
|
||||
|
||||
## 0.0.214
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.213
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.212
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-pets",
|
||||
"private": true,
|
||||
"version": "0.0.212",
|
||||
"version": "0.0.214",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# reactions
|
||||
|
||||
## 0.0.94
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.93
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.92
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "reactions",
|
||||
"private": true,
|
||||
"version": "0.0.92",
|
||||
"version": "0.0.94",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# richtext-tiptap
|
||||
|
||||
## 0.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
- jazz-richtext-tiptap@0.1.7
|
||||
|
||||
## 0.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
- jazz-richtext-tiptap@0.1.6
|
||||
|
||||
## 0.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "richtext-tiptap",
|
||||
"private": true,
|
||||
"version": "0.1.5",
|
||||
"version": "0.1.7",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# richtext
|
||||
|
||||
## 0.0.84
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
- jazz-richtext-prosemirror@0.1.18
|
||||
|
||||
## 0.0.83
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
- jazz-richtext-prosemirror@0.1.17
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "richtext",
|
||||
"private": true,
|
||||
"version": "0.0.82",
|
||||
"version": "0.0.84",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# todo-vue
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-browser@0.13.31
|
||||
- jazz-vue@0.13.31
|
||||
|
||||
## 0.0.97
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
- jazz-vue@0.13.30
|
||||
|
||||
## 0.0.96
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "todo-vue",
|
||||
"version": "0.0.96",
|
||||
"version": "0.0.98",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# jazz-example-todo
|
||||
|
||||
## 0.0.213
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.212
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.211
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-todo",
|
||||
"private": true,
|
||||
"version": "0.0.211",
|
||||
"version": "0.0.213",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# version-history
|
||||
|
||||
## 0.0.92
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e5b170f]
|
||||
- jazz-tools@0.13.31
|
||||
- jazz-inspector@0.13.31
|
||||
- jazz-react@0.13.31
|
||||
|
||||
## 0.0.91
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.30
|
||||
- jazz-react@0.13.30
|
||||
- jazz-tools@0.13.30
|
||||
|
||||
## 0.0.90
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "version-history",
|
||||
"private": true,
|
||||
"version": "0.0.90",
|
||||
"version": "0.0.92",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
6
flake.lock
generated
6
flake.lock
generated
@@ -20,11 +20,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1739580444,
|
||||
"narHash": "sha256-+/bSz4EAVbqz8/HsIGLroF8aNaO8bLRL7WfACN+24g4=",
|
||||
"lastModified": 1747179050,
|
||||
"narHash": "sha256-qhFMmDkeJX9KJwr5H32f1r7Prs7XbQWtO0h3V0a0rFY=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8bb37161a0488b89830168b81c48aed11569cb93",
|
||||
"rev": "adaa24fbf46737f3f1b5497bf64bae750f82942e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
# JS development
|
||||
nodejs_22
|
||||
nodePackages.pnpm
|
||||
pnpm_9
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
|
||||
@@ -4,8 +4,6 @@ import { clsx } from "clsx";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { Icon } from "../atoms/Icon";
|
||||
|
||||
// TODO: add tabs feature, and remove CodeExampleTabs
|
||||
|
||||
export function CopyButton({
|
||||
code,
|
||||
size,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ExampleCard } from "@/components/examples/ExampleCard";
|
||||
import { ExampleDemo } from "@/components/examples/ExampleDemo";
|
||||
import { ClerkFullLogo } from "@/components/icons/ClerkFullLogo";
|
||||
import { ReactLogo } from "@/components/icons/ReactLogo";
|
||||
import { ReactNativeLogo } from "@/components/icons/ReactNativeLogo";
|
||||
@@ -508,16 +507,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: "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",
|
||||
@@ -681,15 +680,11 @@ export default function Page() {
|
||||
|
||||
<GappedGrid>
|
||||
{category.examples.map((example) =>
|
||||
example.showDemo ? (
|
||||
<ExampleDemo key={example.slug} example={example} />
|
||||
) : (
|
||||
<ExampleCard
|
||||
className="border bg-stone-50 shadow-sm p-3 rounded-lg dark:bg-stone-950"
|
||||
key={example.slug}
|
||||
example={example}
|
||||
/>
|
||||
),
|
||||
<ExampleCard
|
||||
className="border bg-stone-50 shadow-sm p-3 rounded-lg dark:bg-stone-950"
|
||||
key={example.slug}
|
||||
example={example}
|
||||
/>
|
||||
)}
|
||||
</GappedGrid>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import { HelpLinks } from "@/components/docs/HelpLinks";
|
||||
import { TableOfContents } from "@/components/docs/TableOfContents";
|
||||
import { JazzMobileNav } from "@/components/nav";
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { clsx } from "clsx";
|
||||
import { useState } from "react";
|
||||
|
||||
interface CodeExampleTab {
|
||||
name: string;
|
||||
content: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface CodeExampleTabsProps {
|
||||
tabs: Array<CodeExampleTab>;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
// TODO: handle tabs in CodeGroup component
|
||||
|
||||
export function CodeExampleTabs({
|
||||
tabs,
|
||||
className = "",
|
||||
}: CodeExampleTabsProps) {
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"bg-white h-full flex flex-col",
|
||||
"dark:bg-stone-925",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className="flex border-b overflow-x-auto overflow-y-hidden dark:bg-stone-950">
|
||||
{tabs.map((tab, index) => (
|
||||
<div key={index}>
|
||||
<button
|
||||
key={index}
|
||||
className={clsx(
|
||||
activeTab === index
|
||||
? "border-blue-700 bg-white text-stone-700 dark:bg-stone-925 dark:text-blue-500 dark:border-blue-500"
|
||||
: "border-transparent text-stone-500 hover:text-stone-700 dark:hover:text-blue-500",
|
||||
"flex items-center -mb-px transition-colors px-3 pb-2 pt-2.5 block text-xs border-b-2 ",
|
||||
)}
|
||||
onClick={() => setActiveTab(index)}
|
||||
>
|
||||
{tab.name}
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex-1 overflow-y-auto">{tabs[activeTab].content}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import { CodeExampleTabs } from "@/components/examples/CodeExampleTabs";
|
||||
import { ExampleLinks } from "@/components/examples/ExampleLinks";
|
||||
import { ExampleTags } from "@/components/examples/ExampleTags";
|
||||
import { Example } from "@/content/example";
|
||||
import { GappedGrid } from "@garden-co/design-system/src/components/molecules/GappedGrid";
|
||||
|
||||
export function ExampleDemo({ example }: { example: Example }) {
|
||||
const { name, demoUrl, illustration } = example;
|
||||
|
||||
return (
|
||||
<GappedGrid
|
||||
gap="none"
|
||||
className="border bg-stone-50 shadow-sm rounded-lg dark:bg-stone-950 overflow-hidden"
|
||||
>
|
||||
<div className="p-3 col-span-full flex flex-col gap-2 justify-between items-baseline border-b sm:flex-row">
|
||||
<div className="flex flex-col gap-2 items-baseline sm:flex-row">
|
||||
<h2 className="font-medium text-stone-900 dark:text-white leading-none">
|
||||
{name}
|
||||
</h2>
|
||||
<ExampleTags example={example} />
|
||||
</div>
|
||||
|
||||
<ExampleLinks example={example} />
|
||||
</div>
|
||||
<div className="h-[25rem] lg:h-[30rem] border-t overflow-auto col-span-full md:col-span-2 lg:col-span-3 order-last md:order-none md:border-r md:border-t-0">
|
||||
{example.codeSamples && (
|
||||
<CodeExampleTabs tabs={example.codeSamples}></CodeExampleTabs>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-span-full md:p-8 md:col-span-2 lg:col-span-3 h-[25rem] lg:h-[30rem] lg:p-12">
|
||||
<iframe
|
||||
width="100%"
|
||||
height="100%"
|
||||
className="md:rounded-lg md:shadow-lg"
|
||||
src={demoUrl}
|
||||
title={name}
|
||||
/>
|
||||
</div>
|
||||
</GappedGrid>
|
||||
);
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
import {
|
||||
CodeExampleTabs as CodeExampleTabsClient,
|
||||
CodeExampleTabsProps,
|
||||
} from "@/components/examples/CodeExampleTabs";
|
||||
|
||||
import {
|
||||
ContentByFramework as ContentByFrameworkClient,
|
||||
ContentByFrameworkProps,
|
||||
@@ -14,10 +9,6 @@ import { FileDownloadLink as FileDownloadLinkClient } from "./FileDownloadLink";
|
||||
import { Framework as FrameworkClient } from "./docs/Framework";
|
||||
import { IssueTrackerPreview as IssueTrackerPreviewClient } from "./docs/IssueTrackerPreview";
|
||||
|
||||
export function CodeExampleTabs(props: CodeExampleTabsProps) {
|
||||
return <CodeExampleTabsClient {...props} />;
|
||||
}
|
||||
|
||||
export function CodeGroup(props: { children: React.ReactNode }) {
|
||||
return <CodeGroupClient {...props}></CodeGroupClient>;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { ContentByFramework, FileDownloadLink, CodeGroup } from '@/components/forMdx'
|
||||
|
||||
export const metadata = {
|
||||
description: "Learn how to leverage AI tools when building Jazz apps. Use llms.txt to help LLMs understand Jazz."
|
||||
};
|
||||
|
||||
# Using AI to build Jazz apps
|
||||
|
||||
AI tools, particularly large language models (LLMs), can accelerate your development with Jazz. Searching docs, responding to questions and even helping you write code are all things that LLMs are starting to get good at.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Authentication States" };
|
||||
export const metadata = {
|
||||
description: "Learn about Jazz's authentication states: anonymous, guest, and fully authenticated."
|
||||
};
|
||||
|
||||
import { CodeGroup, ContentByFramework } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Clerk Authentication" };
|
||||
export const metadata = {
|
||||
description: "Integrate Clerk with your Jazz app to authenticate users. This method combines Clerk's comprehensive authentication services with Jazz's local-first capabilities."
|
||||
};
|
||||
|
||||
import { CodeGroup, ContentByFramework } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
export const metadata = {
|
||||
description: "We do not currently support Clerk in React Native, but we do have support for React Native Expo."
|
||||
};
|
||||
|
||||
|
||||
# Clerk Authentication
|
||||
|
||||
We do not currently support Clerk in React Native, but we do have support for [React Native Expo](/docs/react-native-expo/authentication/clerk).
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Authentication methods" };
|
||||
export const metadata = {
|
||||
description: "Learn about the different authentication methods that you can use with your Jazz app."
|
||||
};
|
||||
|
||||
import { CodeGroup, ContentByFramework } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Passkey Authentication" };
|
||||
export const metadata = {
|
||||
description: "Passkey authentication is fully local-first and the most secure of the auth methods that Jazz provides because keys are managed by the device/operating system itself."
|
||||
};
|
||||
|
||||
import { CodeGroup, ContentByFramework } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Passphrase Authentication" };
|
||||
export const metadata = {
|
||||
description: "Passphrase authentication lets users log into any device using a recovery phrase consisting of multiple words (similar to cryptocurrency wallets). "
|
||||
};
|
||||
|
||||
import { CodeGroup, ContentByFramework } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
export const metadata = {
|
||||
description: "This feature has already been released, but the documentation is in progress."
|
||||
};
|
||||
|
||||
# Documentation coming soon
|
||||
|
||||
Grayed out pages on our sidebar indicate that documentation for this feature is still in progress. We're excited to bring you comprehensive guides and tutorials as soon as possible.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Form design pattern" };
|
||||
export const metadata = {
|
||||
description: "Learn how to handle autosaved forms in Jazz, storing drafts, and validating data."
|
||||
};
|
||||
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Organization design pattern" };
|
||||
export const metadata = {
|
||||
description: "Learn how to share a set of data between users through organizations."
|
||||
};
|
||||
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
@@ -148,10 +150,12 @@ declare module "jazz-react" {
|
||||
}
|
||||
// ---cut---
|
||||
export function AcceptInvitePage() {
|
||||
const { me } = useAccount({ resolve: { root: { organizations: true } } });
|
||||
const { me } = useAccount({
|
||||
resolve: { root: { organizations: { $each: { $onError: null } } } },
|
||||
});
|
||||
|
||||
const onAccept = (organizationId: ID<Organization>) => {
|
||||
if (me?.root?.organizations) {
|
||||
if (me) {
|
||||
Organization.load(organizationId).then((organization) => {
|
||||
if (organization) {
|
||||
// avoid duplicates
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
export const metadata = {
|
||||
description: "Get answers to common questions about Jazz and our commitment to open source."
|
||||
};
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
## How established is Jazz?
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { ContentByFramework, CodeGroup } from '@/components/forMdx'
|
||||
|
||||
export const metadata = { title: "Group inheritance" };
|
||||
export const metadata = {
|
||||
description: "Create Groups that inherit members from other Groups."
|
||||
};
|
||||
|
||||
# Group Inheritance
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Groups as permission scopes" };
|
||||
export const metadata = {
|
||||
description: "Manage permissions of CoValues using Groups. Learn how to add members to a Group, check permissions, and more."
|
||||
};
|
||||
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
export const metadata = { title: "Public sharing and invites" };
|
||||
export const metadata = {
|
||||
description: "Share CoValues in Jazz through public sharing and invite links. Enable collaboration by granting access to everyone or specific users with different permission levels."
|
||||
};
|
||||
|
||||
import { ContentByFramework, CodeGroup } from '@/components/forMdx'
|
||||
|
||||
# Public sharing and invites
|
||||
|
||||
...more docs coming soon
|
||||
|
||||
## Public sharing
|
||||
|
||||
You can share CoValues publicly by setting the `owner` to a `Group`, and granting
|
||||
@@ -92,3 +92,104 @@ useAcceptInvite({
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
### Requesting Invites
|
||||
|
||||
To allow a non-group member to request an invitation to a group you can use the `writeOnly` role.
|
||||
This means that users only have write access to a specific requests list (they can't read other requests).
|
||||
However, Administrators can review and approve these requests.
|
||||
|
||||
Create the data models.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { CoMap, co, CoValue, Account, CoList } from "jazz-tools";
|
||||
// ---cut-before---
|
||||
class JoinRequest extends CoMap {
|
||||
account = co.ref(Account);
|
||||
status = co.literal("pending", "approved", "rejected");
|
||||
}
|
||||
|
||||
class RequestsList extends CoList.Of(co.ref(JoinRequest)) {};
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Set up the request system with appropriate access controls.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { Group, co, CoList, CoMap, Account } from "jazz-tools";
|
||||
import { createInviteLink } from "jazz-react";
|
||||
|
||||
export class JoinRequest extends CoMap {
|
||||
account = co.ref(Account);
|
||||
status = co.literal("pending", "approved", "rejected");
|
||||
}
|
||||
|
||||
export class RequestsList extends CoList.Of(co.ref(JoinRequest)) {};
|
||||
|
||||
// ---cut-before---
|
||||
function createRequestsToJoin() {
|
||||
const requestsGroup = Group.create();
|
||||
requestsGroup.addMember("everyone", "writeOnly");
|
||||
|
||||
return RequestsList.create([], requestsGroup);
|
||||
}
|
||||
|
||||
async function sendJoinRequest(
|
||||
requestsList: RequestsList,
|
||||
account: Account,
|
||||
) {
|
||||
const request = JoinRequest.create(
|
||||
{
|
||||
account,
|
||||
status: "pending",
|
||||
},
|
||||
requestsList._owner // Inherit the access controls of the requestsList
|
||||
);
|
||||
|
||||
requestsList.push(request);
|
||||
|
||||
return request;
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Using the write-only access users can submit requests that only administrators can review and approve.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co, CoMap, CoList, ID, Account, Group, Resolved } from "jazz-tools";
|
||||
|
||||
class JoinRequest extends CoMap {
|
||||
account = co.ref(Account);
|
||||
status = co.string; // Can be "pending", "approved", "rejected"
|
||||
}
|
||||
|
||||
export class RequestsList extends CoList.Of(co.ref(JoinRequest)) {};
|
||||
|
||||
export class RequestsToJoin extends CoMap {
|
||||
writeOnlyInvite = co.string;
|
||||
requests = co.ref(RequestsList);
|
||||
}
|
||||
|
||||
// ---cut-before---
|
||||
async function approveJoinRequest(
|
||||
joinRequest: JoinRequest,
|
||||
targetGroup: Group,
|
||||
) {
|
||||
const account = await Account.load(joinRequest._refs.account.id);
|
||||
|
||||
if (account) {
|
||||
targetGroup.addMember(account, "reader");
|
||||
joinRequest.status = "approved";
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "React guide" };
|
||||
export const metadata = {
|
||||
description: "A step-by-step tutorial where we build an issue tracker app using Jazz and React."
|
||||
};
|
||||
|
||||
import { CodeGroup, IssueTrackerPreview } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { CodeGroup, ContentByFramework, JazzLogo } from '@/components/forMdx'
|
||||
|
||||
export const metadata = {
|
||||
title: "Learn some Jazz",
|
||||
openGraph: {
|
||||
title: "Learn some Jazz",
|
||||
},
|
||||
title: "Documentation",
|
||||
};
|
||||
|
||||
# Learn some <span className="sr-only">Jazz</span> <JazzLogo className="h-[41px] -ml-0.5 -mt-[3px] inline" />
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { CodeGroup, ContentByFramework } from '@/components/forMdx'
|
||||
import { JazzIcon } from "@garden-co/design-system/src/components/atoms/logos/JazzIcon";
|
||||
|
||||
export const metadata = {
|
||||
description: "Visually inspect a Jazz account and other CoValues using their ID."
|
||||
};
|
||||
|
||||
# Jazz Inspector
|
||||
|
||||
[Jazz Inspector](https://inspector.jazz.tools) is a tool to visually inspect a Jazz account or other CoValues.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Providers - React Native Expo" };
|
||||
export const metadata = {
|
||||
description: "Configure your JazzProvider - the core component that connects your app to Jazz, handling sync, storage, account schema, and auth."
|
||||
};
|
||||
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Providers - React Native" };
|
||||
export const metadata = {
|
||||
description: "Configure your JazzProvider - the core component that connects your app to Jazz, handling sync, storage, account schema, and auth."
|
||||
};
|
||||
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Providers" };
|
||||
export const metadata = {
|
||||
description: "Configure your JazzProvider - the core component that connects your app to Jazz, handling sync, storage, account schema, and auth.",
|
||||
};
|
||||
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
@@ -190,4 +192,4 @@ See [Authentication States](/docs/authentication/authentication-states) for more
|
||||
|
||||
## 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.
|
||||
If you have questions about configuring the Jazz Provider for your specific use case, [join our Discord community](https://discord.gg/utDMjHYg42) for help.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "React Native (Expo)" };
|
||||
export const metadata = {
|
||||
description: "Learn how to set up Jazz in your React Native Expo application."
|
||||
};
|
||||
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "React Native" };
|
||||
export const metadata = {
|
||||
description: "Learn how to set up Jazz in your React Native application."
|
||||
};
|
||||
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
export const metadata = { title: "Installation" };
|
||||
export const metadata = {
|
||||
description: "Learn how to set up Jazz in your React application."
|
||||
};
|
||||
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
# Installation and Setup
|
||||
|
||||
Add Jazz to your React application in minutes. This setup covers standard React apps, Next.js, and gives an overview of experimental SSR approaches.
|
||||
Add Jazz to your React application in minutes. This setup covers standard React apps, Next.js, and gives an overview of experimental SSR approaches.
|
||||
|
||||
Integrating Jazz with React is straightforward. You'll define data schemas that describe your application's structure, then wrap your app with a provider that handles sync and storage. The whole process takes just three steps:
|
||||
|
||||
@@ -149,7 +151,7 @@ import { useAccount } from "jazz-react";
|
||||
|
||||
export function Profile() {
|
||||
const { me } = useAccount();
|
||||
|
||||
|
||||
return <div>Hello, {me?.name}</div>;
|
||||
}
|
||||
```
|
||||
@@ -189,11 +191,11 @@ import { MyCollection, MyItem } from "./schema";
|
||||
export default async function PublicData() {
|
||||
// Load data directly in the server component
|
||||
const items = await MyCollection.load(collectionID);
|
||||
|
||||
|
||||
if (!items) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<ul>
|
||||
{items.map(item => (
|
||||
@@ -285,10 +287,10 @@ export function ItemListHydrator({ initialItems }: { initialItems: MyItem[] }) {
|
||||
const items = Array.from(myCollection?.values() || []).filter(
|
||||
(item): item is MyItem => !!item
|
||||
);
|
||||
|
||||
|
||||
// Use server data until client data is available
|
||||
const displayItems = items || initialItems;
|
||||
|
||||
|
||||
return <ItemList items={displayItems} />;
|
||||
}
|
||||
```
|
||||
@@ -340,10 +342,10 @@ export function ItemListHydrator({ initialItems }: { initialItems: MyItem[] }) {
|
||||
const items = Array.from(myCollection?.values() || []).filter(
|
||||
(item): item is MyItem => !!item
|
||||
);
|
||||
|
||||
|
||||
// Use server data until client data is available
|
||||
const displayItems = items || initialItems;
|
||||
|
||||
|
||||
return <ItemList items={displayItems} />;
|
||||
}
|
||||
// @filename: ServerItemPage.tsx
|
||||
@@ -362,7 +364,7 @@ export default async function ServerItemPage() {
|
||||
const items = Array.from(initialItems?.values() || []).filter(
|
||||
(item): item is MyItem => !!item
|
||||
);
|
||||
|
||||
|
||||
// Pass to client hydrator
|
||||
return <ItemListHydrator initialItems={items} />;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const metadata = { title: "Node.JS / server workers" };
|
||||
export const metadata = {
|
||||
description: "Use Jazz server-side through Server Workers which act like Jazz accounts."
|
||||
};
|
||||
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user