Compare commits

...

74 Commits

Author SHA1 Message Date
Benjamin S. Leveritt
e442bb820b Add changeset 2024-11-18 14:35:58 +00:00
Benjamin S. Leveritt
56d94bd8cd Add saveCredentials on successful login 2024-11-18 13:55:29 +00:00
Guido D'Orsi
6610aea708 Merge pull request #761 from gardencmp/changeset-release/main
Version Packages
2024-11-15 20:30:51 +01:00
github-actions[bot]
f6b6c01852 Version Packages 2024-11-15 18:40:37 +00:00
Trisha Lim
63f9aa6b97 fix: active route styling on docs 2024-11-15 18:39:20 +00:00
pax-k
822eb22da6 fix(docs): fix github URL reference 2024-11-15 20:22:46 +02:00
Anselm Eickhoff
fdf3c6e93d Merge pull request #742 from gardencmp/vue-docs
Vue docs
2024-11-15 18:06:41 +00:00
Guido D'Orsi
de38161023 Merge pull request #770 from gardencmp/gudorsi-jazz-492
fix(useAcceptInvite): trigger the onAccept callback on hashchange
2024-11-15 18:50:15 +01:00
Guido D'Orsi
59cc64d697 fix(useAcceptInvite): trigger the onAccept callback on hashchange 2024-11-15 18:33:27 +01:00
pax-k
55c249834a chore(docs): cleanup 2024-11-15 19:26:16 +02:00
pax-k
dd189abd4a chore: pnpm lock 2024-11-15 19:16:32 +02:00
pax-k
df1a8e9c99 feat: vue docs 2024-11-15 19:13:19 +02:00
pax-k
259467ac3f Merge branch 'main' into vue-docs 2024-11-15 19:09:34 +02:00
Anselm Eickhoff
9a93ab2476 Merge pull request #767 from gardencmp/aeplay-jazz-447
Implement dynamic tables of content
2024-11-15 17:02:39 +00:00
Anselm
337272bbdc Merge branch 'main' into aeplay-jazz-447 2024-11-15 16:56:36 +00:00
pax-k
464ef7d9c3 chore: cleanup 2024-11-15 18:50:27 +02:00
pax-k
8727089654 Merge branch 'aeplay-jazz-447' of https://github.com/gardencmp/jazz into aeplay-jazz-447 2024-11-15 18:45:57 +02:00
pax-k
753bceddb3 fix: SSG for docs 2024-11-15 18:44:47 +02:00
Trisha Lim
8202996108 fix: TOC grows too wide if text is long 2024-11-15 16:31:21 +00:00
Trisha Lim
1385c8a66f Remove custom IDs on headings in mdx files 2024-11-15 15:48:02 +00:00
Anselm
2a72942f8e Implement dynamic ToCs 2024-11-15 15:34:35 +00:00
Anselm Eickhoff
e16836becc Merge pull request #765 from gardencmp/trishalim-jazz-480
Move examples page outside of docs
2024-11-15 15:21:06 +00:00
Trisha Lim
134a101a52 Center align book app thumbnail 2024-11-15 14:11:12 +00:00
Trisha Lim
3fc6030776 Update music player thumbnail 2024-11-15 14:08:40 +00:00
Anselm Eickhoff
8aebe61bf9 Merge pull request #762 from gardencmp/trishalim-jazz-440
Put social icons back to nav
2024-11-15 13:58:08 +00:00
Trisha Lim
8c9e807c19 Move examples page outside of docs 2024-11-15 12:07:42 +00:00
Trisha Lim
e25e4080c7 Reduce large prose font size 2024-11-15 12:04:17 +00:00
Trisha Lim
70a8353fe6 Remove roadmap link from footer 2024-11-15 11:53:54 +00:00
Trisha Lim
185b0d866a Replace Twitter with X 2024-11-15 11:53:41 +00:00
Trisha Lim
717667ac4c Fix color of garden logo 2024-11-15 11:51:24 +00:00
Trisha Lim
a0151caf02 Put social icons back to nav 2024-11-15 11:48:19 +00:00
Guido D'Orsi
c259331f57 Merge pull request #752 from gardencmp/reuse-crypto
fix: reuse the crypto instance when creating the browser context
2024-11-15 12:33:35 +01:00
Guido D'Orsi
f6bc8afa06 chore: changeset 2024-11-15 12:21:47 +01:00
Anselm Eickhoff
cee0aea5e6 Merge pull request #713 from gardencmp/trishalim-jazz-440
Redesign main nav on desktop
2024-11-15 11:20:28 +00:00
Anselm Eickhoff
c0e11f543d Merge pull request #741 from gardencmp/marina-onboarding-example
Onboarding example
2024-11-15 10:57:51 +00:00
pax
df359ab6dd Update selfish-wolves-shout.md 2024-11-14 17:01:28 +02:00
Anselm Eickhoff
d89da07d42 Merge pull request #753 from gardencmp/bensleveritt-patch-1
Fix mesh reference
2024-11-14 11:37:46 +00:00
pax
94098c1f1f Merge pull request #755 from gardencmp/JAZZ-485-docs-pin-react-native-deps
Updated react-native docs and removed babel config section
2024-11-14 12:07:25 +02:00
pax-k
e71e83a217 Merge branch 'main' into JAZZ-485-docs-pin-react-native-deps 2024-11-14 11:58:30 +02:00
pax-k
df0b21caed chore: pnpm lock 2024-11-14 11:58:06 +02:00
Anselm Eickhoff
6921e621d7 Merge pull request #749 from gardencmp/changeset-release/main
Version Packages
2024-11-14 09:41:28 +00:00
pax-k
ec9e03c266 fix: updated react-native docs and removed babel config section 2024-11-14 11:40:27 +02:00
github-actions[bot]
1b0ef401fb Version Packages 2024-11-14 09:29:38 +00:00
pax
1833983b8d Merge pull request #754 from gardencmp/jazz-tools-ts-target
Change jazz-tools TS target to ES2021
2024-11-14 11:28:21 +02:00
pax-k
149ca97c48 chore: changeset 2024-11-14 11:15:25 +02:00
pax-k
f01a7621b0 fix: change jazz-tools TS target to ES2021 2024-11-14 11:13:13 +02:00
Benjamin S. Leveritt
e6a1e2f169 Fix mesh reference 2024-11-14 06:32:10 +00:00
Guido D'Orsi
6413059709 fix: assign a unique name to the IndexedDB storage peer 2024-11-13 20:14:22 +01:00
Guido D'Orsi
3c6fd37aba fix: reuse the crypto instance when creating the browser context 2024-11-13 18:39:49 +01:00
Anselm Eickhoff
ec7c416097 Merge pull request #744 from gardencmp/better-known-state
fix: dispatch more updates to knownState
2024-11-13 14:16:50 +00:00
Guido D'Orsi
0f30eeaec6 chore: changeset 2024-11-13 15:12:18 +01:00
Guido D'Orsi
5a3cf04ba7 fix: dispatch more updates to knownState 2024-11-13 12:32:24 +01:00
pax-k
1fe74be8af fix(jazz-vue): useCoState accepts id as either a ref or a plain value 2024-11-13 12:47:05 +02:00
pax-k
376032f54c chore: cleanup 2024-11-13 11:39:23 +02:00
Anselm Eickhoff
d6e744d948 Merge pull request #738 from gardencmp/changeset-release/main 2024-11-12 22:11:31 +00:00
github-actions[bot]
23b3acb58c Version Packages 2024-11-12 22:10:32 +00:00
Anselm Eickhoff
f32d0c1fad Merge pull request #743 from gardencmp/fix/react-provider-multiple-storage
fix: fixes the react provider intialization when multiple storage options are provided
2024-11-12 22:09:16 +00:00
Guido D'Orsi
a69ed0b7cd chore: changeset 2024-11-12 22:43:19 +01:00
Guido D'Orsi
b4d7024b98 fix: fixes the react provider intialization when multiple storage options are provided 2024-11-12 22:42:27 +01:00
pax-k
d27cff5c67 feat(docs): added VueJS docs 2024-11-12 20:41:53 +02:00
pax-k
a734530cc3 chore: added changeset 2024-11-12 19:55:58 +02:00
pax-k
cc51926d14 chore: biome fix 2024-11-12 19:53:52 +02:00
pax-k
fce808cc48 fix(chat-vue): pass computed(id) to useCoState 2024-11-12 19:37:49 +02:00
pax-k
4a9217eb25 fix(jazz-vue): useCoState reactive to id 2024-11-12 19:36:46 +02:00
pax-k
69df98f4fa feat(todo-vue): implemented a Todo demo app for jazz-vue 2024-11-12 19:35:59 +02:00
Trisha Lim
adaf01f7fa Add bg blur effect on popover 2024-11-11 19:37:41 +00:00
Trisha Lim
c048f4eda9 Increase spacing in popover 2024-11-11 19:37:41 +00:00
Trisha Lim
b06272ff17 Layout fix 2024-11-11 19:37:40 +00:00
Trisha Lim
ac37bfab2d Close popover on click of link 2024-11-11 19:37:40 +00:00
Trisha Lim
d8e50824cb Add description and icon to mega menu items 2024-11-11 19:37:40 +00:00
Trisha Lim
29b27291a3 Links placement in desktop nav 2024-11-11 19:37:40 +00:00
Trisha Lim
efa1b60585 Add mobile nav 2024-11-11 19:37:39 +00:00
Trisha Lim
9d0b39c5cb Add popover menu to main nav using headless 2024-11-11 19:37:18 +00:00
Trisha Lim
2a02a5b212 Remove unused shadcn configs 2024-11-11 19:37:18 +00:00
142 changed files with 2626 additions and 1019 deletions

View File

@@ -1,5 +0,0 @@
---
"jazz-react": patch
---
Move auto login check to useEffect

View File

@@ -1,8 +0,0 @@
---
"jazz-react-native-media-images": patch
"cojson-storage-indexeddb": patch
"jazz-react-native": patch
"jazz-react": patch
---
Remove typescript from the direct dependencies

View File

@@ -1,5 +0,0 @@
---
"jazz-react": patch
---
Add user prop to demo auth to skip login on demos

View File

@@ -0,0 +1,5 @@
---
"jazz-browser": patch
---
Persist PasskeyAuth credentials on reload

View File

