Compare commits
30 Commits
jazz-run@0
...
jazz-run@0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b8f5ed3ca | ||
|
|
fcf0baee2e | ||
|
|
07183ffe5b | ||
|
|
11c36460ac | ||
|
|
e0d7b266e7 | ||
|
|
3706360ffc | ||
|
|
3d7a20ca64 | ||
|
|
381ecaaf96 | ||
|
|
25435ba597 | ||
|
|
c56fd81bff | ||
|
|
707bf332d0 | ||
|
|
40225635f1 | ||
|
|
e4ff701488 | ||
|
|
314cdee815 | ||
|
|
fa549f49b7 | ||
|
|
c38460afd2 | ||
|
|
7657c8469e | ||
|
|
97abe86d7e | ||
|
|
a339dfaeb0 | ||
|
|
3710776d09 | ||
|
|
dffc2ee2fe | ||
|
|
cd47928252 | ||
|
|
4b84ede0b5 | ||
|
|
0de4d684d8 | ||
|
|
d78a5364f6 | ||
|
|
228dfa1799 | ||
|
|
74a66eaa94 | ||
|
|
96670db342 | ||
|
|
e4655c3705 | ||
|
|
5a5f767b3d |
106
.github/workflows/build-and-deploy.yaml
vendored
106
.github/workflows/build-and-deploy.yaml
vendored
@@ -1,106 +0,0 @@
|
||||
name: Build and Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
build-examples:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
example: ["chat", "pets", "todo", "inspector"]
|
||||
# example: ["twit", "chat", "counter-js-auth0", "pets", "twit", "file-drop", "inspector"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Enable corepack
|
||||
run: corepack enable
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Get pnpm store directory
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ env.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: gardencmp
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Pnpm Build
|
||||
run: |
|
||||
pnpm install
|
||||
pnpm turbo build;
|
||||
working-directory: ./examples/${{ matrix.example }}
|
||||
|
||||
- name: Docker Build & Push
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: ./examples/${{ matrix.example }}
|
||||
push: true
|
||||
tags: ghcr.io/gardencmp/${{github.event.repository.name}}-example-${{ matrix.example }}:${{github.head_ref || github.ref_name}}-${{github.sha}}-${{github.run_number}}-${{github.run_attempt}}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
deploy-examples:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-examples
|
||||
strategy:
|
||||
matrix:
|
||||
example: ["chat", "pets", "todo", "inspector"]
|
||||
# example: ["twit", "chat", "counter-js-auth0", "pets", "twit", "file-drop", "inspector"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
- uses: gacts/install-nomad@v1
|
||||
- name: Tailscale
|
||||
uses: tailscale/github-action@v1
|
||||
with:
|
||||
authkey: ${{ secrets.TAILSCALE_AUTHKEY }}
|
||||
|
||||
- name: Deploy on Nomad
|
||||
run: |
|
||||
if [ "${{github.ref_name}}" == "main" ]; then
|
||||
export BRANCH_SUFFIX="";
|
||||
export BRANCH_SUBDOMAIN="";
|
||||
else
|
||||
export BRANCH_SUFFIX=-${{github.head_ref || github.ref_name}};
|
||||
export BRANCH_SUBDOMAIN=${{github.head_ref || github.ref_name}}.;
|
||||
fi
|
||||
|
||||
export DOCKER_USER=gardencmp;
|
||||
export DOCKER_PASSWORD=${{ secrets.DOCKER_PULL_PAT }};
|
||||
export DOCKER_TAG=ghcr.io/gardencmp/${{github.event.repository.name}}-example-${{ matrix.example }}:${{github.head_ref || github.ref_name}}-${{github.sha}}-${{github.run_number}}-${{github.run_attempt}};
|
||||
|
||||
envsubst '${DOCKER_USER} ${DOCKER_PASSWORD} ${DOCKER_TAG} ${BRANCH_SUFFIX} ${BRANCH_SUBDOMAIN}' < job-template.nomad > job-instance.nomad;
|
||||
cat job-instance.nomad;
|
||||
NOMAD_ADDR=${{ secrets.NOMAD_ADDR }} nomad job run job-instance.nomad;
|
||||
working-directory: ./examples/${{ matrix.example }}
|
||||
58
.github/workflows/build-examples.yaml
vendored
Normal file
58
.github/workflows/build-examples.yaml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: Build Examples
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
build-examples:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
example: [
|
||||
"chat",
|
||||
"chat-clerk",
|
||||
"inspector",
|
||||
"music-player",
|
||||
"password-manager",
|
||||
"pets",
|
||||
"todo",
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Enable corepack
|
||||
run: corepack enable
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Get pnpm store directory
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ env.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
|
||||
- name: Pnpm Build
|
||||
run: |
|
||||
pnpm install
|
||||
pnpm turbo build;
|
||||
working-directory: ./examples/${{ matrix.example }}
|
||||
9
e2e/BinaryCoStream/CHANGELOG.md
Normal file
9
e2e/BinaryCoStream/CHANGELOG.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# @jazz-e2e/binarycostream
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-tools@0.8.1
|
||||
- jazz-react@0.8.1
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@jazz-e2e/binarycostream",
|
||||
"private": true,
|
||||
"version": "0.0.81",
|
||||
"version": "0.0.82",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -14,11 +14,11 @@
|
||||
"*.{js,jsx,mdx,json}": "prettier --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.7.35-guest-auth.5",
|
||||
"cojson": "workspace:0.8.0",
|
||||
"hash-slash": "workspace:0.2.0",
|
||||
"is-ci": "^3.0.1",
|
||||
"jazz-react": "workspace:0.7.35-guest-auth.6",
|
||||
"jazz-tools": "workspace:0.7.35-guest-auth.6",
|
||||
"jazz-react": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
|
||||
@@ -2,12 +2,12 @@ module.exports = {
|
||||
root: true,
|
||||
env: { browser: true, es2020: true },
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
],
|
||||
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['react-refresh'],
|
||||
ignorePatterns: ["dist", ".eslintrc.cjs"],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["react-refresh"],
|
||||
rules: {},
|
||||
}
|
||||
};
|
||||
|
||||
2
examples/chat-clerk/.gitignore
vendored
2
examples/chat-clerk/.gitignore
vendored
@@ -22,3 +22,5 @@ dist-ssr
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
sync-db/
|
||||
10
examples/chat-clerk/.prettierrc
Normal file
10
examples/chat-clerk/.prettierrc
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "avoid",
|
||||
"printWidth": 80
|
||||
}
|
||||
@@ -1,88 +1,184 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.80
|
||||
## 0.0.81
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-tools@0.8.1
|
||||
- jazz-react@0.8.1
|
||||
- jazz-react-auth-clerk@0.8.1
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- bcec3be: Implement Clerk auth method + example
|
||||
- Updated dependencies [6a147c2]
|
||||
- Updated dependencies [ad40b88]
|
||||
- Updated dependencies [23369dc]
|
||||
- Updated dependencies [c2b62a0]
|
||||
- Updated dependencies [bcec3be]
|
||||
- Updated dependencies [1a979b6]
|
||||
- Updated dependencies [bcec3be]
|
||||
- Updated dependencies [6ce2051]
|
||||
- cojson@0.8.0
|
||||
- jazz-tools@0.8.0
|
||||
- jazz-react@0.8.0
|
||||
- jazz-react-auth-clerk@0.8.0
|
||||
|
||||
## 0.0.80-guest-auth.6
|
||||
## 0.0.82-guest-auth.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-react@0.7.35-guest-auth.6
|
||||
- jazz-tools@0.7.35-guest-auth.6
|
||||
- jazz-react-auth-clerk@0.7.35-guest-auth.6
|
||||
|
||||
## 0.0.80-guest-auth.5
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [49a8b54]
|
||||
- Updated dependencies [35bbcd9]
|
||||
- Updated dependencies [6f80282]
|
||||
- Updated dependencies [35bbcd9]
|
||||
- Updated dependencies [cac2ec9]
|
||||
- Updated dependencies [f350e90]
|
||||
- jazz-tools@0.7.35
|
||||
- cojson@0.7.35
|
||||
- jazz-react@0.7.35
|
||||
|
||||
## 0.0.81
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5d91f9f]
|
||||
- Updated dependencies [5094e6d]
|
||||
- Updated dependencies [b09589b]
|
||||
- Updated dependencies [2c3a40c]
|
||||
- Updated dependencies [4e16575]
|
||||
- Updated dependencies [ea882ab]
|
||||
- cojson@0.7.34
|
||||
- jazz-react@0.7.34
|
||||
- jazz-tools@0.7.34
|
||||
|
||||
## 0.0.81-neverthrow.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- cojson@0.7.35-guest-auth.5
|
||||
- jazz-react@0.7.35-guest-auth.5
|
||||
- jazz-react-auth-clerk@0.7.35-guest-auth.5
|
||||
- jazz-tools@0.7.35-guest-auth.5
|
||||
- cojson@0.7.34-neverthrow.8
|
||||
- jazz-react@0.7.34-neverthrow.8
|
||||
- jazz-tools@0.7.34-neverthrow.8
|
||||
|
||||
## 0.0.80-guest-auth.4
|
||||
## 0.0.81-neverthrow.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-react@0.7.35-guest-auth.4
|
||||
- jazz-tools@0.7.35-guest-auth.4
|
||||
- jazz-react-auth-clerk@0.7.35-guest-auth.4
|
||||
- cojson@0.7.34-neverthrow.7
|
||||
- jazz-react@0.7.34-neverthrow.7
|
||||
- jazz-tools@0.7.34-neverthrow.7
|
||||
|
||||
## 0.0.80-guest-auth.3
|
||||
## 0.0.81-neverthrow.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-react@0.7.35-guest-auth.3
|
||||
- jazz-tools@0.7.35-guest-auth.3
|
||||
- jazz-react-auth-clerk@0.7.33-guest-auth.3
|
||||
- cojson@0.7.34-neverthrow.4
|
||||
- jazz-react@0.7.34-neverthrow.4
|
||||
- jazz-tools@0.7.34-neverthrow.4
|
||||
|
||||
## 0.0.80-unique.2
|
||||
## 0.0.81-neverthrow.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-tools@0.7.35-unique.2
|
||||
- cojson@0.7.35-unique.2
|
||||
- jazz-react@0.7.35-unique.2
|
||||
- jazz-react-auth-clerk@0.7.33-unique.2
|
||||
- cojson@0.7.34-neverthrow.3
|
||||
- jazz-react@0.7.34-neverthrow.3
|
||||
- jazz-tools@0.7.34-neverthrow.3
|
||||
|
||||
## 0.0.80-new-auth.1
|
||||
## 0.0.81-neverthrow.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.7.34-neverthrow.2
|
||||
|
||||
## 0.0.81-neverthrow.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-react@0.7.35-new-auth.1
|
||||
- jazz-react-auth-clerk@0.7.33-new-auth.1
|
||||
- cojson@0.7.34-neverthrow.1
|
||||
- jazz-react@0.7.34-neverthrow.1
|
||||
- jazz-tools@0.7.34-neverthrow.1
|
||||
|
||||
## 0.0.80-new-auth.0
|
||||
## 0.0.81-neverthrow.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Implement Clerk auth method + example
|
||||
- Updated dependencies
|
||||
- cojson@0.7.34-neverthrow.0
|
||||
- jazz-react@0.7.34-neverthrow.0
|
||||
- jazz-tools@0.7.34-neverthrow.0
|
||||
|
||||
## 0.0.80
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [b297c93]
|
||||
- Updated dependencies [3bf5127]
|
||||
- Updated dependencies [a8b74ff]
|
||||
- Updated dependencies [db53161]
|
||||
- cojson@0.7.33
|
||||
- jazz-react@0.7.33
|
||||
- jazz-tools@0.7.33
|
||||
|
||||
## 0.0.80-hotfixes.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-react-auth-clerk@0.7.33-new-auth.0
|
||||
- jazz-react@0.7.35-new-auth.0
|
||||
- jazz-tools@0.7.35-new-auth.0
|
||||
- cojson@0.7.33-hotfixes.5
|
||||
- jazz-react@0.7.33-hotfixes.5
|
||||
- jazz-tools@0.7.33-hotfixes.5
|
||||
|
||||
## 0.0.80-hotfixes.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- cojson@0.7.33-hotfixes.4
|
||||
- jazz-react@0.7.33-hotfixes.4
|
||||
- jazz-tools@0.7.33-hotfixes.4
|
||||
|
||||
## 0.0.80-hotfixes.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- cojson@0.7.33-hotfixes.3
|
||||
- jazz-react@0.7.33-hotfixes.3
|
||||
- jazz-tools@0.7.33-hotfixes.3
|
||||
|
||||
## 0.0.80-hotfixes.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.7.33-hotfixes.2
|
||||
|
||||
## 0.0.80-hotfixes.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.7.33-hotfixes.1
|
||||
|
||||
## 0.0.80-hotfixes.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- cojson@0.7.33-hotfixes.0
|
||||
- jazz-react@0.7.33-hotfixes.0
|
||||
- jazz-tools@0.7.33-hotfixes.0
|
||||
|
||||
## 0.0.79
|
||||
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
# Jazz Chat Example
|
||||
# Jazz Chat Example (with Clerk auth)
|
||||
|
||||
Live version: https://example-chat.jazz.tools
|
||||
<!-- Live version: [https://chat-clerk.jazz.tools](https://chat-clerk.jazz.tools) -->
|
||||
|
||||
## Installing & running the example locally
|
||||
|
||||
(this requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation))
|
||||
|
||||
Start by checking out `jazz`
|
||||
|
||||
```bash
|
||||
git clone https://github.com/gardencmp/jazz.git
|
||||
cd jazz/examples/chat
|
||||
cd jazz/examples/chat-clerk
|
||||
pnpm pack --pack-destination /tmp
|
||||
mkdir -p ~/jazz-examples/chat # or any other directory
|
||||
tar -xf /tmp/jazz-example-chat-* --strip-components 1 -C ~/jazz-examples/chat
|
||||
cd ~/jazz-examples/chat
|
||||
mkdir -p ~/jazz-examples/chat-clerk # or any other directory
|
||||
tar -xf /tmp/jazz-example-chat-* --strip-components 1 -C ~/jazz-examples/chat-clerk
|
||||
cd ~/jazz-examples/chat-clerk
|
||||
```
|
||||
|
||||
This ensures that you have the example app without git history and independent of the Jazz multi-package monorepo.
|
||||
@@ -34,9 +35,8 @@ pnpm dev
|
||||
|
||||
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 Global Mesh](https://jazz.tools/mesh) (`wss://sync.jazz.tools`) - so cross-device use, invites and collaboration should just work.
|
||||
|
||||
You can also run a local sync server by running `npx cojson-simple-sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?sync=ws://localhost:4200`), or by setting the `sync` parameter of the `<Jazz.Provider>` provider component in [./src/2_main.tsx](./src/2_main.tsx).
|
||||
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 the `<Jazz.Provider>` provider component in [./src/2_main.tsx](./src/2_main.tsx).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat-clerk",
|
||||
"private": true,
|
||||
"version": "0.0.80",
|
||||
"version": "0.0.81",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -23,9 +23,9 @@
|
||||
"clsx": "^2.0.0",
|
||||
"cojson": "workspace:0.8.0",
|
||||
"hash-slash": "workspace:0.2.0",
|
||||
"jazz-react": "workspace:0.8.0",
|
||||
"jazz-react-auth-clerk": "workspace:0.8.0",
|
||||
"jazz-tools": "workspace:0.8.0",
|
||||
"jazz-react": "workspace:0.8.1",
|
||||
"jazz-react-auth-clerk": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -3,4 +3,4 @@ export default {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,85 +1,30 @@
|
||||
import { CoMap, CoList, co, Group, ID } from "jazz-tools";
|
||||
import { createJazzReactApp } from "jazz-react";
|
||||
import { useJazzClerkAuth } from "jazz-react-auth-clerk";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { Group, ID } from "jazz-tools";
|
||||
import { useIframeHashRouter } from "hash-slash";
|
||||
import { useAccount } from "./main.tsx";
|
||||
import { Chat } from "./schema.ts";
|
||||
import { ChatScreen } from "./chatScreen.tsx";
|
||||
import { StrictMode } from "react";
|
||||
import { AppContainer, TopBar } from "./ui.tsx";
|
||||
|
||||
import {
|
||||
ClerkProvider,
|
||||
SignInButton,
|
||||
useAuth,
|
||||
useClerk,
|
||||
} from "@clerk/clerk-react";
|
||||
export function App() {
|
||||
const { me, logOut } = useAccount();
|
||||
|
||||
export class Message extends CoMap {
|
||||
text = co.string;
|
||||
const createChat = () => {
|
||||
if (!me) return;
|
||||
const group = Group.create({ owner: me });
|
||||
group.addMember("everyone", "writer");
|
||||
const chat = Chat.create([], { owner: group });
|
||||
location.hash = "/chat/" + chat.id;
|
||||
};
|
||||
|
||||
return (
|
||||
<AppContainer>
|
||||
<TopBar>
|
||||
{me?.profile?.name} · <button onClick={logOut}>Log out</button>
|
||||
</TopBar>
|
||||
{useIframeHashRouter().route({
|
||||
"/": () => createChat() as never,
|
||||
"/chat/:id": id => <ChatScreen chatID={id as ID<Chat>} />,
|
||||
})}
|
||||
</AppContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export class Chat extends CoList.Of(co.ref(Message)) {}
|
||||
|
||||
const Jazz = createJazzReactApp();
|
||||
export const { useAccount, useCoState } = Jazz;
|
||||
|
||||
function AuthAndJazz({ children }: { children: React.ReactNode }) {
|
||||
const clerk = useClerk();
|
||||
const [auth, state] = useJazzClerkAuth(clerk);
|
||||
|
||||
return (
|
||||
<>
|
||||
{state.errors.map((error) => (
|
||||
<div key={error}>{error}</div>
|
||||
))}
|
||||
{auth ? (
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
peer="wss://mesh.jazz.tools/?key=chat-example-jazz-clerk@gcmp.io"
|
||||
>
|
||||
{children}
|
||||
</Jazz.Provider>
|
||||
) : (
|
||||
<SignInButton />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function App() {
|
||||
const { signOut } = useAuth();
|
||||
const { me } = useAccount();
|
||||
|
||||
const createChat = () => {
|
||||
if (!me) return;
|
||||
const group = Group.create({ owner: me });
|
||||
group.addMember("everyone", "writer");
|
||||
const chat = Chat.create([], { owner: group });
|
||||
location.hash = "/chat/" + chat.id;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-between w-screen h-screen p-2 dark:bg-black dark:text-white">
|
||||
<div className="rounded mb-5 px-2 py-1 text-sm self-end">
|
||||
{me?.profile?.name} ·{" "}
|
||||
<button onClick={() => signOut()}>Log Out</button>
|
||||
</div>
|
||||
{useIframeHashRouter().route({
|
||||
"/": () => createChat() as never,
|
||||
"/chat/:id": (id) => <ChatScreen chatID={id as ID<Chat>} />,
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<ClerkProvider
|
||||
publishableKey={import.meta.env.VITE_CLERK_PUBLISHABLE_KEY}
|
||||
afterSignOutUrl="/"
|
||||
>
|
||||
<AuthAndJazz>
|
||||
<App />
|
||||
</AuthAndJazz>
|
||||
</ClerkProvider>
|
||||
</StrictMode>
|
||||
);
|
||||
|
||||
@@ -1,42 +1,43 @@
|
||||
import { ID } from 'jazz-tools';
|
||||
import { Chat, Message, useCoState } from './app.tsx';
|
||||
import { ID } from "jazz-tools";
|
||||
import { Chat, Message } from "./schema.ts";
|
||||
import { useCoState } from "./main.tsx";
|
||||
import {
|
||||
BubbleBody,
|
||||
BubbleContainer,
|
||||
BubbleInfo,
|
||||
ChatContainer,
|
||||
ChatInput,
|
||||
EmptyChatMessage,
|
||||
} from "./ui.tsx";
|
||||
|
||||
export function ChatScreen(props: { chatID: ID<Chat> }) {
|
||||
const chat = useCoState(Chat, props.chatID, [{}]);
|
||||
|
||||
return chat ? <div className='w-full max-w-xl h-full flex flex-col items-stretch'>
|
||||
{chat.length > 0
|
||||
? chat.map((msg) => <ChatBubble msg={msg} key={msg.id} />)
|
||||
: <div className='m-auto text-sm'>(Empty chat)</div>}
|
||||
<ChatInput onSubmit={(text) => {
|
||||
chat.push(
|
||||
Message.create({ text }, { owner: chat._owner })
|
||||
);
|
||||
}} />
|
||||
</div> : <div>Loading...</div>;
|
||||
return chat ? (
|
||||
<ChatContainer>
|
||||
{chat.length > 0 ? (
|
||||
chat.map(msg => <ChatBubble msg={msg} key={msg.id} />)
|
||||
) : (
|
||||
<EmptyChatMessage />
|
||||
)}
|
||||
<ChatInput
|
||||
onSubmit={text => {
|
||||
chat.push(Message.create({ text }, { owner: chat._owner }));
|
||||
}}
|
||||
/>
|
||||
</ChatContainer>
|
||||
) : (
|
||||
<div>Loading...</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ChatBubble(props: { msg: Message }) {
|
||||
const lastEdit = props.msg._edits.text;
|
||||
const align = lastEdit.by?.isMe ? 'items-end' : 'items-start';
|
||||
|
||||
return <div className={`${align} flex flex-col`}>
|
||||
<div className='rounded-xl bg-stone-100 dark:bg-stone-700 dark:text-white py-2 px-4 mt-2 min-w-[5rem]'>
|
||||
{ props.msg.text }
|
||||
</div>
|
||||
<div className='text-xs text-neutral-500 ml-2'>
|
||||
{ lastEdit.by?.profile?.name }{' '}
|
||||
{ lastEdit.madeAt?.toLocaleTimeString() }
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
function ChatInput(props: { onSubmit: (text: string) => void }) {
|
||||
return <input className='rounded p-2 border mt-auto dark:bg-black dark:text-white border-stone-300 dark:border-stone-700'
|
||||
placeholder='Type a message and press Enter'
|
||||
onKeyDown={({ key, currentTarget: input }) => {
|
||||
if (key !== 'Enter' || !input.value) return;
|
||||
props.onSubmit(input.value);
|
||||
input.value = '';
|
||||
}} />;
|
||||
return (
|
||||
<BubbleContainer fromMe={lastEdit.by?.isMe}>
|
||||
<BubbleBody>{props.msg.text}</BubbleBody>
|
||||
<BubbleInfo by={lastEdit.by?.profile?.name} madeAt={lastEdit.madeAt} />
|
||||
</BubbleContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,4 +75,4 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
46
examples/chat-clerk/src/main.tsx
Normal file
46
examples/chat-clerk/src/main.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { createJazzReactApp } from "jazz-react";
|
||||
import { App } from "./app.tsx";
|
||||
|
||||
import { ClerkProvider, SignInButton, useClerk } from "@clerk/clerk-react";
|
||||
import { useJazzClerkAuth } from "jazz-react-auth-clerk";
|
||||
|
||||
const Jazz = createJazzReactApp();
|
||||
export const { useAccount, useCoState } = Jazz;
|
||||
|
||||
function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const clerk = useClerk();
|
||||
const [auth, state] = useJazzClerkAuth(clerk);
|
||||
|
||||
return (
|
||||
<>
|
||||
{state.errors.map(error => (
|
||||
<div key={error}>{error}</div>
|
||||
))}
|
||||
{auth ? (
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
peer="wss://mesh.jazz.tools/?key=chat-example-jazz-clerk@gcmp.io"
|
||||
>
|
||||
{children}
|
||||
</Jazz.Provider>
|
||||
) : (
|
||||
<SignInButton />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<ClerkProvider
|
||||
publishableKey={import.meta.env.VITE_CLERK_PUBLISHABLE_KEY}
|
||||
afterSignOutUrl="/"
|
||||
>
|
||||
<JazzAndAuth>
|
||||
<App />
|
||||
</JazzAndAuth>
|
||||
</ClerkProvider>
|
||||
</StrictMode>
|
||||
);
|
||||
7
examples/chat-clerk/src/schema.ts
Normal file
7
examples/chat-clerk/src/schema.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { CoMap, CoList, co } from "jazz-tools";
|
||||
|
||||
export class Message extends CoMap {
|
||||
text = co.string;
|
||||
}
|
||||
|
||||
export class Chat extends CoList.Of(co.ref(Message)) {}
|
||||
63
examples/chat-clerk/src/ui.tsx
Normal file
63
examples/chat-clerk/src/ui.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
export function AppContainer(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-between w-screen h-screen p-2 dark:bg-black dark:text-white">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function TopBar(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="mb-5 px-2 py-1 text-sm self-end">{props.children}</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ChatContainer(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="w-full max-w-xl h-full flex flex-col items-stretch">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function EmptyChatMessage() {
|
||||
return <div className="m-auto text-sm">(Empty chat)</div>;
|
||||
}
|
||||
|
||||
export function BubbleContainer(props: {
|
||||
children: React.ReactNode;
|
||||
fromMe: boolean | undefined;
|
||||
}) {
|
||||
const align = props.fromMe ? "items-end" : "items-start";
|
||||
return <div className={`${align} flex flex-col`}>{props.children}</div>;
|
||||
}
|
||||
|
||||
export function BubbleBody(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="rounded-xl bg-stone-100 dark:bg-stone-700 dark:text-white py-2 px-4 mt-2 min-w-[5rem]">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function BubbleInfo(props: { by: string | undefined; madeAt: Date }) {
|
||||
return (
|
||||
<div className="text-xs text-neutral-500 ml-2">
|
||||
{props.by} {props.madeAt.toLocaleTimeString()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ChatInput(props: { onSubmit: (text: string) => void }) {
|
||||
return (
|
||||
<input
|
||||
className="rounded p-2 border mt-auto dark:bg-black dark:text-white border-stone-300 dark:border-stone-700"
|
||||
placeholder="Type a message and press Enter"
|
||||
onKeyDown={({ key, currentTarget: input }) => {
|
||||
if (key !== "Enter" || !input.value) return;
|
||||
props.onSubmit(input.value);
|
||||
input.value = "";
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
'./pages/**/*.{ts,tsx}',
|
||||
'./components/**/*.{ts,tsx}',
|
||||
'./app/**/*.{ts,tsx}',
|
||||
'./src/**/*.{ts,tsx}',
|
||||
],
|
||||
"./pages/**/*.{ts,tsx}",
|
||||
"./components/**/*.{ts,tsx}",
|
||||
"./app/**/*.{ts,tsx}",
|
||||
"./src/**/*.{ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
@@ -72,4 +72,4 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react-swc'
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react-swc";
|
||||
import path from "path";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
@@ -11,6 +11,6 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
build: {
|
||||
minify: false
|
||||
}
|
||||
})
|
||||
minify: false,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,12 +2,12 @@ module.exports = {
|
||||
root: true,
|
||||
env: { browser: true, es2020: true },
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
],
|
||||
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['react-refresh'],
|
||||
ignorePatterns: ["dist", ".eslintrc.cjs"],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["react-refresh"],
|
||||
rules: {},
|
||||
}
|
||||
};
|
||||
|
||||
10
examples/chat/.prettierrc
Normal file
10
examples/chat/.prettierrc
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "avoid",
|
||||
"printWidth": 80
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.83
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-tools@0.8.1
|
||||
- jazz-react@0.8.1
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat",
|
||||
"private": true,
|
||||
"version": "0.0.82",
|
||||
"version": "0.0.83",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -22,8 +22,8 @@
|
||||
"clsx": "^2.0.0",
|
||||
"cojson": "workspace:0.8.0",
|
||||
"hash-slash": "workspace:0.2.0",
|
||||
"jazz-react": "workspace:0.8.0",
|
||||
"jazz-tools": "workspace:0.8.0",
|
||||
"jazz-react": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -3,4 +3,4 @@ export default {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,65 +1,30 @@
|
||||
import { CoMap, CoList, co, Group, ID } from "jazz-tools";
|
||||
import { createJazzReactApp, DemoAuthBasicUI, useDemoAuth } from "jazz-react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { Group, ID } from "jazz-tools";
|
||||
import { useIframeHashRouter } from "hash-slash";
|
||||
import { useAccount } from "./main.tsx";
|
||||
import { Chat } from "./schema.ts";
|
||||
import { ChatScreen } from "./chatScreen.tsx";
|
||||
import { StrictMode } from "react";
|
||||
import { AppContainer, TopBar } from "./ui.tsx";
|
||||
|
||||
export class Message extends CoMap {
|
||||
text = co.string;
|
||||
export function App() {
|
||||
const { me, logOut } = useAccount();
|
||||
|
||||
const createChat = () => {
|
||||
if (!me) return;
|
||||
const group = Group.create({ owner: me });
|
||||
group.addMember("everyone", "writer");
|
||||
const chat = Chat.create([], { owner: group });
|
||||
location.hash = "/chat/" + chat.id;
|
||||
};
|
||||
|
||||
return (
|
||||
<AppContainer>
|
||||
<TopBar>
|
||||
{me?.profile?.name} · <button onClick={logOut}>Log out</button>
|
||||
</TopBar>
|
||||
{useIframeHashRouter().route({
|
||||
"/": () => createChat() as never,
|
||||
"/chat/:id": id => <ChatScreen chatID={id as ID<Chat>} />,
|
||||
})}
|
||||
</AppContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export class Chat extends CoList.Of(co.ref(Message)) {}
|
||||
|
||||
const Jazz = createJazzReactApp();
|
||||
export const { useAccount, useCoState } = Jazz;
|
||||
|
||||
function App() {
|
||||
const { me, logOut } = useAccount();
|
||||
|
||||
const createChat = () => {
|
||||
if (!me) return;
|
||||
const group = Group.create({ owner: me });
|
||||
group.addMember("everyone", "writer");
|
||||
const chat = Chat.create([], { owner: group });
|
||||
location.hash = "/chat/" + chat.id;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-between w-screen h-screen p-2 dark:bg-black dark:text-white">
|
||||
<div className="rounded mb-5 px-2 py-1 text-sm self-end">
|
||||
{me?.profile?.name} ·{" "}
|
||||
<button onClick={logOut}>Log Out</button>
|
||||
</div>
|
||||
{useIframeHashRouter().route({
|
||||
"/": () => createChat() as never,
|
||||
"/chat/:id": (id) => <ChatScreen chatID={id as ID<Chat>} />,
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AuthAndJazz({ children }: { children: React.ReactNode }) {
|
||||
const [auth, state] = useDemoAuth();
|
||||
|
||||
return (
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
peer="wss://mesh.jazz.tools/?key=chat-example-jazz@gcmp.io"
|
||||
>
|
||||
{state.state === "signedIn" ? (
|
||||
children
|
||||
) : (
|
||||
<DemoAuthBasicUI appName="Jazz Chat" state={state} />
|
||||
)}
|
||||
</Jazz.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<AuthAndJazz>
|
||||
<App />
|
||||
</AuthAndJazz>
|
||||
</StrictMode>
|
||||
);
|
||||
|
||||
@@ -1,42 +1,43 @@
|
||||
import { ID } from 'jazz-tools';
|
||||
import { Chat, Message, useCoState } from './app.tsx';
|
||||
import { ID } from "jazz-tools";
|
||||
import { Chat, Message } from "./schema.ts";
|
||||
import { useCoState } from "./main.tsx";
|
||||
import {
|
||||
BubbleBody,
|
||||
BubbleContainer,
|
||||
BubbleInfo,
|
||||
ChatContainer,
|
||||
ChatInput,
|
||||
EmptyChatMessage,
|
||||
} from "./ui.tsx";
|
||||
|
||||
export function ChatScreen(props: { chatID: ID<Chat> }) {
|
||||
const chat = useCoState(Chat, props.chatID, [{}]);
|
||||
|
||||
return chat ? <div className='w-full max-w-xl h-full flex flex-col items-stretch'>
|
||||
{chat.length > 0
|
||||
? chat.map((msg) => <ChatBubble msg={msg} key={msg.id} />)
|
||||
: <div className='m-auto text-sm'>(Empty chat)</div>}
|
||||
<ChatInput onSubmit={(text) => {
|
||||
chat.push(
|
||||
Message.create({ text }, { owner: chat._owner })
|
||||
);
|
||||
}} />
|
||||
</div> : <div>Loading...</div>;
|
||||
return chat ? (
|
||||
<ChatContainer>
|
||||
{chat.length > 0 ? (
|
||||
chat.map(msg => <ChatBubble msg={msg} key={msg.id} />)
|
||||
) : (
|
||||
<EmptyChatMessage />
|
||||
)}
|
||||
<ChatInput
|
||||
onSubmit={text => {
|
||||
chat.push(Message.create({ text }, { owner: chat._owner }));
|
||||
}}
|
||||
/>
|
||||
</ChatContainer>
|
||||
) : (
|
||||
<div>Loading...</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ChatBubble(props: { msg: Message }) {
|
||||
const lastEdit = props.msg._edits.text;
|
||||
const align = lastEdit.by?.isMe ? 'items-end' : 'items-start';
|
||||
|
||||
return <div className={`${align} flex flex-col`}>
|
||||
<div className='rounded-xl bg-stone-100 dark:bg-stone-700 dark:text-white py-2 px-4 mt-2 min-w-[5rem]'>
|
||||
{ props.msg.text }
|
||||
</div>
|
||||
<div className='text-xs text-neutral-500 ml-2'>
|
||||
{ lastEdit.by?.profile?.name }{' '}
|
||||
{ lastEdit.madeAt?.toLocaleTimeString() }
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
function ChatInput(props: { onSubmit: (text: string) => void }) {
|
||||
return <input className='rounded p-2 border mt-auto dark:bg-black dark:text-white border-stone-300 dark:border-stone-700'
|
||||
placeholder='Type a message and press Enter'
|
||||
onKeyDown={({ key, currentTarget: input }) => {
|
||||
if (key !== 'Enter' || !input.value) return;
|
||||
props.onSubmit(input.value);
|
||||
input.value = '';
|
||||
}} />;
|
||||
return (
|
||||
<BubbleContainer fromMe={lastEdit.by?.isMe}>
|
||||
<BubbleBody>{props.msg.text}</BubbleBody>
|
||||
<BubbleInfo by={lastEdit.by?.profile?.name} madeAt={lastEdit.madeAt} />
|
||||
</BubbleContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,4 +75,4 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
33
examples/chat/src/main.tsx
Normal file
33
examples/chat/src/main.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { createJazzReactApp, DemoAuthBasicUI, useDemoAuth } from "jazz-react";
|
||||
import { App } from "./app.tsx";
|
||||
|
||||
const Jazz = createJazzReactApp();
|
||||
export const { useAccount, useCoState } = Jazz;
|
||||
|
||||
function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const [auth, state] = useDemoAuth();
|
||||
|
||||
console.log(state, auth)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
peer="wss://mesh.jazz.tools/?key=chat-example-jazz@gcmp.io"
|
||||
>
|
||||
{children}
|
||||
</Jazz.Provider>
|
||||
{state.state !== "signedIn" && <DemoAuthBasicUI appName="Jazz Chat" state={state} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<JazzAndAuth>
|
||||
<App />
|
||||
</JazzAndAuth>
|
||||
</StrictMode>
|
||||
);
|
||||
7
examples/chat/src/schema.ts
Normal file
7
examples/chat/src/schema.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { CoMap, CoList, co } from "jazz-tools";
|
||||
|
||||
export class Message extends CoMap {
|
||||
text = co.string;
|
||||
}
|
||||
|
||||
export class Chat extends CoList.Of(co.ref(Message)) {}
|
||||
63
examples/chat/src/ui.tsx
Normal file
63
examples/chat/src/ui.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
export function AppContainer(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-between w-screen h-screen p-2 dark:bg-black dark:text-white">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function TopBar(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="mb-5 px-2 py-1 text-sm self-end">{props.children}</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ChatContainer(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="w-full max-w-xl h-full flex flex-col items-stretch">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function EmptyChatMessage() {
|
||||
return <div className="m-auto text-sm">(Empty chat)</div>;
|
||||
}
|
||||
|
||||
export function BubbleContainer(props: {
|
||||
children: React.ReactNode;
|
||||
fromMe: boolean | undefined;
|
||||
}) {
|
||||
const align = props.fromMe ? "items-end" : "items-start";
|
||||
return <div className={`${align} flex flex-col`}>{props.children}</div>;
|
||||
}
|
||||
|
||||
export function BubbleBody(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="rounded-xl bg-stone-100 dark:bg-stone-700 dark:text-white py-2 px-4 mt-2 min-w-[5rem]">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function BubbleInfo(props: { by: string | undefined; madeAt: Date }) {
|
||||
return (
|
||||
<div className="text-xs text-neutral-500 ml-2">
|
||||
{props.by} {props.madeAt.toLocaleTimeString()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ChatInput(props: { onSubmit: (text: string) => void }) {
|
||||
return (
|
||||
<input
|
||||
className="rounded p-2 border mt-auto dark:bg-black dark:text-white border-stone-300 dark:border-stone-700"
|
||||
placeholder="Type a message and press Enter"
|
||||
onKeyDown={({ key, currentTarget: input }) => {
|
||||
if (key !== "Enter" || !input.value) return;
|
||||
props.onSubmit(input.value);
|
||||
input.value = "";
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
'./pages/**/*.{ts,tsx}',
|
||||
'./components/**/*.{ts,tsx}',
|
||||
'./app/**/*.{ts,tsx}',
|
||||
'./src/**/*.{ts,tsx}',
|
||||
],
|
||||
"./pages/**/*.{ts,tsx}",
|
||||
"./components/**/*.{ts,tsx}",
|
||||
"./app/**/*.{ts,tsx}",
|
||||
"./src/**/*.{ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
@@ -72,4 +72,4 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react-swc'
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react-swc";
|
||||
import path from "path";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
@@ -11,6 +11,6 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
build: {
|
||||
minify: false
|
||||
}
|
||||
})
|
||||
minify: false,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-example-musicplayer
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-tools@0.8.1
|
||||
- jazz-react@0.8.1
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-music-player",
|
||||
"private": true,
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -17,8 +17,8 @@
|
||||
"dependencies": {
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-react": "workspace:0.8.0",
|
||||
"jazz-tools": "workspace:0.8.0",
|
||||
"jazz-react": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router": "^6.16.0",
|
||||
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
@@ -96,20 +96,23 @@ function Main() {
|
||||
);
|
||||
}
|
||||
|
||||
function AuthAndJazz({ children }: { children: React.ReactNode }) {
|
||||
function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const [auth, state] = useDemoAuth();
|
||||
|
||||
return (
|
||||
<Jazz.Provider auth={auth} peer="wss://mesh.jazz.tools/?key=music-player-example-jazz@gcmp.io">
|
||||
{state.state === "signedIn" ? children : <DemoAuthBasicUI appName="Jazz Music Player" state={state} />}
|
||||
</Jazz.Provider>
|
||||
<>
|
||||
<Jazz.Provider auth={auth} peer="wss://mesh.jazz.tools/?key=music-player-example-jazz@gcmp.io">
|
||||
{children}
|
||||
</Jazz.Provider>
|
||||
<DemoAuthBasicUI appName="Jazz Music Player" state={state} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<AuthAndJazz>
|
||||
<JazzAndAuth>
|
||||
<Main />
|
||||
</AuthAndJazz>
|
||||
</JazzAndAuth>
|
||||
</React.StrictMode>,
|
||||
);
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-password-manager
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-tools@0.8.1
|
||||
- jazz-react@0.8.1
|
||||
|
||||
## 0.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-password-manager",
|
||||
"private": true,
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.3",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -11,8 +11,8 @@
|
||||
"clean-install": "rm -rf node_modules pnpm-lock.yaml && pnpm install"
|
||||
},
|
||||
"dependencies": {
|
||||
"jazz-react": "workspace:0.8.0",
|
||||
"jazz-tools": "workspace:0.8.0",
|
||||
"jazz-react": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "^7.41.5",
|
||||
|
||||
@@ -15,29 +15,28 @@ const Jazz = createJazzReactApp<PasswordManagerAccount>({
|
||||
|
||||
export const { useAccount, useCoState, useAcceptInvite } = Jazz;
|
||||
|
||||
function AuthAndJazz({ children }: { children: React.ReactNode }) {
|
||||
function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const [auth, state] = usePasskeyAuth({
|
||||
appName: "Jazz Password Manager",
|
||||
});
|
||||
|
||||
return (
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
peer="wss://mesh.jazz.tools/?key=password-manager-example-jazz@gcmp.io"
|
||||
>
|
||||
{state.state === "signedIn" ? (
|
||||
children
|
||||
) : (
|
||||
<PasskeyAuthBasicUI state={state} />
|
||||
)}
|
||||
</Jazz.Provider>
|
||||
<>
|
||||
<Jazz.Provider
|
||||
auth={auth}
|
||||
peer="wss://mesh.jazz.tools/?key=password-manager-example-jazz@gcmp.io"
|
||||
>
|
||||
{children}
|
||||
</Jazz.Provider>
|
||||
<PasskeyAuthBasicUI state={state} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<AuthAndJazz>
|
||||
<JazzAndAuth>
|
||||
<App />
|
||||
</AuthAndJazz>
|
||||
</JazzAndAuth>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# jazz-example-pets
|
||||
|
||||
## 0.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-tools@0.8.1
|
||||
- jazz-browser-media-images@0.8.1
|
||||
- jazz-react@0.8.1
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-pets",
|
||||
"private": true,
|
||||
"version": "0.0.100",
|
||||
"version": "0.0.101",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -22,9 +22,9 @@
|
||||
"@radix-ui/react-toast": "^1.1.4",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-browser-media-images": "workspace:0.8.0",
|
||||
"jazz-react": "workspace:0.8.0",
|
||||
"jazz-tools": "workspace:0.8.0",
|
||||
"jazz-browser-media-images": "workspace:0.8.1",
|
||||
"jazz-react": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -36,7 +36,7 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
auth={auth}
|
||||
peer="wss://mesh.jazz.tools/?key=pets-example-jazz@gcmp.io"
|
||||
>
|
||||
{authState.state === "signedIn" && children}
|
||||
{children}
|
||||
</Jazz.Provider>
|
||||
<DemoAuthBasicUI appName={appName} state={authState} />
|
||||
</>
|
||||
@@ -100,7 +100,7 @@ export default function App() {
|
||||
}
|
||||
variant="outline"
|
||||
>
|
||||
Log Out
|
||||
Log out
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -9,7 +9,7 @@ export class LoginPage {
|
||||
this.page = page;
|
||||
this.usernameInput = page.getByRole("textbox");
|
||||
this.signupButton = page.getByRole("button", {
|
||||
name: "Sign Up as new account",
|
||||
name: "Sign up as new account",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ export class LoginPage {
|
||||
async loginAs(value: string) {
|
||||
await this.page
|
||||
.getByRole("button", {
|
||||
name: `Log In as "${value}"`,
|
||||
name: `Log in as "${value}"`,
|
||||
})
|
||||
.click();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-example-todo
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- jazz-tools@0.8.1
|
||||
- jazz-react@0.8.1
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-todo",
|
||||
"private": true,
|
||||
"version": "0.0.99",
|
||||
"version": "0.0.100",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -20,8 +20,8 @@
|
||||
"@radix-ui/react-toast": "^1.1.4",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-react": "workspace:0.8.0",
|
||||
"jazz-tools": "workspace:0.8.0",
|
||||
"jazz-react": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -41,16 +41,15 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const [passkeyAuth, passKeyState] = usePasskeyAuth({ appName });
|
||||
|
||||
return (
|
||||
<Jazz.Provider
|
||||
auth={passkeyAuth}
|
||||
peer="wss://mesh.jazz.tools/?key=todo-example-jazz@gcmp.io"
|
||||
>
|
||||
{passKeyState.state === "signedIn" ? (
|
||||
children
|
||||
) : (
|
||||
<PasskeyAuthBasicUI state={passKeyState} />
|
||||
)}
|
||||
</Jazz.Provider>
|
||||
<>
|
||||
<Jazz.Provider
|
||||
auth={passkeyAuth}
|
||||
peer="wss://mesh.jazz.tools/?key=todo-example-jazz@gcmp.io"
|
||||
>
|
||||
{children}
|
||||
</Jazz.Provider>
|
||||
<PasskeyAuthBasicUI state={passKeyState} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -111,7 +110,7 @@ export default function App() {
|
||||
}
|
||||
variant="outline"
|
||||
>
|
||||
Log Out
|
||||
Log out
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ export function CodeRef({ children }: { children: React.ReactNode }) {
|
||||
"border",
|
||||
"text-stone-800 dark:text-stone-200",
|
||||
"bg-stone-100 dark:bg-stone-800",
|
||||
"border-stone-200 dark:border-stone-800"
|
||||
"border-stone-200 dark:border-stone-900"
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -6,11 +6,11 @@ export function GridCard(props: { children: ReactNode; className?: string }) {
|
||||
<div
|
||||
className={clsx(
|
||||
"col-span-2 p-4 [&>h4]:mt-0 [&>h3]:mt-0 [&>:last-child]:mb-0",
|
||||
"border border-stone-200 dark:border-stone-800 rounded-xl shadow-sm",
|
||||
"border border-stone-200 dark:border-stone-900 rounded-xl shadow-sm",
|
||||
props.className
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import clsx from "clsx";
|
||||
|
||||
export function H1({ children }: { children: React.ReactNode }) {
|
||||
interface HeadingProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function H1({ children, className }: HeadingProps) {
|
||||
return (
|
||||
<h1
|
||||
className={clsx(
|
||||
className,
|
||||
"font-display",
|
||||
"text-stone-950 dark:text-white",
|
||||
"text-5xl lg:text-6xl",
|
||||
"mb-3",
|
||||
"font-medium",
|
||||
@@ -16,11 +23,13 @@ export function H1({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
export function H2({ children }: { children: React.ReactNode }) {
|
||||
export function H2({ children, className }: HeadingProps) {
|
||||
return (
|
||||
<h2
|
||||
className={clsx(
|
||||
className,
|
||||
"font-display",
|
||||
"text-stone-950 dark:text-white",
|
||||
"text-2xl",
|
||||
"mb-2",
|
||||
"font-semibold",
|
||||
@@ -32,11 +41,13 @@ export function H2({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
export function H3({ children }: { children: React.ReactNode }) {
|
||||
export function H3({ children, className }: HeadingProps) {
|
||||
return (
|
||||
<h3
|
||||
className={clsx(
|
||||
className,
|
||||
"font-display",
|
||||
"text-stone-950 dark:text-white",
|
||||
"text-xl",
|
||||
"mb-2",
|
||||
"font-semibold",
|
||||
@@ -48,6 +59,6 @@ export function H3({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
export function H4({ children }: { children: React.ReactNode }) {
|
||||
return <h4 className="text-bold">{children}</h4>;
|
||||
export function H4({ children, className }: HeadingProps) {
|
||||
return <h4 className={clsx(className, "text-bold")}>{children}</h4>;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import clsx from "clsx";
|
||||
import { ReactNode } from "react";
|
||||
import { H2 } from "../../components/atoms/Headings";
|
||||
|
||||
export function GappedGrid({
|
||||
children,
|
||||
@@ -18,14 +19,8 @@ export function GappedGrid({
|
||||
className
|
||||
)}
|
||||
>
|
||||
{title && <h2 className={clsx(
|
||||
"col-span-full",
|
||||
"font-display",
|
||||
"text-2xl",
|
||||
"font-semibold",
|
||||
"tracking-tight"
|
||||
)}>{title}</h2>}
|
||||
{title && <H2 className="col-span-full">{title}</H2>}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ export function HairlineBleedGrid({ children }: { children: React.ReactNode }) {
|
||||
"mb-10",
|
||||
"items-stretch",
|
||||
"gap-[1px]",
|
||||
"-mx-4 md:-mx-6",
|
||||
"rounded-xl",
|
||||
"overflow-hidden",
|
||||
"bg-stone-50 dark:bg-stone-950",
|
||||
|
||||
@@ -29,7 +29,7 @@ export function HeroHeader({
|
||||
pt?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<hgroup className={clsx(pt && "md:pt-20", "mb-10")}>
|
||||
<hgroup className={clsx(pt && "pt-12 md:pt-20", "mb-10")}>
|
||||
<H1>{title}</H1>
|
||||
<H1Sub>{slogan}</H1Sub>
|
||||
</hgroup>
|
||||
|
||||
@@ -13,13 +13,15 @@ export function LabelledFeatureIcon({
|
||||
className={clsx(
|
||||
"p-4 flex flex-col items-center justify-center gap-2",
|
||||
"not-prose text-base",
|
||||
"border border-stone-200 dark:border-stone-800 rounded-xl"
|
||||
"border border-stone-200 dark:border-stone-900 rounded-xl"
|
||||
)}
|
||||
>
|
||||
<div className="text-stone-500 mr-2">
|
||||
<Icon strokeWidth={1} strokeLinecap="butt" size={40} />
|
||||
</div>
|
||||
<div className="text-stone-700 dark:text-stone-300">{label}</div>
|
||||
<div className="text-sm text-stone-700 md:text-base dark:text-stone-300">
|
||||
{label}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export function Prose(props: { children: ReactNode; className?: string }) {
|
||||
"prose-p:max-w-3xl prose-p:leading-snug",
|
||||
"prose-strong:font-medium",
|
||||
"prose-code:font-normal prose-code:leading-tight prose-code:before:content-none prose-code:after:content-none prose-code:bg-stone-100 prose-code:dark:bg-stone-900 prose-code:p-1 prose-code:rounded",
|
||||
"prose-pre:text-black dark:prose-pre:text-white prose-pre:max-w-3xl prose-pre:text-[0.8em] prose-pre:leading-[1.3] prose-pre:-mt-2 prose-pre:my-4 prose-pre:px-10 prose-pre:py-2 prose-pre:-mx-10 prose-pre:bg-transparent",
|
||||
"prose-pre:text-black dark:prose-pre:text-white prose-pre:max-w-3xl prose-pre:text-[0.8em] prose-pre:leading-[1.3] prose-pre:-mt-2 prose-pre:my-4 prose-pre:px-10 prose-pre:py-2 prose-pre:bg-transparent",
|
||||
"[&_pre_.line]:relative [&_pre_.line]:min-h-[1.3em] [&_pre_.lineNo]:text-[0.75em] [&_pre_.lineNo]:text-stone-300 [&_pre_.lineNo]:dark:text-stone-700 [&_pre_.lineNo]:absolute [&_pre_.lineNo]:text-right [&_pre_.lineNo]:w-8 [&_pre_.lineNo]:-left-10 [&_pre_.lineNo]:top-[0.3em] [&_pre_.lineNo]:select-none",
|
||||
props.className || "prose lg:prose-lg"
|
||||
)}
|
||||
@@ -25,4 +25,4 @@ export function Prose(props: { children: ReactNode; className?: string }) {
|
||||
|
||||
export function SmallProse(props: { children: ReactNode; className?: string }) {
|
||||
return <Prose className="prose prose-sm">{props.children}</Prose>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ export function Footer({ logo, companyName, sections }: FooterProps) {
|
||||
</div>
|
||||
{sections.map((section, index) => (
|
||||
<div key={index} className="flex flex-col gap-2 text-sm">
|
||||
<h1 className="font-medium">{section.title}</h1>
|
||||
<h2 className="font-medium">{section.title}</h2>
|
||||
{section.links.map((link, linkIndex) => (
|
||||
<FooterLink
|
||||
key={linkIndex}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<h2 className="not-prose text-2xl font-medium tracking-tight mt-3 md:mt-5 mb-6">Hard things are easy now.</h2>
|
||||
<h2 className="not-prose text-2xl font-medium tracking-tight mt-3 md:mt-5 mb-6 dark:text-white">Hard things are easy now.</h2>
|
||||
|
||||
Jazz is an **open-source toolkit** that replaces APIs, databases and message queues with **a single new abstraction:**
|
||||
|
||||
**“Collaborative Values”** — **distributed state** with **secure permissions built-in.**
|
||||
|
||||
Features that used to take months to build now work out-of-the-box.
|
||||
Features that used to take months to build now work out-of-the-box.
|
||||
|
||||
@@ -27,8 +27,13 @@ import {
|
||||
MousePointerSquareDashedIcon,
|
||||
} from "lucide-react";
|
||||
|
||||
import { App_tsx, ChatScreen_tsx } from "@/codeSamples/examples/chat/src";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
Main_tsx,
|
||||
Schema_ts,
|
||||
App_tsx,
|
||||
ChatScreen_tsx,
|
||||
Ui_tsx,
|
||||
} from "@/codeSamples/examples/chat/src";
|
||||
|
||||
import Intro from "./intro.mdx";
|
||||
import CoValuesIntro from "./coValuesIntro.mdx";
|
||||
@@ -52,7 +57,7 @@ import { H3 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<div className="space-y-16">
|
||||
<HeroHeader
|
||||
title="Instant sync."
|
||||
slogan="A new way to build apps with distributed state."
|
||||
@@ -99,41 +104,56 @@ export default function Home() {
|
||||
</div>
|
||||
</HairlineBleedGrid>
|
||||
|
||||
<div className="-mx-[calc(min(0,(100vw-95rem)/2))]">
|
||||
<div>
|
||||
<SectionHeader
|
||||
title="First impressions..."
|
||||
slogan="A chat app in 84 lines of code."
|
||||
slogan="A chat app in 174 lines of code."
|
||||
/>
|
||||
|
||||
<GappedGrid className="mt-0 -mx-4 md:-mx-6">
|
||||
<GappedGrid className="mt-0">
|
||||
<CodeExampleTabs
|
||||
tabs={[
|
||||
{
|
||||
name: "main.tsx",
|
||||
content: <Main_tsx />,
|
||||
},
|
||||
{
|
||||
name: "app.tsx",
|
||||
content: <App_tsx />,
|
||||
},
|
||||
{
|
||||
name: "schema.ts",
|
||||
content: <Schema_ts />,
|
||||
},
|
||||
{
|
||||
name: "chatScreen.tsx",
|
||||
content: <ChatScreen_tsx />,
|
||||
},
|
||||
{
|
||||
name: "ui.tsx",
|
||||
content: <Ui_tsx />,
|
||||
},
|
||||
]}
|
||||
className="col-span-full md:col-span-4"
|
||||
/>
|
||||
<ResponsiveIframe
|
||||
src="https://chat.jazz.tools"
|
||||
localSrc="http://localhost:5173"
|
||||
className="col-span-full lg:col-span-2 rounded-xl overflow-hidden min-h-[50vh]"
|
||||
className="order-first col-span-full lg:col-span-2 rounded-sm overflow-hidden min-h-[50vh] lg:order-last"
|
||||
/>
|
||||
</GappedGrid>
|
||||
</div>
|
||||
|
||||
<SectionHeader
|
||||
title="Collaborative Values"
|
||||
slogan="Your new building blocks."
|
||||
/>
|
||||
<Prose>
|
||||
<CoValuesIntro />
|
||||
</Prose>
|
||||
<div>
|
||||
<SectionHeader
|
||||
title="Collaborative Values"
|
||||
slogan="Your new building blocks."
|
||||
/>
|
||||
|
||||
<Prose>
|
||||
<CoValuesIntro />
|
||||
</Prose>
|
||||
</div>
|
||||
|
||||
<GappedGrid
|
||||
title="Bread-and-butter datastructures"
|
||||
@@ -222,15 +242,17 @@ export default function Home() {
|
||||
</GridCard>
|
||||
</GappedGrid>
|
||||
|
||||
<SectionHeader
|
||||
title="The Jazz Toolkit"
|
||||
slogan="A high-level toolkit for building apps around CoValues."
|
||||
/>
|
||||
<div>
|
||||
<SectionHeader
|
||||
title="The Jazz Toolkit"
|
||||
slogan="A high-level toolkit for building apps around CoValues."
|
||||
/>
|
||||
|
||||
<Prose>Supported environments:</Prose>
|
||||
<SmallProse>
|
||||
<SupportedEnvironments />
|
||||
</SmallProse>
|
||||
<Prose>Supported environments:</Prose>
|
||||
<SmallProse>
|
||||
<SupportedEnvironments />
|
||||
</SmallProse>
|
||||
</div>
|
||||
|
||||
<GappedGrid>
|
||||
<GridCard>
|
||||
@@ -299,38 +321,42 @@ export default function Home() {
|
||||
</GridCard>
|
||||
</GappedGrid>
|
||||
|
||||
<SectionHeader
|
||||
title="Jazz Mesh"
|
||||
slogan="Serverless sync & storage for Jazz apps"
|
||||
/>
|
||||
<div>
|
||||
<SectionHeader
|
||||
title="Jazz Mesh"
|
||||
slogan="Serverless sync & storage for Jazz apps"
|
||||
/>
|
||||
|
||||
<Prose>
|
||||
<MeshIntro />
|
||||
</Prose>
|
||||
<Prose>
|
||||
<MeshIntro />
|
||||
</Prose>
|
||||
|
||||
<P>
|
||||
{"->"}{" "}
|
||||
<TextLink href="/mesh" target="_blank">
|
||||
Learn more about Jazz Mesh
|
||||
</TextLink>
|
||||
</P>
|
||||
|
||||
<H3>Get Started</H3>
|
||||
<UL>
|
||||
<LI>
|
||||
<TextLink href="/docs" target="_blank">
|
||||
Read the docs
|
||||
<P>
|
||||
{"->"}{" "}
|
||||
<TextLink href="/mesh" target="_blank">
|
||||
Learn more about Jazz Mesh
|
||||
</TextLink>
|
||||
</LI>
|
||||
<LI>
|
||||
<TextLink
|
||||
href="https://discord.gg/utDMjHYg42"
|
||||
target="_blank"
|
||||
>
|
||||
Join our Discord
|
||||
</TextLink>
|
||||
</LI>
|
||||
</UL>
|
||||
</>
|
||||
</P>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<H3>Get Started</H3>
|
||||
<UL>
|
||||
<LI>
|
||||
<TextLink href="/docs" target="_blank">
|
||||
Read the docs
|
||||
</TextLink>
|
||||
</LI>
|
||||
<LI>
|
||||
<TextLink
|
||||
href="https://discord.gg/utDMjHYg42"
|
||||
target="_blank"
|
||||
>
|
||||
Join our Discord
|
||||
</TextLink>
|
||||
</LI>
|
||||
</UL>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { ComingSoonBadge } from "gcmp-design-system/src/app/components/atoms/ComingSoonBadge";
|
||||
|
||||
|
||||
Supported environments:
|
||||
|
||||
- Browser (sync via WebSockets, IndexedDB persistence)
|
||||
- React
|
||||
- Vanilla JS / framework agnostic base
|
||||
- React Native <ComingSoonBadge/>
|
||||
- NodeJS (sync via WebSockets, SQLite persistence) <ComingSoonBadge/>
|
||||
- Swift, Kotlin, Rust <ComingSoonBadge when="later"/>
|
||||
- Swift, Kotlin, Rust <ComingSoonBadge when="later"/>
|
||||
|
||||
@@ -69,7 +69,7 @@ We'll build everything **step-by-step,** in typical, immediately usable stages.
|
||||
// replace `you@example.com` with your email as a temporary API key
|
||||
peer="wss://mesh.jazz.tools/?key=you@example.com"
|
||||
>
|
||||
{ authState.state === "signedIn" && children }
|
||||
{children}
|
||||
</Jazz.Provider>
|
||||
<DemoAuthBasicUI appName="Circular" state={authState} />
|
||||
</>
|
||||
@@ -354,7 +354,7 @@ This works because CoValues
|
||||
- notify subscribers of the change (who will receive a fresh, updated view of the CoValue)
|
||||
|
||||
<aside className="text-sm border border-stone-300 dark:border-stone-700 rounded px-4 my-4 max-w-3xl [&_pre]:mx-0">
|
||||
<h4 className="not-prose text-base py-2 mb-3 -mx-4 px-4 border-b border-stone-300 dark:border-stone-700">💡 A Quick Overview of Subscribing to CoValues</h4>
|
||||
<h4 className="not-prose text-base py-2 mb-3 px-4 border-b border-stone-300 dark:border-stone-700">💡 A Quick Overview of Subscribing to CoValues</h4>
|
||||
|
||||
There are three main ways to subscribe to a CoValue:
|
||||
|
||||
|
||||
@@ -72,9 +72,7 @@
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
|
||||
.overlay-close {
|
||||
background-color: "black";
|
||||
}
|
||||
@@ -134,7 +132,7 @@ pre.twoslash data-lsp::before {
|
||||
position: absolute;
|
||||
transform: translate(0, 1.2rem);
|
||||
max-width: 30rem;
|
||||
@apply text-xs px-1.5 py-1 rounded border border-stone-200 dark:border-stone-800 shadow-lg overflow-hidden whitespace-pre-wrap text-stone-700 bg-stone-50 dark:text-stone-200 dark:bg-stone-950;
|
||||
@apply text-xs px-1.5 py-1 rounded border border-stone-200 dark:border-stone-900 shadow-lg overflow-hidden whitespace-pre-wrap text-stone-700 bg-stone-50 dark:text-stone-200 dark:bg-stone-950;
|
||||
text-align: left;
|
||||
z-index: 100;
|
||||
opacity: 0;
|
||||
|
||||
@@ -57,7 +57,7 @@ export default function RootLayout({
|
||||
manrope.variable,
|
||||
commitMono.variable,
|
||||
inter.className,
|
||||
"flex flex-col items-center bg-stone-50 dark:bg-stone-950",
|
||||
"flex flex-col items-center bg-stone-50 text-stone-700 dark:text-stone-400 dark:bg-stone-950",
|
||||
].join(" ")}
|
||||
>
|
||||
<SpeedInsights />
|
||||
@@ -69,7 +69,7 @@ export default function RootLayout({
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<JazzNav />
|
||||
<main className="flex min-h-screen flex-col p-8 max-w-[80rem] w-full [&_*]:scroll-mt-[6rem]">
|
||||
<main className="flex min-h-screen flex-col container w-full">
|
||||
{children}
|
||||
</main>
|
||||
<JazzFooter />
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user