Compare commits
37 Commits
lotion
...
jazz-react
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f224b2b4ea | ||
|
|
f70d34fb0b | ||
|
|
a075f90890 | ||
|
|
66686e4f71 | ||
|
|
e8a6f9d123 | ||
|
|
9246c009b8 | ||
|
|
afa43dc248 | ||
|
|
effa15082e | ||
|
|
2a648a620c | ||
|
|
f10d13be3b | ||
|
|
e8f7e90220 | ||
|
|
6bf16fd52c | ||
|
|
f143a4aa4d | ||
|
|
0c07fcee1c | ||
|
|
eca9698bbc | ||
|
|
de66d90b85 | ||
|
|
4bc815a576 | ||
|
|
0bd4fea0dd | ||
|
|
35c310dc47 | ||
|
|
f80442793a | ||
|
|
98be05f697 | ||
|
|
0b6e9e6c4d | ||
|
|
45046f571f | ||
|
|
4ccad8ac0b | ||
|
|
e4d68bb56b | ||
|
|
ab7c560fbb | ||
|
|
32c820be56 | ||
|
|
f5d7c9fd6b | ||
|
|
6b90c6048b | ||
|
|
80bb793e3a | ||
|
|
b275ffbe01 | ||
|
|
49f60bda67 | ||
|
|
8b52f180af | ||
|
|
46365a35fe | ||
|
|
ac9dab0b3b | ||
|
|
9b1227915e | ||
|
|
dbb024e4da |
2
.github/workflows/playwright.yml
vendored
2
.github/workflows/playwright.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
project: ["e2e/BinaryCoStream", "examples/pets"]
|
||||
project: ["e2e/BinaryCoStream", "e2e/CoValues", "examples/pets"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @jazz-e2e/binarycostream
|
||||
|
||||
## 0.0.83
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-react@0.8.2
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<link rel="icon" type="image/png" href="/jazz-logo.png" />
|
||||
<link rel="stylesheet" href="/src/index.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Jazz Chat Example</title>
|
||||
<title>Jazz BinaryCoStream Tests</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@jazz-e2e/binarycostream",
|
||||
"private": true,
|
||||
"version": "0.0.82",
|
||||
"version": "0.0.83",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -17,8 +17,8 @@
|
||||
"cojson": "workspace:0.8.0",
|
||||
"hash-slash": "workspace:0.2.0",
|
||||
"is-ci": "^3.0.1",
|
||||
"jazz-react": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-react": "workspace:0.8.2",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
|
||||
30
e2e/CoValues/.gitignore
vendored
Normal file
30
e2e/CoValues/.gitignore
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
sync-db/
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
9
e2e/CoValues/CHANGELOG.md
Normal file
9
e2e/CoValues/CHANGELOG.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# @jazz-e2e/covalues
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-react@0.8.2
|
||||
14
e2e/CoValues/index.html
Normal file
14
e2e/CoValues/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/png" href="/jazz-logo.png" />
|
||||
<link rel="stylesheet" href="/src/index.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Jazz CoValues tests</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/app.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
37
e2e/CoValues/package.json
Normal file
37
e2e/CoValues/package.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@jazz-e2e/covalues",
|
||||
"private": true,
|
||||
"version": "0.0.82",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"test": "playwright test",
|
||||
"test:ui": "playwright test --ui"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,mdx,json}": "prettier --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"cojson": "workspace:*",
|
||||
"hash-slash": "workspace:*",
|
||||
"is-ci": "^3.0.1",
|
||||
"jazz-react": "workspace:*",
|
||||
"jazz-tools": "workspace:*",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router": "^6.16.0",
|
||||
"react-router-dom": "^6.16.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.46.1",
|
||||
"@types/node": "^22.5.1",
|
||||
"@types/react": "^18.2.19",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
"jstat": "^1.9.6",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.10"
|
||||
}
|
||||
}
|
||||
49
e2e/CoValues/playwright.config.ts
Normal file
49
e2e/CoValues/playwright.config.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
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: isCI ? "http://localhost:4173/" : "http://localhost:5173",
|
||||
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: "on-first-retry",
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: "chromium",
|
||||
use: { ...devices["Desktop Chrome"] },
|
||||
},
|
||||
],
|
||||
|
||||
/* Run your local dev server before starting the tests */
|
||||
webServer: isCI ? {
|
||||
command: "pnpm preview",
|
||||
url: "http://localhost:4173/",
|
||||
} : undefined,
|
||||
});
|
||||
25
e2e/CoValues/src/app.tsx
Normal file
25
e2e/CoValues/src/app.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { AuthAndJazz } from "./jazz";
|
||||
import { TestInput } from "./pages/TestInput";
|
||||
import { RouterProvider, createHashRouter } from "react-router-dom";
|
||||
|
||||
const router = createHashRouter([
|
||||
{
|
||||
path: "/",
|
||||
element: <TestInput />,
|
||||
},
|
||||
{
|
||||
path: "/test-input",
|
||||
element: <TestInput />,
|
||||
},
|
||||
]);
|
||||
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<AuthAndJazz>
|
||||
<RouterProvider router={router} />
|
||||
</AuthAndJazz>
|
||||
</React.StrictMode>,
|
||||
);
|
||||
25
e2e/CoValues/src/jazz.tsx
Normal file
25
e2e/CoValues/src/jazz.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { createJazzReactApp } from "jazz-react";
|
||||
import { ephemeralCredentialsAuth } from "jazz-tools";
|
||||
import { useState } from "react";
|
||||
|
||||
const key = `test-comap@jazz.tools`;
|
||||
|
||||
const localSync = new URLSearchParams(location.search).has("localSync");
|
||||
|
||||
const Jazz = createJazzReactApp();
|
||||
|
||||
export const { useAccount, useCoState } = Jazz;
|
||||
|
||||
export function AuthAndJazz({ children }: { children: React.ReactNode }) {
|
||||
const [ephemeralAuth] = useState(ephemeralCredentialsAuth())
|
||||
|
||||
return (
|
||||
<Jazz.Provider auth={ephemeralAuth} peer={
|
||||
localSync
|
||||
? `ws://localhost:4200?key=${key}`
|
||||
: `wss://mesh.jazz.tools/?key=${key}`
|
||||
}>
|
||||
{children}
|
||||
</Jazz.Provider>
|
||||
);
|
||||
}
|
||||
35
e2e/CoValues/src/pages/TestInput.tsx
Normal file
35
e2e/CoValues/src/pages/TestInput.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { co, CoMap, Group, ID } from "jazz-tools";
|
||||
import { useAccount, useCoState } from "../jazz";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export class InputTestCoMap extends CoMap {
|
||||
title = co.string;
|
||||
}
|
||||
|
||||
export function TestInput() {
|
||||
const [id, setId] = useState<ID<InputTestCoMap> | undefined>(undefined);
|
||||
const coMap = useCoState(InputTestCoMap, id);
|
||||
const { me } = useAccount();
|
||||
|
||||
useEffect(() => {
|
||||
if (!me || id) return;
|
||||
|
||||
const group = Group.create({ owner: me });
|
||||
|
||||
group.addMember("everyone", "writer");
|
||||
|
||||
setId(InputTestCoMap.create({ title: "" }, { owner: group }).id);
|
||||
}, [me]);
|
||||
|
||||
if (!coMap) return null;
|
||||
|
||||
return (
|
||||
<input
|
||||
value={coMap?.title ?? ""}
|
||||
onChange={(e) => {
|
||||
if (!coMap) return;
|
||||
coMap.title = e.target.value;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
1
e2e/CoValues/src/vite-env.d.ts
vendored
Normal file
1
e2e/CoValues/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
14
e2e/CoValues/tests/TestInput.spec.ts
Normal file
14
e2e/CoValues/tests/TestInput.spec.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test.describe("CoMap - TestInput", () => {
|
||||
test("should keep the cursor position when typing", async ({ page }) => {
|
||||
await page.goto("/test-input");
|
||||
|
||||
await page.getByRole("textbox").fill("xx");
|
||||
await page.getByRole('textbox').press('ArrowLeft');
|
||||
await page.getByRole("textbox").press("y");
|
||||
await page.getByRole("textbox").press("y");
|
||||
|
||||
await expect(page.getByRole('textbox')).toHaveValue("xyyx");
|
||||
});
|
||||
});
|
||||
25
e2e/CoValues/tsconfig.json
Normal file
25
e2e/CoValues/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"baseUrl": "."
|
||||
},
|
||||
"include": ["src"],
|
||||
}
|
||||
10
e2e/CoValues/vite.config.ts
Normal file
10
e2e/CoValues/vite.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react-swc'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
build: {
|
||||
minify: false
|
||||
}
|
||||
})
|
||||
@@ -1,5 +1,14 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-react@0.8.2
|
||||
- jazz-react-auth-clerk@0.8.2
|
||||
|
||||
## 0.0.81
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat-clerk",
|
||||
"private": true,
|
||||
"version": "0.0.81",
|
||||
"version": "0.0.82",
|
||||
"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.1",
|
||||
"jazz-react-auth-clerk": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-react": "workspace:0.8.2",
|
||||
"jazz-react-auth-clerk": "workspace:0.8.2",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.84
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-react@0.8.2
|
||||
|
||||
## 0.0.83
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat",
|
||||
"private": true,
|
||||
"version": "0.0.83",
|
||||
"version": "0.0.84",
|
||||
"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.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-react": "workspace:0.8.2",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -19,7 +19,7 @@ export function App() {
|
||||
return (
|
||||
<AppContainer>
|
||||
<TopBar>
|
||||
{me?.profile?.name} · <button onClick={logOut}>Log out</button>
|
||||
<p>{me?.profile?.name}</p> · <button onClick={logOut}>Log out</button>
|
||||
</TopBar>
|
||||
{useIframeHashRouter().route({
|
||||
"/": () => createChat() as never,
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
BubbleBody,
|
||||
BubbleContainer,
|
||||
BubbleInfo,
|
||||
ChatContainer,
|
||||
ChatBody,
|
||||
ChatInput,
|
||||
EmptyChatMessage,
|
||||
} from "./ui.tsx";
|
||||
@@ -14,18 +14,20 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
|
||||
const chat = useCoState(Chat, props.chatID, [{}]);
|
||||
|
||||
return chat ? (
|
||||
<ChatContainer>
|
||||
{chat.length > 0 ? (
|
||||
chat.map(msg => <ChatBubble msg={msg} key={msg.id} />)
|
||||
) : (
|
||||
<EmptyChatMessage />
|
||||
)}
|
||||
<>
|
||||
<ChatBody>
|
||||
{chat.length > 0 ? (
|
||||
chat.map(msg => <ChatBubble msg={msg} key={msg.id} />)
|
||||
) : (
|
||||
<EmptyChatMessage />
|
||||
)}
|
||||
</ChatBody>
|
||||
<ChatInput
|
||||
onSubmit={text => {
|
||||
chat.push(Message.create({ text }, { owner: chat._owner }));
|
||||
}}
|
||||
/>
|
||||
</ChatContainer>
|
||||
</>
|
||||
) : (
|
||||
<div>Loading...</div>
|
||||
);
|
||||
|
||||
@@ -9,8 +9,6 @@ export const { useAccount, useCoState } = Jazz;
|
||||
function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
const [auth, state] = useDemoAuth();
|
||||
|
||||
console.log(state, auth)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Jazz.Provider
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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">
|
||||
<div className="flex flex-col justify-between w-screen h-screen bg-stone-50 dark:bg-black dark:text-white">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
@@ -8,20 +8,22 @@ export function AppContainer(props: { children: React.ReactNode }) {
|
||||
|
||||
export function TopBar(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="mb-5 px-2 py-1 text-sm self-end">{props.children}</div>
|
||||
<div className="p-3 bg-white w-full flex justify-end gap-1 text-xs border-b dark:bg-transparent dark:border-stone-800">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ChatContainer(props: { children: React.ReactNode }) {
|
||||
export function ChatBody(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="w-full max-w-xl h-full flex flex-col items-stretch">
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function EmptyChatMessage() {
|
||||
return <div className="m-auto text-sm">(Empty chat)</div>;
|
||||
return <div className="h-full text-base text-stone-500 flex items-center justify-center px-3 md:text-xl">Start a conversation below.</div>;
|
||||
}
|
||||
|
||||
export function BubbleContainer(props: {
|
||||
@@ -29,12 +31,12 @@ export function BubbleContainer(props: {
|
||||
fromMe: boolean | undefined;
|
||||
}) {
|
||||
const align = props.fromMe ? "items-end" : "items-start";
|
||||
return <div className={`${align} flex flex-col`}>{props.children}</div>;
|
||||
return <div className={`${align} flex flex-col m-2`}>{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]">
|
||||
<div className="rounded-2xl text-sm bg-white dark:bg-stone-700 dark:text-white py-1 px-3 shadow-sm">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
@@ -42,22 +44,24 @@ export function BubbleBody(props: { children: React.ReactNode }) {
|
||||
|
||||
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 className="text-xs text-neutral-500 mt-1.5">
|
||||
{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 = "";
|
||||
}}
|
||||
/>
|
||||
<div className="p-3 bg-white border-t shadow-2xl mt-auto dark:bg-transparent dark:border-stone-800">
|
||||
<input
|
||||
className="rounded-full py-2 px-4 text-sm border block w-full dark:bg-black dark:text-white 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 = "";
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-example-musicplayer
|
||||
|
||||
## 0.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-react@0.8.2
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-music-player",
|
||||
"private": true,
|
||||
"version": "0.0.4",
|
||||
"version": "0.0.5",
|
||||
"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.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-react": "workspace:0.8.2",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router": "^6.16.0",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-password-manager
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-react@0.8.2
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-password-manager",
|
||||
"private": true,
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"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.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-react": "workspace:0.8.2",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "^7.41.5",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# jazz-example-pets
|
||||
|
||||
## 0.0.102
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-browser-media-images@0.8.2
|
||||
- jazz-react@0.8.2
|
||||
|
||||
## 0.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-pets",
|
||||
"private": true,
|
||||
"version": "0.0.101",
|
||||
"version": "0.0.102",
|
||||
"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.1",
|
||||
"jazz-react": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-browser-media-images": "workspace:0.8.2",
|
||||
"jazz-react": "workspace:0.8.2",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-example-todo
|
||||
|
||||
## 0.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-react@0.8.2
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-todo",
|
||||
"private": true,
|
||||
"version": "0.0.100",
|
||||
"version": "0.0.101",
|
||||
"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.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-react": "workspace:0.8.2",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -6,16 +6,16 @@ export function Prose(props: { children: ReactNode; className?: string }) {
|
||||
<div
|
||||
className={clsx(
|
||||
"mb-4",
|
||||
"max-w-none prose-stone dark:prose-invert",
|
||||
"max-w-4xl prose-stone dark:prose-invert",
|
||||
"prose-headings:font-display",
|
||||
"prose-h1:text-4xl lg:prose-h1:text-5xl prose-h1:font-medium prose-h1:tracking-tight",
|
||||
"prose-h2:text-2xl lg:prose-h2:text-3xl prose-h2:font-medium prose-h2:tracking-tight",
|
||||
"prose-p:max-w-3xl prose-p:leading-snug",
|
||||
"lg:prose-h1:text-5xl prose-h1:font-medium prose-h1:tracking-tight",
|
||||
"lg:prose-h2:text-3xl prose-h2:font-medium prose-h2:tracking-tight",
|
||||
"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: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"
|
||||
"prose-code:font-normal 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:border prose-pre:p-0 prose-pre:bg-white prose-pre:dark:bg-stone-900 dark:prose-pre:border-stone-800",
|
||||
"prose-pre:text-black dark:prose-pre:text-white",
|
||||
props.className || "prose"
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
|
||||
@@ -104,7 +104,7 @@ export function Nav({
|
||||
<nav
|
||||
className={clsx(
|
||||
"md:hidden fixed flex flex-col bottom-4 right-4 z-50",
|
||||
"bg-stone-50 dark:bg-stone-925 dark:text-white border border-stone-100 dark:border-stone-900 dark:outline dark:outline-1 dark:outline-black/60 rounded-lg shadow-lg",
|
||||
"bg-stone-50 dark:bg-stone-925 border border-stone-100 dark:border-stone-900 dark:outline dark:outline-1 dark:outline-black/60 rounded-lg shadow-lg",
|
||||
menuOpen || searchOpen ? "left-4" : "",
|
||||
)}
|
||||
>
|
||||
@@ -133,8 +133,8 @@ export function Nav({
|
||||
))}
|
||||
</div>
|
||||
|
||||
{pathname === "/docs" && (
|
||||
<div className="max-h-[calc(100dvh-15rem)] p-4 border-b border-stone-100 dark:border-stone-900 overflow-x-auto prose-sm prose-ul:pl-1 prose-ul:ml-1 prose-li:my-2 prose-li:leading-tight prose-ul:list-['-']">
|
||||
{pathname.startsWith("/docs") && (
|
||||
<div className="max-h-[calc(100dvh-15rem)] p-4 border-b border-stone-100 dark:border-stone-900 overflow-x-auto">
|
||||
{docNav}
|
||||
</div>
|
||||
)}
|
||||
@@ -295,4 +295,4 @@ function NavLinkLogo({
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,22 @@ const inter = Inter({
|
||||
variable: "--font-inter",
|
||||
display: "swap",
|
||||
});
|
||||
const pragmata = localFont({
|
||||
src: "../../fonts/ppr_0829.woff2",
|
||||
variable: "--font-ppr",
|
||||
|
||||
const commitMono = localFont({
|
||||
src: [
|
||||
{
|
||||
path: "../../fonts/CommitMono-Regular.woff2",
|
||||
weight: "400",
|
||||
style: "normal",
|
||||
},
|
||||
{
|
||||
path: "../../fonts/CommitMono-Regular.woff",
|
||||
weight: "400",
|
||||
style: "normal",
|
||||
},
|
||||
],
|
||||
variable: "--font-commit-mono",
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -31,12 +44,13 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={[
|
||||
manrope.variable,
|
||||
pragmata.variable,
|
||||
inter.className,
|
||||
].join(" ")}>{children}</body>
|
||||
<html lang="en" className="h-full">
|
||||
<body className={[
|
||||
manrope.variable,
|
||||
commitMono.variable,
|
||||
inter.className,
|
||||
"h-full",
|
||||
].join(" ")}>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,42 +1,7 @@
|
||||
import Image from 'next/image';
|
||||
import { Hero } from './components/organisms/Hero';
|
||||
import { Headline } from './components/molecules/Headline';
|
||||
import { Title } from './components/atoms/Title';
|
||||
import { Body } from './components/atoms/Body';
|
||||
import { Card } from './components/molecules/Card';
|
||||
import { CardSet } from './components/organisms/CardSet';
|
||||
|
||||
const catIpsumLong = 'Shake treat bag. Vomit food and eat it again all of a sudden cat goes crazy murr i hate humans they are so annoying where is it? i saw that bird i need to bring it home to mommy squirrel! hack up furballs. Meeeeouw walk on keyboard and slap the dog because cats rule, and behind the couch. Catto munch salmono love the best thing in the universe is a cardboard box or favor packaging over toy cat ass trophy. I vomit in the bed in the middle of the night chase laser. Eat and than sleep on your face play riveting piece on synthesizer keyboard reward the chosen human with a slow blink plan your travel.';
|
||||
const catIpsumShort = <>Tuxedo cats <strong>always</strong> looking dapper chew iPad power cord, get away from me stupid dog for thinking about you i'm joking it's food always food so roll on the floor purring your whiskers off</>;
|
||||
const catIpsumHeadline = <>Need to check on <em>human</em>, have not seen in an hour might be dead</>;
|
||||
|
||||
const card = {
|
||||
cardTitle: "Cats are awesome",
|
||||
text: catIpsumShort,
|
||||
}
|
||||
|
||||
const cardSet = {
|
||||
card1: card,
|
||||
card2: card,
|
||||
card3: card,
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center px-24">
|
||||
<Hero title="Title" subheading="Subheading" />
|
||||
|
||||
<Headline headline="Headline" text={catIpsumHeadline} />
|
||||
<Title text="Title" />
|
||||
{/* <Label text="text" /> */}
|
||||
<Body text={catIpsumLong}/>
|
||||
{/* <Icon text="text" /> */}
|
||||
{/* <Button text="text" /> */}
|
||||
<Card cardTitle="Cats are awesome" text={catIpsumShort} />
|
||||
<Body text={catIpsumShort}/>
|
||||
<CardSet cardSet={cardSet} />
|
||||
|
||||
|
||||
<main className="container h-full flex flex-col gap-8 py-8 lg:py-16">
|
||||
<h1 className="text-2xl font-semibold font-display">Jazz Design System</h1>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import harmonyPalette from "@evilmartians/harmony/tailwind";
|
||||
import typography from "@tailwindcss/typography";
|
||||
import tailwindCSSAnimate from "tailwindcss-animate";
|
||||
const colors = require("tailwindcss/colors")
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
const config = {
|
||||
@@ -28,8 +29,12 @@ const config = {
|
||||
"950": "oklch(0.193359 0.002 75 / <alpha-value>)",
|
||||
},
|
||||
blue: {
|
||||
...harmonyPalette.blue,
|
||||
...colors.indigo,
|
||||
"500": "#5870F1",
|
||||
"600": "#3651E7",
|
||||
"700": "#3313F7",
|
||||
"800": "#2A12BE",
|
||||
"900": "#12046A",
|
||||
DEFAULT: "#3313F7",
|
||||
},
|
||||
},
|
||||
@@ -93,23 +98,23 @@ const config = {
|
||||
"accordion-down": "accordion-down 0.2s ease-out",
|
||||
"accordion-up": "accordion-up 0.2s ease-out",
|
||||
},
|
||||
},
|
||||
container: {
|
||||
center: true,
|
||||
padding: {
|
||||
DEFAULT: "0.75rem",
|
||||
sm: "1rem",
|
||||
lg: "2rem",
|
||||
container: {
|
||||
center: true,
|
||||
padding: {
|
||||
DEFAULT: "0.75rem",
|
||||
sm: "1rem",
|
||||
lg: "2rem",
|
||||
},
|
||||
screens: {
|
||||
md: "960px",
|
||||
lg: "1280px",
|
||||
},
|
||||
},
|
||||
screens: {
|
||||
md: "960px",
|
||||
lg: "1280px",
|
||||
},
|
||||
},
|
||||
screens: {
|
||||
md: "960px",
|
||||
lg: "1280px",
|
||||
},
|
||||
},
|
||||
plugins: [tailwindCSSAnimate, typography()],
|
||||
};
|
||||
|
||||
@@ -110,7 +110,7 @@ export default function Home() {
|
||||
slogan="A chat app in 174 lines of code."
|
||||
/>
|
||||
|
||||
<GappedGrid className="mt-0">
|
||||
<div className="flex flex-col md:grid md:grid-cols-2 md:divide-x border rounded-sm overflow-hidden shadow-sm dark:border-stone-900 dark:divide-stone-900">
|
||||
<CodeExampleTabs
|
||||
tabs={[
|
||||
{
|
||||
@@ -134,14 +134,19 @@ export default function Home() {
|
||||
content: <Ui_tsx />,
|
||||
},
|
||||
]}
|
||||
className="col-span-full md:col-span-4"
|
||||
/>
|
||||
<ResponsiveIframe
|
||||
src="https://chat.jazz.tools"
|
||||
localSrc="http://localhost:5173"
|
||||
className="order-first col-span-full lg:col-span-2 rounded-sm overflow-hidden min-h-[50vh] lg:order-last"
|
||||
/>
|
||||
</GappedGrid>
|
||||
<div className="border-b order-first md:order-last flex flex-col md:border-b-0">
|
||||
<div className="flex border-b overflow-x-auto overflow-y-hidden bg-white dark:border-stone-900 dark:bg-stone-900">
|
||||
<p className="flex items-center -mb-px transition-colors px-3 pb-1.5 pt-2 block text-xs border-b-2 border-blue-700 text-stone-700 dark:bg-stone-925 dark:text-blue-500 dark:border-blue-500">
|
||||
result
|
||||
</p>
|
||||
</div>
|
||||
<ResponsiveIframe
|
||||
src="https://chat.jazz.tools"
|
||||
localSrc="http://localhost:5173"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@@ -7,7 +7,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function Page({ params }: Props) {
|
||||
if (!packages.includes(params.package)) {
|
||||
if (!packages.map((p) => p.name).includes(params.package)) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
@@ -24,11 +24,5 @@ export async function generateMetadata({ params }: Props) {
|
||||
|
||||
export async function generateStaticParams() {
|
||||
// TODO: ideally we check which files exist in ../../typedoc
|
||||
return [
|
||||
"jazz-tools",
|
||||
"jazz-react",
|
||||
"jazz-nodejs",
|
||||
"jazz-browser",
|
||||
"jazz-browser-media-images",
|
||||
].map((pkg) => ({ package: pkg }));
|
||||
return packages.map((pkg) => ({ package: pkg.name }));
|
||||
}
|
||||
|
||||
104
homepage/homepage/app/docs/api-reference/page.tsx
Normal file
104
homepage/homepage/app/docs/api-reference/page.tsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import { packages } from "@/lib/packages";
|
||||
import { MessageCircleQuestionIcon, PackageIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { clsx } from "clsx";
|
||||
|
||||
const CardHeading = ({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}) => {
|
||||
return (
|
||||
<h2
|
||||
className={clsx(
|
||||
className,
|
||||
"font-medium text-stone-950 dark:text-white text-lg transition-colors",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</h2>
|
||||
);
|
||||
};
|
||||
|
||||
const CardBody = ({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}) => {
|
||||
return <p className={clsx(className, "text-sm")}>{children}</p>;
|
||||
};
|
||||
|
||||
const Card = ({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
className,
|
||||
"not-prose p-4 h-full rounded-xl flex flex-col gap-1.5 group lg:p-5",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<>
|
||||
<h1>API Reference</h1>
|
||||
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{packages.map(({ name, description }) => (
|
||||
<Link
|
||||
className="not-prose block"
|
||||
href={`/docs/api-reference/${name}`}
|
||||
key={name}
|
||||
>
|
||||
<Card className="border border-stone-200 dark:border-stone-900 shadow-sm">
|
||||
<PackageIcon
|
||||
size={25}
|
||||
strokeWidth={1.5}
|
||||
className="text-stone-500 dark:text-stone-400"
|
||||
/>
|
||||
<CardHeading className="group-hover:text-blue dark:group-hover:text-blue-600">
|
||||
{name}
|
||||
</CardHeading>
|
||||
<CardBody>{description}</CardBody>
|
||||
</Card>
|
||||
</Link>
|
||||
))}
|
||||
|
||||
<Card className="bg-stone-50 dark:bg-stone-925">
|
||||
<MessageCircleQuestionIcon
|
||||
size={25}
|
||||
strokeWidth={1.5}
|
||||
className="text-stone-500 dark:text-stone-400"
|
||||
/>
|
||||
<CardHeading>
|
||||
Can't find what you're looking for?
|
||||
</CardHeading>
|
||||
<CardBody>
|
||||
Get help from our{" "}
|
||||
<Link href="https://discord.gg/utDMjHYg42">
|
||||
Discord
|
||||
</Link>
|
||||
, or open an issue on{" "}
|
||||
<Link href="https://github.com/gardencmp/jazz">
|
||||
GitHub
|
||||
</Link>
|
||||
.
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -10,9 +10,17 @@ import { ComingSoonBadge } from 'gcmp-design-system/src/app/components/atoms/Com
|
||||
/>
|
||||
</div>
|
||||
|
||||
Our issues app will be quite simple, but it will have team collaboration. <span className="text-nowrap">**Let's call it... “Circular.”**</span>
|
||||
## About this guide
|
||||
|
||||
We'll build everything **step-by-step,** in typical, immediately usable stages. We'll explore many important things Jazz does — so **follow along** or **just pick things out.**
|
||||
You might notice that right now, this guide is the only form of documentation there is for Jazz.
|
||||
Over time, we're hoping to introduce independent doc sections for every concept in Jazz, but right now this works as:
|
||||
|
||||
- a quickstart guide
|
||||
- a reference for the concepts in Jazz (ordered from simple & most important to more advanced)
|
||||
- a tutorial that makes you build a full app (that you can use as a base)
|
||||
|
||||
Plus, if you get stuck or you have questions, [ask us on Discord](https://discord.gg/utDMjHYg42)
|
||||
and we'll know exactly where you're at.
|
||||
|
||||
<h2 id="guide-setup">Project Setup</h2>
|
||||
|
||||
@@ -86,9 +94,9 @@ We'll build everything **step-by-step,** in typical, immediately usable stages.
|
||||
); // old
|
||||
```
|
||||
|
||||
This sets Jazz up, extracts app-specific hooks for later, and wraps our app in the provider.
|
||||
This sets Jazz up, extracts app-specific hooks for later, and wraps our app in the provider.
|
||||
|
||||
TODO: explain Auth
|
||||
{/* TODO: explain Auth */}
|
||||
|
||||
<h2 id="intro-to-covalues">Intro to CoValues</h2>
|
||||
|
||||
@@ -122,7 +130,7 @@ export class Issue extends CoMap {
|
||||
}
|
||||
```
|
||||
|
||||
TODO: explain what's happening
|
||||
{/* TODO: explain what's happening */}
|
||||
|
||||
<h3 id="reading-covalues">Reading from CoValues</h3>
|
||||
|
||||
@@ -451,7 +459,11 @@ To see that sync is also already working, try the following:
|
||||
- copy the URL to a new tab in the same browser window and see the same issue
|
||||
- edit the issue and see the changes reflected in the other tab!
|
||||
|
||||
This works because we load the issue as the same account that created it and owns it (remember setting `{ owner: me }`?).
|
||||
This works because we load the issue as the same account that created it and owns it (remember how you set `{ owner: me }`).
|
||||
|
||||
But how can we share an Issue with someone else?
|
||||
|
||||
<h3 id="simple-public-sharing">Simple Public Sharing</h3>
|
||||
|
||||
We'll learn more about access control in "Groups & Permissions", but for now let's build a super simple way of sharing an Issue by just making it publicly readable & writable.
|
||||
|
||||
@@ -504,9 +516,6 @@ export default App; // old
|
||||
|
||||
This concludes our intro to the essence of CoValues. Hopefully you're starting to have a feeling for how CoValues behave and how they're magically available everywhere.
|
||||
|
||||
<h3 id="simple-public-sharing">Simple Public Sharing</h3>
|
||||
<ComingSoonBadge/>
|
||||
|
||||
<h2 id="refs-and-on-demand-subscribe">Refs & Auto-Subscribe</h2>
|
||||
|
||||
Now let's have a look at how to compose CoValues into more complex structures and build a whole app around them.
|
||||
@@ -636,6 +645,8 @@ Two things to note here:
|
||||
- We only need to use `useCoState` on the Project, and the nested `ListOfIssues` and each `Issue` will be **automatically loaded and subscribed to when we access them.**
|
||||
- However, because either the `Project`, `ListOfIssues`, or each `Issue` might not be loaded yet, we have to check for them being defined.
|
||||
|
||||
<h3 id="loading-depth">Precise Loading Depths</h3>
|
||||
|
||||
The load-and-subscribe-on-access is a convenient way to have your rendering drive data loading (including in nested components!) and lets you quickly chuck UIs together without worrying too much about the shape of all data you'll need.
|
||||
|
||||
But you can also take more precise control over loading by defining a minimum-depth to load in `useCoState`:
|
||||
@@ -680,8 +691,123 @@ The loading-depth spec `{ issues: [{}] }` means "in `Project`, load `issues` and
|
||||
- Now, we can get rid of a lot of coniditional accesses because we know that once `project` is loaded, `project.issues` and each `Issue` in it will be loaded as well.
|
||||
- This also results in only one rerender and visual update when everything is loaded, which is faster (especially for long lists) and gives you more control over the loading UX.
|
||||
|
||||
TODO: explain about not loaded vs not set/defined and `_refs` basics
|
||||
{/* TODO: explain about not loaded vs not set/defined and `_refs` basics */}
|
||||
|
||||
<h2 id="groups-and-permissions">Groups & Permissions</h2>
|
||||
|
||||
We've seen briefly how we can use Groups to give everyone access to a Project,
|
||||
and how we can use `{ owner: me }` to make something private to the current user.
|
||||
|
||||
<h3 id="groups-accounts-as-scopes">Groups / Accounts as Permission Scopes</h3>
|
||||
|
||||
This gives us a hint of how permissions work in Jazz: **every CoValue has an owner,
|
||||
and the access rights on that CoValue are determined by its owner.**
|
||||
|
||||
- If the owner is an Account, only that Account can read and write the CoValue.
|
||||
- If the owner is a Group, the access rights depend on the *role* of the Account (that is trying to access the CoValue) in that Group.
|
||||
- `"reader"`s can read but not write to CoValues belonging to the Group.
|
||||
- `"writer"`s can read and write to CoValues belonging to the Group.
|
||||
- `"admin"`s can read and write to CoValues belonging to the Group *and can add and remove other members from the Group itself.*
|
||||
|
||||
<h3 id="creating-invites">Creating Invites</h3>
|
||||
|
||||
There is also an abstraction for creating *invitations to join a Group* (with a specific role) that you can use
|
||||
to add people without having to know their Account ID.
|
||||
|
||||
Let's use these abstractions to build teams for a Project that we can invite people to.
|
||||
|
||||
Turns out, we're already mostly there! First, let's remove making the Project public:
|
||||
|
||||
{/* prettier-ignore */}
|
||||
```tsx
|
||||
import { useState } from "react"; // old
|
||||
import { Project, ListOfIssues } from "./schema"; // old
|
||||
import { ProjectComponent } from "./components/Project.tsx"; // old
|
||||
import { useAccount } from "./main"; // old
|
||||
import { ID, Group } from "jazz-tools" // old
|
||||
// old
|
||||
function App() { // old
|
||||
const { me } = useAccount(); // old
|
||||
const [projectID, setProjectID] = useState<ID<Project> | undefined>( // old
|
||||
(window.location.search?.replace("?project=", "") || undefined) as ID<Project> | undefined, // old
|
||||
); // old
|
||||
// old
|
||||
const createProject = () => { // old
|
||||
const group = Group.create({ owner: me }); // old
|
||||
group.addMember("everyone", "writer"); // *bin*
|
||||
// old
|
||||
const newProject = Project.create( // old
|
||||
{ // old
|
||||
name: "New Project", // old
|
||||
issues: ListOfIssues.create([], { owner: group }) // old
|
||||
}, // old
|
||||
{ owner: group }, // old
|
||||
); // old
|
||||
setProjectID(newProject.id); // old
|
||||
window.history.pushState({}, "", `?project=${newProject.id}`); // old
|
||||
}; // old
|
||||
// old
|
||||
if (projectID) { // old
|
||||
return <ProjectComponent projectID={projectID} />; // old
|
||||
} else { // old
|
||||
return <button onClick={createProject}>Create Project</button>; // old
|
||||
} // old
|
||||
} // old
|
||||
// old
|
||||
export default App; // old
|
||||
```
|
||||
|
||||
Now, inside ProjectComponent, let's add a button to invite guests (read-only) or members (read-write) to the Project.
|
||||
|
||||
{/* prettier-ignore */}
|
||||
```tsx
|
||||
import { ID } from "jazz-tools"; // old
|
||||
import { Project, Issue } from "../schema"; // old
|
||||
import { IssueComponent } from "./Issue.tsx"; // old
|
||||
import { useCoState } from "../main"; // old
|
||||
import { createInviteLink } from "jazz-react";
|
||||
// old
|
||||
|
||||
export function ProjectComponent({ projectID }: { projectID: ID<Project> }) {// old
|
||||
const project = useCoState(Project, projectID, { issues: [{}] }); // old
|
||||
|
||||
const invite = (role: "reader" | "writer") => {
|
||||
const link = createInviteLink(project, role, { valueHint: "project" });
|
||||
navigator.clipboard.writeText(link);
|
||||
};
|
||||
|
||||
const createAndAddIssue = () => {// old
|
||||
project?.issues.push(Issue.create({ // old
|
||||
title: "",// old
|
||||
description: "",// old
|
||||
estimate: 0,// old
|
||||
status: "backlog",// old
|
||||
}, { owner: project._owner }));// old
|
||||
};// old
|
||||
// old
|
||||
return project ? (// old
|
||||
<div>// old
|
||||
<h1>{project.name}</h1>// old
|
||||
{project._owner?.myRole() === "admin" && (
|
||||
<>
|
||||
<button onClick={() => invite("reader")}>Invite Guest</button>
|
||||
<button onClick={() => invite("writer")}>Invite Member</button>
|
||||
</>
|
||||
)}
|
||||
<div className="border-r border-b">// old
|
||||
{project.issues.map((issue) => ( // old
|
||||
<IssueComponent key={issue.id} issue={issue} /> // old
|
||||
))}// old
|
||||
<button onClick={createAndAddIssue}>Create Issue</button>// old
|
||||
</div>// old
|
||||
</div>// old
|
||||
) : (// old
|
||||
<div>Loading project...</div>// old
|
||||
);// old
|
||||
}// old
|
||||
```
|
||||
|
||||
<h3 id="consuming-invites">Consuming Invites</h3>
|
||||
<div className="text-amber-500 mt-52">
|
||||
🚧 OH NO - This is as far as we've written the Guide. 🚧
|
||||
</div>
|
||||
|
||||
@@ -14,17 +14,13 @@ export default function DocsLayout({
|
||||
}) {
|
||||
return (
|
||||
<div className="relative grid grid-cols-12 gap-x-8 py-8">
|
||||
<div
|
||||
<DocNav
|
||||
className={cn(
|
||||
"md:col-span-4 lg:col-span-3",
|
||||
"sticky align-start top-[4.75rem] h-[calc(100vh-8rem)] overflow-y-auto overflow-x-hidden",
|
||||
"bg-stone-100 dark:bg-stone-900 text-stone-700 dark:text-stone-300 p-4 rounded-xl",
|
||||
"hidden md:block",
|
||||
"prose-sm prose-ul:pl-1 prose-ul:ml-1 prose-li:my-2 prose-li:leading-tight prose-ul:list-['-']",
|
||||
)}
|
||||
>
|
||||
<DocNav />
|
||||
</div>
|
||||
/>
|
||||
<div className="col-span-12 md:col-span-8 lg:col-span-9">
|
||||
<Prose>{children}</Prose>
|
||||
</div>
|
||||
|
||||
40
homepage/homepage/app/docs/resources/examples/page.tsx
Normal file
40
homepage/homepage/app/docs/resources/examples/page.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
export default function Page() {
|
||||
const examples = [
|
||||
{
|
||||
name: "Chat",
|
||||
slug: "chat",
|
||||
},
|
||||
{
|
||||
name: "Music player",
|
||||
slug: "music-player",
|
||||
},
|
||||
{
|
||||
name: "Pets",
|
||||
slug: "pets",
|
||||
},
|
||||
{
|
||||
name: "Todo",
|
||||
slug: "todo",
|
||||
},
|
||||
{
|
||||
name: "Password manager",
|
||||
slug: "password-manager",
|
||||
},
|
||||
];
|
||||
return (
|
||||
<>
|
||||
<h1>Example Apps</h1>
|
||||
<ul>
|
||||
{examples.map(({ name, slug }) => (
|
||||
<li key={name}>
|
||||
<a
|
||||
href={`https://github.com/gardencmp/jazz/tree/main/examples/${slug}`}
|
||||
>
|
||||
{name}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base, shiki;
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
@@ -66,350 +64,16 @@
|
||||
--input: 12 6.5% 15.1%;
|
||||
--ring: 24 5.7% 82.9%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
|
||||
.overlay-close {
|
||||
background-color: "black";
|
||||
@apply bg-black;
|
||||
}
|
||||
}
|
||||
|
||||
pre.shiki {
|
||||
overflow: hidden;
|
||||
}
|
||||
pre.shiki:hover .dim {
|
||||
opacity: 1;
|
||||
}
|
||||
pre.shiki div.dim {
|
||||
opacity: 0.5;
|
||||
}
|
||||
pre.shiki div.dim,
|
||||
pre.shiki div.highlight {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
pre.shiki div.highlight {
|
||||
opacity: 1;
|
||||
background-color: #f1f8ff;
|
||||
}
|
||||
pre.shiki div.line {
|
||||
/* min-height: 1rem; */
|
||||
counter-increment: lineNumber 1;
|
||||
}
|
||||
|
||||
pre.shiki div.line::before {
|
||||
content: counter(lineNumber);
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 1.3rem;
|
||||
padding-right: 0.3rem;
|
||||
text-align: right;
|
||||
transition: color 0.3s;
|
||||
@apply text-stone-200/50 dark:text-stone-900 text-[0.65rem];
|
||||
}
|
||||
|
||||
pre.shiki div.line:hover::before {
|
||||
@apply text-stone-400 dark:text-stone-600;
|
||||
}
|
||||
|
||||
/** Don't show the language identifiers */
|
||||
pre.shiki .language-id {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/** When you mouse over the pre, show the underlines */
|
||||
pre.twoslash:hover data-lsp {
|
||||
@apply border-dotted border-b border-stone-300 dark:border-stone-700;
|
||||
}
|
||||
|
||||
/** The tooltip-like which provides the LSP response */
|
||||
pre.twoslash data-lsp::before {
|
||||
content: attr(lsp);
|
||||
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-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;
|
||||
transition: opacity 0.3s;
|
||||
pointer-events: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
pre.twoslash data-lsp:hover::before {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
pointer-events: visible;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.shiki-outer {
|
||||
@apply shadow-sm rounded-xl;
|
||||
}
|
||||
|
||||
.shiki-filename {
|
||||
@apply px-3 py-2 bg-stone-100 text-stone-700 dark:bg-stone-900 dark:text-stone-300 rounded-t-xl text-xs;
|
||||
}
|
||||
|
||||
pre .code-container {
|
||||
@apply overflow-auto p-2 pl-0 bg-white dark:bg-stone-925 rounded-b-xl text-xs dark:border-stone-900;
|
||||
}
|
||||
/* The try button */
|
||||
pre .code-container > a {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
bottom: 8px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #719af4;
|
||||
padding: 0 8px;
|
||||
color: #719af4;
|
||||
text-decoration: none;
|
||||
opacity: 0;
|
||||
transition-timing-function: ease;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
/* Respect no animations */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
pre .code-container > a {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
pre .code-container > a:hover {
|
||||
color: white;
|
||||
background-color: #719af4;
|
||||
}
|
||||
pre .code-container:hover a {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
pre code {
|
||||
white-space: pre;
|
||||
}
|
||||
pre code a {
|
||||
text-decoration: none;
|
||||
}
|
||||
pre data-err {
|
||||
/* Extracted from VS Code */
|
||||
background: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23c94824'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")
|
||||
repeat-x bottom left;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
pre .query {
|
||||
margin-bottom: 10px;
|
||||
color: #137998;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* In order to have the 'popped out' style design and to not break the layout
|
||||
/* we need to place a fake and un-selectable copy of the error which _isn't_ broken out
|
||||
/* behind the actual error message.
|
||||
|
||||
/* This sections keeps both of those two in in sync */
|
||||
|
||||
pre .error,
|
||||
pre .error-behind {
|
||||
margin-left: -14px;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 4px;
|
||||
padding: 6px;
|
||||
padding-left: 14px;
|
||||
width: calc(100% - 20px);
|
||||
white-space: pre-wrap;
|
||||
display: block;
|
||||
}
|
||||
pre .error {
|
||||
position: absolute;
|
||||
background-color: #fee;
|
||||
border-left: 2px solid #bf1818;
|
||||
/* Give the space to the error code */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: black;
|
||||
}
|
||||
pre .error .code {
|
||||
display: none;
|
||||
}
|
||||
pre .error-behind {
|
||||
user-select: none;
|
||||
visibility: transparent;
|
||||
color: #fee;
|
||||
}
|
||||
/* Queries */
|
||||
pre .arrow {
|
||||
/* Transparent background */
|
||||
background-color: #eee;
|
||||
position: relative;
|
||||
top: -7px;
|
||||
margin-left: 0.1rem;
|
||||
/* Edges */
|
||||
border-left: 1px solid #eee;
|
||||
border-top: 1px solid #eee;
|
||||
transform: translateY(25%) rotate(45deg);
|
||||
/* Size */
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
}
|
||||
pre .popover {
|
||||
margin-bottom: 10px;
|
||||
background-color: #eee;
|
||||
display: inline-block;
|
||||
padding: 0 0.5rem 0.3rem;
|
||||
margin-top: 10px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
/* Completion */
|
||||
pre .inline-completions ul.dropdown {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
width: 240px;
|
||||
background-color: gainsboro;
|
||||
color: grey;
|
||||
padding-top: 4px;
|
||||
font-family: var(--code-font);
|
||||
font-size: 0.8rem;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-left: 4px solid #4b9edd;
|
||||
}
|
||||
pre .inline-completions ul.dropdown::before {
|
||||
background-color: #4b9edd;
|
||||
width: 2px;
|
||||
position: absolute;
|
||||
top: -1.2rem;
|
||||
left: -3px;
|
||||
content: " ";
|
||||
}
|
||||
pre .inline-completions ul.dropdown li {
|
||||
overflow-x: hidden;
|
||||
padding-left: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
pre .inline-completions ul.dropdown li.deprecated {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
pre .inline-completions ul.dropdown li span.result-found {
|
||||
color: #4b9edd;
|
||||
}
|
||||
pre .inline-completions ul.dropdown li span.result {
|
||||
width: 100px;
|
||||
color: black;
|
||||
display: inline-block;
|
||||
}
|
||||
.dark-theme .markdown pre {
|
||||
background-color: #d8d8d8;
|
||||
border-color: #ddd;
|
||||
filter: invert(98%) hue-rotate(180deg);
|
||||
}
|
||||
data-lsp {
|
||||
/* Ensures there's no 1px jump when the hover happens */
|
||||
border-bottom: 1px dotted transparent;
|
||||
/* Fades in unobtrusively */
|
||||
transition-timing-function: ease;
|
||||
transition: border-color 0.3s;
|
||||
}
|
||||
/* Respect people's wishes to not have animations */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
data-lsp {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
/** Annotations support, providing a tool for meta commentary */
|
||||
.tag-container {
|
||||
position: relative;
|
||||
}
|
||||
.tag-container .twoslash-annotation {
|
||||
position: absolute;
|
||||
font-family:
|
||||
"JetBrains Mono",
|
||||
Menlo,
|
||||
Monaco,
|
||||
Consolas,
|
||||
Courier New,
|
||||
monospace;
|
||||
right: -10px;
|
||||
/** Default annotation text to 200px */
|
||||
width: 200px;
|
||||
color: #187abf;
|
||||
background-color: #fcf3d9 bb;
|
||||
}
|
||||
.tag-container .twoslash-annotation p {
|
||||
text-align: left;
|
||||
font-size: 0.8rem;
|
||||
line-height: 0.9rem;
|
||||
}
|
||||
.tag-container .twoslash-annotation svg {
|
||||
float: left;
|
||||
margin-left: -44px;
|
||||
}
|
||||
.tag-container .twoslash-annotation.left {
|
||||
right: auto;
|
||||
left: -200px;
|
||||
}
|
||||
.tag-container .twoslash-annotation.left svg {
|
||||
float: right;
|
||||
margin-right: -5px;
|
||||
}
|
||||
|
||||
/** Support for showing console log/warn/errors inline */
|
||||
pre .logger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: black;
|
||||
padding: 6px;
|
||||
padding-left: 8px;
|
||||
width: calc(100% - 19px);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
pre .logger svg {
|
||||
margin-right: 9px;
|
||||
}
|
||||
pre .logger.error-log {
|
||||
background-color: #fee;
|
||||
border-left: 2px solid #bf1818;
|
||||
}
|
||||
pre .logger.warn-log {
|
||||
background-color: #ffe;
|
||||
border-left: 2px solid #eae662;
|
||||
}
|
||||
pre .logger.log-log {
|
||||
background-color: #e9e9e9;
|
||||
border-left: 2px solid #ababab;
|
||||
}
|
||||
pre .logger.log-log svg {
|
||||
margin-left: 6px;
|
||||
margin-right: 9px;
|
||||
}
|
||||
|
||||
body {
|
||||
--shiki-color-text: #606060;
|
||||
--shiki-color-background: transparent;
|
||||
--shiki-token-constant: #00a5a5;
|
||||
--shiki-token-string: #4e3a2c;
|
||||
--shiki-token-comment: #aaa;
|
||||
--shiki-token-keyword: #7b8bff;
|
||||
--shiki-token-parameter: #ff9800;
|
||||
--shiki-token-function: #445dd7;
|
||||
--shiki-token-string-expression: #38a35f;
|
||||
--shiki-token-punctuation: #969696;
|
||||
--shiki-token-link: #1aa245;
|
||||
}
|
||||
|
||||
.dark body {
|
||||
--shiki-color-text: #d1d1d1;
|
||||
--shiki-token-constant: #2dc9c9;
|
||||
--shiki-token-string: #feb179;
|
||||
--shiki-token-comment: #6b737c;
|
||||
--shiki-token-keyword: #7b8bff;
|
||||
--shiki-token-parameter: #ff9800;
|
||||
--shiki-token-function: #9babff;
|
||||
--shiki-token-string-expression: #42bb69;
|
||||
--shiki-token-punctuation: #bbb;
|
||||
--shiki-token-link: #ffab70;
|
||||
@layer components {
|
||||
@import "shiki.css";
|
||||
}
|
||||
|
||||
@@ -57,7 +57,8 @@ export default function RootLayout({
|
||||
manrope.variable,
|
||||
commitMono.variable,
|
||||
inter.className,
|
||||
"flex flex-col items-center bg-stone-50 text-stone-700 dark:text-stone-400 dark:bg-stone-950",
|
||||
"flex flex-col items-center [&_*]:scroll-mt-[5rem]",
|
||||
"bg-stone-50 text-stone-700 dark:text-stone-400 dark:bg-stone-950",
|
||||
].join(" ")}
|
||||
>
|
||||
<SpeedInsights />
|
||||
@@ -69,7 +70,7 @@ export default function RootLayout({
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<JazzNav />
|
||||
<main className="flex min-h-screen flex-col container w-full">
|
||||
<main className="flex flex-col container w-full">
|
||||
{children}
|
||||
</main>
|
||||
<JazzFooter />
|
||||
|
||||
335
homepage/homepage/app/shiki.css
Normal file
335
homepage/homepage/app/shiki.css
Normal file
@@ -0,0 +1,335 @@
|
||||
pre.shiki {
|
||||
overflow: hidden;
|
||||
}
|
||||
pre.shiki:hover .dim {
|
||||
opacity: 1;
|
||||
}
|
||||
pre.shiki div.dim {
|
||||
opacity: 0.5;
|
||||
}
|
||||
pre.shiki div.dim,
|
||||
pre.shiki div.highlight {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
pre.shiki div.highlight {
|
||||
opacity: 1;
|
||||
background-color: #f1f8ff;
|
||||
}
|
||||
pre.shiki div.line {
|
||||
/* min-height: 1rem; */
|
||||
counter-increment: lineNumber 1;
|
||||
}
|
||||
|
||||
pre.shiki div.line::before {
|
||||
content: counter(lineNumber);
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 1.3rem;
|
||||
padding-right: 0.3rem;
|
||||
text-align: right;
|
||||
transition: color 0.3s;
|
||||
@apply text-stone-200/70 dark:text-stone-900 text-[0.65rem];
|
||||
}
|
||||
|
||||
pre.shiki div.line:hover::before {
|
||||
@apply text-stone-400 dark:text-stone-600;
|
||||
}
|
||||
|
||||
/** Don't show the language identifiers */
|
||||
pre.shiki .language-id {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/** When you mouse over the pre, show the underlines */
|
||||
pre.twoslash:hover data-lsp {
|
||||
@apply border-dotted border-b border-stone-300 dark:border-stone-700;
|
||||
}
|
||||
|
||||
/** The tooltip-like which provides the LSP response */
|
||||
pre.twoslash data-lsp::before {
|
||||
content: attr(lsp);
|
||||
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-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;
|
||||
transition: opacity 0.3s;
|
||||
pointer-events: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
pre.twoslash data-lsp:hover::before {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
pointer-events: visible;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.shiki-outer {
|
||||
@apply shadow-sm rounded-xl;
|
||||
}
|
||||
|
||||
.shiki-filename {
|
||||
@apply px-3 py-2 bg-stone-100 text-stone-700 dark:bg-stone-900 dark:text-stone-300 rounded-t-xl text-xs;
|
||||
}
|
||||
|
||||
pre .code-container {
|
||||
@apply overflow-auto p-2 pl-0 bg-white dark:bg-stone-925 rounded-b-xl text-xs dark:border-stone-900;
|
||||
}
|
||||
/* The try button */
|
||||
pre .code-container > a {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
bottom: 8px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #719af4;
|
||||
padding: 0 8px;
|
||||
color: #719af4;
|
||||
text-decoration: none;
|
||||
opacity: 0;
|
||||
transition-timing-function: ease;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
/* Respect no animations */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
pre .code-container > a {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
pre .code-container > a:hover {
|
||||
color: white;
|
||||
background-color: #719af4;
|
||||
}
|
||||
pre .code-container:hover a {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
pre code {
|
||||
white-space: pre;
|
||||
}
|
||||
pre code a {
|
||||
text-decoration: none;
|
||||
}
|
||||
pre data-err {
|
||||
/* Extracted from VS Code */
|
||||
background: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23c94824'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")
|
||||
repeat-x bottom left;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
pre .query {
|
||||
margin-bottom: 10px;
|
||||
color: #137998;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* In order to have the 'popped out' style design and to not break the layout
|
||||
/* we need to place a fake and un-selectable copy of the error which _isn't_ broken out
|
||||
/* behind the actual error message.
|
||||
|
||||
/* This sections keeps both of those two in in sync */
|
||||
|
||||
pre .error,
|
||||
pre .error-behind {
|
||||
margin-left: -14px;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 4px;
|
||||
padding: 6px;
|
||||
padding-left: 14px;
|
||||
width: calc(100% - 20px);
|
||||
white-space: pre-wrap;
|
||||
display: block;
|
||||
}
|
||||
pre .error {
|
||||
position: absolute;
|
||||
background-color: #fee;
|
||||
border-left: 2px solid #bf1818;
|
||||
/* Give the space to the error code */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: black;
|
||||
}
|
||||
pre .error .code {
|
||||
display: none;
|
||||
}
|
||||
pre .error-behind {
|
||||
user-select: none;
|
||||
visibility: transparent;
|
||||
color: #fee;
|
||||
}
|
||||
/* Queries */
|
||||
pre .arrow {
|
||||
/* Transparent background */
|
||||
background-color: #eee;
|
||||
position: relative;
|
||||
top: -7px;
|
||||
margin-left: 0.1rem;
|
||||
/* Edges */
|
||||
border-left: 1px solid #eee;
|
||||
border-top: 1px solid #eee;
|
||||
transform: translateY(25%) rotate(45deg);
|
||||
/* Size */
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
}
|
||||
pre .popover {
|
||||
margin-bottom: 10px;
|
||||
background-color: #eee;
|
||||
display: inline-block;
|
||||
padding: 0 0.5rem 0.3rem;
|
||||
margin-top: 10px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
/* Completion */
|
||||
pre .inline-completions ul.dropdown {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
width: 240px;
|
||||
background-color: gainsboro;
|
||||
color: grey;
|
||||
padding-top: 4px;
|
||||
font-family: var(--code-font);
|
||||
font-size: 0.8rem;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-left: 4px solid #4b9edd;
|
||||
}
|
||||
pre .inline-completions ul.dropdown::before {
|
||||
background-color: #4b9edd;
|
||||
width: 2px;
|
||||
position: absolute;
|
||||
top: -1.2rem;
|
||||
left: -3px;
|
||||
content: " ";
|
||||
}
|
||||
pre .inline-completions ul.dropdown li {
|
||||
overflow-x: hidden;
|
||||
padding-left: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
pre .inline-completions ul.dropdown li.deprecated {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
pre .inline-completions ul.dropdown li span.result-found {
|
||||
color: #4b9edd;
|
||||
}
|
||||
pre .inline-completions ul.dropdown li span.result {
|
||||
width: 100px;
|
||||
color: black;
|
||||
display: inline-block;
|
||||
}
|
||||
.dark-theme .markdown pre {
|
||||
background-color: #d8d8d8;
|
||||
border-color: #ddd;
|
||||
filter: invert(98%) hue-rotate(180deg);
|
||||
}
|
||||
data-lsp {
|
||||
/* Ensures there's no 1px jump when the hover happens */
|
||||
border-bottom: 1px dotted transparent;
|
||||
/* Fades in unobtrusively */
|
||||
transition-timing-function: ease;
|
||||
transition: border-color 0.3s;
|
||||
}
|
||||
/* Respect people's wishes to not have animations */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
data-lsp {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
/** Annotations support, providing a tool for meta commentary */
|
||||
.tag-container {
|
||||
position: relative;
|
||||
}
|
||||
.tag-container .twoslash-annotation {
|
||||
position: absolute;
|
||||
font-family:
|
||||
"JetBrains Mono",
|
||||
Menlo,
|
||||
Monaco,
|
||||
Consolas,
|
||||
Courier New,
|
||||
monospace;
|
||||
right: -10px;
|
||||
/** Default annotation text to 200px */
|
||||
width: 200px;
|
||||
color: #187abf;
|
||||
background-color: #fcf3d9 bb;
|
||||
}
|
||||
.tag-container .twoslash-annotation p {
|
||||
text-align: left;
|
||||
font-size: 0.8rem;
|
||||
line-height: 0.9rem;
|
||||
}
|
||||
.tag-container .twoslash-annotation svg {
|
||||
float: left;
|
||||
margin-left: -44px;
|
||||
}
|
||||
.tag-container .twoslash-annotation.left {
|
||||
right: auto;
|
||||
left: -200px;
|
||||
}
|
||||
.tag-container .twoslash-annotation.left svg {
|
||||
float: right;
|
||||
margin-right: -5px;
|
||||
}
|
||||
|
||||
/** Support for showing console log/warn/errors inline */
|
||||
pre .logger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: black;
|
||||
padding: 6px;
|
||||
padding-left: 8px;
|
||||
width: calc(100% - 19px);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
pre .logger svg {
|
||||
margin-right: 9px;
|
||||
}
|
||||
pre .logger.error-log {
|
||||
background-color: #fee;
|
||||
border-left: 2px solid #bf1818;
|
||||
}
|
||||
pre .logger.warn-log {
|
||||
background-color: #ffe;
|
||||
border-left: 2px solid #eae662;
|
||||
}
|
||||
pre .logger.log-log {
|
||||
background-color: #e9e9e9;
|
||||
border-left: 2px solid #ababab;
|
||||
}
|
||||
pre .logger.log-log svg {
|
||||
margin-left: 6px;
|
||||
margin-right: 9px;
|
||||
}
|
||||
|
||||
body {
|
||||
--shiki-color-text: #606060;
|
||||
--shiki-color-background: transparent;
|
||||
--shiki-token-constant: #00a5a5;
|
||||
--shiki-token-string: #4e3a2c;
|
||||
--shiki-token-comment: #aaa;
|
||||
--shiki-token-keyword: #7b8bff;
|
||||
--shiki-token-parameter: #ff9800;
|
||||
--shiki-token-function: #445dd7;
|
||||
--shiki-token-string-expression: #38a35f;
|
||||
--shiki-token-punctuation: #969696;
|
||||
--shiki-token-link: #1aa245;
|
||||
}
|
||||
|
||||
.dark body {
|
||||
--shiki-color-text: #d1d1d1;
|
||||
--shiki-token-constant: #2dc9c9;
|
||||
--shiki-token-string: #feb179;
|
||||
--shiki-token-comment: #6b737c;
|
||||
--shiki-token-keyword: #7b8bff;
|
||||
--shiki-token-parameter: #ff9800;
|
||||
--shiki-token-function: #9babff;
|
||||
--shiki-token-string-expression: #42bb69;
|
||||
--shiki-token-punctuation: #bbb;
|
||||
--shiki-token-link: #ffab70;
|
||||
}
|
||||
@@ -22,12 +22,12 @@ export function CodeExampleTabs({
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"shadow-sm bg-white border rounded-sm overflow-hidden h-[40rem] max-h-[80vh] flex flex-col",
|
||||
"dark:bg-stone-925 dark:border-stone-800",
|
||||
"bg-white h-[40rem] max-h-[80vh] flex flex-col",
|
||||
"dark:bg-stone-925",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className="flex border-b overflow-x-auto dark:border-stone-800 dark:bg-stone-900">
|
||||
<div className="flex border-b overflow-x-auto overflow-y-hidden dark:border-stone-900 dark:bg-stone-900">
|
||||
{tabs.map((tab, index) => (
|
||||
<div key={index}>
|
||||
<button
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useLayoutEffect, useState, useRef, IframeHTMLAttributes } from "react";
|
||||
import { CopyIcon } from "lucide-react";
|
||||
|
||||
export function ResponsiveIframe(
|
||||
props: IframeHTMLAttributes<HTMLIFrameElement> & { localSrc: string },
|
||||
@@ -52,31 +53,51 @@ export function ResponsiveIframe(
|
||||
);
|
||||
}, [props.src, props.localSrc]);
|
||||
|
||||
const copyUrl = () => {
|
||||
if (url) {
|
||||
navigator.clipboard.writeText(url);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
"w-full h-full flex flex-col items-stretch border dark:border-stone-800 " +
|
||||
props.className
|
||||
}
|
||||
>
|
||||
<div className="rounded-t-sm bg-white border-b dark:border-stone-800 dark:bg-stone-900 py-1.5 px-10 flex">
|
||||
<>
|
||||
<div className="bg-white flex gap-3 border-b dark:border-stone-900 text-xs dark:bg-stone-925">
|
||||
<input
|
||||
className="text-xs px-1 py-0.5 bg-white dark:bg-stone-900 outline outline-1 outline-stone-200 dark:outline-stone-800 w-full rounded text-center"
|
||||
className="flex-1 font-mono bg-transparent overflow-hidden text-ellipsis py-2 px-3"
|
||||
value={url?.replace("http://", "").replace("https://", "")}
|
||||
onClick={(e) => e.currentTarget.select()}
|
||||
onBlur={(e) => e.currentTarget.setSelectionRange(0, 0)}
|
||||
readOnly
|
||||
/>
|
||||
{url?.includes("/#/chat/") && (
|
||||
<button
|
||||
type="button"
|
||||
className="text-blue-600 flex items-center gap-1.5 py-2 px-3"
|
||||
onClick={copyUrl}
|
||||
>
|
||||
<CopyIcon className="hidden sm:inline" size={12} />
|
||||
<span>
|
||||
Copy URL{" "}
|
||||
<span className="hidden sm:inline">
|
||||
to invite others
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex-grow" ref={containerRef}>
|
||||
<iframe
|
||||
{...props}
|
||||
src={src}
|
||||
className="dark:bg-black"
|
||||
{...dimensions}
|
||||
allowFullScreen
|
||||
/>
|
||||
<div className="flex-1 bg-stone-100 flex items-stretch justify-center p-2 sm:p-6 dark:bg-stone-925">
|
||||
<div className="border rounded-lg overflow-hidden shadow-2xl w-[20rem] min-h-[30rem] dark:border-stone-900">
|
||||
<div className="h-full" ref={containerRef}>
|
||||
<iframe
|
||||
{...props}
|
||||
src={src}
|
||||
className="dark:bg-black w-full"
|
||||
{...dimensions}
|
||||
allowFullScreen
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,86 +1,169 @@
|
||||
import { requestProject } from "./requestProject";
|
||||
import { PackageIcon } from "lucide-react";
|
||||
import { ChevronRight, PackageIcon } from "lucide-react";
|
||||
import { packages } from "@/lib/packages";
|
||||
import Link from "next/link";
|
||||
import { ReactNode } from "react";
|
||||
import { clsx } from "clsx";
|
||||
|
||||
export function DocNav() {
|
||||
export function DocNav({ className }: { className?: string }) {
|
||||
const comingSoon = [
|
||||
"Groups & Permissions",
|
||||
"Auth, Accounts & Migrations",
|
||||
"Edit Metadata & Time Travel",
|
||||
"Backend Workers",
|
||||
];
|
||||
|
||||
const covaluesItems = [
|
||||
{
|
||||
name: "Declaration",
|
||||
href: "/docs#declaring-covalues",
|
||||
},
|
||||
{
|
||||
name: "Reading",
|
||||
href: "/docs#reading-covalues",
|
||||
},
|
||||
{
|
||||
name: "Creation",
|
||||
href: "/docs#creating-covalues",
|
||||
},
|
||||
{
|
||||
name: "Editing & Subscription",
|
||||
href: "/docs#editing-and-subscription",
|
||||
},
|
||||
{
|
||||
name: "Persistence",
|
||||
href: "/docs#persistence",
|
||||
},
|
||||
{
|
||||
name: "Remote Sync",
|
||||
href: "/docs#remote-sync",
|
||||
},
|
||||
{
|
||||
name: "Simple Public Sharing",
|
||||
href: "/docs#simple-public-sharing",
|
||||
},
|
||||
];
|
||||
|
||||
const refsItems = [
|
||||
{
|
||||
name: "Precise Loading Depths",
|
||||
href: "/docs#loading-depth",
|
||||
},
|
||||
];
|
||||
|
||||
const groupsItems = [
|
||||
{
|
||||
name: "Groups/Accounts as Scopes",
|
||||
href: "/docs#groups-accounts-as-scopes",
|
||||
},
|
||||
{
|
||||
name: "Creating Invites",
|
||||
href: "/docs#creating-invites",
|
||||
},
|
||||
{
|
||||
name: "Consuming Invites",
|
||||
href: "/docs#consuming-invites",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className="mt-0 font-medium">
|
||||
<DocNavLink href="/docs">Guide</DocNavLink>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<DocNavLink href="/docs#guide-setup">
|
||||
Project Setup
|
||||
</DocNavLink>
|
||||
</li>
|
||||
<li>
|
||||
<DocNavLink href="/docs#intro-to-covalues">
|
||||
Intro to CoValues
|
||||
</DocNavLink>
|
||||
<ul>
|
||||
<li>
|
||||
<DocNavLink href="/docs#declaring-covalues">
|
||||
Declaration
|
||||
</DocNavLink>
|
||||
<div className={clsx(className, "text-sm space-y-5 pr-3")}>
|
||||
<div>
|
||||
<DocNavHeader href="/docs">Guide</DocNavHeader>
|
||||
<ul>
|
||||
<li>
|
||||
<DocNavLink href="/docs#guide-setup">
|
||||
Project Setup
|
||||
</DocNavLink>
|
||||
</li>
|
||||
<li>
|
||||
<DocNavLink href="/docs#intro-to-covalues">
|
||||
Intro to CoValues
|
||||
</DocNavLink>
|
||||
<ul>
|
||||
{covaluesItems.map((item) => (
|
||||
<li key={item.name}>
|
||||
<DocNavLink
|
||||
className="pl-4"
|
||||
href={item.href}
|
||||
>
|
||||
{item.name}
|
||||
</DocNavLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<DocNavLink href="/docs#refs-and-on-demand-subscribe">
|
||||
Refs & Auto-Subscribe
|
||||
</DocNavLink>
|
||||
<ul>
|
||||
{refsItems.map((item) => (
|
||||
<li key={item.name}>
|
||||
<DocNavLink
|
||||
className="pl-4"
|
||||
href={item.href}
|
||||
>
|
||||
{item.name}
|
||||
</DocNavLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<DocNavLink href="/docs#groups-and-permissions">
|
||||
Groups & Permissions
|
||||
</DocNavLink>
|
||||
<ul>
|
||||
{groupsItems.map((item) => (
|
||||
<li key={item.name}>
|
||||
<DocNavLink
|
||||
className="pl-4"
|
||||
href={item.href}
|
||||
>
|
||||
{item.name}
|
||||
</DocNavLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<DocNavHeader>Coming soon</DocNavHeader>
|
||||
<ul>
|
||||
{comingSoon.map((item) => (
|
||||
<li className="py-1" key={item}>
|
||||
{item}
|
||||
</li>
|
||||
<li>
|
||||
<DocNavLink href="/docs#reading-covalues">
|
||||
Reading
|
||||
</DocNavLink>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<DocNavHeader>Resources</DocNavHeader>
|
||||
<ul>
|
||||
<li>
|
||||
<DocNavLink href="/docs/resources/examples">
|
||||
Example Apps
|
||||
</DocNavLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<DocNavHeader href="/docs/api-reference">
|
||||
API Reference
|
||||
</DocNavHeader>
|
||||
<ul className="space-y-8">
|
||||
{packages.map(({ name }) => (
|
||||
<li key={name}>
|
||||
<NavPackage package={name} />
|
||||
</li>
|
||||
<li>
|
||||
<DocNavLink href="/docs#creating-covalues">
|
||||
Creation
|
||||
</DocNavLink>
|
||||
</li>
|
||||
<li>
|
||||
<DocNavLink href="/docs#editing-and-subscription">
|
||||
Editing & Subscription
|
||||
</DocNavLink>
|
||||
</li>
|
||||
<li>
|
||||
<DocNavLink href="/docs#persistence">
|
||||
Persistence
|
||||
</DocNavLink>
|
||||
</li>
|
||||
<li>
|
||||
<DocNavLink href="/docs#remote-sync">
|
||||
Remote Sync
|
||||
</DocNavLink>
|
||||
</li>
|
||||
<li>
|
||||
<DocNavLink href="/docs#simple-public-sharing">
|
||||
Simple Public Sharing
|
||||
</DocNavLink>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<DocNavLink href="/docs#refs-and-on-demand-subscribe">
|
||||
Refs & Auto-Subscribe
|
||||
</DocNavLink>
|
||||
</li>
|
||||
</ul>
|
||||
Coming soon:
|
||||
<ul>
|
||||
{comingSoon.map((item) => (
|
||||
<li key={item}>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
{packages.map((packageName) => (
|
||||
<NavPackage key={packageName} package={packageName} />
|
||||
))}
|
||||
</>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,38 +176,38 @@ export async function NavPackage({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Link
|
||||
<DocNavLink
|
||||
className="mb-1 flex gap-2 items-center"
|
||||
href={`/docs/api-reference/${packageName}`}
|
||||
className="text-sm mt-4 font-mono flex gap-1 items-center -mx-4 px-4 pt-4 border-t border-stone-200 dark:border-stone-900 "
|
||||
>
|
||||
{packageName}
|
||||
<PackageIcon size={15} strokeWidth={1.5} />
|
||||
</Link>
|
||||
{packageName}
|
||||
</DocNavLink>
|
||||
{project.categories?.map((category) => {
|
||||
return (
|
||||
<details
|
||||
key={category.title}
|
||||
open={category.title !== "Other"}
|
||||
className="[&:not([open])_summary]:after:content-['...']"
|
||||
className="group ml-1.5 border-l dark:border-stone-900"
|
||||
>
|
||||
<summary className="block text-xs mt-2 mb-1 cursor-pointer">
|
||||
<summary className="pl-[13px] py-1 cursor-pointer flex gap-2 items-center justify-between hover:text-stone-800 dark:hover:text-stone-200 [&::-webkit-details-marker]:hidden">
|
||||
{category.title}
|
||||
|
||||
<ChevronRight className="w-4 h-4 text-stone-300 group-open:rotate-90 transition-transform dark:text-stone-800" />
|
||||
</summary>
|
||||
<div className="flex gap-1 flex-wrap text-balance">
|
||||
<div className="pl-6">
|
||||
{category.children.map(
|
||||
(child, i, children) =>
|
||||
(i == 0 ||
|
||||
child.name !==
|
||||
children[i - 1]!.name) && (
|
||||
<>
|
||||
<Link
|
||||
key={child.id}
|
||||
className="text-ellipsis overflow-hidden text-xs font-mono py-0.5 px-1.5 text-stone-800 dark:text-stone-200 bg-stone-200 dark:bg-stone-800 rounded opacity-70 hover:opacity-100"
|
||||
href={`/docs/api-reference/${packageName}#${child.name}`}
|
||||
>
|
||||
{child.name}
|
||||
</Link>
|
||||
</>
|
||||
<Link
|
||||
key={child.id}
|
||||
className="block py-0.5 text-ellipsis overflow-hidden font-mono hover:text-stone-800 dark:hover:text-stone-200"
|
||||
href={`/docs/api-reference/${packageName}#${child.name}`}
|
||||
>
|
||||
{child.name}
|
||||
</Link>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
@@ -138,20 +221,41 @@ export async function NavPackage({
|
||||
export function DocNavLink({
|
||||
href,
|
||||
children,
|
||||
className = "",
|
||||
}: {
|
||||
href: string;
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className={clsx(
|
||||
className,
|
||||
"py-1 hover:text-black dark:hover:text-stone-200 block hover:transition-colors",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
function DocNavHeader({
|
||||
href,
|
||||
children,
|
||||
}: {
|
||||
href?: string;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const className = "block font-medium text-stone-900 py-1 dark:text-white";
|
||||
|
||||
if (href) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className="hover:text-black dark:hover:text-white py-1 hover:transition-colors"
|
||||
>
|
||||
<Link className={className} href={href}>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
return <span className="py-1">{children}</span>;
|
||||
return <p className={className}>{children}</p>;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { readFile } from "fs/promises";
|
||||
import { ProjectReflection, Deserializer, JSONOutput } from "typedoc";
|
||||
|
||||
import JazzToolsDocs from "../../typedoc/jazz-tools.json";
|
||||
|
||||
@@ -1,7 +1,26 @@
|
||||
export const packages = [
|
||||
"jazz-tools",
|
||||
"jazz-react",
|
||||
"jazz-browser",
|
||||
"jazz-browser-media-images",
|
||||
"jazz-nodejs",
|
||||
{
|
||||
name: "jazz-tools",
|
||||
description:
|
||||
"The base implementation for Jazz. Provides a high-level API around the CoJSON protocol.",
|
||||
},
|
||||
{
|
||||
name: "jazz-react",
|
||||
description: "React bindings.",
|
||||
},
|
||||
{
|
||||
name: "jazz-browser",
|
||||
description:
|
||||
"Browser bindings for writing Jazz apps using plain JavaScript, or to build your framework bindings for Jazz.",
|
||||
},
|
||||
{
|
||||
name: "jazz-browser-media-images",
|
||||
description:
|
||||
"Support for creating ImageDefinition-compatible image sets from images provided as File or Blob objects.",
|
||||
},
|
||||
{
|
||||
name: "jazz-nodejs",
|
||||
description:
|
||||
"Node.js bindings for writing server-side workers that interact with Jazz state.",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -45,7 +45,7 @@ function highlightPlugin() {
|
||||
let lineNo = -1;
|
||||
|
||||
node.type = "html";
|
||||
node.value = `<pre><code class="not-prose">${lines
|
||||
node.value = `<pre><code class="not-prose py-2 flex flex-col leading-relaxed">${lines
|
||||
.map((line) => {
|
||||
const isSubduedLine = line.some((token) =>
|
||||
token.content.includes("// old"),
|
||||
@@ -57,11 +57,11 @@ function highlightPlugin() {
|
||||
lineNo++;
|
||||
}
|
||||
return (
|
||||
`<span class="line" style="${isBinnedLine ? "opacity: 0.3; text-decoration: line-through; user-select: none" : ""}"><div class="lineNo" style="${isSubduedLine ? "opacity: 0.3;" : ""}${isBinnedLine ? "color: red;" : ""}">${node.lang === "bash" ? ">" : isBinnedLine ? "✕" : (lineNo + 1)}</div>` +
|
||||
`<span class="block px-3 ${isBinnedLine ? 'bg-red-100 dark:bg-red-800' : ''}" style="${isBinnedLine ? "user-select: none" : ""}">` +
|
||||
line
|
||||
.map(
|
||||
(token) =>
|
||||
`<span style="color: ${isBinnedLine ? "red" : token.color};${isSubduedLine ? "opacity: 0.3;" : ""}">${escape(token.content.replace("// old", "").replace("// *bin*", ""))}</span>`,
|
||||
`<span style="color: ${token.color};${isSubduedLine ? "opacity: 0.4;" : ""}">${escape(token.content.replace("// old", "").replace("// *bin*", ""))}</span>`,
|
||||
)
|
||||
.join("") +
|
||||
"</span>"
|
||||
|
||||
@@ -8,6 +8,7 @@ const config: Config = {
|
||||
"./codeSamples/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./next.config.mjs",
|
||||
"./node_modules/gcmp-design-system/src/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
{
|
||||
"name": "cojson-storage-indexeddb",
|
||||
"version": "0.8.0",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
"types": "src/index.ts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.8.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitest/browser": "^0.34.1",
|
||||
"fake-indexeddb": "^6.0.0",
|
||||
"vitest": "1.5.3",
|
||||
"webdriverio": "^8.15.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsc --watch --sourceMap --outDir dist",
|
||||
"lint": "eslint . --ext ts,tsx",
|
||||
"format": "prettier --write './src/**/*.{ts,tsx}'",
|
||||
"build": "npm run lint && rm -rf ./dist && tsc --sourceMap --outDir dist",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx}": "eslint --fix",
|
||||
"*.{js,jsx,mdx,json}": "prettier --write"
|
||||
},
|
||||
"gitHead": "33c27053293b4801b968c61d5c4c989f93a67d13"
|
||||
"name": "cojson-storage-indexeddb",
|
||||
"version": "0.8.0",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
"types": "src/index.ts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.8.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitest/browser": "^0.34.1",
|
||||
"fake-indexeddb": "^6.0.0",
|
||||
"vitest": "1.5.3",
|
||||
"webdriverio": "^8.15.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsc --watch --sourceMap --outDir dist",
|
||||
"test": "vitest --run --root ../../ --project cojson-storage-indexeddb",
|
||||
"test:watch": "vitest --watch --root ../../ --project cojson-storage-indexeddb",
|
||||
"lint": "eslint . --ext ts,tsx",
|
||||
"format": "prettier --write './src/**/*.{ts,tsx}'",
|
||||
"build": "npm run lint && rm -rf ./dist && tsc --sourceMap --outDir dist",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx}": "eslint --fix",
|
||||
"*.{js,jsx,mdx,json}": "prettier --write"
|
||||
},
|
||||
"gitHead": "33c27053293b4801b968c61d5c4c989f93a67d13"
|
||||
}
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import 'fake-indexeddb/auto'; // Polyfill for IndexedDB
|
||||
import "fake-indexeddb/auto"; // Polyfill for IndexedDB
|
||||
|
||||
import { expect, test } from "vitest";
|
||||
import {
|
||||
ControlledAgent,
|
||||
LocalNode,
|
||||
WasmCrypto,
|
||||
} from "cojson";
|
||||
import { IDBStorage } from "./index.js";
|
||||
import { ControlledAgent, LocalNode, WasmCrypto } from "cojson";
|
||||
import { IDBStorage } from "../index.js";
|
||||
|
||||
const Crypto = await WasmCrypto.create();
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
{
|
||||
"name": "cojson-transport-ws",
|
||||
"type": "module",
|
||||
"version": "0.8.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.8.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsc --watch --sourceMap --outDir dist",
|
||||
"lint": "eslint . --ext ts,tsx",
|
||||
"format": "prettier --write './src/**/*.{ts,tsx}'",
|
||||
"build": "npm run lint && rm -rf ./dist && tsc --sourceMap --outDir dist",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ws": "^8.5.5"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx}": "eslint --fix",
|
||||
"*.{js,jsx,mdx,json}": "prettier --write"
|
||||
}
|
||||
"name": "cojson-transport-ws",
|
||||
"type": "module",
|
||||
"version": "0.8.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.8.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsc --watch --sourceMap --outDir dist",
|
||||
"test": "vitest --run --root ../../ --project cojson-transport-ws",
|
||||
"test:watch": "vitest --watch --root ../../ --project cojson-transport-ws",
|
||||
"lint": "eslint . --ext ts,tsx",
|
||||
"format": "prettier --write './src/**/*.{ts,tsx}'",
|
||||
"build": "npm run lint && rm -rf ./dist && tsc --sourceMap --outDir dist",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ws": "^8.5.5"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx}": "eslint --fix",
|
||||
"*.{js,jsx,mdx,json}": "prettier --write"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { describe, test, expect, vi, Mocked } from "vitest";
|
||||
import { BUFFER_LIMIT, BUFFER_LIMIT_POLLING_INTERVAL, createWebSocketPeer } from "./index.js";
|
||||
import { AnyWebSocket, PingMsg } from "./types.js";
|
||||
import {
|
||||
BUFFER_LIMIT,
|
||||
BUFFER_LIMIT_POLLING_INTERVAL,
|
||||
createWebSocketPeer,
|
||||
} from "../index.js";
|
||||
import { AnyWebSocket, PingMsg } from "../types.js";
|
||||
import { SyncMessage } from "cojson";
|
||||
import { Channel } from "cojson/src/streamUtils";
|
||||
|
||||
@@ -47,8 +51,14 @@ describe("createWebSocketPeer", () => {
|
||||
test("should handle ping messages", async () => {
|
||||
const { listeners } = setup();
|
||||
|
||||
const pingMessage: PingMsg = { type: "ping", time: Date.now(), dc: "test-dc" };
|
||||
const messageEvent = new MessageEvent("message", { data: JSON.stringify(pingMessage) });
|
||||
const pingMessage: PingMsg = {
|
||||
type: "ping",
|
||||
time: Date.now(),
|
||||
dc: "test-dc",
|
||||
};
|
||||
const messageEvent = new MessageEvent("message", {
|
||||
data: JSON.stringify(pingMessage),
|
||||
});
|
||||
|
||||
const messageHandler = listeners.get("message");
|
||||
|
||||
@@ -67,7 +77,9 @@ describe("createWebSocketPeer", () => {
|
||||
|
||||
const { listeners, peer } = setup();
|
||||
|
||||
const incoming = peer.incoming as Channel<SyncMessage | "Disconnected" | "PingTimeout">;
|
||||
const incoming = peer.incoming as Channel<
|
||||
SyncMessage | "Disconnected" | "PingTimeout"
|
||||
>;
|
||||
const pushSpy = vi.spyOn(incoming, "push");
|
||||
|
||||
const closeHandler = listeners.get("close");
|
||||
@@ -81,7 +93,9 @@ describe("createWebSocketPeer", () => {
|
||||
vi.useFakeTimers();
|
||||
const { listeners, peer } = setup();
|
||||
|
||||
const incoming = peer.incoming as Channel<SyncMessage | "Disconnected" | "PingTimeout">;
|
||||
const incoming = peer.incoming as Channel<
|
||||
SyncMessage | "Disconnected" | "PingTimeout"
|
||||
>;
|
||||
const pushSpy = vi.spyOn(incoming, "push");
|
||||
|
||||
const messageHandler = listeners.get("message");
|
||||
@@ -98,17 +112,22 @@ describe("createWebSocketPeer", () => {
|
||||
test("should send outgoing messages", async () => {
|
||||
const { peer, mockWebSocket } = setup();
|
||||
|
||||
const testMessage: SyncMessage = { action: "known", id: "co_ztest", header: false, sessions: {} };
|
||||
const testMessage: SyncMessage = {
|
||||
action: "known",
|
||||
id: "co_ztest",
|
||||
header: false,
|
||||
sessions: {},
|
||||
};
|
||||
const promise = peer.outgoing.push(testMessage);
|
||||
|
||||
await new Promise<void>(queueMicrotask);
|
||||
|
||||
expect(mockWebSocket.send).toHaveBeenCalledWith(JSON.stringify(testMessage));
|
||||
expect(mockWebSocket.send).toHaveBeenCalledWith(
|
||||
JSON.stringify(testMessage),
|
||||
);
|
||||
await expect(promise).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
|
||||
|
||||
test("should stop sending messages when the websocket is closed", async () => {
|
||||
const { peer, mockWebSocket } = setup();
|
||||
|
||||
@@ -116,16 +135,32 @@ describe("createWebSocketPeer", () => {
|
||||
mockWebSocket.readyState = 0;
|
||||
});
|
||||
|
||||
const message1: SyncMessage = { action: "known", id: "co_ztest", header: false, sessions: {} };
|
||||
const message2: SyncMessage = { action: "content", id: "co_zlow", new: {}, priority: 1 };
|
||||
|
||||
const message1: SyncMessage = {
|
||||
action: "known",
|
||||
id: "co_ztest",
|
||||
header: false,
|
||||
sessions: {},
|
||||
};
|
||||
const message2: SyncMessage = {
|
||||
action: "content",
|
||||
id: "co_zlow",
|
||||
new: {},
|
||||
priority: 1,
|
||||
};
|
||||
|
||||
void peer.outgoing.push(message1);
|
||||
void peer.outgoing.push(message2);
|
||||
|
||||
await new Promise<void>(queueMicrotask);
|
||||
|
||||
expect(mockWebSocket.send).toHaveBeenNthCalledWith(1, JSON.stringify(message1));
|
||||
expect(mockWebSocket.send).not.toHaveBeenNthCalledWith(2, JSON.stringify(message2));
|
||||
expect(mockWebSocket.send).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
JSON.stringify(message1),
|
||||
);
|
||||
expect(mockWebSocket.send).not.toHaveBeenNthCalledWith(
|
||||
2,
|
||||
JSON.stringify(message2),
|
||||
);
|
||||
});
|
||||
|
||||
test("should wait for the buffer to be under BUFFER_LIMIT before sending more messages", async () => {
|
||||
@@ -136,22 +171,41 @@ describe("createWebSocketPeer", () => {
|
||||
mockWebSocket.bufferedAmount = BUFFER_LIMIT + 1;
|
||||
});
|
||||
|
||||
const message1: SyncMessage = { action: "known", id: "co_ztest", header: false, sessions: {} };
|
||||
const message2: SyncMessage = { action: "content", id: "co_zlow", new: {}, priority: 1 };
|
||||
|
||||
const message1: SyncMessage = {
|
||||
action: "known",
|
||||
id: "co_ztest",
|
||||
header: false,
|
||||
sessions: {},
|
||||
};
|
||||
const message2: SyncMessage = {
|
||||
action: "content",
|
||||
id: "co_zlow",
|
||||
new: {},
|
||||
priority: 1,
|
||||
};
|
||||
|
||||
void peer.outgoing.push(message1);
|
||||
void peer.outgoing.push(message2);
|
||||
|
||||
await new Promise<void>(queueMicrotask);
|
||||
|
||||
expect(mockWebSocket.send).toHaveBeenNthCalledWith(1, JSON.stringify(message1));
|
||||
expect(mockWebSocket.send).not.toHaveBeenNthCalledWith(2, JSON.stringify(message2));
|
||||
expect(mockWebSocket.send).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
JSON.stringify(message1),
|
||||
);
|
||||
expect(mockWebSocket.send).not.toHaveBeenNthCalledWith(
|
||||
2,
|
||||
JSON.stringify(message2),
|
||||
);
|
||||
|
||||
mockWebSocket.bufferedAmount = 0;
|
||||
|
||||
await vi.advanceTimersByTimeAsync(BUFFER_LIMIT_POLLING_INTERVAL + 1);
|
||||
|
||||
expect(mockWebSocket.send).toHaveBeenNthCalledWith(2, JSON.stringify(message2));
|
||||
expect(mockWebSocket.send).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
JSON.stringify(message2),
|
||||
);
|
||||
|
||||
vi.useRealTimers();
|
||||
});
|
||||
@@ -163,4 +217,4 @@ describe("createWebSocketPeer", () => {
|
||||
|
||||
expect(mockWebSocket.close).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -29,8 +29,8 @@
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsc --watch --sourceMap --outDir dist",
|
||||
"test": "vitest --run",
|
||||
"test-watch": "vitest",
|
||||
"test": "vitest --run --root ../../ --project cojson",
|
||||
"test:watch": "vitest --watch --root ../../ --project cojson",
|
||||
"lint": "eslint . --ext ts,tsx",
|
||||
"format": "prettier --write './src/**/*.{ts,tsx}'",
|
||||
"build": "npm run lint && rm -rf ./dist && tsc --sourceMap --outDir dist",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-browser@0.8.2
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-browser-auth-clerk",
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.2",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
@@ -11,8 +11,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.8.0",
|
||||
"jazz-browser": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1"
|
||||
"jazz-browser": "workspace:0.8.2",
|
||||
"jazz-tools": "workspace:0.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint . --ext ts,tsx",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-browser@0.8.2
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-browser-media-images",
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.2",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
@@ -8,8 +8,8 @@
|
||||
"dependencies": {
|
||||
"@types/image-blob-reduce": "^4.1.1",
|
||||
"image-blob-reduce": "^4.1.0",
|
||||
"jazz-browser": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-browser": "workspace:0.8.2",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"pica": "^9.0.1",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# jazz-browser
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-browser",
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.2",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
@@ -10,7 +10,7 @@
|
||||
"cojson": "workspace:0.8.0",
|
||||
"cojson-storage-indexeddb": "workspace:0.8.0",
|
||||
"cojson-transport-ws": "workspace:0.8.0",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# jazz-autosub
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
"types": "src/index.ts",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.2",
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.8.0",
|
||||
"cojson-transport-ws": "workspace:0.8.0",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"ws": "^8.14.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-browser-auth-clerk@0.8.2
|
||||
- jazz-react@0.8.2
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-react-auth-clerk",
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.2",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.tsx",
|
||||
@@ -11,9 +11,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.8.0",
|
||||
"jazz-browser-auth-clerk": "workspace:0.8.1",
|
||||
"jazz-react": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1"
|
||||
"jazz-browser-auth-clerk": "workspace:0.8.2",
|
||||
"jazz-react": "workspace:0.8.2",
|
||||
"jazz-tools": "workspace:0.8.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.2.0"
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-react
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
- jazz-browser@0.8.2
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-react",
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.2",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
@@ -8,8 +8,8 @@
|
||||
"dependencies": {
|
||||
"@scure/bip39": "^1.3.0",
|
||||
"cojson": "workspace:0.8.0",
|
||||
"jazz-browser": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-browser": "workspace:0.8.2",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# jazz-run
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a075f90]
|
||||
- jazz-tools@0.8.2
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"bin": "./dist/index.js",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.2",
|
||||
"scripts": {
|
||||
"lint": "eslint . --ext ts,tsx",
|
||||
"format": "prettier --write './src/**/*.{ts,tsx}'",
|
||||
@@ -21,7 +21,7 @@
|
||||
"cojson-storage-sqlite": "workspace:0.8.0",
|
||||
"cojson-transport-ws": "workspace:0.8.0",
|
||||
"effect": "^3.6.5",
|
||||
"jazz-tools": "workspace:0.8.1",
|
||||
"jazz-tools": "workspace:0.8.2",
|
||||
"ws": "^8.14.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# jazz-tools
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- a075f90: Fixed cursor reset when interacting with text inputs
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
"types": "./src/index.ts",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.2",
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.8.0",
|
||||
"fast-check": "^3.17.2"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vitest --run",
|
||||
"test-watch": "vitest",
|
||||
"test": "vitest --run --root ../../ --project jazz-tools",
|
||||
"test:watch": "vitest --watch --root ../../ --project jazz-tools",
|
||||
"lint": "eslint . --ext ts,tsx",
|
||||
"format": "prettier --write './src/**/*.{ts,tsx}'",
|
||||
"build": "npm run lint && rm -rf ./dist && tsc --sourceMap --outDir dist",
|
||||
|
||||
@@ -62,13 +62,7 @@ export class SubscriptionScope<Root extends CoValue> {
|
||||
}
|
||||
|
||||
scheduleUpdate() {
|
||||
if (!this.scheduledUpdate) {
|
||||
this.scheduledUpdate = true;
|
||||
queueMicrotask(() => {
|
||||
this.scheduledUpdate = false;
|
||||
this.onUpdate(this.rootEntry.value);
|
||||
});
|
||||
}
|
||||
this.onUpdate(this.rootEntry.value);
|
||||
}
|
||||
|
||||
onRefAccessedOrSet(
|
||||
|
||||
60
pnpm-lock.yaml
generated
60
pnpm-lock.yaml
generated
@@ -79,6 +79,61 @@ importers:
|
||||
specifier: ^5.0.10
|
||||
version: 5.0.10(@types/node@22.5.1)
|
||||
|
||||
e2e/CoValues:
|
||||
dependencies:
|
||||
cojson:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/cojson
|
||||
hash-slash:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/hash-slash
|
||||
is-ci:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
jazz-react:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/jazz-react
|
||||
jazz-tools:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/jazz-tools
|
||||
react:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0
|
||||
react-dom:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0(react@18.2.0)
|
||||
react-router:
|
||||
specifier: ^6.16.0
|
||||
version: 6.21.0(react@18.2.0)
|
||||
react-router-dom:
|
||||
specifier: ^6.16.0
|
||||
version: 6.21.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
devDependencies:
|
||||
'@playwright/test':
|
||||
specifier: ^1.46.1
|
||||
version: 1.46.1
|
||||
'@types/node':
|
||||
specifier: ^22.5.1
|
||||
version: 22.5.1
|
||||
'@types/react':
|
||||
specifier: ^18.2.19
|
||||
version: 18.2.45
|
||||
'@types/react-dom':
|
||||
specifier: ^18.2.7
|
||||
version: 18.2.18
|
||||
'@vitejs/plugin-react-swc':
|
||||
specifier: ^3.3.2
|
||||
version: 3.5.0(vite@5.0.10(@types/node@22.5.1))
|
||||
jstat:
|
||||
specifier: ^1.9.6
|
||||
version: 1.9.6
|
||||
typescript:
|
||||
specifier: ^5.3.3
|
||||
version: 5.3.3
|
||||
vite:
|
||||
specifier: ^5.0.10
|
||||
version: 5.0.10(@types/node@22.5.1)
|
||||
|
||||
examples/chat:
|
||||
dependencies:
|
||||
'@radix-ui/react-checkbox':
|
||||
@@ -3700,6 +3755,9 @@ packages:
|
||||
jsonfile@4.0.0:
|
||||
resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
|
||||
|
||||
jstat@1.9.6:
|
||||
resolution: {integrity: sha512-rPBkJbK2TnA8pzs93QcDDPlKcrtZWuuCo2dVR0TFLOJSxhqfWOVCSp8aV3/oSbn+4uY4yw1URtLpHQedtmXfug==}
|
||||
|
||||
keyv@4.5.4:
|
||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||
|
||||
@@ -8175,6 +8233,8 @@ snapshots:
|
||||
optionalDependencies:
|
||||
graceful-fs: 4.2.11
|
||||
|
||||
jstat@1.9.6: {}
|
||||
|
||||
keyv@4.5.4:
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
|
||||
Reference in New Issue
Block a user