@@ -15,6 +15,6 @@ For community and support, please join our [Discord](https://discord.gg/utDMjHYg
- Homepage: [jazz.tools](https://jazz.tools)
- Docs: [jazz.tools/docs](https://jazz.tools/docs)
- Community & support: [Discord](https://discord.gg/utDMjHYg42)
- Updates: [Twitter](https://twitter.com/jazz_tools) & [Email](https://gcmp.io/news)
- Updates: [X](https://x.com/jazz_tools) & [Email](https://gcmp.io/news)
Copyright 2024 — Garden Computing, Inc.
Copyright 2024 — Garden Computing, Inc.

View File

@@ -7,7 +7,7 @@
},
"files": {
"ignoreUnknown": false,
"ignore": ["jazz-tools.json"]
"ignore": ["jazz-tools.json", "**/ios/**", "**/android/**"]
},
"formatter": {
"enabled": true,

View File

@@ -1,5 +1,32 @@
# @jazz-e2e/binarycostream
## 0.0.100
### Patch Changes
- Updated dependencies [59cc64d]
- jazz-react@0.8.22
## 0.0.99
### Patch Changes
- Updated dependencies [0f30eea]
- Updated dependencies [149ca97]
- cojson@0.8.21
- jazz-tools@0.8.21
- jazz-react@0.8.21
## 0.0.98
### Patch Changes
- Updated dependencies [dd9b13f]
- Updated dependencies [a69ed0b]
- Updated dependencies [3ef3ff3]
- Updated dependencies [c6931b8]
- jazz-react@0.8.20
## 0.0.97
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "@jazz-e2e/binarycostream",
"private": true,
"version": "0.0.97",
"version": "0.0.100",
"type": "module",
"scripts": {
"dev": "vite",
@@ -13,11 +13,11 @@
"test:ui": "playwright test --ui"
},
"dependencies": {
"cojson": "workspace:0.8.19",
"cojson": "workspace:0.8.21",
"hash-slash": "workspace:0.2.1",
"is-ci": "^3.0.1",
"jazz-react": "workspace:0.8.19",
"jazz-tools": "workspace:0.8.19",
"jazz-react": "workspace:0.8.22",
"jazz-tools": "workspace:0.8.21",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},

View File

@@ -1,5 +1,32 @@
# @jazz-e2e/covalues
## 0.0.99
### Patch Changes
- Updated dependencies [59cc64d]
- jazz-react@0.8.22
## 0.0.98
### Patch Changes
- Updated dependencies [0f30eea]
- Updated dependencies [149ca97]
- cojson@0.8.21
- jazz-tools@0.8.21
- jazz-react@0.8.21
## 0.0.97
### Patch Changes
- Updated dependencies [dd9b13f]
- Updated dependencies [a69ed0b]
- Updated dependencies [3ef3ff3]
- Updated dependencies [c6931b8]
- jazz-react@0.8.20
## 0.0.96
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "@jazz-e2e/covalues",
"private": true,
"version": "0.0.96",
"version": "0.0.99",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,33 @@
# jazz-example-book-shelf
## 0.1.15
### Patch Changes
- Updated dependencies [59cc64d]
- jazz-react@0.8.22
- jazz-browser-media-images@0.8.22
## 0.1.14
### Patch Changes
- Updated dependencies [149ca97]
- jazz-tools@0.8.21
- jazz-react@0.8.21
- jazz-browser-media-images@0.8.21
## 0.1.13
### Patch Changes
- Updated dependencies [dd9b13f]
- Updated dependencies [a69ed0b]
- Updated dependencies [3ef3ff3]
- Updated dependencies [c6931b8]
- jazz-react@0.8.20
- jazz-browser-media-images@0.8.20
## 0.1.12
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-example-book-shelf",
"version": "0.1.12",
"version": "0.1.15",
"private": true,
"scripts": {
"dev": "next dev",
@@ -11,9 +11,9 @@
},
"dependencies": {
"clsx": "^2.0.0",
"jazz-browser-media-images": "workspace:0.8.19",
"jazz-react": "workspace:0.8.19",
"jazz-tools": "workspace:0.8.19",
"jazz-browser-media-images": "workspace:0.8.22",
"jazz-react": "workspace:0.8.22",
"jazz-tools": "workspace:0.8.21",
"next": "14.2.5",
"react": "^18.2.0",
"react-dom": "^18.2.0"

View File

@@ -1,5 +1,35 @@
# jazz-example-chat
## 0.0.99
### Patch Changes
- Updated dependencies [59cc64d]
- jazz-react@0.8.22
- jazz-react-auth-clerk@0.8.22
## 0.0.98
### Patch Changes
- Updated dependencies [0f30eea]
- Updated dependencies [149ca97]
- cojson@0.8.21
- jazz-tools@0.8.21
- jazz-react@0.8.21
- jazz-react-auth-clerk@0.8.21
## 0.0.97
### Patch Changes
- Updated dependencies [dd9b13f]
- Updated dependencies [a69ed0b]
- Updated dependencies [3ef3ff3]
- Updated dependencies [c6931b8]
- jazz-react@0.8.20
- jazz-react-auth-clerk@0.8.20
## 0.0.96
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-chat-clerk",
"private": true,
"version": "0.0.96",
"version": "0.0.99",
"type": "module",
"scripts": {
"dev": "vite",
@@ -17,11 +17,11 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cojson": "workspace:0.8.19",
"cojson": "workspace:0.8.21",
"hash-slash": "workspace:0.2.1",
"jazz-react": "workspace:0.8.19",
"jazz-react-auth-clerk": "workspace:0.8.19",
"jazz-tools": "workspace:0.8.19",
"jazz-react": "workspace:0.8.22",
"jazz-react-auth-clerk": "workspace:0.8.22",
"jazz-tools": "workspace:0.8.21",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",

View File

@@ -1,5 +1,30 @@
# chat-rn-clerk
## 1.0.15
### Patch Changes
- jazz-react-auth-clerk@0.8.22
## 1.0.14
### Patch Changes
- Updated dependencies [149ca97]
- jazz-tools@0.8.21
- jazz-react-auth-clerk@0.8.21
- jazz-react-native@0.8.21
- jazz-react-native-media-images@0.8.17
## 1.0.13
### Patch Changes
- Updated dependencies [3ef3ff3]
- jazz-react-native-media-images@0.8.16
- jazz-react-native@0.8.20
- jazz-react-auth-clerk@0.8.20
## 1.0.12
### Patch Changes

View File

@@ -2,6 +2,6 @@ module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: ["nativewind/babel", "@babel/plugin-transform-class-static-block"],
plugins: ["nativewind/babel"],
};
};

View File

@@ -1,7 +1,7 @@
{
"name": "chat-rn-clerk",
"main": "index.js",
"version": "1.0.12",
"version": "1.0.15",
"scripts": {
"build": "expo export -p ios",
"start": "expo start",
@@ -65,7 +65,6 @@
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/plugin-transform-class-static-block": "^7.24.7",
"@types/jest": "^29.5.3",
"@types/react": "^18.2.19",
"@types/react-test-renderer": "^18.0.7",

View File

@@ -1,5 +1,20 @@
# chat-rn
## 1.0.16
### Patch Changes
- Updated dependencies [149ca97]
- jazz-tools@0.8.21
- jazz-react-native@0.8.21
## 1.0.15
### Patch Changes
- Updated dependencies [3ef3ff3]
- jazz-react-native@0.8.20
## 1.0.14
### Patch Changes

View File

@@ -2,6 +2,6 @@ module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: ["nativewind/babel", "@babel/plugin-transform-class-static-block"],
plugins: ["nativewind/babel"],
};
};

View File

@@ -1,6 +1,6 @@
{
"name": "chat-rn",
"version": "1.0.14",
"version": "1.0.16",
"main": "index.js",
"scripts": {
"build": "expo export -p ios",
@@ -45,7 +45,6 @@
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/plugin-transform-class-static-block": "^7.24.7",
"@types/react": "^18.2.19",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3"

View File

@@ -1,5 +1,31 @@
# chat-vue
## 0.0.7
### Patch Changes
- a734530: fix useCoState reactivity
- Updated dependencies [f6bc8af]
- Updated dependencies [a734530]
- jazz-browser@0.8.22
- jazz-vue@0.8.12
## 0.0.6
### Patch Changes
- Updated dependencies [149ca97]
- jazz-tools@0.8.21
- jazz-browser@0.8.21
- jazz-vue@0.8.11
## 0.0.5
### Patch Changes
- jazz-browser@0.8.20
- jazz-vue@0.8.10
## 0.0.4
### Patch Changes

View File

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

View File

@@ -1,5 +1,32 @@
# jazz-example-chat
## 0.0.101
### Patch Changes
- Updated dependencies [59cc64d]
- jazz-react@0.8.22
## 0.0.100
### Patch Changes
- Updated dependencies [0f30eea]
- Updated dependencies [149ca97]
- cojson@0.8.21
- jazz-tools@0.8.21
- jazz-react@0.8.21
## 0.0.99
### Patch Changes
- Updated dependencies [dd9b13f]
- Updated dependencies [a69ed0b]
- Updated dependencies [3ef3ff3]
- Updated dependencies [c6931b8]
- jazz-react@0.8.20
## 0.0.98
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-chat",
"private": true,
"version": "0.0.98",
"version": "0.0.101",
"type": "module",
"scripts": {
"dev": "vite",
@@ -18,10 +18,10 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cojson": "workspace:0.8.19",
"cojson": "workspace:0.8.21",
"hash-slash": "workspace:0.2.1",
"jazz-react": "workspace:0.8.19",
"jazz-tools": "workspace:0.8.19",
"jazz-react": "workspace:0.8.22",
"jazz-tools": "workspace:0.8.21",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",

View File

@@ -1,5 +1,13 @@
# jazz-example-inspector
## 0.0.73
### Patch Changes
- Updated dependencies [0f30eea]
- cojson@0.8.21
- cojson-transport-ws@0.8.21
## 0.0.72
### Patch Changes

View File

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

View File

@@ -1,5 +1,30 @@
# jazz-example-musicplayer
## 0.0.21
### Patch Changes
- Updated dependencies [59cc64d]
- jazz-react@0.8.22
## 0.0.20
### Patch Changes
- Updated dependencies [149ca97]
- jazz-tools@0.8.21
- jazz-react@0.8.21
## 0.0.19
### Patch Changes
- Updated dependencies [dd9b13f]
- Updated dependencies [a69ed0b]
- Updated dependencies [3ef3ff3]
- Updated dependencies [c6931b8]
- jazz-react@0.8.20
## 0.0.18
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-music-player",
"private": true,
"version": "0.0.18",
"version": "0.0.21",
"type": "module",
"scripts": {
"dev": "vite",
@@ -18,8 +18,8 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-react": "workspace:0.8.19",
"jazz-tools": "workspace:0.8.19",
"jazz-react": "workspace:0.8.22",
"jazz-tools": "workspace:0.8.21",
"lucide-react": "^0.274.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",

View File

@@ -70,7 +70,11 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
return (
<>
<Jazz.Provider auth={auth} peer={peer}>
<Jazz.Provider
storage={["singleTabOPFS", "indexedDB"]}
auth={auth}
peer={peer}
>
{children}
</Jazz.Provider>
<DemoAuthBasicUI appName="Jazz Music Player" state={state} />

View File

@@ -0,0 +1,9 @@
# jazz-example-onboarding
## 0.0.2
### Patch Changes
- Updated dependencies [59cc64d]
- jazz-react@0.8.22
- jazz-browser-media-images@0.8.22

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-onboarding",
"private": true,
"version": "0.0.1",
"version": "0.0.2",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,30 @@
# jazz-password-manager
## 0.0.20
### Patch Changes
- Updated dependencies [59cc64d]
- jazz-react@0.8.22
## 0.0.19
### Patch Changes
- Updated dependencies [149ca97]
- jazz-tools@0.8.21
- jazz-react@0.8.21
## 0.0.18
### Patch Changes
- Updated dependencies [dd9b13f]
- Updated dependencies [a69ed0b]
- Updated dependencies [3ef3ff3]
- Updated dependencies [c6931b8]
- jazz-react@0.8.20
## 0.0.17
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-password-manager",
"private": true,
"version": "0.0.17",
"version": "0.0.20",
"type": "module",
"scripts": {
"dev": "vite",
@@ -12,8 +12,8 @@
"clean-install": "rm -rf node_modules pnpm-lock.yaml && pnpm install"
},
"dependencies": {
"jazz-react": "workspace:0.8.19",
"jazz-tools": "workspace:0.8.19",
"jazz-react": "workspace:0.8.22",
"jazz-tools": "workspace:0.8.21",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.41.5",

View File

@@ -1,5 +1,33 @@
# jazz-example-pets
## 0.0.118
### Patch Changes
- Updated dependencies [59cc64d]
- jazz-react@0.8.22
- jazz-browser-media-images@0.8.22
## 0.0.117
### Patch Changes
- Updated dependencies [149ca97]
- jazz-tools@0.8.21
- jazz-react@0.8.21
- jazz-browser-media-images@0.8.21
## 0.0.116
### Patch Changes
- Updated dependencies [dd9b13f]
- Updated dependencies [a69ed0b]
- Updated dependencies [3ef3ff3]
- Updated dependencies [c6931b8]
- jazz-react@0.8.20
- jazz-browser-media-images@0.8.20
## 0.0.115
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-pets",
"private": true,
"version": "0.0.115",
"version": "0.0.118",
"type": "module",
"scripts": {
"dev": "vite",
@@ -19,9 +19,9 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-browser-media-images": "workspace:0.8.19",
"jazz-react": "workspace:0.8.19",
"jazz-tools": "workspace:0.8.19",
"jazz-browser-media-images": "workspace:0.8.22",
"jazz-react": "workspace:0.8.22",
"jazz-tools": "workspace:0.8.21",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",
@@ -41,7 +41,7 @@
"@vitejs/plugin-react-swc": "^3.3.2",
"autoprefixer": "^10.4.14",
"is-ci": "^3.0.1",
"jazz-run": "workspace:0.8.19",
"jazz-run": "workspace:0.8.21",
"postcss": "^8.4.27",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",

1
examples/todo-vue/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
dist

View File

@@ -0,0 +1,11 @@
# todo-vue
## 0.0.5
### Patch Changes
- a734530: fix useCoState reactivity
- Updated dependencies [f6bc8af]
- Updated dependencies [a734530]
- jazz-browser@0.8.22
- jazz-vue@0.8.12

View File

@@ -0,0 +1,39 @@
# todo-vue
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
## Type Support for `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
## Customize configuration
See [Vite Configuration Reference](https://vite.dev/config/).
## Project Setup
```sh
pnpm install
```
### Compile and Hot-Reload for Development
```sh
pnpm dev
```
### Type-Check, Compile and Minify for Production
```sh
pnpm build
```
### Lint with [ESLint](https://eslint.org/)
```sh
pnpm lint
```

1
examples/todo-vue/env.d.ts vendored Normal file
View File

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

View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -0,0 +1,39 @@
{
"name": "todo-vue",
"version": "0.0.5",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build-type-check": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build": "vite build",
"type-check": "vue-tsc --build --force",
"format-and-lint": "biome check .",
"format-and-lint:fix": "biome check . --write"
},
"dependencies": {
"jazz-browser": "workspace:*",
"jazz-tools": "workspace:*",
"jazz-vue": "workspace:*",
"vue": "^3.5.11",
"vue-router": "^4.4.5"
},
"devDependencies": {
"@tsconfig/node20": "^20.1.4",
"@types/node": "^22.5.1",
"@vitejs/plugin-vue": "^5.1.4",
"@vitejs/plugin-vue-jsx": "^4.0.1",
"@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.14",
"eslint": "^8.46.0",
"eslint-plugin-vue": "^9.28.0",
"npm-run-all2": "^6.2.3",
"postcss": "^8.4.27",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",
"vite": "^5.0.10",
"vite-plugin-vue-devtools": "^7.4.6",
"vue-tsc": "^2.1.6"
}
}

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,69 @@
<template>
<div class="app-container">
<header v-if="me" class="app-header">
<h1>Todo App</h1>
<div class="user-section">
<span>{{ me.profile?.name }}</span>
<button class="logout-btn" @click="logOut">Log out</button>
</div>
</header>
<main>
<router-view />
</main>
</div>
</template>
<style scoped>
.app-container {
min-height: 100vh;
background-color: #f5f5f5;
}
.app-header {
background-color: #fff;
padding: 1rem 2rem;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
display: flex;
justify-content: space-between;
align-items: center;
}
h1 {
color: #2c3e50;
margin: 0;
font-size: 1.5rem;
}
.user-section {
display: flex;
align-items: center;
gap: 1rem;
}
.logout-btn {
background-color: transparent;
border: 1px solid #dc3545;
color: #dc3545;
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
}
.logout-btn:hover {
background-color: #dc3545;
color: white;
}
main {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
</style>
<script setup lang="ts">
import { useAccount } from "./main";
const { me, logOut } = useAccount();
</script>

View File

@@ -0,0 +1,74 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition: color 0.5s, background-color 0.5s;
line-height: 1.6;
font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

View File

@@ -0,0 +1 @@
@import "./base.css";

View File

@@ -0,0 +1,42 @@
import "./assets/main.css";
import { DemoAuthBasicUI, createJazzVueApp, useDemoAuth } from "jazz-vue";
import { createApp, defineComponent, h } from "vue";
import App from "./App.vue";
import router from "./router";
import { ToDoAccount } from "./schema";
const Jazz = createJazzVueApp<ToDoAccount>({ AccountSchema: ToDoAccount });
export const { useAccount, useCoState } = Jazz;
const { JazzProvider } = Jazz;
const RootComponent = defineComponent({
name: "RootComponent",
setup() {
const { authMethod, state } = useDemoAuth();
return () => [
h(
JazzProvider,
{
auth: authMethod.value,
peer: "wss://mesh.jazz.tools/?key=vue-todo-example-jazz@gcmp.io",
},
{
default: () => h(App),
},
),
state.state !== "signedIn" &&
h(DemoAuthBasicUI, {
appName: "Jazz Vue Todo",
state,
}),
];
},
});
const app = createApp(RootComponent);
app.use(router);
app.mount("#app");

View File

@@ -0,0 +1,15 @@
import { createRouter, createWebHistory } from "vue-router";
import Home from "../views/HomeView.vue";
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/",
name: "Home",
component: Home,
},
],
});
export default router;

View File

@@ -0,0 +1,52 @@
import { Account, CoList, CoMap, Group, Profile, co } from "jazz-tools";
export class ToDoItem extends CoMap {
name = co.string;
completed = co.boolean;
}
export class ToDoList extends CoList.Of(co.ref(ToDoItem)) {}
export class Folder extends CoMap {
name = co.string;
items = co.ref(ToDoList);
}
export class FolderList extends CoList.Of(co.ref(Folder)) {}
export class ToDoAccountRoot extends CoMap {
folders = co.ref(FolderList);
}
export class ToDoAccount extends Account {
profile = co.ref(Profile);
root = co.ref(ToDoAccountRoot);
migrate(this: ToDoAccount, creationProps?: { name: string }) {
super.migrate(creationProps);
if (!this._refs.root) {
const group = Group.create({ owner: this });
const exampleTodo = ToDoItem.create(
{ name: "Example todo", completed: false },
{ owner: group },
);
const defaultFolder = Folder.create(
{
name: "Default",
items: ToDoList.create([exampleTodo], { owner: group }),
},
{ owner: group },
);
this.root = ToDoAccountRoot.create(
{
folders: FolderList.create([defaultFolder], {
owner: this,
}),
},
{ owner: this },
);
}
}
}

View File

@@ -0,0 +1,285 @@
<template>
<div class="todo-container">
<div class="folders">
<div class="section-header">
<h2>Folders</h2>
<div class="new-folder">
<input
v-model="newFolderName"
placeholder="New folder name"
class="input"
/>
<button class="btn btn-primary" @click="createFolder">Create</button>
</div>
</div>
<div class="folder-list">
<div
v-for="folder in folders"
:key="folder?.id"
:class="['folder-item', { active: selectedFolder?.id === folder?.id }]"
@click="selectFolder(folder)"
>
<span class="folder-name">{{ folder?.name }}</span>
<button class="btn btn-icon" @click.stop="deleteFolder(folder?.id)">
<span class="material-icons">delete</span>
</button>
</div>
</div>
</div>
<div class="todos" v-if="selectedFolder">
<div class="section-header">
<h2>{{ selectedFolder?.name }}</h2>
<div class="new-todo">
<input
v-model="newTodoTitle"
placeholder="Add a new task"
class="input"
/>
<button class="btn btn-primary" @click="createTodo">Add</button>
</div>
</div>
<div class="todo-list">
<template v-if="selectedFolder?.items?.length">
<div v-for="todo in selectedFolder.items" :key="todo?.id" class="todo-item">
<label class="todo-label">
<input
type="checkbox"
:checked="todo?.completed"
@change="toggleTodo(todo)"
/>
<span :class="{ completed: todo?.completed }">{{ todo?.name }}</span>
</label>
<button class="btn btn-icon" @click="deleteTodo(todo?.id)">
<span class="material-icons">delete</span>
</button>
</div>
</template>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { Group, type ID } from "jazz-tools";
import { ref, toRaw, watch } from "vue";
import { computed } from "vue";
import { useAccount, useCoState } from "../main";
import { Folder, FolderList, ToDoItem, ToDoList } from "../schema";
const { me } = useAccount();
const computedFoldersId = computed(() => me.value?.root?.folders?.id);
const folders = useCoState(FolderList, computedFoldersId, [{ items: [{}] }]);
const selectedFolder = ref<Folder>();
const newFolderName = ref("");
const newTodoTitle = ref("");
// Select the first folder if none is selected
watch(folders, (loadedFolders) => {
if (selectedFolder.value) return;
selectedFolder.value = loadedFolders?.[0] || undefined;
});
const selectFolder = (folder: Folder) => {
selectedFolder.value = folder;
};
const createFolder = () => {
if (!newFolderName.value.trim()) return;
// Create a group where the folder will be owned by the current user
const group = Group.create({ owner: me.value });
// Create the folder
const newFolder = Folder.create(
{
name: newFolderName.value,
items: ToDoList.create([], { owner: group }),
},
{ owner: group },
);
// Add the folder to the list of folders. This change will be synced to all connected clients.
folders.value?.push(newFolder);
newFolderName.value = "";
};
const deleteFolder = (folderId: ID<Folder> | undefined) => {
if (!folders.value || !folderId) return;
const index = folders.value.findIndex((f) => f.id === folderId);
if (index !== -1) {
// Remove the folder from the list. This change will be synced to all connected clients.
folders.value.splice(index, 1);
}
if (selectedFolder.value?.id === folderId) {
selectedFolder.value = folders.value[0] || null;
}
};
// Todo handlers
const createTodo = () => {
if (!newTodoTitle.value.trim() || !selectedFolder.value) return;
const group = Group.create({ owner: me.value });
const newTodo = ToDoItem.create(
{
name: newTodoTitle.value,
completed: false,
},
{ owner: group },
);
// Add the todo to the list of todos. This change will be synced to all connected clients.
// toRaw is used to get the plain object from the reactive object, because the plain object is already proxied by Jazz.
// otherwise it will throw an error.
toRaw(selectedFolder.value)?.items?.push(newTodo);
newTodoTitle.value = "";
};
const deleteTodo = (todoId: ID<ToDoItem> | undefined) => {
if (!selectedFolder.value?.items || !todoId) return;
const index = toRaw(selectedFolder.value)?.items?.findIndex(
(t) => t?.id === todoId,
);
if (index !== -1 && index !== undefined) {
toRaw(selectedFolder.value)?.items?.splice(index, 1);
}
};
const toggleTodo = (todo: ToDoItem | null) => {
if (!todo) return;
todo.completed = !todo.completed;
};
</script>
<style scoped>
.todo-container {
display: grid;
grid-template-columns: 300px 1fr;
gap: 2rem;
height: 100%;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.section-header {
padding: 1.5rem;
border-bottom: 1px solid #eee;
}
h2 {
color: #2c3e50;
margin: 0 0 1rem 0;
font-size: 1.25rem;
}
.folders {
border-right: 1px solid #eee;
}
.folder-list,
.todo-list {
padding: 1rem;
}
.folder-item {
padding: 0.75rem 1rem;
margin: 0.25rem 0;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 6px;
transition: all 0.2s;
color: #333;
}
.folder-item:hover {
background-color: #f8f9fa;
}
.folder-item.active {
background-color: #e9ecef;
}
.todo-item {
padding: 0.75rem 1rem;
margin: 0.25rem 0;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 6px;
transition: all 0.2s;
color: #333;
}
.todo-item:hover {
background-color: #f8f9fa;
}
.todo-label {
display: flex;
align-items: center;
gap: 0.75rem;
cursor: pointer;
color: #333;
}
.completed {
text-decoration: line-through;
color: #6c757d;
}
.input {
padding: 0.5rem 1rem;
border: 1px solid #dee2e6;
border-radius: 4px;
font-size: 0.9rem;
width: 100%;
}
.btn {
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
border: none;
font-size: 0.9rem;
transition: all 0.2s;
}
.btn-primary {
background-color: #007bff;
color: white;
}
.btn-primary:hover {
background-color: #0056b3;
}
.btn-icon {
padding: 0.25rem;
background: transparent;
color: #dc3545;
}
.btn-icon:hover {
background-color: #fee2e2;
}
.new-folder,
.new-todo {
display: flex;
gap: 0.5rem;
}
.folder-name {
color: #333;
}
</style>

View File

@@ -0,0 +1,8 @@
/** @type {import('tailwindcss').Config} */
export default {
purge: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};

View File

@@ -0,0 +1,14 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}

View File

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

View File

@@ -0,0 +1,19 @@
{
"extends": "@tsconfig/node20/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*"
],
"compilerOptions": {
"composite": true,
"noEmit": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}

View File

@@ -0,0 +1,16 @@
import { URL, fileURLToPath } from "node:url";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import { defineConfig } from "vite";
import vueDevTools from "vite-plugin-vue-devtools";
// https://vite.dev/config/
export default defineConfig({
plugins: [vue(), vueJsx(), vueDevTools()],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});

View File

@@ -1,5 +1,30 @@
# jazz-example-todo
## 0.0.117
### Patch Changes
- Updated dependencies [59cc64d]
- jazz-react@0.8.22
## 0.0.116
### Patch Changes
- Updated dependencies [149ca97]
- jazz-tools@0.8.21
- jazz-react@0.8.21
## 0.0.115
### Patch Changes
- Updated dependencies [dd9b13f]
- Updated dependencies [a69ed0b]
- Updated dependencies [3ef3ff3]
- Updated dependencies [c6931b8]
- jazz-react@0.8.20
## 0.0.114
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-todo",
"private": true,
"version": "0.0.114",
"version": "0.0.117",
"type": "module",
"scripts": {
"dev": "vite",
@@ -16,8 +16,8 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-react": "workspace:0.8.19",
"jazz-tools": "workspace:0.8.19",
"jazz-react": "workspace:0.8.22",
"jazz-tools": "workspace:0.8.21",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",

View File

@@ -11,6 +11,7 @@
},
"dependencies": {
"@evilmartians/harmony": "^1.0.0",
"@headlessui/react": "^2.2.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"lucide-react": "^0.436.0",

View File

@@ -21,7 +21,7 @@ export function Button(props: ButtonProps) {
const sizeClasses = {
sm: "text-sm py-1 px-2",
md: "py-2 px-3",
md: "py-1.5 px-3",
lg: "md:text-lg py-2 px-3 md:px-8 md:py-3",
};

View File

@@ -1,3 +1,5 @@
import { clsx } from "clsx";
export function GcmpLogo({
monochrome,
className,
@@ -10,7 +12,7 @@ export function GcmpLogo({
viewBox="0 0 557 164"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
className={clsx(className, "text-black dark:text-white")}
>
<g clipPath="url(#clip0_12197_1172)">
<path

View File

@@ -13,7 +13,7 @@ export function Prose({
const sizeClassName = {
sm: "prose-sm",
md: "",
lg: "prose-xl",
lg: "prose-lg lg:prose-xl",
}[size];
return (

View File

@@ -1,30 +1,115 @@
"use client";
import {
CloseButton,
Popover,
PopoverButton,
PopoverGroup,
PopoverPanel,
} from "@headlessui/react";
import clsx from "clsx";
import { MenuIcon, XIcon } from "lucide-react";
import { ChevronDownIcon, MenuIcon, XIcon } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { ReactNode, useEffect, useLayoutEffect, useRef, useState } from "react";
import { BreadCrumb } from "../molecules/Breadcrumb";
import { ThemeToggle } from "../molecules/ThemeToggle";
export function Nav({
mainLogo,
items,
docNav,
cta,
}: {
type NavItemProps = {
href: string;
icon?: ReactNode;
title: string;
firstOnRight?: boolean;
newTab?: boolean;
items?: NavItemProps[];
description?: string;
};
type NavProps = {
mainLogo: ReactNode;
items: {
href: string;
icon?: ReactNode;
title: string;
firstOnRight?: boolean;
newTab?: boolean;
}[];
items: NavItemProps[];
docNav?: ReactNode;
cta?: ReactNode;
};
function NavItem({
item,
className,
}: {
item: NavItemProps;
className?: string;
}) {
const { href, icon, title, items, firstOnRight } = item;
const path = usePathname();
if (!items?.length) {
if (item.icon) {
return (
<NavLinkLogo className="px-3" {...item}>
{icon}
<span className="sr-only">{title}</span>
</NavLinkLogo>
);
}
return (
<NavLink
className={clsx(
className,
"text-sm px-2 lg:px-4 py-3 ",
firstOnRight && "ml-auto",
path === href ? "text-black dark:text-white" : "",
)}
{...item}
>
{title}
</NavLink>
);
}
return (
<Popover className={clsx("relative", className, firstOnRight && "ml-auto")}>
<PopoverButton
className={clsx(
"flex items-center gap-1.5 text-sm px-2 lg:px-4 py-3 max-sm:w-full text-stone-600 dark:text-stone-400 hover:text-black dark:hover:text-white transition-colors hover:transition-none focus-visible:outline-none",
path === href ? "text-black dark:text-white" : "",
)}
>
<span>{title}</span>
<ChevronDownIcon aria-hidden="true" className="size-4" />
</PopoverButton>
<PopoverPanel
transition
className="absolute left-1/2 -translate-x-1/2 z-10 flex w-screen max-w-[24rem] mt-5 transition data-[closed]:translate-y-1 data-[closed]:opacity-0 data-[enter]:duration-200 data-[leave]:duration-150 data-[enter]:ease-out data-[leave]:ease-in"
>
<div className="flex-auto overflow-hidden rounded-lg ring-1 ring-stone-300/60 bg-white/90 backdrop-blur-lg shadow-lg dark:ring-stone-800/50 dark:bg-stone-925/90">
<div className="p-3 grid">
{items.map(({ href, title, description, icon }) => (
<CloseButton
className="p-3 rounded-md flex gap-3 hover:bg-stone-100/80 dark:hover:bg-stone-900/80 transition-colors"
href={href}
aria-label={title}
as={Link}
>
{icon}
<div className="grid gap-1.5 mt-px">
<p className="text-sm font-medium text-stone-900 dark:text-white">
{title}
</p>
<p className="text-sm leading-relaxed">{description}</p>
</div>
</CloseButton>
))}
</div>
</div>
</PopoverPanel>
</Popover>
);
}
export function MobileNav({ mainLogo, items, docNav, cta }: NavProps) {
const [menuOpen, setMenuOpen] = useState(false);
const [searchOpen, setSearchOpen] = useState(false);
const searchRef = useRef<HTMLInputElement>(null);
@@ -41,44 +126,6 @@ export function Nav({
return (
<>
<nav
className={[
clsx(
"hidden md:flex sticky left-0 right-0 top-0 w-full justify-center",
"bg-white dark:bg-stone-950 border-b",
"z-50",
),
].join(" ")}
>
<div className="flex flex-wrap items-center max-sm:justify-between md:gap-2 container w-full">
<div className="flex items-center flex-shrink">
<NavLinkLogo prominent href="/" className="-ml-2">
{mainLogo}
</NavLinkLogo>
</div>
{items.map((item, i) =>
"icon" in item ? (
<NavLinkLogo key={i} href={item.href} newTab={item.newTab}>
{item.icon}
</NavLinkLogo>
) : (
<NavLink
key={i}
href={item.href}
newTab={item.newTab}
className={clsx(
"max-sm:w-full",
item.firstOnRight ? "md:ml-auto" : "",
)}
>
{item.title}
</NavLink>
),
)}
{cta}
</div>
</nav>
<div className="md:hidden px-4 flex items-center self-stretch dark:text-white">
<NavLinkLogo prominent href="/" className="mr-auto">
{mainLogo}
@@ -137,12 +184,12 @@ export function Nav({
</div>
)}
<div className="flex gap-4 justify-end -mb-2">
{items
<div className="flex flex-wrap justify-end py-2 gap-x-3 gap-y-1 border-b">
{[{ title: "Home", href: "/" }, ...items]
.filter((item) => !("icon" in item))
.slice(0, 3)
.map((item, i) => (
<NavLink
className="p-1 text-sm"
key={i}
href={item.href}
onClick={() => setMenuOpen(false)}
@@ -152,47 +199,8 @@ export function Nav({
</NavLink>
))}
</div>
<div className="flex gap-4 justify-end border-b">
{items
.filter((item) => !("icon" in item))
.slice(3)
.map((item, i) => (
<NavLink
key={i}
href={item.href}
onClick={() => setMenuOpen(false)}
newTab={item.newTab}
className={clsx("")}
>
{item.title}
</NavLink>
))}
</div>
</div>
<div className="flex items-center self-stretch justify-between">
{/* <input
type="text"
className={clsx(
menuOpen || searchOpen ? "" : "hidden",
"ml-2 border px-2 py-1 rounded w-full"
)}
placeholder="Search docs..."
ref={searchRef}
/> */}
{/* <button
className="flex p-3 rounded-xl"
onClick={() => {
setSearchOpen(true);
}}
onBlur={(e) => {
if (!e.currentTarget.value) {
setSearchOpen(false);
}
}}
>
<SearchIcon className="" />
</button> */}
{(menuOpen || searchOpen) && <ThemeToggle className="p-3" />}
<button
className="flex gap-2 p-3 rounded-xl items-center"
@@ -236,11 +244,8 @@ function NavLink({
<Link
href={href}
className={clsx(
"px-2 lg:px-4 py-3 text-sm",
"text-stone-600 dark:text-stone-400 hover:text-black dark:hover:text-white transition-colors hover:transition-none",
className,
path === href
? "font-medium text-black dark:text-white cursor-default"
: "text-stone-600 dark:text-stone-400 hover:text-black dark:hover:text-white transition-colors hover:transition-none",
)}
onClick={onClick}
target={newTab ? "_blank" : undefined}
@@ -261,7 +266,6 @@ function NavLinkLogo({
href,
className,
children,
prominent,
onClick,
newTab,
}: {
@@ -272,19 +276,11 @@ function NavLinkLogo({
onClick?: () => void;
newTab?: boolean;
}) {
const path = usePathname();
return (
<Link
href={href}
className={clsx(
"max-sm:px-4 px-2 lg:px-3 py-3 transition-opacity hover:transition-none",
path === href
? "cursor-default"
: prominent
? "hover:opacity-50"
: "opacity-60 hover:opacity-100",
"text-black dark:text-white",
"py-3 hover:text-stone-900 dark:hover:text-white",
className,
)}
onClick={onClick}
@@ -294,3 +290,29 @@ function NavLinkLogo({
</Link>
);
}
export function Nav(props: NavProps) {
const { mainLogo, items, docNav, cta } = props;
return (
<>
<div className="w-full border-b py-2 sticky top-0 z-50 bg-white dark:bg-stone-950 hidden md:block">
<PopoverGroup className="flex flex-wrap items-center max-sm:justify-between md:gap-2 container w-full">
<Link href="/" className="flex items-center">
{mainLogo}
</Link>
{items.map((item, i) => (
<NavItem
key={i}
item={item}
className={i == items.length - 1 ? "mr-3" : ""}
/>
))}
{cta}
</PopoverGroup>
</div>
<MobileNav {...props} />
</>
);
}

View File

@@ -60,56 +60,6 @@ const config = {
fontSize: {
"2xs": ["0.75rem", { lineHeight: "1.25rem" }],
},
// shadcn-ui
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
container: {
center: true,
padding: {
@@ -228,6 +178,9 @@ const config = {
".dark *": {
borderColor: "var(--gcmp-invert-border-color)",
},
"*:focus": {
outline: "none",
},
}),
),
],

View File

@@ -1,36 +0,0 @@
import { clsx } from "clsx";
export function GardenLogo(props: React.SVGProps<SVGSVGElement>) {
return (
<svg
width="175"
viewBox="0 0 540 164"
fill="none"
{...props}
className={clsx(props.className, "text-black dark:text-white")}
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_3069_1)">
<path
d="M226.005 55.6V60.935C221.77 56.535 215.885 53.95 208.515 53.95C191.795 53.95 181.4 67.315 181.4 85.245C181.4 103.065 191.74 116.65 208.295 116.65C215.005 116.65 220.45 114.56 224.63 110.875V116.485C224.795 126.715 219.075 131.995 209.285 131.995C204.005 131.995 198.835 129.74 196.25 124.68L185.635 130.07C190.475 138.54 199.605 143.05 209.175 143.05C223.035 143.05 232.935 137.44 235.41 125.395C236.015 122.59 236.18 119.785 236.18 116.595V55.6H226.005ZM209.89 106.255C198.835 106.255 193.61 97.015 193.61 85.245C193.61 73.585 198.835 64.345 210.275 64.345C221.11 64.345 226.005 72.925 226.005 85.245C226.005 97.565 221.22 106.255 209.89 106.255ZM291.829 65.28C288.144 57.47 279.894 53.95 269.279 53.95C255.529 53.95 247.279 60.44 244.419 70.615L255.144 73.915C257.179 67.315 262.899 64.565 269.169 64.565C278.464 64.565 282.204 68.415 282.589 76.61C272.964 77.93 263.174 79.195 256.299 81.23C247.114 84.145 242.274 89.865 242.274 98.83C242.274 108.51 249.204 116.65 262.349 116.65C271.974 116.65 278.849 113.35 283.744 106.365V115H293.919V78.425C293.919 73.475 293.699 69.185 291.829 65.28ZM264.384 107.245C257.014 107.245 253.659 103.34 253.659 98.72C253.659 94.045 257.124 91.515 261.854 89.92C266.859 88.435 273.514 87.5 282.479 86.18C282.424 88.93 282.204 92.725 281.269 95.475C279.949 101.25 274.174 107.245 264.384 107.245ZM317.881 58.955C315.626 60.44 313.756 62.585 312.381 65.06V55.6H302.151V115H313.756V85.025C313.756 78.04 315.626 71.77 321.236 68.195C325.196 65.665 330.366 65.335 334.216 66.38V55.6C328.881 54.61 322.336 55.655 317.881 58.955ZM377.551 35.8V59.67C373.426 56.04 368.036 53.95 361.381 53.95C344.661 53.95 334.266 67.315 334.266 85.245C334.266 103.065 344.606 116.65 361.161 116.65C368.641 116.65 374.581 114.01 378.871 109.555V115H389.101V35.8H377.551ZM362.756 106.255C351.701 106.255 346.476 97.015 346.476 85.245C346.476 73.585 351.701 64.345 363.141 64.345C373.976 64.345 378.871 72.925 378.871 85.245C378.871 97.565 374.086 106.255 362.756 106.255ZM407.459 88.545H451.734C452.944 67.26 442.384 53.95 424.234 53.95C406.854 53.95 395.139 66.325 395.139 85.795C395.139 104.165 407.019 116.65 424.784 116.65C436.279 116.65 446.344 110.545 450.964 99.93L439.689 96.355C436.774 102.46 431.384 105.815 424.234 105.815C414.224 105.815 408.394 99.6 407.459 88.545ZM424.674 64.125C433.804 64.125 438.754 69.075 439.964 79.58H407.734C409.219 69.515 414.884 64.125 424.674 64.125ZM486.278 54.005C477.698 54.005 470.988 57.195 466.643 62.695V55.6H456.358V115H468.018V84.09C468.018 70.01 474.838 64.895 483.088 64.895C495.738 64.895 498.103 76.555 498.103 85.795V115H509.763V82C509.763 72.815 506.738 54.005 486.278 54.005Z"
fill="currentColor"
></path>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M129.988 44.3845C130.172 44.2449 130.355 44.1054 130.539 43.9661L130.658 44.0735C130.434 44.1767 130.211 44.2804 129.988 44.3845ZM39.0525 139.076L45.3628 139.076C49.6432 131.896 54.1741 124.911 58.9404 118.13L57.3623 112.133H52.1219C46.8244 120.321 42.1253 128.999 38.102 138.123L39.0525 139.076Z"
fill="#42BB69"
></path>
<path
d="M82.5315 57.3805C79.3982 51.5075 76.846 45.4544 74.8578 39.275C74.5484 39.4079 74.2394 39.5426 73.931 39.679C65.031 43.6161 56.744 48.9482 49.5431 55.3708L49.543 55.3707C49.4471 55.4562 49.3516 55.542 49.2565 55.6281C49.4618 64.8598 51.8486 73.8528 56.4599 81.9511C51.0264 76.0801 46.3449 69.8102 42.4097 63.2312C41.3378 64.7087 40.3643 66.2329 39.4971 67.7939C36.9797 72.3255 35.4076 77.0787 34.8708 81.7821C34.3339 86.4854 34.8428 91.0468 36.3683 95.2058C37.8937 99.3648 40.406 103.04 43.7616 106.022C45.4394 107.512 47.506 108.627 49.8434 109.302C51.024 109.643 52.262 109.868 53.5385 109.977C60.6749 99.2754 68.8435 89.4366 77.8657 80.5635L77.8805 80.5489C93.1057 65.5787 110.761 53.3583 129.988 44.3845C130.172 44.2449 130.355 44.1054 130.539 43.9661L130.658 44.0735C130.434 44.1767 130.211 44.2804 129.988 44.3845C113.587 56.8641 98.2957 70.8841 84.357 86.3032L84.343 86.3187C75.6615 95.9234 67.5049 106.071 59.9322 116.727C60.0716 117.428 60.2633 118.113 60.5069 118.777C61.2696 120.856 62.5258 122.694 64.2036 124.184C67.5592 127.166 71.6924 129.395 76.3672 130.745C81.042 132.095 86.1669 132.54 91.4492 132.053C96.7316 131.566 102.068 130.157 107.154 127.907C110.193 126.563 113.106 124.934 115.837 123.058C104.785 118.874 94.3576 113.318 84.8544 106.375C97.965 112.264 113.15 114.043 128.211 111.832C132.295 107.26 135.812 102.344 138.67 97.2002C139.416 95.8575 140.114 94.5037 140.764 93.141C129.699 91.2029 118.905 88.0557 108.612 83.6429C120.293 86.137 132.678 85.8577 144.642 83.0796C145.66 79.6346 146.372 76.17 146.766 72.7208C147.146 69.3887 147.227 66.0974 147.01 62.877C139.63 61.9724 132.319 60.5435 125.138 58.5674C132.194 59.1483 139.343 58.7882 146.374 57.5667C145.876 54.7067 145.132 51.9198 144.145 49.2292C143.791 48.2641 143.407 47.3138 142.993 46.3792L142.272 44.3173L141.717 36.8508L133.329 36.371L131.011 35.7334C129.961 35.3664 128.892 35.026 127.807 34.7127C123.483 33.4639 118.939 32.6579 114.25 32.3015C113.594 37.0369 113.498 41.8046 113.999 46.5239C112.338 41.7743 111.017 36.9598 110.025 32.1028C107.192 32.0504 104.317 32.1572 101.414 32.4248C94.593 33.0536 87.7207 34.5604 81.0112 36.8888C80.2968 43.7957 80.7762 50.7136 82.5315 57.3805Z"
fill="#42BB69"
></path>
</g>
<defs>
<clipPath id="clip0_3069_1">
<rect width="540" height="164" fill="white"></rect>
</clipPath>
</defs>
</svg>
);
}

View File

@@ -1,9 +1,9 @@
import { GardenLogo } from "@/components/GardenLogo";
import { TilescapeLogo } from "@/components/TilescapeLogo";
import { Button } from "gcmp-design-system/src/app/components/atoms/Button";
import { GridCard } from "gcmp-design-system/src/app/components/atoms/GridCard";
import { H2, H3 } from "gcmp-design-system/src/app/components/atoms/Headings";
import { P } from "gcmp-design-system/src/app/components/atoms/Paragraph";
import { GcmpLogo } from "gcmp-design-system/src/app/components/atoms/logos/GcmpLogo";
import { JazzLogo } from "gcmp-design-system/src/app/components/atoms/logos/JazzLogo";
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
@@ -52,7 +52,7 @@ export default function Products() {
<div className="mt-8 space-y-3">
<div className="flex items-center justify-between gap-4">
<GardenLogo className="h-10 w-auto" />
<GcmpLogo className="h-10 w-auto" />
<div>
<ComingSoon>Coming 2024</ComingSoon>
</div>

View File

@@ -1,13 +1,14 @@
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
export const metadata = {
title: "Docs",
description: "Jazz Guide & Docs.",
};
export default function DocsLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<Prose className="container w-full max-w-full col-span-12 md:col-span-8 lg:col-span-9">
{children}
</Prose>
);
return <Prose className="py-6 overflow-x-hidden lg:flex-1">{children}</Prose>;
}

View File

@@ -38,8 +38,8 @@ export default function Page() {
<p>Also make sure to:</p>
<ul>
<li>
Find an <a href="/docs/examples">example app with code</a> most
similar to what you want to build
Find an <a href="/examples">example app with code</a> most similar to
what you want to build
</li>
<li>
Check out the <a href="/docs/api-reference">API Reference</a> (work in

View File

@@ -22,7 +22,7 @@ Over time, we're hoping to introduce independent doc sections for every concept
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>
## Project Setup
1. Create a project called "circular" from a generic Vite starter template:
@@ -104,7 +104,7 @@ This sets Jazz up, extracts app-specific hooks for later, and wraps our app in t
{/* TODO: explain Auth */}
<h2 id="intro-to-covalues">Intro to CoValues</h2>
## Intro to CoValues
Let's learn about the **central idea** behind Jazz: **Collaborative Values.**
@@ -117,7 +117,7 @@ We can
- **edit** CoValues, from anywhere, by mutating them like local state
- **subscribe to edits** in CoValues, whether they're local or remote
<h3 id="declaring-covalues">Declaring our own CoValues</h3>
### Declaring our own CoValues
To make our own CoValues, we first need to declare a schema for them. Think of a schema as a combination of TypeScript types and runtime type information.
@@ -140,7 +140,7 @@ export class Issue extends CoMap {
{/* TODO: explain what's happening */}
<h3 id="reading-covalues">Reading from CoValues</h3>
### Reading from CoValues
CoValues are designed to be read like simple local JSON state. Let's see how we can read from an Issue by building a component to render one.
@@ -166,7 +166,7 @@ export function IssueComponent({ issue }: { issue: Issue }) {
Simple enough!
<h3 id="creating-covalues">Creating CoValues</h3>
### Creating CoValues
To actually see an Issue, we have to create one. This is where things start to get interesting...
@@ -255,7 +255,7 @@ We'll already notice one interesting thing here:
We'll make use of both of these facts in a bit, but for now let's start with local editing and subscribing.
<h3 id="editing-and-subscription">Editing CoValues and subscribing to edits</h3>
### Editing CoValues and subscribing to edits
Since we're the owner of the CoValue, we should be able to edit it, right?
@@ -427,7 +427,7 @@ This works because CoValues
We have one subscriber on our Issue, with `useCoState` in `src/App.tsx`, which will cause the `App` component and its children **to** re-render whenever the Issue changes.
<h3 id="persistence">Automatic local & cloud persistence</h3>
### Automatic local & cloud persistence
So far our Issue CoValues just looked like ephemeral local state. We'll now start exploring the first main feature that makes CoValues special: **automatic persistence.**
@@ -479,7 +479,7 @@ export default App; // old
🏁 Now you should be able to create an issue, edit it, reload the page, and still see the same issue.
<h3 id="remote-sync">Remote sync</h3>
### Remote sync
To see that sync is also already working, try the following:
@@ -490,7 +490,7 @@ This works because we load the issue as the same account that created it and own
But how can we share an Issue with someone else?
<h3 id="simple-public-sharing">Simple Public Sharing</h3>
### Simple Public Sharing
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.
@@ -545,7 +545,7 @@ 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.
<h2 id="refs-and-on-demand-subscribe">Refs & Auto-Subscribe</h2>
## Refs & Auto-Subscribe
Now let's have a look at how to compose CoValues into more complex structures and build a whole app around them.
@@ -682,7 +682,7 @@ 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>
### Precise Loading Depths
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.
@@ -732,12 +732,12 @@ The loading-depth spec `{ issues: [{}] }` means "in `Project`, load `issues` and
{/* TODO: explain about not loaded vs not set/defined and `_refs` basics */}
<h2 id="groups-and-permissions">Groups & Permissions</h2>
## Groups & Permissions
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>
### Groups / Accounts as Permission Scopes
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.**
@@ -748,7 +748,7 @@ and the access rights on that CoValue are determined by its owner.**
- `"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>
### Creating Invites
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.
@@ -850,7 +850,7 @@ export function ProjectComponent({ projectID }: { projectID: ID<Project> }) {//
```
</CodeGroup>
<h3 id="consuming-invites">Consuming Invites</h3>
### Consuming Invites
<div className="text-amber-500 mt-52">
🚧 OH NO - This is as far as we've written the Guide. 🚧
</div>

View File

@@ -0,0 +1,61 @@
import fs from "fs";
import path from "path";
import { TableOfContents } from "@/components/docs/TableOfContents";
import type { Toc } from "@stefanprobst/rehype-extract-toc";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
export default async function Page({ params }: { params: { slug: string[] } }) {
const slugPath = params.slug.join("/");
try {
const { default: Content, tableOfContents } = await import(
`./${slugPath}.mdx`
);
return (
<>
<Prose className="overflow-x-hidden lg:flex-1 pt-6">
<Content />
</Prose>
{tableOfContents && <TableOfContents items={tableOfContents as Toc} />}
</>
);
} catch (error) {
console.error("Error loading MDX file:" + slugPath, error);
return (
<Prose className="overflow-x-hidden lg:flex-1">
<h3>Error loading page: {slugPath}</h3>
</Prose>
);
}
}
// https://nextjs.org/docs/app/api-reference/functions/generate-static-params
export const dynamicParams = false;
export const dynamic = "force-static";
export async function generateStaticParams() {
const docsDir = path.join(process.cwd(), "app/docs/[...slug]");
const getAllMdxPaths = (dir: string, basePath = ""): string[] => {
const entries = fs.readdirSync(dir, { withFileTypes: true });
const paths: string[] = [];
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
const relativePath = path.join(basePath, entry.name);
if (entry.isDirectory()) {
paths.push(...getAllMdxPaths(fullPath, relativePath));
} else if (entry.isFile() && entry.name.endsWith(".mdx")) {
paths.push(relativePath.replace(/\.mdx$/, ""));
}
}
return paths;
};
const paths = getAllMdxPaths(docsDir).map((slug) => ({
slug: slug.split("/"),
}));
return paths;
}

View File

@@ -2,7 +2,7 @@ import { CodeGroup } from "@/components/forMdx";
# Next.js
## <span id="next-csr">Client-side only</span>
## Client-side only
The easiest way to use Jazz with Next.JS is to only use it on the client side. You can ensure this by:
@@ -39,7 +39,7 @@ The easiest way to use Jazz with Next.JS is to only use it on the client side. Y
- marking any file with components where you use Jazz hooks (such as `useAccount` or `useCoState`) as `"use client"`
## <span id="next-ssr">SSR use (experimental)</span>
## SSR use (experimental)
Pure SSR use of Jazz is basically just using jazz-nodejs (see [Node.JS / Server Workers](/docs/project-setup/server-side)) inside Server Components.
@@ -51,7 +51,7 @@ This should work well for cases like rendering publicly-readable information, si
In the future, it will be possible to use trusted auth methods (such as Clerk, Auth0, etc.) that let you act as the same Jazz user both on the client and on the server, letting you use SSR even for data private to that user.
## <span id="next-ssr-plus-csr">SSR + client-side (experimental)</span>
## SSR + client-side (experimental)
You can combine the two approaches by creating

View File

@@ -1,6 +1,6 @@
import { CodeGroup } from "@/components/forMdx";
# <span id="react-native">React Native</span>
# React Native
Jazz requires an [Expo development build](https://docs.expo.dev/develop/development-builds/introduction/) using [Expo Prebuild](https://docs.expo.dev/workflow/prebuild/) for native code. It is **not compatible** with Expo Go. Jazz also supports the [New Architecture](https://docs.expo.dev/guides/new-architecture/).
@@ -14,7 +14,7 @@ Tested with:
```
</CodeGroup>
## <span id="react-native-setup">Setup</span>
## Setup
### Create a New Project
@@ -102,16 +102,16 @@ For monorepos, use the following metro.config.js:
config.watchFolders = [workspaceRoot];
config.resolver.nodeModulesPaths = [
path.resolve(projectRoot, "node_modules"),
path.resolve(workspaceRoot, "node_modules"),
path.resolve(projectRoot, "node_modules"),
path.resolve(workspaceRoot, "node_modules"),
];
config.resolver.sourceExts = ["mjs", "js", "json", "ts", "tsx"];
config.resolver.unstable_enablePackageExports = true;
config.resolver.requireCycleIgnorePatterns = [/(^|\/|\\)node_modules($|\/|\\)/];
config.cacheStores = [
new FileStore({
root: path.join(projectRoot, "node_modules", ".cache", "metro"),
}),
new FileStore({
root: path.join(projectRoot, "node_modules", ".cache", "metro"),
}),
];
module.exports = config;
@@ -126,38 +126,19 @@ For monorepos, use the following metro.config.js:
<CodeGroup>
```json
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"@babel/*",
"expo-modules-*",
"typescript"
]
}
}
"peerDependencyRules": {
"ignoreMissing": [
"@babel/*",
"expo-modules-*",
"typescript"
]
}
}
```
</CodeGroup>
For more information, refer to [this](https://github.com/byCedric/expo-monorepo-example#pnpm-workarounds) Expo monorepo example.
### Configure Babel
Add `@babel/plugin-transform-class-static-block` to the array of Babel plugins inside `babel.config.js`:
<CodeGroup>
```ts
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: [
"nativewind/babel",
"@babel/plugin-transform-class-static-block",
],
};
};
```
</CodeGroup>
### Add Polyfills
Create a file `polyfills.js` at the project root with the following content:
@@ -205,7 +186,7 @@ Lastly, ensure that the `"main"` field in your `package.json` points to `index.j
```
</CodeGroup>
## <span id="react-native-using-jazz">Using Jazz</span>
## Using Jazz
### `createJazzRNApp()`
@@ -247,9 +228,9 @@ To work with images in Jazz, import the `createImage` function from [`jazz-react
const base64ImageDataURI = "data:image/png;base64,...";
const image = await createImage(base64ImageDataURI, {
owner: newPetPost._owner,
maxSize: 2048, // optional: specify maximum image size
});
owner: newPetPost._owner,
maxSize: 2048, // optional: specify maximum image size
});
someCovalue.image = image;
```

View File

@@ -55,7 +55,7 @@ Currently, the recommended pattern to set up a React app with Jazz is to create
<>
<Jazz.Provider
auth={passkeyAuth}
peer="wss://mesh.jazz.tools/?key=you@example.com"
peer="wss://cloud.jazz.tools/?key=you@example.com"
>
{children}
</Jazz.Provider>

View File

@@ -0,0 +1,262 @@
import { CodeGroup } from "@/components/forMdx";
# VueJS Demo Todo App Guide
This guide provides step-by-step instructions for setting up and running a Jazz-powered Todo application using VueJS.
See the full example [here](https://github.com/gardencmp/jazz/tree/main/examples/todo-vue).
---
## Setup
### Create a New App
Run the following command to create a new VueJS application:
<CodeGroup>
```bash
pnpm create vue@latest
✔ Project name: … vue-setup-guide
✔ Add TypeScript? … Yes
✔ Add JSX Support? … No
✔ Add Vue Router for Single Page Application development? … Yes
✔ Add Pinia for state management? … No
✔ Add Vitest for Unit Testing? … No
✔ Add an End-to-End Testing Solution? No
✔ Add ESLint for code quality? Yes
✔ Add Prettier for code formatting? … Yes
```
</CodeGroup>
### Install Dependencies
Run the following command to install Jazz libraries:
<CodeGroup>
```bash
pnpm install jazz-tools jazz-browser jazz-vue
```
</CodeGroup>
### Implement `schema.ts`
Define the schema for your application.
Example schema inside `src/schema.ts` for a todo app:
<CodeGroup>
```typescript
import { Account, CoList, CoMap, Group, Profile, co } from "jazz-tools";
export class ToDoItem extends CoMap {
name = co.string;
completed = co.boolean;
}
export class ToDoList extends CoList.Of(co.ref(ToDoItem)) {}
export class Folder extends CoMap {
name = co.string;
items = co.ref(ToDoList);
}
export class FolderList extends CoList.Of(co.ref(Folder)) {}
export class ToDoAccountRoot extends CoMap {
folders = co.ref(FolderList);
}
export class ToDoAccount extends Account {
profile = co.ref(Profile);
root = co.ref(ToDoAccountRoot);
migrate(this: ToDoAccount, creationProps?: { name: string }) {
super.migrate(creationProps);
if (!this._refs.root) {
const group = Group.create({ owner: this });
const firstFolder = Folder.create(
{
name: "Default",
items: ToDoList.create([], { owner: group }),
},
{ owner: group },
);
this.root = ToDoAccountRoot.create(
{
folders: FolderList.create([firstFolder], {
owner: this,
}),
},
{ owner: this },
);
}
}
}
```
</CodeGroup>
### Refactor `main.ts`
Update the `src/main.ts` file to integrate Jazz:
<CodeGroup>
```typescript
import "./assets/main.css";
import { DemoAuthBasicUI, createJazzVueApp, useDemoAuth } from "jazz-vue";
import { createApp, defineComponent, h } from "vue";
import App from "./App.vue";
import router from "./router";
import { ToDoAccount } from "./schema";
const Jazz = createJazzVueApp<ToDoAccount>({ AccountSchema: ToDoAccount });
export const { useAccount, useCoState } = Jazz;
const { JazzProvider } = Jazz;
const RootComponent = defineComponent({
name: "RootComponent",
setup() {
const { authMethod, state } = useDemoAuth();
return () => [
h(
JazzProvider,
{
auth: authMethod.value,
peer: "wss://mesh.jazz.tools/?key=vue-todo-example-jazz@gcmp.io",
},
{
default: () => h(App),
},
),
state.state !== "signedIn" &&
h(DemoAuthBasicUI, {
appName: "Jazz Vue Todo",
state,
}),
];
},
});
const app = createApp(RootComponent);
app.use(router);
app.mount("#app");
```
</CodeGroup>
### Set up `router/index.ts`:
Create a basic Vue router configuration. For example:
<CodeGroup>
```typescript
import { createRouter, createWebHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/",
name: "Home",
component: HomeView,
},
],
});
export default router;
```
</CodeGroup>
### Implement `App.vue`
Update the `App.vue` file to include logout functionality:
<CodeGroup>
```typescript
<template>
<div class="app-container">
<header v-if="me" class="app-header">
<h1>Todo App</h1>
<div class="user-section">
<span>{{ me.profile?.name }}</span>
<button class="logout-btn" @click="logOut">Log out</button>
</div>
</header>
<main>
<router-view />
</main>
</div>
</template>
<script setup lang="ts">
import { useAccount } from "./main";
const { me, logOut } = useAccount();
</script>
```
</CodeGroup>
## Subscribing to a CoValue
Subscribe to a CoValue inside `src/views/HomeView.vue`:
<CodeGroup>
```typescript
<script setup lang="ts">
import { Group, type ID } from "jazz-tools";
import { ref, toRaw, watch } from "vue";
import { computed } from "vue";
import { useAccount, useCoState } from "../main";
import { Folder, FolderList, ToDoItem, ToDoList } from "../schema";
const { me } = useAccount();
// Computed ID for the folders list
const computedFoldersId = computed(() => me.value?.root?.folders?.id);
// Load folders and nested values
const folders = useCoState(FolderList, computedFoldersId, [{ items: [{}] }]);
```
</CodeGroup>
See the full example [here](https://github.com/gardencmp/jazz/tree/main/examples/todo-vue).
## Mutating a CoValue
Here's how to create a new folder:
<CodeGroup>
```typescript
// continues previous example
const createFolder = async (name: string) => {
// Create a group owned by the current user
const group = Group.create({ owner: me.value });
// Create the folder
const newFolder = Folder.create(
{
name,
items: ToDoList.create([], { owner: group }),
},
{ owner: group },
);
// Add the folder to the list of folders.
// This change is sent to all connected clients and will be synced in real time.
folders.value?.push(newFolder);
newFolderName.value = "";
};
```
</CodeGroup>
See the full example [here](https://github.com/gardencmp/jazz/tree/main/examples/todo-vue).

View File

@@ -9,7 +9,7 @@ Jazz Cloud will
- safely persist CoValues on redundant storage nodes with additional backups
- make use of geographically distributed cache nodes for low latency
### Free Public Alpha <a id="free-public-alpha"/>
### Free Public Alpha
- Jazz Cloud is free during the public alpha, with no strict usage limits
- We plan to keep a free tier, so you'll always be able to get started with zero setup
@@ -23,7 +23,7 @@ Jazz Cloud will
Once we support per-app API keys, we'll email you an API key you can use instead.
## Running your own sync server <a id="running-your-own"/>
## Running your own sync server
You can run your own sync server using:
@@ -36,12 +36,12 @@ And then use `ws://localhost:4200` as the sync server URL.
You can also run this simple sync server behind a proxy that supports WebSockets, for example to provide TLS.
In this case, provide the WebSocket endpoint your proxy exposes as the sync server URL.
### Command line options: <a id="command-line-options"/>
### Command line options:
- `--port` / `-p` - the port to run the sync server on. Defaults to 4200.
- `--in-memory` - keep CoValues in-memory only and do sync only, no persistence. Persistence is enabled by default.
- `--db` - the path to the file where to store the data (SQLite). Defaults to `sync-db/storage.db`.
### Source code <a id="source-code"/>
### Source code
The implementation of this simple sync server is available open-source [on GitHub](https://github.com/gardencmp/jazz/blob/main/packages/jazz-run/src/startSync.ts).
The implementation of this simple sync server is available open-source [on GitHub](https://github.com/gardencmp/jazz/blob/main/packages/jazz-run/src/startSync.ts).

View File

@@ -1,89 +0,0 @@
import { TableOfContents } from "@/components/docs/TableOfContents";
import { clsx } from "clsx";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
import Guide from "./guide.mdx";
const navItems = [
{
name: "Project Setup",
href: "/docs/guide#project-setup",
},
{
name: "Intro to CoValues",
href: "/docs/guide#intro-to-covalues",
items: [
{
name: "Declaration",
href: "/docs/guide#declaring-covalues",
},
{
name: "Reading",
href: "/docs/guide#reading-covalues",
},
{
name: "Creation",
href: "/docs/guide#creating-covalues",
},
{
name: "Editing & Subscription",
href: "/docs/guide#editing-and-subscription",
},
{
name: "Persistence",
href: "/docs/guide#persistence",
},
{
name: "Remote Sync",
href: "/docs/guide#remote-sync",
},
{
name: "Simple Public Sharing",
href: "/docs/guide#simple-public-sharing",
},
],
},
{
name: "Refs & Auto-Subscribe",
href: "/docs/guide#refs-and-on-demand-subscribe",
items: [
{
name: "Precise Loading Depths",
href: "/docs/guide#loading-depth",
},
],
},
{
name: "Groups & Permissions",
href: "/docs/guide#groups-and-permissions",
items: [
{
name: "Groups/Accounts as Scopes",
href: "/docs/guide#groups-accounts-as-scopes",
},
{
name: "Creating Invites",
href: "/docs/guide#creating-invites",
},
{
name: "Consuming Invites",
href: "/docs/guide#consuming-invites",
},
],
},
];
export default function Page() {
return (
<div
className={clsx(
"col-span-12 md:col-span-8 lg:col-span-9",
"flex justify-center lg:gap-5",
)}
>
<Prose className="overflow-x-hidden lg:flex-1">
<Guide />
</Prose>
<TableOfContents className="w-48 shrink-0" items={navItems} />
</div>
);
}

View File

@@ -1,4 +1,5 @@
import { DocNav } from "@/components/docs/nav";
import { clsx } from "clsx";
export const metadata = {
title: "Docs",
@@ -11,9 +12,16 @@ export default function DocsLayout({
children: React.ReactNode;
}) {
return (
<div className="container relative grid grid-cols-12 gap-5 py-8">
<DocNav />
{children}
<div className="container relative grid grid-cols-12 gap-5">
<DocNav className="py-6" />
<div
className={clsx(
"col-span-12 md:col-span-8 lg:col-span-9",
"flex justify-center lg:gap-5",
)}
>
{children}
</div>
</div>
);
}

View File

@@ -1,35 +0,0 @@
import { TableOfContents } from "@/components/docs/TableOfContents";
import { clsx } from "clsx";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
import NextGuide from "./next.mdx";
const navItems = [
{
name: "Client-side only",
href: "/docs/project-setup/react#next-csr",
},
{
name: "SSR use 🧪",
href: "/docs/project-setup/react#next-ssr",
},
{
name: "SSR + client-side 🧪",
href: "/docs/project-setup/react#next-ssr-plus-csr",
},
];
export default function Page() {
return (
<div
className={clsx(
"col-span-12 md:col-span-8 lg:col-span-9",
"flex justify-center lg:gap-5",
)}
>
<Prose className="overflow-x-hidden lg:flex-1">
<NextGuide />
</Prose>
<TableOfContents className="w-48 shrink-0" items={navItems} />
</div>
);
}

View File

@@ -1,30 +0,0 @@
import { TableOfContents } from "@/components/docs/TableOfContents";
import { clsx } from "clsx";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
import ReactNativeGuide from "./react-native.mdx";
const navItems = [
{
name: "Setup",
href: "/docs/project-setup/react#react-native-setup",
},
{
name: "Using Jazz",
href: "/docs/project-setup/react#react-native-using-jazz",
},
];
export default function Page() {
return (
<div
className={clsx(
"col-span-12 md:col-span-8 lg:col-span-9",
"flex justify-center lg:gap-5",
)}
>
<Prose className="overflow-x-hidden lg:flex-1">
<ReactNativeGuide />
</Prose>
<TableOfContents className="w-48 shrink-0" items={navItems} />
</div>
);
}

View File

@@ -1,18 +0,0 @@
import { clsx } from "clsx";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
import ReactGuide from "./react.mdx";
export default function Page() {
return (
<div
className={clsx(
"col-span-12 md:col-span-8 lg:col-span-9",
"flex justify-center lg:gap-5",
)}
>
<Prose className="overflow-x-hidden lg:flex-1">
<ReactGuide />
</Prose>
</div>
);
}

View File

@@ -1,39 +0,0 @@
import { TableOfContents } from "@/components/docs/TableOfContents";
import { clsx } from "clsx";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
import ServerGuide from "./server-side.mdx";
const navItems = [
{
name: "Generating Credentials",
href: "/docs/project-setup/server-side#generating-credentials",
},
{
name: "Storing and Providing Credentials",
href: "/docs/project-setup/server-side#storing-credentials",
},
{
name: "Starting a Server Worker",
href: "/docs/project-setup/server-side#starting",
},
{
name: "Using CoValues instead of Requests",
href: "/docs/project-setup/server-side#covalues-instead-of-requests",
},
];
export default function Page() {
return (
<div
className={clsx(
"col-span-12 md:col-span-8 lg:col-span-9",
"flex justify-center lg:gap-5",
)}
>
<Prose className="overflow-x-hidden lg:flex-1">
<ServerGuide />
</Prose>
<TableOfContents className="w-48 shrink-0" items={navItems} />
</div>
);
}

View File

@@ -1,75 +0,0 @@
import { TableOfContents } from "@/components/docs/TableOfContents";
import { clsx } from "clsx";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
import CoValuesGuide from "./covalues.mdx";
const navItems = [
{
name: "CoValues",
href: "/docs/schemas/covalues",
},
{
name: "Schemas as Your App's First Step",
href: "/docs/schemas/covalues#schemas-as-first-step",
},
{
name: "CoValue field types",
href: "/docs/schemas/covalues#field-types",
items: [
{
name: "Primitive Fields",
href: "/docs/schemas/covalues#primitive-fields",
},
{
name: "Refs",
href: "/docs/schemas/covalues#refs",
},
{
name: "Computed Fields, Methods & Constructors ",
href: "/docs/schemas/covalues#custom-fields",
},
],
},
{
name: "CoMaps",
href: "/docs/schemas/covalues#comaps",
items: [
{
name: "Struct-like CoMaps",
href: "/docs/schemas/covalues#comaps-struct-like",
},
{
name: "Dict/Record-like CoMaps",
href: "/docs/schemas/covalues#comaps-dict-like",
},
],
},
{
name: "CoLists",
href: "/docs/schemas/covalues#colists",
},
{
name: "CoStreams",
href: "/docs/schemas/covalues#costreams",
},
{
name: "BinaryCoStreams",
href: "/docs/schemas/covalues#binarycostreams",
},
];
export default function Page() {
return (
<div
className={clsx(
"col-span-12 md:col-span-8 lg:col-span-9",
"flex justify-center lg:gap-5",
)}
>
<Prose className="overflow-x-hidden lg:flex-1">
<CoValuesGuide />
</Prose>
<TableOfContents className="w-48 shrink-0" items={navItems} />
</div>
);
}

View File

@@ -1,47 +0,0 @@
import { TableOfContents } from "@/components/docs/TableOfContents";
import { clsx } from "clsx";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
import SyncAndStorage from "./sync-and-storage.mdx";
const navItems = [
{
name: "Using Jazz Cloud",
href: "/docs/sync-and-storage#using-jazz-cloud",
items: [
{
name: "Free Public Alpha",
href: "/docs/sync-and-storage#free-public-alpha",
},
],
},
{
name: "Running your own sync server",
href: "/docs/sync-and-storage#running-your-own",
items: [
{
name: "Command line options",
href: "/docs/sync-and-storage#command-line-options",
},
{
name: "Source code",
href: "/docs/sync-and-storage#source-code",
},
],
},
];
export default function Page() {
return (
<div
className={clsx(
"col-span-12 md:col-span-8 lg:col-span-9",
"flex justify-center lg:gap-5",
)}
>
<Prose className="overflow-x-hidden lg:flex-1">
<SyncAndStorage />
</Prose>
<TableOfContents className="w-48 shrink-0" items={navItems} />
</div>
);
}

View File

@@ -3,7 +3,9 @@ import { NextjsLogo } from "@/components/icons/NextjsLogo";
import { ReactLogo } from "@/components/icons/ReactLogo";
import { ReactNativeLogo } from "@/components/icons/ReactNativeLogo";
import { Button } from "gcmp-design-system/src/app/components/atoms/Button";
import { H2 } from "gcmp-design-system/src/app/components/atoms/Headings";
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
import { HeroHeader } from "gcmp-design-system/src/app/components/molecules/HeroHeader";
import { CloudUploadIcon, FingerprintIcon, KeyRoundIcon } from "lucide-react";
type Example = {
@@ -55,21 +57,21 @@ const ClerkIllustration = () => (
const MusicIllustration = () => (
<div className="flex flex-col items-center justify-center h-full p-8">
<div className="py-3 px-4 border border-dashed border-blue dark:border-blue-500 rounded-lg flex gap-2 flex-col items-center">
<div className="py-3 px-8 border border-dashed border-blue dark:border-blue-500 rounded-lg flex gap-2 flex-col items-center">
<CloudUploadIcon
size={30}
size={40}
strokeWidth={1.5}
className="stroke-blue mx-auto dark:stroke-blue-500"
/>
<p className="whitespace-nowrap text-xs text-stone-900 dark:text-white">
tortured-poets-department.mp3
<p className="whitespace-nowrap text-stone-900 dark:text-white">
take-five.mp3
</p>
</div>
</div>
);
const BookShelfIllustration = () => (
<div className="h-full p-6 md:p-5">
<div className="h-full max-w-[30rem] mx-auto flex flex-col justify-center p-6 md:p-5">
<div className="flex justify-between items-baseline">
<p className="font-display font-medium tracking-tight text-sm text-stone-900 dark:text-white">
Your book shelf
@@ -80,7 +82,7 @@ const BookShelfIllustration = () => (
</p>
</div>
<div className="relative grid grid-cols-3 gap-4 mt-3">
<div className="grid grid-cols-3 gap-4 mt-3">
{["malibu.jpg", "pathless.jpg", "upgrade.jpg"].map((book) => (
<img
key={book}
@@ -89,8 +91,6 @@ const BookShelfIllustration = () => (
className="w-full h-full object-cover rounded-r-md shadow-sm border dark:border-none"
/>
))}
<div className="absolute bottom-0 w-full h-10 bg-gradient-to-t from-white dark:from-stone-925 to-transparent md:hidden" />
</div>
</div>
);
@@ -239,7 +239,7 @@ function Example({ example }: { example: Example }) {
const githubUrl = `https://github.com/gardencmp/jazz/tree/main/examples/${slug}`;
return (
<div className="border bg-stone-50 shadow-sm p-3 flex flex-col gap-3 rounded-lg md:gap-4 dark:bg-stone-950">
<div className="col-span-2 border bg-stone-50 shadow-sm p-3 flex flex-col gap-3 rounded-lg md:gap-4 dark:bg-stone-950">
<div className="aspect-[16/9] overflow-hidden w-full rounded-md bg-white border dark:bg-stone-925 sm:aspect-[2/1] md:aspect-[3/2]">
{illustration}
</div>
@@ -284,22 +284,28 @@ function Example({ example }: { example: Example }) {
export default function Page() {
return (
<>
<h1>Example Apps</h1>
{categories.map((category) => (
<div className="my-12" key={category.name}>
<div className="flex items-center gap-3 mb-5">
<category.logo className="h-8 w-8" />
<h2 className="my-0">{category.name}</h2>
</div>
<div className="container flex flex-col gap-6 pb-10 lg:pb-20">
<HeroHeader
title="Example apps"
slogan="Find an example app with code most similar to what you want to build"
/>
<div className="not-prose grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3 gap-4 lg:gap-8">
{category.examples.map((example) => (
<Example key={example.slug} example={example} />
))}
<div className="grid gap-12 lg:gap-20">
{categories.map((category) => (
<div key={category.name}>
<div className="flex items-center gap-3 mb-5">
<category.logo className="h-8 w-8" />
<H2 className="!mb-0">{category.name}</H2>
</div>
<GappedGrid>
{category.examples.map((example) => (
<Example key={example.slug} example={example} />
))}
</GappedGrid>
</div>
</div>
))}
</>
))}
</div>
</div>
);
}

View File

@@ -8,6 +8,7 @@ import { JazzFooter } from "@/components/footer";
import { JazzNav } from "@/components/nav";
import { Analytics } from "@vercel/analytics/react";
import { SpeedInsights } from "@vercel/speed-insights/next";
import { clsx } from "clsx";
import { ThemeProvider } from "gcmp-design-system/src/app/components/molecules/ThemeProvider";
// If loading a variable font, you don't need to specify the font weight
@@ -95,8 +96,10 @@ export default function RootLayout({
enableSystem
disableTransitionOnChange
>
<JazzNav />
<main className="flex-1 w-full">{children}</main>
<div className="flex-1 w-full">
<JazzNav />
<main>{children}</main>
</div>
<JazzFooter />
</ThemeProvider>
</body>

View File

@@ -1,16 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "stone",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}

View File

@@ -27,9 +27,9 @@ export function SideNavItem({
className={clsx(
classes,
href &&
"hover:text-black dark:hover:text-stone-200 transition-colors hover:transition-none",
"hover:text-stone-900 dark:hover:text-stone-200 transition-colors hover:transition-none",
{
"text-black": path === href,
"text-stone-900 dark:text-white": path === href,
},
)}
>

View File

@@ -1,17 +1,25 @@
import type { Toc, TocEntry } from "@stefanprobst/rehype-extract-toc";
import { clsx } from "clsx";
import Link from "next/link";
interface NavItem {
name: string;
href: string;
items?: NavItem[];
}
const TocList = ({ items }: { items: TocEntry[] }) => {
return (
<ul className="list-disc pl-4 space-y-2">
{items.map((item) => (
<li key={item.id} className="space-y-2">
<Link href={`#${item.id}`}>{item.value}</Link>
{item.children && <TocList items={item.children} />}
</li>
))}
</ul>
);
};
export function TableOfContents({
className,
items,
}: {
items: NavItem[];
items: Toc;
className?: string;
}) {
if (!items.length) return null;
@@ -19,27 +27,12 @@ export function TableOfContents({
return (
<div
className={clsx(
"pl-3 sticky align-start top-[4.75rem] h-[calc(100vh-8rem)] overflow-y-auto overflow-x-hidden hidden md:block",
"pl-3 py-6 text-sm sticky align-start top-[4.75rem] w-[16rem] h-[calc(100vh-108px)] overflow-y-auto overflow-x-hidden hidden lg:block",
className,
)}
>
<p className="mb-3">On this page:</p>
<ul className="space-y-2 text-sm list-disc pl-4">
{items.map(({ name, href, items }) => (
<li key={name} className="space-y-2">
<Link href={href}>{name}</Link>
{items && items?.length > 0 && (
<ul className="list-disc pl-4 space-y-2">
{items.map(({ name, href }) => (
<li key={href}>
<Link href={href}>{name}</Link>
</li>
))}
</ul>
)}
</li>
))}
</ul>
<TocList items={items} />
</div>
);
}

View File

@@ -16,7 +16,7 @@ export function DocNav({ className }: { className?: string }) {
className={clsx(
twMerge(
"pr-3 md:col-span-4 lg:col-span-3",
"sticky align-start top-[4.75rem] h-[calc(100vh-8rem)] overflow-y-auto overflow-x-hidden",
"sticky align-start top-[4.75rem] h-[calc(100vh-108px)] overflow-y-auto overflow-x-hidden",
"hidden md:block",
className,
),

View File

@@ -30,7 +30,7 @@ export function JazzFooter() {
},
{
href: "https://x.com/jazz_tools",
label: "Twitter",
label: "X",
newTab: true,
},
],
@@ -48,11 +48,6 @@ export function JazzFooter() {
label: "Releases",
newTab: true,
},
{
href: "https://github.com/orgs/gardencmp/projects/4/views/3",
label: "Roadmap",
newTab: true,
},
],
},
]}

View File

@@ -1,18 +1,57 @@
import { SiDiscord, SiGithub, SiTwitter } from "@icons-pack/react-simple-icons";
import { SiDiscord, SiGithub, SiX } from "@icons-pack/react-simple-icons";
import { Button } from "gcmp-design-system/src/app/components/atoms/Button";
import { JazzLogo } from "gcmp-design-system/src/app/components/atoms/logos/JazzLogo";
import { Nav } from "gcmp-design-system/src/app/components/organisms/Nav";
import { BookTextIcon, BoxIcon, CodeIcon } from "lucide-react";
import { DocNav } from "./docs/nav";
export function JazzNav() {
return (
<Nav
mainLogo={<JazzLogo className="w-24 -ml-2" />}
mainLogo={<JazzLogo className="w-24" />}
items={[
{ title: "Home", href: "/" },
{ title: "Jazz Cloud", href: "/cloud" },
{
title: "Docs",
title: "Documentation",
href: "/docs",
items: [
{
icon: (
<BookTextIcon
className="size-5 stroke-blue dark:stroke-blue-500 shrink-0"
strokeWidth={1.5}
/>
),
title: "Documentation",
href: "/docs",
description:
"Get started with using Jazz by learning the core concepts, and going through guides.",
},
{
icon: (
<BoxIcon
className="size-5 stroke-blue dark:stroke-blue-500 shrink-0"
strokeWidth={1.5}
/>
),
title: "API reference",
href: "/docs/api-reference",
description:
"API references for packages like jazz-tools, jazz-react, and more.",
},
{
icon: (
<CodeIcon
className="size-5 stroke-blue dark:stroke-blue-500 shrink-0"
strokeWidth={1.5}
/>
),
title: "Example apps",
href: "/examples",
description:
"Demo and source code for example apps built with Jazz.",
},
],
},
{
title: "Built with Jazz",
@@ -45,7 +84,7 @@ export function JazzNav() {
title: "X",
href: "https://x.com/jazz_tools",
newTab: true,
icon: <SiTwitter className="w-5" />,
icon: <SiX className="w-5" />,
},
]}
docNav={<DocNav className="block h-auto" />}

View File

@@ -43,6 +43,11 @@ export const docNavigationItems = [
href: "/docs/project-setup/server-side",
done: 80,
},
{
name: "VueJS",
href: "/docs/project-setup/vue",
done: 80,
},
],
},
{
@@ -125,7 +130,7 @@ export const docNavigationItems = [
items: [
{
name: "Example apps",
href: "/docs/examples",
href: "/examples",
done: 30,
},
{

View File

@@ -1,4 +1,7 @@
import createMDX from "@next/mdx";
import withToc from "@stefanprobst/rehype-extract-toc";
import withTocExport from "@stefanprobst/rehype-extract-toc/mdx";
import rehypeSlug from "rehype-slug";
import { getHighlighter } from "shiki";
import { SKIP, visit } from "unist-util-visit";
@@ -17,7 +20,7 @@ const withMDX = createMDX({
// Add markdown plugins here, as desired
options: {
remarkPlugins: [highlightPlugin, remarkHtmlToJsx],
rehypePlugins: [],
rehypePlugins: [rehypeSlug, withToc, withTocExport],
},
});

View File

@@ -12,10 +12,12 @@
},
"packageManager": "pnpm@9.1.4",
"dependencies": {
"@headlessui/react": "^2.2.0",
"@icons-pack/react-simple-icons": "^9.1.0",
"@mdx-js/loader": "^2.3.0",
"@mdx-js/react": "^2.3.0",
"@next/mdx": "^13.5.4",
"@stefanprobst/rehype-extract-toc": "^2.2.0",
"@types/mdx": "^2.0.8",
"@vercel/analytics": "^1.3.1",
"@vercel/speed-insights": "^1.0.12",
@@ -28,6 +30,7 @@
"next": "13.5.4",
"react": "^18",
"react-dom": "^18",
"rehype-slug": "^6.0.0",
"shiki": "^0.14.6",
"shiki-twoslash": "^3.1.2",
"tailwind-merge": "^1.14.0",

View File

@@ -22,6 +22,12 @@
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"mdx.d.ts"
],
"exclude": ["node_modules"]
}

238
homepage/pnpm-lock.yaml generated
View File

@@ -11,6 +11,9 @@ importers:
'@evilmartians/harmony':
specifier: ^1.0.0
version: 1.2.0
'@headlessui/react':
specifier: ^2.2.0
version: 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
class-variance-authority:
specifier: ^0.7.0
version: 0.7.0
@@ -166,6 +169,9 @@ importers:
homepage:
dependencies:
'@headlessui/react':
specifier: ^2.2.0
version: 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@icons-pack/react-simple-icons':
specifier: ^9.1.0
version: 9.4.1(react@18.3.1)
@@ -178,6 +184,9 @@ importers:
'@next/mdx':
specifier: ^13.5.4
version: 13.5.6(@mdx-js/loader@2.3.0(webpack@5.91.0))(@mdx-js/react@2.3.0(react@18.3.1))
'@stefanprobst/rehype-extract-toc':
specifier: ^2.2.0
version: 2.2.0
'@types/mdx':
specifier: ^2.0.8
version: 2.0.13
@@ -214,6 +223,9 @@ importers:
react-dom:
specifier: ^18
version: 18.3.1(react@18.3.1)
rehype-slug:
specifier: ^6.0.0
version: 6.0.0
shiki:
specifier: ^0.14.6
version: 0.14.7
@@ -366,6 +378,34 @@ packages:
'@evilmartians/harmony@1.2.0':
resolution: {integrity: sha512-Ua8gpC+28Eo9D2/xynTrrZIrSawgtobwtRLLYq4wH8N19qoMspWZ1vqfsDDVPgQFa+iHsVAk/SbdmoPAj6OH1g==}
'@floating-ui/core@1.6.8':
resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==}
'@floating-ui/dom@1.6.12':
resolution: {integrity: sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==}
'@floating-ui/react-dom@2.1.2':
resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
'@floating-ui/react@0.26.27':
resolution: {integrity: sha512-jLP72x0Kr2CgY6eTYi/ra3VA9LOkTo4C+DUTrbFgFOExKy3omYVmwMjNKqxAHdsnyLS96BIDLcO2SlnsNf8KUQ==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
'@floating-ui/utils@0.2.8':
resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==}
'@headlessui/react@2.2.0':
resolution: {integrity: sha512-RzCEg+LXsuI7mHiSomsu/gBJSjpupm6A1qIZ5sWjd7JhARNlMiSA4kKfJpCKwU9tE+zMRterhhrP74PvfJrpXQ==}
engines: {node: '>=10'}
peerDependencies:
react: ^18 || ^19 || ^19.0.0-rc
react-dom: ^18 || ^19 || ^19.0.0-rc
'@icons-pack/react-simple-icons@9.4.1':
resolution: {integrity: sha512-oDX8iE/AOyRIY0ys56+eybKSsyZODHQIPZ5mAGVxx3TszkA5l8lIxKl8HI9F801Y1CJxcySBjIk1XibrnFF0Hw==}
peerDependencies:
@@ -610,6 +650,27 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
'@react-aria/focus@3.18.4':
resolution: {integrity: sha512-91J35077w9UNaMK1cpMUEFRkNNz0uZjnSwiyBCFuRdaVuivO53wNC9XtWSDNDdcO5cGy87vfJRVAiyoCn/mjqA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@react-aria/interactions@3.22.4':
resolution: {integrity: sha512-E0vsgtpItmknq/MJELqYJwib+YN18Qag8nroqwjk1qOnBa9ROIkUhWJerLi1qs5diXq9LHKehZDXRlwPvdEFww==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@react-aria/ssr@3.9.6':
resolution: {integrity: sha512-iLo82l82ilMiVGy342SELjshuWottlb5+VefO3jOQqQRNYnJBFpUSadswDPbRimSgJUZuFwIEYs6AabkP038fA==}
engines: {node: '>= 12'}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@react-aria/utils@3.25.3':
resolution: {integrity: sha512-PR5H/2vaD8fSq0H/UB9inNbc8KDcVmW6fYAfSWkkn+OAdhTTMVKqXXrZuZBWyFfSD5Ze7VN6acr4hrOQm2bmrA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@react-email/render@0.0.17':
resolution: {integrity: sha512-xBQ+/73+WsGuXKY7r1U73zMBNV28xdV0cp9cFjhNYipBReDHhV97IpA6v7Hl0dDtDzt+yS/72dY5vYXrF1v8NA==}
engines: {node: '>=18.0.0'}
@@ -617,9 +678,23 @@ packages:
react: ^18.2.0
react-dom: ^18.2.0
'@react-stately/utils@3.10.4':
resolution: {integrity: sha512-gBEQEIMRh5f60KCm7QKQ2WfvhB2gLUr9b72sqUdIZ2EG+xuPgaIlCBeSicvjmjBvYZwOjoOEnmIkcx2GHp/HWw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@react-types/shared@3.25.0':
resolution: {integrity: sha512-OZSyhzU6vTdW3eV/mz5i6hQwQUhkRs7xwY2d1aqPvTdMe0+2cY7Fwp45PAiwYLEj73i9ro2FxF9qC4DvHGSCgQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@selderee/plugin-htmlparser2@0.11.0':
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
'@stefanprobst/rehype-extract-toc@2.2.0':
resolution: {integrity: sha512-/4UjstX8ploZklY8MmlOQoXB1jWIo3Go4MP0R39sbkoWuN6rJ7Zt6l4bjkDPM4hKsjoODh9SSKn2otlp3XL3/A==}
engines: {node: '>=14.17'}
'@swc/counter@0.1.3':
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
@@ -634,6 +709,15 @@ packages:
peerDependencies:
tailwindcss: '>=3.0.0 || insiders'
'@tanstack/react-virtual@3.10.8':
resolution: {integrity: sha512-VbzbVGSsZlQktyLrP5nxE+vE1ZR+U0NFAWPbJLoG2+DKPwd2D7dVICTVIIaYlJqX1ZCEnYDbaOpmMwbsyhBoIA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
'@tanstack/virtual-core@3.10.8':
resolution: {integrity: sha512-PBu00mtt95jbKFi6Llk9aik8bnR3tR/oQP1o3TSi+iG//+Q2RTIzCEgKkHG8BB86kxMNW6O8wku+Lmi+QFR6jA==}
'@types/acorn@4.0.6':
resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==}
@@ -791,6 +875,7 @@ packages:
acorn-import-assertions@1.9.0:
resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==}
deprecated: package has been renamed to acorn-import-attributes
peerDependencies:
acorn: ^8
@@ -1070,6 +1155,10 @@ packages:
estree-util-to-js@1.2.0:
resolution: {integrity: sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==}
estree-util-value-to-estree@1.3.0:
resolution: {integrity: sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==}
engines: {node: '>=12.0.0'}
estree-util-visit@1.2.1:
resolution: {integrity: sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==}
@@ -1125,6 +1214,9 @@ packages:
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
github-slugger@2.0.0:
resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==}
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -1152,9 +1244,21 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
hast-util-heading-rank@2.1.1:
resolution: {integrity: sha512-iAuRp+ESgJoRFJbSyaqsfvJDY6zzmFoEnL1gtz1+U8gKtGGj1p0CVlysuUAUjq95qlZESHINLThwJzNGmgGZxA==}
hast-util-heading-rank@3.0.0:
resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==}
hast-util-to-estree@2.3.3:
resolution: {integrity: sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==}
hast-util-to-string@2.0.0:
resolution: {integrity: sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A==}
hast-util-to-string@3.0.1:
resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==}
hast-util-whitespace@2.0.1:
resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==}
@@ -1210,6 +1314,10 @@ packages:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
is-plain-obj@3.0.0:
resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==}
engines: {node: '>=10'}
is-plain-obj@4.1.0:
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
engines: {node: '>=12'}
@@ -1791,6 +1899,9 @@ packages:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
rehype-slug@6.0.0:
resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==}
remark-mdx@2.3.0:
resolution: {integrity: sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==}
@@ -1936,6 +2047,9 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
tabbable@6.2.0:
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
tailwind-merge@1.14.0:
resolution: {integrity: sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==}
@@ -2214,6 +2328,40 @@ snapshots:
'@evilmartians/harmony@1.2.0': {}
'@floating-ui/core@1.6.8':
dependencies:
'@floating-ui/utils': 0.2.8
'@floating-ui/dom@1.6.12':
dependencies:
'@floating-ui/core': 1.6.8
'@floating-ui/utils': 0.2.8
'@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/dom': 1.6.12
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
'@floating-ui/react@0.26.27(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@floating-ui/utils': 0.2.8
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
tabbable: 6.2.0
'@floating-ui/utils@0.2.8': {}
'@headlessui/react@2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@floating-ui/react': 0.26.27(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@react-aria/focus': 3.18.4(react@18.3.1)
'@react-aria/interactions': 3.22.4(react@18.3.1)
'@tanstack/react-virtual': 3.10.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
'@icons-pack/react-simple-icons@9.4.1(react@18.3.1)':
dependencies:
react: 18.3.1
@@ -2396,6 +2544,37 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
'@react-aria/focus@3.18.4(react@18.3.1)':
dependencies:
'@react-aria/interactions': 3.22.4(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-types/shared': 3.25.0(react@18.3.1)
'@swc/helpers': 0.5.5
clsx: 2.1.1
react: 18.3.1
'@react-aria/interactions@3.22.4(react@18.3.1)':
dependencies:
'@react-aria/ssr': 3.9.6(react@18.3.1)
'@react-aria/utils': 3.25.3(react@18.3.1)
'@react-types/shared': 3.25.0(react@18.3.1)
'@swc/helpers': 0.5.5
react: 18.3.1
'@react-aria/ssr@3.9.6(react@18.3.1)':
dependencies:
'@swc/helpers': 0.5.5
react: 18.3.1
'@react-aria/utils@3.25.3(react@18.3.1)':
dependencies:
'@react-aria/ssr': 3.9.6(react@18.3.1)
'@react-stately/utils': 3.10.4(react@18.3.1)
'@react-types/shared': 3.25.0(react@18.3.1)
'@swc/helpers': 0.5.5
clsx: 2.1.1
react: 18.3.1
'@react-email/render@0.0.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
html-to-text: 9.0.5
@@ -2404,11 +2583,28 @@ snapshots:
react-dom: 18.3.1(react@18.3.1)
react-promise-suspense: 0.3.4
'@react-stately/utils@3.10.4(react@18.3.1)':
dependencies:
'@swc/helpers': 0.5.5
react: 18.3.1
'@react-types/shared@3.25.0(react@18.3.1)':
dependencies:
react: 18.3.1
'@selderee/plugin-htmlparser2@0.11.0':
dependencies:
domhandler: 5.0.3
selderee: 0.11.0
'@stefanprobst/rehype-extract-toc@2.2.0':
dependencies:
estree-util-is-identifier-name: 2.1.0
estree-util-value-to-estree: 1.3.0
hast-util-heading-rank: 2.1.1
hast-util-to-string: 2.0.0
unist-util-visit: 4.1.2
'@swc/counter@0.1.3': {}
'@swc/helpers@0.5.2':
@@ -2428,6 +2624,14 @@ snapshots:
postcss-selector-parser: 6.0.10
tailwindcss: 3.4.3
'@tanstack/react-virtual@3.10.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@tanstack/virtual-core': 3.10.8
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
'@tanstack/virtual-core@3.10.8': {}
'@types/acorn@4.0.6':
dependencies:
'@types/estree': 1.0.5
@@ -2866,6 +3070,10 @@ snapshots:
astring: 1.8.6
source-map: 0.7.4
estree-util-value-to-estree@1.3.0:
dependencies:
is-plain-obj: 3.0.0
estree-util-visit@1.2.1:
dependencies:
'@types/estree-jsx': 1.0.5
@@ -2920,6 +3128,8 @@ snapshots:
function-bind@1.1.2: {}
github-slugger@2.0.0: {}
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
@@ -2946,6 +3156,14 @@ snapshots:
dependencies:
function-bind: 1.1.2
hast-util-heading-rank@2.1.1:
dependencies:
'@types/hast': 2.3.10
hast-util-heading-rank@3.0.0:
dependencies:
'@types/hast': 3.0.4
hast-util-to-estree@2.3.3:
dependencies:
'@types/estree': 1.0.5
@@ -2966,6 +3184,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
hast-util-to-string@2.0.0:
dependencies:
'@types/hast': 2.3.10
hast-util-to-string@3.0.1:
dependencies:
'@types/hast': 3.0.4
hast-util-whitespace@2.0.1: {}
html-to-text@9.0.5:
@@ -3018,6 +3244,8 @@ snapshots:
is-number@7.0.0: {}
is-plain-obj@3.0.0: {}
is-plain-obj@4.1.0: {}
is-reference@3.0.2:
@@ -3953,6 +4181,14 @@ snapshots:
dependencies:
picomatch: 2.3.1
rehype-slug@6.0.0:
dependencies:
'@types/hast': 3.0.4
github-slugger: 2.0.0
hast-util-heading-rank: 3.0.0
hast-util-to-string: 3.0.1
unist-util-visit: 5.0.0
remark-mdx@2.3.0:
dependencies:
mdast-util-mdx: 2.0.1
@@ -4118,6 +4354,8 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
tabbable@6.2.0: {}
tailwind-merge@1.14.0: {}
tailwindcss-animate@1.0.7(tailwindcss@3.4.3):

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