Compare commits
149 Commits
jazz-tools
...
jazz-brows
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aca5642671 | ||
|
|
a5bed20c4a | ||
|
|
09bf53a8d3 | ||
|
|
061ec996b1 | ||
|
|
7aae2441a1 | ||
|
|
650e95a528 | ||
|
|
3d80ab11d9 | ||
|
|
85e6489a3e | ||
|
|
45b6c87ade | ||
|
|
edadc4b986 | ||
|
|
455b722357 | ||
|
|
ad2e1d1e98 | ||
|
|
7c94b70c31 | ||
|
|
74bcf1752e | ||
|
|
97a54b3911 | ||
|
|
c393c8880f | ||
|
|
359157fa70 | ||
|
|
62d9680449 | ||
|
|
db6067439d | ||
|
|
5051d6a410 | ||
|
|
25efaf30f5 | ||
|
|
98aadd9842 | ||
|
|
d555b18c11 | ||
|
|
550111f8a1 | ||
|
|
3d4a00a19d | ||
|
|
d06c6677dc | ||
|
|
ce30f3c4ff | ||
|
|
1072b9c2fe | ||
|
|
5ea41c69ef | ||
|
|
2d8eed3b69 | ||
|
|
45c9c8558f | ||
|
|
dccb80edf0 | ||
|
|
fc55e5c8e8 | ||
|
|
4a74ccf399 | ||
|
|
a442315995 | ||
|
|
0d5ee3ed07 | ||
|
|
4e32cae8a7 | ||
|
|
49d721a29b | ||
|
|
2c6d27598d | ||
|
|
e637cb0700 | ||
|
|
c42848ece9 | ||
|
|
841a818dff | ||
|
|
f74881a3fe | ||
|
|
c559054378 | ||
|
|
d6d9c0adcb | ||
|
|
cdf9b5a71c | ||
|
|
4b950bce14 | ||
|
|
8343d8f0fe | ||
|
|
eeb280f17b | ||
|
|
a927334b40 | ||
|
|
be0c1bcda5 | ||
|
|
b861daca60 | ||
|
|
b4cd307eba | ||
|
|
1d0e83d3fa | ||
|
|
be7c4c29a1 | ||
|
|
ffa4db0b61 | ||
|
|
7daf992c51 | ||
|
|
333c583265 | ||
|
|
bfa5e14112 | ||
|
|
dcdf89bba7 | ||
|
|
a6e6939015 | ||
|
|
71aa24054d | ||
|
|
4c88421440 | ||
|
|
64bad01d9a | ||
|
|
4dfa809a77 | ||
|
|
726df167f8 | ||
|
|
2f62cbde13 | ||
|
|
93ef74219d | ||
|
|
495aa81335 | ||
|
|
99caaba328 | ||
|
|
4bfcc787a1 | ||
|
|
7e96eb12dd | ||
|
|
a71eba2eb5 | ||
|
|
b129cf9328 | ||
|
|
a6e31c41b7 | ||
|
|
47746ff9ba | ||
|
|
4e4319a546 | ||
|
|
d1de8baf1d | ||
|
|
d427a2a13c | ||
|
|
1fa6c3987a | ||
|
|
ddf49e532f | ||
|
|
a0c4ef72ef | ||
|
|
99009a9054 | ||
|
|
e512df4eff | ||
|
|
da3ede8b54 | ||
|
|
56ed6d3271 | ||
|
|
78112bb19a | ||
|
|
ac6b0c6561 | ||
|
|
632365a4fb | ||
|
|
14f52dbc4e | ||
|
|
82e4256e26 | ||
|
|
5e253cc717 | ||
|
|
0c1663505c | ||
|
|
ad85703373 | ||
|
|
3a6ec3791c | ||
|
|
f9590f9120 | ||
|
|
706ebf87da | ||
|
|
00dd317a5d | ||
|
|
5ced45fb90 | ||
|
|
23daa7cdde | ||
|
|
c018752c0c | ||
|
|
ba3bdcc268 | ||
|
|
4177f6f92c | ||
|
|
e32a1f7392 | ||
|
|
7c43fd37ae | ||
|
|
48168d619b | ||
|
|
1b9b9273e5 | ||
|
|
2f4eada56c | ||
|
|
709b3432d7 | ||
|
|
78a7672401 | ||
|
|
bb214f0e8b | ||
|
|
8706398f74 | ||
|
|
1502a6b421 | ||
|
|
f167112d99 | ||
|
|
d4d6cb3307 | ||
|
|
9565cdf323 | ||
|
|
dfb21ff0f2 | ||
|
|
98d697fafb | ||
|
|
9150d53f90 | ||
|
|
ac7ecc278c | ||
|
|
99595bc7e3 | ||
|
|
f5bae09679 | ||
|
|
a7b9ae0b76 | ||
|
|
196efcf48e | ||
|
|
153aa972b3 | ||
|
|
4508524f77 | ||
|
|
e7e9062dff | ||
|
|
65e8d135c1 | ||
|
|
0b8e84e22d | ||
|
|
7b51e38cf6 | ||
|
|
fcc2cbdc93 | ||
|
|
5aa13b5afc | ||
|
|
dc746a2fc9 | ||
|
|
ca39bae001 | ||
|
|
020b12fa32 | ||
|
|
bfea02c229 | ||
|
|
74e6495beb | ||
|
|
3fe683206a | ||
|
|
f869d9a4dd | ||
|
|
156167e6d7 | ||
|
|
aef84cf2ef | ||
|
|
275a26e2c1 | ||
|
|
946ae63070 | ||
|
|
5cfe47ebbe | ||
|
|
6ee0ec755e | ||
|
|
8ffca202bd | ||
|
|
6d2bcc7490 | ||
|
|
e7733a5428 | ||
|
|
4683cc7ada |
@@ -2,8 +2,8 @@
|
|||||||
"$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
|
"$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
|
||||||
"changelog": "@changesets/cli/changelog",
|
"changelog": "@changesets/cli/changelog",
|
||||||
"commit": false,
|
"commit": false,
|
||||||
"fixed": [],
|
"linked": [],
|
||||||
"linked": [
|
"fixed": [
|
||||||
[
|
[
|
||||||
"cojson",
|
"cojson",
|
||||||
"cojson-storage",
|
"cojson-storage",
|
||||||
@@ -27,6 +27,8 @@
|
|||||||
"jazz-react-native-core",
|
"jazz-react-native-core",
|
||||||
"jazz-react-native",
|
"jazz-react-native",
|
||||||
"jazz-react-native-media-images",
|
"jazz-react-native-media-images",
|
||||||
|
"jazz-richtext-prosemirror",
|
||||||
|
"jazz-richtext-tiptap",
|
||||||
"jazz-run",
|
"jazz-run",
|
||||||
"jazz-svelte",
|
"jazz-svelte",
|
||||||
"jazz-tools",
|
"jazz-tools",
|
||||||
|
|||||||
1
.github/workflows/e2e-rn-test.yml
vendored
1
.github/workflows/e2e-rn-test.yml
vendored
@@ -38,7 +38,6 @@ jobs:
|
|||||||
- name: chat-rn-expo App Pre Build
|
- name: chat-rn-expo App Pre Build
|
||||||
working-directory: ./examples/chat-rn-expo
|
working-directory: ./examples/chat-rn-expo
|
||||||
run: |
|
run: |
|
||||||
pnpm build
|
|
||||||
pnpm expo prebuild --clean
|
pnpm expo prebuild --clean
|
||||||
|
|
||||||
- name: Install Maestro
|
- name: Install Maestro
|
||||||
|
|||||||
46
.github/workflows/playwright-homepage.yml
vendored
Normal file
46
.github/workflows/playwright-homepage.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
name: Playwright Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["main"]
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
timeout-minutes: 60
|
||||||
|
runs-on: blacksmith-4vcpu-ubuntu-2204
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
project: ["homepage/homepage"]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Setup Source Code
|
||||||
|
uses: ./.github/actions/source-code/
|
||||||
|
|
||||||
|
- name: Install project dependencies
|
||||||
|
run: pnpm install
|
||||||
|
working-directory: ./${{ matrix.project }}
|
||||||
|
|
||||||
|
- name: Pnpm Build
|
||||||
|
run: pnpm turbo build
|
||||||
|
working-directory: ./${{ matrix.project }}
|
||||||
|
|
||||||
|
- name: Install Playwright Browsers
|
||||||
|
run: pnpm exec playwright install
|
||||||
|
working-directory: ./${{ matrix.project }}
|
||||||
|
|
||||||
|
- name: Run Playwright tests
|
||||||
|
run: pnpm exec playwright test
|
||||||
|
working-directory: ./${{ matrix.project }}
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
name: ${{ hashFiles(format('{0}/package.json', matrix.project)) }}-playwright-report
|
||||||
|
path: ./${{ matrix.project }}/playwright-report/
|
||||||
|
retention-days: 30
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -20,6 +20,9 @@ __screenshots__
|
|||||||
# Playwright
|
# Playwright
|
||||||
test-results
|
test-results
|
||||||
|
|
||||||
|
# Java
|
||||||
|
.java-version
|
||||||
|
|
||||||
.husky
|
.husky
|
||||||
|
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"include": ["packages/**/src/tests/**"],
|
"include": ["**/tests/**"],
|
||||||
"linter": {
|
"linter": {
|
||||||
"rules": {
|
"rules": {
|
||||||
"correctness": {
|
"correctness": {
|
||||||
|
|||||||
@@ -1,5 +1,107 @@
|
|||||||
# betterauth
|
# betterauth
|
||||||
|
|
||||||
|
## 0.1.22
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-betterauth-client-plugin@0.14.19
|
||||||
|
- jazz-betterauth-server-plugin@0.14.19
|
||||||
|
- jazz-react-auth-betterauth@0.14.19
|
||||||
|
- jazz-inspector@0.14.19
|
||||||
|
- jazz-react@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 0.1.21
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-betterauth-server-plugin@0.14.18
|
||||||
|
- jazz-inspector@0.14.18
|
||||||
|
- jazz-react@0.14.18
|
||||||
|
- jazz-react-auth-betterauth@0.14.18
|
||||||
|
- jazz-betterauth-client-plugin@0.14.18
|
||||||
|
|
||||||
|
## 0.1.20
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-betterauth-server-plugin@0.14.17
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-betterauth-client-plugin@0.14.17
|
||||||
|
- jazz-inspector@0.14.17
|
||||||
|
- jazz-react@0.14.17
|
||||||
|
- jazz-react-auth-betterauth@0.14.17
|
||||||
|
|
||||||
|
## 0.1.19
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-betterauth-server-plugin@0.14.16
|
||||||
|
- jazz-inspector@0.14.16
|
||||||
|
- jazz-react@0.14.16
|
||||||
|
- jazz-react-auth-betterauth@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
- jazz-betterauth-client-plugin@0.14.16
|
||||||
|
|
||||||
|
## 0.1.18
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [f9590f9]
|
||||||
|
- jazz-react@0.14.15
|
||||||
|
- jazz-betterauth-server-plugin@0.14.15
|
||||||
|
- jazz-inspector@0.14.15
|
||||||
|
- jazz-react-auth-betterauth@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
- jazz-betterauth-client-plugin@0.14.15
|
||||||
|
|
||||||
|
## 0.1.17
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-betterauth-server-plugin@0.14.14
|
||||||
|
- jazz-inspector@0.14.14
|
||||||
|
- jazz-react@0.14.14
|
||||||
|
- jazz-react-auth-betterauth@0.14.14
|
||||||
|
- jazz-betterauth-client-plugin@0.14.14
|
||||||
|
|
||||||
|
## 0.1.16
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.13
|
||||||
|
- jazz-react@0.14.13
|
||||||
|
- jazz-react-auth-betterauth@0.14.13
|
||||||
|
|
||||||
|
## 0.1.15
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.12
|
||||||
|
- jazz-react@0.14.12
|
||||||
|
- jazz-react-auth-betterauth@0.14.12
|
||||||
|
|
||||||
|
## 0.1.14
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-react-auth-betterauth@0.14.10
|
||||||
|
- jazz-inspector@0.14.10
|
||||||
|
- jazz-react@0.14.10
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
- jazz-betterauth-server-plugin@0.14.10
|
||||||
|
- jazz-betterauth-client-plugin@0.14.10
|
||||||
|
|
||||||
## 0.1.13
|
## 0.1.13
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "betterauth",
|
"name": "betterauth",
|
||||||
"version": "0.1.13",
|
"version": "0.1.22",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,5 +1,89 @@
|
|||||||
# chat-rn-expo-clerk
|
# chat-rn-expo-clerk
|
||||||
|
|
||||||
|
## 1.0.142
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [061ec99]
|
||||||
|
- jazz-expo@0.14.19
|
||||||
|
- jazz-react-native-media-images@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 1.0.141
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-expo@0.14.18
|
||||||
|
- jazz-react-native-media-images@0.14.18
|
||||||
|
|
||||||
|
## 1.0.140
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-expo@0.14.17
|
||||||
|
- jazz-react-native-media-images@0.14.17
|
||||||
|
|
||||||
|
## 1.0.139
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-expo@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
- jazz-react-native-media-images@0.14.16
|
||||||
|
|
||||||
|
## 1.0.138
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-expo@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
- jazz-react-native-media-images@0.14.15
|
||||||
|
|
||||||
|
## 1.0.137
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-expo@0.14.14
|
||||||
|
- jazz-react-native-media-images@0.14.14
|
||||||
|
|
||||||
|
## 1.0.136
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-expo@0.14.13
|
||||||
|
|
||||||
|
## 1.0.135
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-expo@0.14.12
|
||||||
|
|
||||||
|
## 1.0.134
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [98d697f]
|
||||||
|
- jazz-expo@0.14.11
|
||||||
|
|
||||||
|
## 1.0.133
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-react-native-media-images@0.14.10
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
- jazz-expo@0.14.10
|
||||||
|
|
||||||
## 1.0.132
|
## 1.0.132
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "chat-rn-expo-clerk",
|
"name": "chat-rn-expo-clerk",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"version": "1.0.132",
|
"version": "1.0.142",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "expo export -p ios",
|
"build": "expo export -p ios",
|
||||||
"start": "expo start",
|
"start": "expo start",
|
||||||
|
|||||||
7
examples/chat-rn-expo/.gitignore
vendored
7
examples/chat-rn-expo/.gitignore
vendored
@@ -7,8 +7,10 @@ node_modules/
|
|||||||
.expo/
|
.expo/
|
||||||
dist/
|
dist/
|
||||||
web-build/
|
web-build/
|
||||||
|
expo-env.d.ts
|
||||||
|
|
||||||
# Native
|
# Native
|
||||||
|
.kotlin/
|
||||||
*.orig.*
|
*.orig.*
|
||||||
*.jks
|
*.jks
|
||||||
*.p8
|
*.p8
|
||||||
@@ -33,6 +35,5 @@ yarn-error.*
|
|||||||
|
|
||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
android/
|
||||||
ios
|
ios/
|
||||||
android
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,24 +0,0 @@
|
|||||||
# 🎷 Jazz + Expo + `react-navigation` + Demo Auth
|
|
||||||
|
|
||||||
## 🚀 How to Run
|
|
||||||
|
|
||||||
### 1. Inside the Workspace Root
|
|
||||||
|
|
||||||
First, install dependencies and build the project:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm i
|
|
||||||
pnpm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Inside the `examples/chat-rn-expo` Directory
|
|
||||||
|
|
||||||
Next, navigate to the specific example project and run the following commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm expo prebuild
|
|
||||||
pnpx pod-install
|
|
||||||
pnpm expo run:ios
|
|
||||||
```
|
|
||||||
|
|
||||||
This will set up and launch the app on iOS. For Android, you can replace the last command with `pnpm expo run:android`.
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
const { withBuildProperties } = require("expo-build-properties");
|
|
||||||
const { withDangerousMod } = require("@expo/config-plugins");
|
|
||||||
const fs = require("fs/promises");
|
|
||||||
const path = require("path");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* https://github.com/mrousavy/nitro/issues/422#issuecomment-2545988256
|
|
||||||
*/
|
|
||||||
function withCustomIosMod(config) {
|
|
||||||
// Use expo-build-properties to bump iOS deployment target
|
|
||||||
config = withBuildProperties(config, { ios: { deploymentTarget: "16.0" } });
|
|
||||||
// Patch the generated Podfile fallback to ensure platform is always 16.0
|
|
||||||
config = withDangerousMod(config, [
|
|
||||||
"ios",
|
|
||||||
async (modConfig) => {
|
|
||||||
const podfilePath = path.join(
|
|
||||||
modConfig.modRequest.platformProjectRoot,
|
|
||||||
"Podfile",
|
|
||||||
);
|
|
||||||
let contents = await fs.readFile(podfilePath, "utf-8");
|
|
||||||
|
|
||||||
// Check if the IPHONEOS_DEPLOYMENT_TARGET setting is already present
|
|
||||||
// We search for the key being assigned, e.g., config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] =
|
|
||||||
const deploymentTargetSettingExists =
|
|
||||||
/\.build_settings\s*\[\s*['"]IPHONEOS_DEPLOYMENT_TARGET['"]\s*\]\s*=/.test(
|
|
||||||
contents,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!deploymentTargetSettingExists) {
|
|
||||||
// IPHONEOS_DEPLOYMENT_TARGET setting not found, proceed to add it.
|
|
||||||
contents = contents.replace(
|
|
||||||
/(post_install\s+do\s+\|installer\|[\s\S]*?)(\r?\n\s end\s*)$/m,
|
|
||||||
`$1
|
|
||||||
|
|
||||||
# Expo Build Properties: force deployment target
|
|
||||||
# https://github.com/mrousavy/nitro/issues/422#issuecomment-2545988256
|
|
||||||
installer.pods_project.targets.each do |target|
|
|
||||||
target.build_configurations.each do |config|
|
|
||||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.0'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
$2`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await fs.writeFile(podfilePath, contents);
|
|
||||||
return modConfig;
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ({ config }) => {
|
|
||||||
return withCustomIosMod(config);
|
|
||||||
};
|
|
||||||
@@ -1,39 +1,32 @@
|
|||||||
{
|
{
|
||||||
"expo": {
|
"expo": {
|
||||||
"name": "jazz-chat-rn-expo",
|
"name": "chat-rn-expo",
|
||||||
"scheme": "jazz-chat-rn-expo",
|
"slug": "chat-rn-expo",
|
||||||
"slug": "jazz-chat-rn-expo",
|
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icon": "./assets/icon.png",
|
"icon": "./assets/icon.png",
|
||||||
"userInterfaceStyle": "light",
|
"userInterfaceStyle": "light",
|
||||||
|
"newArchEnabled": true,
|
||||||
"splash": {
|
"splash": {
|
||||||
"image": "./assets/splash.png",
|
"image": "./assets/splash-icon.png",
|
||||||
"resizeMode": "contain",
|
"resizeMode": "contain",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
},
|
},
|
||||||
"ios": {
|
"ios": {
|
||||||
"supportsTablet": true,
|
"supportsTablet": true,
|
||||||
"bundleIdentifier": "com.jazz.chatrn"
|
"bundleIdentifier": "tools.jazz.chatrnexpo"
|
||||||
},
|
},
|
||||||
"android": {
|
"android": {
|
||||||
"adaptiveIcon": {
|
"adaptiveIcon": {
|
||||||
"foregroundImage": "./assets/adaptive-icon.png",
|
"foregroundImage": "./assets/adaptive-icon.png",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
},
|
},
|
||||||
"package": "com.jazz.chatrn"
|
"edgeToEdgeEnabled": true,
|
||||||
|
"package": "tools.jazz.chatrnexpo"
|
||||||
},
|
},
|
||||||
"plugins": [
|
"web": {
|
||||||
"expo-secure-store",
|
"favicon": "./assets/favicon.png"
|
||||||
"expo-sqlite",
|
|
||||||
"expo-build-properties",
|
|
||||||
"expo-web-browser"
|
|
||||||
],
|
|
||||||
"extra": {
|
|
||||||
"eas": {
|
|
||||||
"projectId": "e0e61872-1906-4c84-b9d8-9be77355cad0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"owner": "paxx"
|
"plugins": ["expo-secure-store", "expo-sqlite"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
examples/chat-rn-expo/assets/splash-icon.png
Normal file
BIN
examples/chat-rn-expo/assets/splash-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 46 KiB |
@@ -1,9 +0,0 @@
|
|||||||
module.exports = function (api) {
|
|
||||||
api.cache(true);
|
|
||||||
return {
|
|
||||||
presets: [
|
|
||||||
["babel-preset-expo", { jsxImportSource: "nativewind" }],
|
|
||||||
"nativewind/babel",
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"cli": {
|
|
||||||
"version": ">= 12.5.1",
|
|
||||||
"appVersionSource": "remote"
|
|
||||||
},
|
|
||||||
"build": {
|
|
||||||
"development": {
|
|
||||||
"developmentClient": true,
|
|
||||||
"distribution": "internal"
|
|
||||||
},
|
|
||||||
"ios-simulator": {
|
|
||||||
"extends": "development",
|
|
||||||
"ios": {
|
|
||||||
"simulator": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"preview": {
|
|
||||||
"distribution": "internal"
|
|
||||||
},
|
|
||||||
"production": {
|
|
||||||
"autoIncrement": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"submit": {
|
|
||||||
"production": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
import "./polyfills";
|
|
||||||
import { registerRootComponent } from "expo";
|
|
||||||
import App from "./src/App";
|
|
||||||
registerRootComponent(App);
|
|
||||||
9
examples/chat-rn-expo/index.ts
Normal file
9
examples/chat-rn-expo/index.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { registerRootComponent } from "expo";
|
||||||
|
import "./polyfills";
|
||||||
|
|
||||||
|
import App from "./src/App";
|
||||||
|
|
||||||
|
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
|
||||||
|
// It also ensures that whether you load the app in Expo Go or in a native build,
|
||||||
|
// the environment is set up appropriately
|
||||||
|
registerRootComponent(App);
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
// Learn more https://docs.expo.dev/guides/monorepos
|
|
||||||
const { getDefaultConfig } = require("expo/metro-config");
|
|
||||||
const { withNativeWind } = require("nativewind/metro");
|
|
||||||
const { FileStore } = require("metro-cache");
|
|
||||||
const path = require("path");
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
const projectRoot = __dirname;
|
|
||||||
const workspaceRoot = path.resolve(projectRoot, "../..");
|
|
||||||
|
|
||||||
const config = getDefaultConfig(projectRoot, { isCSSEnabled: true });
|
|
||||||
|
|
||||||
// Since we are using pnpm, we have to setup the monorepo manually for Metro
|
|
||||||
// #1 - Watch all files in the monorepo
|
|
||||||
config.watchFolders = [workspaceRoot];
|
|
||||||
// #2 - Try resolving with project modules first, then workspace modules
|
|
||||||
config.resolver.nodeModulesPaths = [
|
|
||||||
path.resolve(projectRoot, "node_modules"),
|
|
||||||
path.resolve(workspaceRoot, "node_modules"),
|
|
||||||
];
|
|
||||||
config.resolver.sourceExts = ["mjs", "js", "json", "ts", "tsx"];
|
|
||||||
config.resolver.requireCycleIgnorePatterns = [
|
|
||||||
/(^|\/|\\)node_modules($|\/|\\)/,
|
|
||||||
/(^|\/|\\)packages($|\/|\\)/,
|
|
||||||
];
|
|
||||||
|
|
||||||
// Use turborepo to restore the cache when possible
|
|
||||||
config.cacheStores = [
|
|
||||||
new FileStore({
|
|
||||||
root: path.join(projectRoot, "node_modules", ".cache", "metro"),
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
// module.exports = config;
|
|
||||||
module.exports = withNativeWind(config, { input: "./global.css" });
|
|
||||||
1
examples/chat-rn-expo/nativewind-env.d.ts
vendored
1
examples/chat-rn-expo/nativewind-env.d.ts
vendored
@@ -1 +0,0 @@
|
|||||||
/// <reference types="nativewind/types" />
|
|
||||||
@@ -1,53 +1,35 @@
|
|||||||
{
|
{
|
||||||
"name": "chat-rn-expo",
|
"name": "chat-rn-expo",
|
||||||
"version": "1.0.119",
|
"version": "1.0.10",
|
||||||
"main": "index.js",
|
"main": "index.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc --noEmit && expo export -p ios",
|
"build": "expo prebuild",
|
||||||
"start": "expo start",
|
"start": "expo start",
|
||||||
"format-and-lint": "biome check .",
|
|
||||||
"format-and-lint:fix": "biome check . --write",
|
|
||||||
"android": "expo run:android",
|
"android": "expo run:android",
|
||||||
"ios": "expo prebuild && pnpx pod-install && expo run:ios",
|
"ios": "expo run:ios",
|
||||||
"web": "expo start --web"
|
"web": "expo start --web"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/core-asynciterator-polyfill": "^1.0.2",
|
"@azure/core-asynciterator-polyfill": "^1.0.2",
|
||||||
"@bacons/text-decoder": "0.0.0",
|
"@bacons/text-decoder": "^0.0.0",
|
||||||
"@craftzdog/react-native-buffer": "6.0.5",
|
"@craftzdog/react-native-buffer": "^6.0.5",
|
||||||
"@react-native-community/netinfo": "11.4.1",
|
"@react-native-community/netinfo": "11.4.1",
|
||||||
"@react-navigation/native": "7.0.19",
|
"expo": "~53.0.9",
|
||||||
"@react-navigation/native-stack": "7.2.1",
|
"expo-clipboard": "^7.1.4",
|
||||||
"clsx": "^2.0.0",
|
|
||||||
"expo": "53.0.8",
|
|
||||||
"expo-build-properties": "~0.14.6",
|
|
||||||
"expo-clipboard": "~7.1.4",
|
|
||||||
"expo-constants": "~17.1.6",
|
|
||||||
"expo-dev-client": "~5.1.8",
|
|
||||||
"expo-linking": "~7.1.4",
|
|
||||||
"expo-secure-store": "~14.2.3",
|
"expo-secure-store": "~14.2.3",
|
||||||
"expo-sqlite": "15.2.9",
|
"expo-sqlite": "~15.2.10",
|
||||||
"expo-status-bar": "~2.2.3",
|
"expo-status-bar": "~2.2.3",
|
||||||
"expo-web-browser": "~14.1.6",
|
|
||||||
"jazz-expo": "workspace:*",
|
"jazz-expo": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"nativewind": "^4.1.21",
|
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-dom": "19.0.0",
|
|
||||||
"react-native": "0.79.2",
|
"react-native": "0.79.2",
|
||||||
"react-native-get-random-values": "^1.11.0",
|
"react-native-get-random-values": "^1.11.0",
|
||||||
"react-native-safe-area-context": "5.4.0",
|
"readable-stream": "^4.7.0"
|
||||||
"react-native-screens": "4.10.0",
|
|
||||||
"react-native-nitro-modules": "0.25.2",
|
|
||||||
"react-native-quick-crypto": "1.0.0-beta.15",
|
|
||||||
"react-native-url-polyfill": "^2.0.0",
|
|
||||||
"readable-stream": "4.7.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
"@types/react": "~19.0.14",
|
"@types/react": "~19.0.10",
|
||||||
"tailwindcss": "^3.4.17",
|
"typescript": "~5.8.3"
|
||||||
"typescript": "5.8.3"
|
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +1,18 @@
|
|||||||
import "../global.css";
|
|
||||||
|
|
||||||
import {
|
|
||||||
NavigationContainer,
|
|
||||||
useNavigationContainerRef,
|
|
||||||
} from "@react-navigation/native";
|
|
||||||
import { createNativeStackNavigator } from "@react-navigation/native-stack";
|
|
||||||
import * as Linking from "expo-linking";
|
|
||||||
import { RNQuickCrypto } from "jazz-expo/crypto";
|
|
||||||
import React, { StrictMode, useEffect, useState } from "react";
|
|
||||||
import HandleInviteScreen from "./invite";
|
|
||||||
|
|
||||||
import { JazzProvider } from "jazz-expo";
|
import { JazzProvider } from "jazz-expo";
|
||||||
|
import React, { StrictMode } from "react";
|
||||||
import { apiKey } from "./apiKey";
|
import { apiKey } from "./apiKey";
|
||||||
import ChatScreen from "./chat";
|
import ChatScreen from "./chat";
|
||||||
|
|
||||||
const Stack = createNativeStackNavigator();
|
export default function App() {
|
||||||
|
|
||||||
const prefix = Linking.createURL("/");
|
|
||||||
|
|
||||||
const linking = {
|
|
||||||
prefixes: [prefix],
|
|
||||||
config: {
|
|
||||||
screens: {
|
|
||||||
HandleInviteScreen: {
|
|
||||||
path: "router/invite/:valueHint?/:valueID/:inviteSecret",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [initialRoute, setInitialRoute] = useState<
|
|
||||||
"ChatScreen" | "HandleInviteScreen"
|
|
||||||
>("ChatScreen");
|
|
||||||
const navigationRef = useNavigationContainerRef();
|
|
||||||
useEffect(() => {
|
|
||||||
Linking.getInitialURL().then((url) => {
|
|
||||||
if (url) {
|
|
||||||
if (url && url.includes("invite")) {
|
|
||||||
setInitialRoute("HandleInviteScreen");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<JazzProvider
|
<JazzProvider
|
||||||
CryptoProvider={RNQuickCrypto}
|
|
||||||
sync={{
|
sync={{
|
||||||
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<NavigationContainer linking={linking} ref={navigationRef}>
|
<ChatScreen />
|
||||||
<Stack.Navigator initialRouteName={initialRoute}>
|
|
||||||
<Stack.Screen
|
|
||||||
options={{ title: "Jazz Chat" }}
|
|
||||||
name="ChatScreen"
|
|
||||||
// @ts-ignore
|
|
||||||
component={ChatScreen}
|
|
||||||
/>
|
|
||||||
<Stack.Screen
|
|
||||||
name="HandleInviteScreen"
|
|
||||||
component={HandleInviteScreen}
|
|
||||||
/>
|
|
||||||
</Stack.Navigator>
|
|
||||||
</NavigationContainer>
|
|
||||||
</JazzProvider>
|
</JazzProvider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import clsx from "clsx";
|
|
||||||
import * as Clipboard from "expo-clipboard";
|
import * as Clipboard from "expo-clipboard";
|
||||||
import { Group, ID, Loaded, Profile } from "jazz-tools";
|
import { Account, Group } from "jazz-tools";
|
||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
import React, {
|
import React, {
|
||||||
Button,
|
Button,
|
||||||
FlatList,
|
FlatList,
|
||||||
@@ -12,54 +11,38 @@ import React, {
|
|||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
View,
|
View,
|
||||||
Alert,
|
Alert,
|
||||||
|
StyleSheet,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
|
|
||||||
import { useAccount, useCoState } from "jazz-expo";
|
import { useAccount, useCoState } from "jazz-expo";
|
||||||
import { Chat, Message } from "./schema";
|
import { Chat, Message } from "./schema";
|
||||||
|
|
||||||
export default function ChatScreen({ navigation }: { navigation: any }) {
|
export default function ChatScreen() {
|
||||||
const { me, logOut } = useAccount();
|
const { me, logOut } = useAccount(Account, { resolve: { profile: true } });
|
||||||
const [chatId, setChatId] = useState<string>();
|
const [chatId, setChatId] = useState<string>();
|
||||||
const [chatIdInput, setChatIdInput] = useState<string>();
|
const [chatIdInput, setChatIdInput] = useState<string>();
|
||||||
const loadedChat = useCoState(Chat, chatId, { resolve: { $each: true } });
|
const loadedChat = useCoState(Chat, chatId, { resolve: { $each: true } });
|
||||||
const [message, setMessage] = useState("");
|
const [message, setMessage] = useState("");
|
||||||
const profile = useCoState(Profile, me._refs.profile?.id, {});
|
|
||||||
|
|
||||||
function handleLogOut() {
|
function handleLogOut() {
|
||||||
setChatId(undefined);
|
setChatId(undefined);
|
||||||
logOut();
|
logOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
navigation.setOptions({
|
|
||||||
headerRight: () => <Button onPress={handleLogOut} title="Logout" />,
|
|
||||||
headerLeft: () =>
|
|
||||||
loadedChat ? (
|
|
||||||
<Button
|
|
||||||
onPress={() => {
|
|
||||||
if (loadedChat?.id) {
|
|
||||||
Clipboard.setStringAsync(
|
|
||||||
`https://chat.jazz.tools/#/chat/${loadedChat.id}`,
|
|
||||||
);
|
|
||||||
Alert.alert("Copied to clipboard", `Chat ID: ${loadedChat.id}`);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
title="Share"
|
|
||||||
/>
|
|
||||||
) : null,
|
|
||||||
});
|
|
||||||
}, [navigation, loadedChat]);
|
|
||||||
|
|
||||||
const createChat = () => {
|
const createChat = () => {
|
||||||
const group = Group.create({ owner: me });
|
const group = Group.create();
|
||||||
group.addMember("everyone", "writer");
|
group.addMember("everyone", "writer");
|
||||||
const chat = Chat.create([], { owner: group });
|
const chat = Chat.create([], group);
|
||||||
setChatId(chat.id);
|
setChatId(chat.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const joinChat = () => {
|
const joinChat = () => {
|
||||||
if (chatIdInput) {
|
if (chatIdInput) {
|
||||||
setChatId(chatIdInput);
|
if (chatIdInput.startsWith("https://chat.jazz.tools/#/chat/")) {
|
||||||
|
setChatId(chatIdInput.split("/").pop());
|
||||||
|
} else {
|
||||||
|
setChatId(chatIdInput);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Alert.alert("Error", "Chat ID cannot be empty.");
|
Alert.alert("Error", "Chat ID cannot be empty.");
|
||||||
}
|
}
|
||||||
@@ -75,41 +58,28 @@ export default function ChatScreen({ navigation }: { navigation: any }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderMessageItem = ({ item }: { item: Loaded<typeof Message> }) => {
|
const renderMessageItem = ({ item }: { item: Message }) => {
|
||||||
const isMe = item._edits?.text?.by?.isMe;
|
const isMe = item._edits?.text?.by?.isMe;
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
className={clsx(
|
style={[
|
||||||
`rounded-lg p-1 px-1.5 max-w-[80%] `,
|
styles.messageContainer,
|
||||||
|
isMe ? styles.myMessage : styles.otherMessage,
|
||||||
isMe ? `bg-gray-200 self-end text-right` : `bg-gray-300 self-start `,
|
]}
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{!isMe ? (
|
{!isMe ? (
|
||||||
<Text
|
<Text
|
||||||
className={clsx(
|
style={[
|
||||||
`text-xs text-gray-500`,
|
styles.messageSender,
|
||||||
isMe ? "text-right" : "text-left",
|
{ textAlign: isMe ? "right" : "left" },
|
||||||
)}
|
]}
|
||||||
>
|
>
|
||||||
{item?._edits?.text?.by?.profile?.name}
|
{item?._edits?.text?.by?.profile?.name}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
<View
|
<View style={styles.messageContent}>
|
||||||
className={clsx(
|
<Text style={styles.messageText}>{item.text}</Text>
|
||||||
"flex relative items-end justify-between",
|
<Text style={[styles.messageTime, { marginTop: !isMe ? 8 : 4 }]}>
|
||||||
isMe ? "flex-row" : "flex-row",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Text className={clsx(`text-black text-md max-w-[85%]`)}>
|
|
||||||
{item.text}
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
className={clsx(
|
|
||||||
"text-[10px] text-gray-500 text-right ml-2",
|
|
||||||
!isMe ? "mt-2" : "mt-1",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{item?._edits?.text?.madeAt?.getHours().toString().padStart(2, "0")}
|
{item?._edits?.text?.madeAt?.getHours().toString().padStart(2, "0")}
|
||||||
:
|
:
|
||||||
{item?._edits?.text?.madeAt
|
{item?._edits?.text?.madeAt
|
||||||
@@ -123,31 +93,28 @@ export default function ChatScreen({ navigation }: { navigation: any }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="flex flex-col h-full">
|
<View style={styles.container}>
|
||||||
{!loadedChat ? (
|
{!loadedChat ? (
|
||||||
<View className="flex flex-col h-full items-center justify-center">
|
<View style={styles.welcomeContainer}>
|
||||||
<Text className="text-m font-bold mb-6">Username</Text>
|
<Text style={styles.usernameTitle}>Username</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
className="rounded h-12 p-2 mb-12 w-40 border border-gray-200 block"
|
style={styles.usernameInput}
|
||||||
value={profile?.name ?? ""}
|
value={me?.profile.name ?? ""}
|
||||||
onChangeText={(value) => {
|
onChangeText={(value) => {
|
||||||
if (profile) {
|
if (me?.profile) {
|
||||||
profile.name = value;
|
me.profile.name = value;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
textAlignVertical="center"
|
textAlignVertical="center"
|
||||||
onSubmitEditing={sendMessage}
|
onSubmitEditing={sendMessage}
|
||||||
testID="username-input"
|
testID="username-input"
|
||||||
/>
|
/>
|
||||||
<TouchableOpacity
|
<TouchableOpacity onPress={createChat} style={styles.newChatButton}>
|
||||||
onPress={createChat}
|
<Text style={styles.newChatButtonText}>Start new chat</Text>
|
||||||
className="bg-blue-500 p-4 rounded-md"
|
|
||||||
>
|
|
||||||
<Text className="text-white font-semibold">Start new chat</Text>
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<Text className="text-m font-bold mt-6">Join existing chat</Text>
|
<Text style={styles.joinChatTitle}>Join existing chat</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
className="rounded h-12 p-2 m-2 mt-4 w-80 border border-gray-200 block"
|
style={styles.chatIdInput}
|
||||||
placeholder="Chat ID"
|
placeholder="Chat ID"
|
||||||
value={chatIdInput ?? ""}
|
value={chatIdInput ?? ""}
|
||||||
onChangeText={(value) => {
|
onChangeText={(value) => {
|
||||||
@@ -161,22 +128,38 @@ export default function ChatScreen({ navigation }: { navigation: any }) {
|
|||||||
}}
|
}}
|
||||||
testID="chat-id-input"
|
testID="chat-id-input"
|
||||||
/>
|
/>
|
||||||
<TouchableOpacity
|
<TouchableOpacity onPress={joinChat} style={styles.joinChatButton}>
|
||||||
onPress={joinChat}
|
<Text style={styles.newChatButtonText}>Join chat</Text>
|
||||||
className="bg-green-500 p-4 rounded-md"
|
|
||||||
>
|
|
||||||
<Text className="text-white font-semibold">Join chat</Text>
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
<View style={styles.chatHeader}>
|
||||||
|
<Button
|
||||||
|
onPress={() => {
|
||||||
|
if (loadedChat?.id) {
|
||||||
|
Clipboard.setStringAsync(
|
||||||
|
`https://chat.jazz.tools/#/chat/${loadedChat.id}`,
|
||||||
|
);
|
||||||
|
Alert.alert(
|
||||||
|
"Copied to clipboard",
|
||||||
|
`Chat ID: ${loadedChat.id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
title="Share"
|
||||||
|
/>
|
||||||
|
<Text style={{ fontWeight: "bold", fontSize: 18 }}>Jazz chat</Text>
|
||||||
|
<Button onPress={handleLogOut} title="Logout" />
|
||||||
|
</View>
|
||||||
<FlatList
|
<FlatList
|
||||||
contentContainerStyle={{
|
contentContainerStyle={{
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
gap: 6,
|
gap: 6,
|
||||||
padding: 8,
|
padding: 8,
|
||||||
|
justifyContent: "flex-end",
|
||||||
}}
|
}}
|
||||||
className="flex"
|
style={styles.messageList}
|
||||||
data={loadedChat}
|
data={loadedChat}
|
||||||
keyExtractor={(item) => item.id}
|
keyExtractor={(item) => item.id}
|
||||||
renderItem={renderMessageItem}
|
renderItem={renderMessageItem}
|
||||||
@@ -185,11 +168,11 @@ export default function ChatScreen({ navigation }: { navigation: any }) {
|
|||||||
<KeyboardAvoidingView
|
<KeyboardAvoidingView
|
||||||
keyboardVerticalOffset={110}
|
keyboardVerticalOffset={110}
|
||||||
behavior="padding"
|
behavior="padding"
|
||||||
className="p-3 bg-white border-t border-gray-300"
|
style={styles.inputContainer}
|
||||||
>
|
>
|
||||||
<SafeAreaView className="flex flex-row items-center gap-2">
|
<SafeAreaView style={styles.inputRow}>
|
||||||
<TextInput
|
<TextInput
|
||||||
className="rounded-full h-8 py-0 px-2 border border-gray-200 block flex-1"
|
style={styles.messageInput}
|
||||||
value={message}
|
value={message}
|
||||||
onChangeText={setMessage}
|
onChangeText={setMessage}
|
||||||
placeholder="Type a message..."
|
placeholder="Type a message..."
|
||||||
@@ -199,7 +182,7 @@ export default function ChatScreen({ navigation }: { navigation: any }) {
|
|||||||
/>
|
/>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={sendMessage}
|
onPress={sendMessage}
|
||||||
className="bg-gray-300 text-white rounded-full h-8 w-8 items-center justify-center"
|
style={styles.sendButton}
|
||||||
testID="send-button"
|
testID="send-button"
|
||||||
>
|
>
|
||||||
<Text>↑</Text>
|
<Text>↑</Text>
|
||||||
@@ -211,3 +194,133 @@ export default function ChatScreen({ navigation }: { navigation: any }) {
|
|||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: "column",
|
||||||
|
height: "100%",
|
||||||
|
},
|
||||||
|
chatHeader: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: 8,
|
||||||
|
paddingTop: 48,
|
||||||
|
backgroundColor: "#f0f0f0",
|
||||||
|
},
|
||||||
|
welcomeContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: "column",
|
||||||
|
height: "100%",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
|
usernameTitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
usernameInput: {
|
||||||
|
borderRadius: 4,
|
||||||
|
height: 48,
|
||||||
|
padding: 8,
|
||||||
|
marginBottom: 48,
|
||||||
|
width: 160,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#e5e5e5",
|
||||||
|
},
|
||||||
|
newChatButton: {
|
||||||
|
backgroundColor: "#3b82f6",
|
||||||
|
padding: 16,
|
||||||
|
borderRadius: 6,
|
||||||
|
},
|
||||||
|
newChatButtonText: {
|
||||||
|
color: "white",
|
||||||
|
fontWeight: "600",
|
||||||
|
},
|
||||||
|
joinChatTitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginTop: 24,
|
||||||
|
},
|
||||||
|
chatIdInput: {
|
||||||
|
borderRadius: 4,
|
||||||
|
height: 48,
|
||||||
|
padding: 8,
|
||||||
|
margin: 8,
|
||||||
|
marginTop: 16,
|
||||||
|
width: 320,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#e5e5e5",
|
||||||
|
},
|
||||||
|
joinChatButton: {
|
||||||
|
backgroundColor: "#22c55e",
|
||||||
|
padding: 16,
|
||||||
|
borderRadius: 6,
|
||||||
|
},
|
||||||
|
messageList: {
|
||||||
|
display: "flex",
|
||||||
|
},
|
||||||
|
messageContainer: {
|
||||||
|
borderRadius: 8,
|
||||||
|
padding: 4,
|
||||||
|
paddingHorizontal: 6,
|
||||||
|
maxWidth: "80%",
|
||||||
|
},
|
||||||
|
myMessage: {
|
||||||
|
backgroundColor: "#e5e5e5",
|
||||||
|
alignSelf: "flex-end",
|
||||||
|
},
|
||||||
|
otherMessage: {
|
||||||
|
backgroundColor: "#d4d4d4",
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
},
|
||||||
|
messageSender: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: "#6b7280",
|
||||||
|
},
|
||||||
|
messageContent: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "flex-end",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
|
messageText: {
|
||||||
|
color: "black",
|
||||||
|
fontSize: 16,
|
||||||
|
maxWidth: "85%",
|
||||||
|
},
|
||||||
|
messageTime: {
|
||||||
|
fontSize: 10,
|
||||||
|
color: "#6b7280",
|
||||||
|
marginLeft: 8,
|
||||||
|
},
|
||||||
|
inputContainer: {
|
||||||
|
padding: 12,
|
||||||
|
backgroundColor: "white",
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderTopColor: "#d4d4d4",
|
||||||
|
},
|
||||||
|
inputRow: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 8,
|
||||||
|
},
|
||||||
|
messageInput: {
|
||||||
|
borderRadius: 9999,
|
||||||
|
height: 32,
|
||||||
|
paddingVertical: 0,
|
||||||
|
paddingHorizontal: 8,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#e5e5e5",
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
sendButton: {
|
||||||
|
backgroundColor: "#d4d4d4",
|
||||||
|
borderRadius: 9999,
|
||||||
|
height: 32,
|
||||||
|
width: 32,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
import { useAcceptInvite } from "jazz-expo";
|
|
||||||
import React, { Text } from "react-native";
|
|
||||||
import { Chat } from "./schema";
|
|
||||||
|
|
||||||
export default function HandleInviteScreen({
|
|
||||||
navigation,
|
|
||||||
}: {
|
|
||||||
navigation: any;
|
|
||||||
}) {
|
|
||||||
useAcceptInvite({
|
|
||||||
invitedObjectSchema: Chat,
|
|
||||||
onAccept: async (chatId) => {
|
|
||||||
navigation.navigate("ChatScreen", { chatId });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return <Text>Accepting invite...</Text>;
|
|
||||||
}
|
|
||||||
@@ -3,5 +3,7 @@ import { co, z } from "jazz-tools";
|
|||||||
export const Message = co.map({
|
export const Message = co.map({
|
||||||
text: z.string(),
|
text: z.string(),
|
||||||
});
|
});
|
||||||
|
export type Message = co.loaded<typeof Message>;
|
||||||
|
|
||||||
export const Chat = co.list(Message);
|
export const Chat = co.list(Message);
|
||||||
|
export type Chat = co.loaded<typeof Chat>;
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
module.exports = {
|
|
||||||
// NOTE: Update this to include the paths to all of your component files.
|
|
||||||
content: [
|
|
||||||
"./app/**/*.{js,jsx,ts,tsx}",
|
|
||||||
"./components/**/*.{js,jsx,ts,tsx}",
|
|
||||||
"./src/**/*.{js,jsx,ts,tsx}",
|
|
||||||
],
|
|
||||||
presets: [require("nativewind/preset")],
|
|
||||||
theme: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
};
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
# fully erased. The tap into the input field hits the middle, and clears all
|
# fully erased. The tap into the input field hits the middle, and clears all
|
||||||
# text to the left. If there's more to the right, it slides left, and thus we
|
# text to the left. If there's more to the right, it slides left, and thus we
|
||||||
# repeat this step. https://maestro.mobile.dev/api-reference/commands/erasetext
|
# repeat this step. https://maestro.mobile.dev/api-reference/commands/erasetext
|
||||||
appId: com.jazz.chatrn
|
appId: tools.jazz.chatrnexpo
|
||||||
---
|
---
|
||||||
- copyTextFrom:
|
- copyTextFrom:
|
||||||
id: ${id}
|
id: ${id}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
appId: com.jazz.chatrn
|
appId: tools.jazz.chatrnexpo
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp
|
||||||
|
|
||||||
@@ -8,10 +8,7 @@ appId: com.jazz.chatrn
|
|||||||
# - assertVisible: "Reload"
|
# - assertVisible: "Reload"
|
||||||
# - tapOn: "Reload"
|
# - tapOn: "Reload"
|
||||||
|
|
||||||
# login
|
- assertVisible: "Username"
|
||||||
- assertVisible: "Logout"
|
|
||||||
- tapOn: "Logout"
|
|
||||||
- assertVisible: "Anonymous user"
|
|
||||||
- runFlow:
|
- runFlow:
|
||||||
label: "Erase existing username"
|
label: "Erase existing username"
|
||||||
file: erase_text.yml
|
file: erase_text.yml
|
||||||
@@ -43,12 +40,13 @@ appId: com.jazz.chatrn
|
|||||||
|
|
||||||
# logout
|
# logout
|
||||||
- tapOn: "Logout"
|
- tapOn: "Logout"
|
||||||
|
- assertVisible: "Username"
|
||||||
- assertVisible: "Anonymous user"
|
- assertVisible: "Anonymous user"
|
||||||
|
|
||||||
# join chat
|
# join chat
|
||||||
- tapOn:
|
# - tapOn:
|
||||||
id: "chat-id-input"
|
# id: "chat-id-input"
|
||||||
- inputText: "co_zFs6KFyhxPw4xtw83tcEMzeHUNv" # Use a static id because maestro doesn't have access to the system clipboard
|
# - inputText: "co_zFs6KFyhxPw4xtw83tcEMzeHUNv" # Use a static id because maestro doesn't have access to the system clipboard
|
||||||
- tapOn: "Join chat"
|
# - tapOn: "Join chat"
|
||||||
- assertVisible: "boorad"
|
# - assertVisible: "boorad"
|
||||||
- assertVisible: "bro, low key, it do be like that tho"
|
# - assertVisible: "bro, low key, it do be like that tho"
|
||||||
|
|||||||
@@ -5,11 +5,15 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
OUTPUT_FILE=~/output/android-install.log
|
||||||
|
mkdir -p ~/output
|
||||||
|
touch $OUTPUT_FILE
|
||||||
|
|
||||||
# build and install the app
|
# build and install the app
|
||||||
echo "Building and installing Android app."
|
echo "Building and installing Android app."
|
||||||
echo "If it fails, its output will be in artifact: android-install.log..."
|
echo "If it fails, its output will be in artifact: android-install.log..."
|
||||||
cd ./android/
|
cd ./android/
|
||||||
./gradlew installRelease >> ~/output/android-install.log 2>&1
|
./gradlew installRelease >> $OUTPUT_FILE 2>&1
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# run the e2e tests
|
# run the e2e tests
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "expo/tsconfig.base",
|
"extends": "expo/tsconfig.base",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"strict": true,
|
"strict": true
|
||||||
"moduleResolution": "bundler"
|
}
|
||||||
},
|
|
||||||
"exclude": ["src/tests"]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,93 @@
|
|||||||
# chat-rn
|
# chat-rn
|
||||||
|
|
||||||
|
## 1.0.137
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [061ec99]
|
||||||
|
- jazz-react-native@0.14.19
|
||||||
|
- cojson@0.14.19
|
||||||
|
- cojson-transport-ws@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 1.0.136
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [0d5ee3e]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- cojson@0.14.18
|
||||||
|
- jazz-react-native@0.14.18
|
||||||
|
- cojson-transport-ws@0.14.18
|
||||||
|
|
||||||
|
## 1.0.135
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-react-native@0.14.17
|
||||||
|
|
||||||
|
## 1.0.134
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [5e253cc]
|
||||||
|
- cojson@0.14.16
|
||||||
|
- cojson-transport-ws@0.14.16
|
||||||
|
- jazz-react-native@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
|
||||||
|
## 1.0.133
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [23daa7c]
|
||||||
|
- cojson@0.14.15
|
||||||
|
- jazz-react-native@0.14.15
|
||||||
|
- cojson-transport-ws@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
|
||||||
|
## 1.0.132
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-react-native@0.14.14
|
||||||
|
|
||||||
|
## 1.0.131
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react-native@0.14.13
|
||||||
|
|
||||||
|
## 1.0.130
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react-native@0.14.12
|
||||||
|
|
||||||
|
## 1.0.129
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [98d697f]
|
||||||
|
- jazz-react-native@0.14.11
|
||||||
|
|
||||||
|
## 1.0.128
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-react-native@0.14.10
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
|
||||||
## 1.0.127
|
## 1.0.127
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ This will set up and launch the app on iOS. For Android, you can skip `pnpm pods
|
|||||||
This was created using the following command:
|
This was created using the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpx @react-native-community/cli init chat-rn --version 0.76.7 --install-pods true --skip-git-init true --package-name com.chatrn --directory chat-rn
|
pnpx @react-native-community/cli init chat-rn --version 0.76.9 --install-pods true --skip-git-init true --package-name com.chatrn --directory chat-rn
|
||||||
```
|
```
|
||||||
|
|
||||||
Then change package name in `package.json`, and begin build instructions above.
|
Then change package name in `package.json`, and begin build instructions above.
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
"name": "ChatRN",
|
"name": "ChatRN",
|
||||||
"displayName": "ChatRN",
|
"displayName": "ChatRN",
|
||||||
"android": {
|
"android": {
|
||||||
"package": "com.anonymous.ChatRN"
|
"package": "tools.jazz.chatrn"
|
||||||
},
|
},
|
||||||
"ios": {
|
"ios": {
|
||||||
"bundleIdentifier": "com.anonymous.ChatRN"
|
"bundleIdentifier": "tools.jazz.chatrn"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@ module.exports = makeMetroConfig({
|
|||||||
resolveRequest: MetroSymlinksResolver(),
|
resolveRequest: MetroSymlinksResolver(),
|
||||||
extraNodeModules,
|
extraNodeModules,
|
||||||
nodeModulesPaths,
|
nodeModulesPaths,
|
||||||
|
sourceExts: ["mjs", "js", "json", "ts", "tsx"],
|
||||||
},
|
},
|
||||||
sourceExts: ["mjs", "js", "json", "ts", "tsx"],
|
|
||||||
watchFolders,
|
watchFolders,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "chat-rn",
|
"name": "chat-rn",
|
||||||
"version": "1.0.127",
|
"version": "1.0.137",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"android": "react-native run-android",
|
"android": "react-native run-android",
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
"cojson-transport-ws": "workspace:*",
|
"cojson-transport-ws": "workspace:*",
|
||||||
"jazz-react-native": "workspace:*",
|
"jazz-react-native": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"react": "18.3.1",
|
"react": "19.0.0",
|
||||||
"react-native": "0.79.2",
|
"react-native": "0.79.2",
|
||||||
"react-native-get-random-values": "^1.11.0",
|
"react-native-get-random-values": "^1.11.0",
|
||||||
"react-native-mmkv": "^3.2.0",
|
"react-native-mmkv": "^3.2.0",
|
||||||
@@ -40,10 +40,10 @@
|
|||||||
"@react-native-community/cli": "15.0.1",
|
"@react-native-community/cli": "15.0.1",
|
||||||
"@react-native-community/cli-platform-android": "15.0.1",
|
"@react-native-community/cli-platform-android": "15.0.1",
|
||||||
"@react-native-community/cli-platform-ios": "15.0.1",
|
"@react-native-community/cli-platform-ios": "15.0.1",
|
||||||
"@react-native/babel-preset": "0.76.7",
|
"@react-native/babel-preset": "0.76.9",
|
||||||
"@react-native/eslint-config": "0.76.7",
|
"@react-native/eslint-config": "0.76.9",
|
||||||
"@react-native/metro-config": "0.76.7",
|
"@react-native/metro-config": "0.76.9",
|
||||||
"@react-native/typescript-config": "0.76.7",
|
"@react-native/typescript-config": "0.76.9",
|
||||||
"@rnx-kit/metro-config": "^2.0.1",
|
"@rnx-kit/metro-config": "^2.0.1",
|
||||||
"@rnx-kit/metro-resolver-symlinks": "^0.2.1",
|
"@rnx-kit/metro-resolver-symlinks": "^0.2.1",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "^18.3.12",
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { useAccount, useCoState } from "jazz-react-native";
|
|||||||
import { CoPlainText, Group, ID, Loaded, Profile } from "jazz-tools";
|
import { CoPlainText, Group, ID, Loaded, Profile } from "jazz-tools";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Alert,
|
|
||||||
Button,
|
Button,
|
||||||
FlatList,
|
FlatList,
|
||||||
KeyboardAvoidingView,
|
KeyboardAvoidingView,
|
||||||
@@ -19,6 +18,7 @@ import { Chat, Message } from "./schema";
|
|||||||
export function ChatScreen({ navigation }: { navigation: any }) {
|
export function ChatScreen({ navigation }: { navigation: any }) {
|
||||||
const { me, logOut } = useAccount();
|
const { me, logOut } = useAccount();
|
||||||
const [chatId, setChatId] = useState<string>();
|
const [chatId, setChatId] = useState<string>();
|
||||||
|
const [chatIdInput, setChatIdInput] = useState<string>();
|
||||||
const loadedChat = useCoState(Chat, chatId, { resolve: { $each: true } });
|
const loadedChat = useCoState(Chat, chatId, { resolve: { $each: true } });
|
||||||
const [message, setMessage] = useState("");
|
const [message, setMessage] = useState("");
|
||||||
const profile = useCoState(Profile, me._refs.profile?.id, {});
|
const profile = useCoState(Profile, me._refs.profile?.id, {});
|
||||||
@@ -36,10 +36,8 @@ export function ChatScreen({ navigation }: { navigation: any }) {
|
|||||||
<Button
|
<Button
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (loadedChat?.id) {
|
if (loadedChat?.id) {
|
||||||
Clipboard.setString(
|
Clipboard.setString(loadedChat.id);
|
||||||
`https://chat.jazz.tools/#/chat/${loadedChat.id}`,
|
console.log("Copied to clipboard", `Chat ID: ${loadedChat.id}`);
|
||||||
);
|
|
||||||
Alert.alert("Copied to clipboard", `Chat ID: ${loadedChat.id}`);
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
title="Share"
|
title="Share"
|
||||||
@@ -56,27 +54,11 @@ export function ChatScreen({ navigation }: { navigation: any }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const joinChat = () => {
|
const joinChat = () => {
|
||||||
Alert.prompt(
|
if (chatIdInput) {
|
||||||
"Join Chat",
|
setChatId(chatIdInput as ID<Chat>);
|
||||||
"Enter the Chat ID (example: co_zBGEHYvRfGuT2YSBraY3njGjnde)",
|
} else {
|
||||||
[
|
console.warn("Error: Chat ID cannot be empty.");
|
||||||
{
|
}
|
||||||
text: "Cancel",
|
|
||||||
style: "cancel",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Join",
|
|
||||||
onPress: (chatId) => {
|
|
||||||
if (chatId) {
|
|
||||||
setChatId(chatId);
|
|
||||||
} else {
|
|
||||||
Alert.alert("Error", "Chat ID cannot be empty.");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"plain-text",
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const sendMessage = () => {
|
const sendMessage = () => {
|
||||||
@@ -153,6 +135,16 @@ export function ChatScreen({ navigation }: { navigation: any }) {
|
|||||||
<TouchableOpacity onPress={createChat} style={styles.newChatButton}>
|
<TouchableOpacity onPress={createChat} style={styles.newChatButton}>
|
||||||
<Text style={styles.buttonText}>Start new chat</Text>
|
<Text style={styles.buttonText}>Start new chat</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
<Text style={styles.usernameLabel}>Join existing chat</Text>
|
||||||
|
<TextInput
|
||||||
|
style={styles.chatIdInput}
|
||||||
|
placeholder="Chat ID"
|
||||||
|
value={chatIdInput ?? ""}
|
||||||
|
onChangeText={setChatIdInput}
|
||||||
|
textAlignVertical="center"
|
||||||
|
onSubmitEditing={joinChat}
|
||||||
|
testID="chat-id-input"
|
||||||
|
/>
|
||||||
<TouchableOpacity onPress={joinChat} style={styles.joinChatButton}>
|
<TouchableOpacity onPress={joinChat} style={styles.joinChatButton}>
|
||||||
<Text style={styles.buttonText}>Join chat</Text>
|
<Text style={styles.buttonText}>Join chat</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
@@ -205,27 +197,91 @@ export function ChatScreen({ navigation }: { navigation: any }) {
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: "column",
|
},
|
||||||
height: "100%",
|
welcomeContainer: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
|
usernameLabel: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
usernameInput: {
|
||||||
|
width: 160,
|
||||||
|
height: 48,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#ddd",
|
||||||
|
borderRadius: 8,
|
||||||
|
paddingHorizontal: 8,
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
chatIdInput: {
|
||||||
|
width: 320,
|
||||||
|
height: 48,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#ddd",
|
||||||
|
borderRadius: 8,
|
||||||
|
paddingHorizontal: 8,
|
||||||
|
marginBottom: 24,
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
newChatButton: {
|
||||||
|
backgroundColor: "#3B82F6",
|
||||||
|
padding: 16,
|
||||||
|
borderRadius: 8,
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
joinChatButton: {
|
||||||
|
backgroundColor: "#10B981",
|
||||||
|
padding: 16,
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
color: "white",
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
textAlign: "center",
|
||||||
|
},
|
||||||
|
messageList: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
inputContainer: {
|
||||||
|
padding: 12,
|
||||||
|
},
|
||||||
|
inputWrapper: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#ddd",
|
||||||
|
borderRadius: 8,
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
},
|
||||||
|
messageInput: {
|
||||||
|
flex: 1,
|
||||||
|
height: 32,
|
||||||
|
paddingHorizontal: 8,
|
||||||
|
},
|
||||||
|
sendButton: {
|
||||||
|
paddingHorizontal: 16,
|
||||||
},
|
},
|
||||||
messageContainer: {
|
messageContainer: {
|
||||||
borderRadius: 8,
|
flexDirection: "column",
|
||||||
paddingVertical: 4,
|
alignItems: "flex-start",
|
||||||
paddingHorizontal: 6,
|
marginBottom: 8,
|
||||||
maxWidth: "80%",
|
|
||||||
},
|
},
|
||||||
myMessage: {
|
myMessage: {
|
||||||
backgroundColor: "#e5e7eb", // gray-200
|
|
||||||
alignSelf: "flex-end",
|
alignSelf: "flex-end",
|
||||||
textAlign: "right",
|
|
||||||
},
|
},
|
||||||
otherMessage: {
|
otherMessage: {
|
||||||
backgroundColor: "#d1d5db", // gray-300
|
|
||||||
alignSelf: "flex-start",
|
alignSelf: "flex-start",
|
||||||
},
|
},
|
||||||
senderName: {
|
senderName: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: "#6b7280", // gray-500
|
color: "#666",
|
||||||
|
marginBottom: 4,
|
||||||
},
|
},
|
||||||
textRight: {
|
textRight: {
|
||||||
textAlign: "right",
|
textAlign: "right",
|
||||||
@@ -234,92 +290,27 @@ const styles = StyleSheet.create({
|
|||||||
textAlign: "left",
|
textAlign: "left",
|
||||||
},
|
},
|
||||||
messageContent: {
|
messageContent: {
|
||||||
position: "relative",
|
backgroundColor: "#f0f0f0",
|
||||||
flexDirection: "row",
|
borderRadius: 8,
|
||||||
alignItems: "flex-end",
|
padding: 8,
|
||||||
justifyContent: "space-between",
|
|
||||||
},
|
},
|
||||||
messageText: {
|
messageText: {
|
||||||
color: "#000000",
|
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
maxWidth: "85%",
|
|
||||||
},
|
},
|
||||||
timestamp: {
|
timestamp: {
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: "#6b7280", // gray-500
|
color: "#666",
|
||||||
textAlign: "right",
|
marginTop: 4,
|
||||||
marginLeft: 8,
|
|
||||||
},
|
},
|
||||||
timestampOther: {
|
timestampOther: {
|
||||||
|
textAlign: "left",
|
||||||
marginTop: 8,
|
marginTop: 8,
|
||||||
},
|
},
|
||||||
timestampMy: {
|
timestampMy: {
|
||||||
|
textAlign: "right",
|
||||||
marginTop: 4,
|
marginTop: 4,
|
||||||
},
|
},
|
||||||
welcomeContainer: {
|
avatar: {
|
||||||
flex: 1,
|
|
||||||
flexDirection: "column",
|
|
||||||
height: "100%",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
},
|
|
||||||
usernameLabel: {
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: "bold",
|
|
||||||
marginBottom: 24,
|
|
||||||
},
|
|
||||||
usernameInput: {
|
|
||||||
borderRadius: 4,
|
|
||||||
height: 48,
|
|
||||||
padding: 8,
|
|
||||||
marginBottom: 48,
|
|
||||||
width: 160,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: "#e5e7eb", // gray-200
|
|
||||||
},
|
|
||||||
newChatButton: {
|
|
||||||
backgroundColor: "#3b82f6", // blue-500
|
|
||||||
padding: 16,
|
|
||||||
borderRadius: 6,
|
|
||||||
},
|
|
||||||
joinChatButton: {
|
|
||||||
backgroundColor: "#10b981", // green-500
|
|
||||||
padding: 16,
|
|
||||||
borderRadius: 6,
|
|
||||||
marginTop: 16,
|
|
||||||
},
|
|
||||||
buttonText: {
|
|
||||||
color: "white",
|
|
||||||
fontWeight: "600",
|
|
||||||
},
|
|
||||||
messageList: {
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
inputContainer: {
|
|
||||||
paddingVertical: 16,
|
|
||||||
paddingHorizontal: 10,
|
|
||||||
backgroundColor: "white",
|
|
||||||
borderTopWidth: 1,
|
|
||||||
borderTopColor: "#d1d5db", // gray-300
|
|
||||||
},
|
|
||||||
inputWrapper: {
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
margin: 5,
|
|
||||||
},
|
|
||||||
messageInput: {
|
|
||||||
borderRadius: 20,
|
|
||||||
height: 32,
|
|
||||||
paddingVertical: 0,
|
|
||||||
paddingHorizontal: 8,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: "#e5e7eb", // gray-200
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
sendButton: {
|
|
||||||
marginLeft: 10,
|
|
||||||
backgroundColor: "#d1d5db", // gray-300
|
|
||||||
borderRadius: 16,
|
borderRadius: 16,
|
||||||
height: 32,
|
height: 32,
|
||||||
width: 32,
|
width: 32,
|
||||||
|
|||||||
@@ -1,5 +1,69 @@
|
|||||||
# chat-vue
|
# chat-vue
|
||||||
|
|
||||||
|
## 0.0.117
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
- jazz-vue@0.14.19
|
||||||
|
|
||||||
|
## 0.0.116
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-browser@0.14.18
|
||||||
|
- jazz-vue@0.14.18
|
||||||
|
|
||||||
|
## 0.0.115
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-browser@0.14.17
|
||||||
|
- jazz-vue@0.14.17
|
||||||
|
|
||||||
|
## 0.0.114
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
- jazz-vue@0.14.16
|
||||||
|
|
||||||
|
## 0.0.113
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
- jazz-vue@0.14.15
|
||||||
|
|
||||||
|
## 0.0.112
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-browser@0.14.14
|
||||||
|
- jazz-vue@0.14.14
|
||||||
|
|
||||||
|
## 0.0.111
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
- jazz-browser@0.14.10
|
||||||
|
- jazz-vue@0.14.10
|
||||||
|
|
||||||
## 0.0.110
|
## 0.0.110
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "chat-vue",
|
"name": "chat-vue",
|
||||||
"version": "0.0.110",
|
"version": "0.0.117",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"vite": "6.0.11",
|
"vite": "6.3.5",
|
||||||
"vite-plugin-vue-devtools": "^7.4.6",
|
"vite-plugin-vue-devtools": "^7.4.6",
|
||||||
"vue-tsc": "^2.1.6"
|
"vue-tsc": "^2.1.6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,85 @@
|
|||||||
# jazz-example-chat
|
# jazz-example-chat
|
||||||
|
|
||||||
|
## 0.0.217
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.19
|
||||||
|
- jazz-react@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 0.0.216
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-inspector@0.14.18
|
||||||
|
- jazz-react@0.14.18
|
||||||
|
|
||||||
|
## 0.0.215
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-inspector@0.14.17
|
||||||
|
- jazz-react@0.14.17
|
||||||
|
|
||||||
|
## 0.0.214
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.16
|
||||||
|
- jazz-react@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
|
||||||
|
## 0.0.213
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [f9590f9]
|
||||||
|
- jazz-react@0.14.15
|
||||||
|
- jazz-inspector@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
|
||||||
|
## 0.0.212
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-inspector@0.14.14
|
||||||
|
- jazz-react@0.14.14
|
||||||
|
|
||||||
|
## 0.0.211
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.13
|
||||||
|
- jazz-react@0.14.13
|
||||||
|
|
||||||
|
## 0.0.210
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.12
|
||||||
|
- jazz-react@0.14.12
|
||||||
|
|
||||||
|
## 0.0.209
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-inspector@0.14.10
|
||||||
|
- hash-slash@0.2.3
|
||||||
|
- jazz-react@0.14.10
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
|
||||||
## 0.0.208
|
## 0.0.208
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-example-chat",
|
"name": "jazz-example-chat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.208",
|
"version": "0.0.217",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -19,20 +19,20 @@
|
|||||||
"jazz-react": "workspace:*",
|
"jazz-react": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"lucide-react": "^0.274.0",
|
"lucide-react": "^0.274.0",
|
||||||
"react": "^18.3.1",
|
"react": "19.0.0",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "19.0.0",
|
||||||
"zod": "4.0.0-beta.20250505T012514"
|
"zod": "3.25.28"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.50.1",
|
"@playwright/test": "^1.50.1",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "19.0.0",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "19.0.0",
|
||||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
"@vitejs/plugin-react-swc": "^3.10.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"is-ci": "^3.0.1",
|
"is-ci": "^3.0.1",
|
||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"vite": "6.0.11"
|
"vite": "6.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,84 @@
|
|||||||
# minimal-auth-clerk
|
# minimal-auth-clerk
|
||||||
|
|
||||||
|
## 0.0.116
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.19
|
||||||
|
- jazz-react-auth-clerk@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 0.0.115
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-react@0.14.18
|
||||||
|
- jazz-react-auth-clerk@0.14.18
|
||||||
|
|
||||||
|
## 0.0.114
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-react@0.14.17
|
||||||
|
- jazz-react-auth-clerk@0.14.17
|
||||||
|
|
||||||
|
## 0.0.113
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.16
|
||||||
|
- jazz-react-auth-clerk@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
|
||||||
|
## 0.0.112
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [f9590f9]
|
||||||
|
- jazz-react@0.14.15
|
||||||
|
- jazz-react-auth-clerk@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
|
||||||
|
## 0.0.111
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-react@0.14.14
|
||||||
|
- jazz-react-auth-clerk@0.14.14
|
||||||
|
|
||||||
|
## 0.0.110
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.13
|
||||||
|
- jazz-react-auth-clerk@0.14.13
|
||||||
|
|
||||||
|
## 0.0.109
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.12
|
||||||
|
- jazz-react-auth-clerk@0.14.12
|
||||||
|
|
||||||
|
## 0.0.108
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-react-auth-clerk@0.14.10
|
||||||
|
- jazz-react@0.14.10
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
|
||||||
## 0.0.107
|
## 0.0.107
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This is an example of how to use clerk authentication with Jazz.
|
This is an example of how to use clerk authentication with Jazz.
|
||||||
|
|
||||||
Live version: https://clerk-demo.jazz.tools
|
Live version: [https://clerk-demo.jazz.tools](https://clerk-demo.jazz.tools)
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "clerk",
|
"name": "clerk",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.107",
|
"version": "0.0.116",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -17,17 +17,17 @@
|
|||||||
"jazz-react": "workspace:*",
|
"jazz-react": "workspace:*",
|
||||||
"jazz-react-auth-clerk": "workspace:*",
|
"jazz-react-auth-clerk": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"react": "^18.3.1",
|
"react": "19.0.0",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "19.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.50.1",
|
"@playwright/test": "^1.50.1",
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "19.0.0",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "19.0.0",
|
||||||
"@vitejs/plugin-react": "^4.3.3",
|
"@vitejs/plugin-react": "^4.5.1",
|
||||||
"globals": "^15.11.0",
|
"globals": "^15.11.0",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"vite": "6.0.11"
|
"vite": "6.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { createRoot } from "react-dom/client";
|
|||||||
import App from "./App.tsx";
|
import App from "./App.tsx";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import { JazzProviderWithClerk } from "jazz-react-auth-clerk";
|
import { JazzProviderWithClerk } from "jazz-react-auth-clerk";
|
||||||
|
import { ReactNode } from "react";
|
||||||
import { apiKey } from "./apiKey";
|
import { apiKey } from "./apiKey";
|
||||||
|
|
||||||
// Import your publishable key
|
// Import your publishable key
|
||||||
@@ -13,7 +14,7 @@ if (!PUBLISHABLE_KEY) {
|
|||||||
throw new Error("Add your Clerk publishable key to the .env.local file");
|
throw new Error("Add your Clerk publishable key to the .env.local file");
|
||||||
}
|
}
|
||||||
|
|
||||||
function JazzProvider({ children }: { children: React.ReactNode }) {
|
function JazzProvider({ children }: { children: ReactNode }) {
|
||||||
const clerk = useClerk();
|
const clerk = useClerk();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,5 +1,81 @@
|
|||||||
# file-share-svelte
|
# file-share-svelte
|
||||||
|
|
||||||
|
## 0.0.101
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector-element@0.14.19
|
||||||
|
- jazz-svelte@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 0.0.100
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-inspector-element@0.14.18
|
||||||
|
- jazz-svelte@0.14.18
|
||||||
|
|
||||||
|
## 0.0.99
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-inspector-element@0.14.17
|
||||||
|
- jazz-svelte@0.14.17
|
||||||
|
|
||||||
|
## 0.0.98
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-svelte@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
- jazz-inspector-element@0.14.16
|
||||||
|
|
||||||
|
## 0.0.97
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-svelte@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
- jazz-inspector-element@0.14.15
|
||||||
|
|
||||||
|
## 0.0.96
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-inspector-element@0.14.14
|
||||||
|
- jazz-svelte@0.14.14
|
||||||
|
|
||||||
|
## 0.0.95
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector-element@0.14.13
|
||||||
|
|
||||||
|
## 0.0.94
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector-element@0.14.12
|
||||||
|
|
||||||
|
## 0.0.93
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
- jazz-inspector-element@0.14.10
|
||||||
|
- jazz-svelte@0.14.10
|
||||||
|
|
||||||
## 0.0.92
|
## 0.0.92
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "file-share-svelte",
|
"name": "file-share-svelte",
|
||||||
"version": "0.0.92",
|
"version": "0.0.101",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"typescript-eslint": "^8.0.0",
|
"typescript-eslint": "^8.0.0",
|
||||||
"vite": "6.0.11"
|
"vite": "6.3.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.15",
|
"@tailwindcss/typography": "^0.5.15",
|
||||||
|
|||||||
@@ -1,5 +1,84 @@
|
|||||||
# jazz-tailwind-demo-auth-starter
|
# jazz-tailwind-demo-auth-starter
|
||||||
|
|
||||||
|
## 0.0.56
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.19
|
||||||
|
- jazz-react@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 0.0.55
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-inspector@0.14.18
|
||||||
|
- jazz-react@0.14.18
|
||||||
|
|
||||||
|
## 0.0.54
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-inspector@0.14.17
|
||||||
|
- jazz-react@0.14.17
|
||||||
|
|
||||||
|
## 0.0.53
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.16
|
||||||
|
- jazz-react@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
|
||||||
|
## 0.0.52
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [f9590f9]
|
||||||
|
- jazz-react@0.14.15
|
||||||
|
- jazz-inspector@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
|
||||||
|
## 0.0.51
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-inspector@0.14.14
|
||||||
|
- jazz-react@0.14.14
|
||||||
|
|
||||||
|
## 0.0.50
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.13
|
||||||
|
- jazz-react@0.14.13
|
||||||
|
|
||||||
|
## 0.0.49
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.12
|
||||||
|
- jazz-react@0.14.12
|
||||||
|
|
||||||
|
## 0.0.48
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-inspector@0.14.10
|
||||||
|
- jazz-react@0.14.10
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
|
||||||
## 0.0.47
|
## 0.0.47
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This is an example of how to upload and render images with Jazz.
|
This is an example of how to upload and render images with Jazz.
|
||||||
|
|
||||||
Live version: https://file-upload-demo.jazz.tools
|
Live version: [https://file-upload-demo.jazz.tools](https://file-upload-demo.jazz.tools)
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "filestream",
|
"name": "filestream",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.47",
|
"version": "0.0.56",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -14,20 +14,20 @@
|
|||||||
"jazz-react": "workspace:*",
|
"jazz-react": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"jazz-inspector": "workspace:*",
|
"jazz-inspector": "workspace:*",
|
||||||
"react": "^18.3.1",
|
"react": "19.0.0",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "19.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "19.0.0",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "19.0.0",
|
||||||
"@vitejs/plugin-react": "^4.3.3",
|
"@vitejs/plugin-react": "^4.5.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"globals": "^15.11.0",
|
"globals": "^15.11.0",
|
||||||
"is-ci": "^3.0.1",
|
"is-ci": "^3.0.1",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"vite": "6.0.11"
|
"vite": "6.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,76 @@
|
|||||||
# form
|
# form
|
||||||
|
|
||||||
|
## 0.1.57
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 0.1.56
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-react@0.14.18
|
||||||
|
|
||||||
|
## 0.1.55
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-react@0.14.17
|
||||||
|
|
||||||
|
## 0.1.54
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
|
||||||
|
## 0.1.53
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [f9590f9]
|
||||||
|
- jazz-react@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
|
||||||
|
## 0.1.52
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-react@0.14.14
|
||||||
|
|
||||||
|
## 0.1.51
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.13
|
||||||
|
|
||||||
|
## 0.1.50
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.12
|
||||||
|
|
||||||
|
## 0.1.49
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- hash-slash@0.2.3
|
||||||
|
- jazz-react@0.14.10
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
|
||||||
## 0.1.48
|
## 0.1.48
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "form",
|
"name": "form",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.48",
|
"version": "0.1.57",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -14,22 +14,22 @@
|
|||||||
"hash-slash": "workspace:*",
|
"hash-slash": "workspace:*",
|
||||||
"jazz-react": "workspace:*",
|
"jazz-react": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"react": "^18.3.1",
|
"react": "19.0.0",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "19.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@playwright/test": "^1.50.1",
|
"@playwright/test": "^1.50.1",
|
||||||
"@tailwindcss/forms": "^0.5.9",
|
"@tailwindcss/forms": "^0.5.9",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "19.0.0",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "19.0.0",
|
||||||
"@vitejs/plugin-react": "^4.3.3",
|
"@vitejs/plugin-react": "^4.5.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"globals": "^15.11.0",
|
"globals": "^15.11.0",
|
||||||
"is-ci": "^3.0.1",
|
"is-ci": "^3.0.1",
|
||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"vite": "6.0.11"
|
"vite": "6.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,75 @@
|
|||||||
# image-upload
|
# image-upload
|
||||||
|
|
||||||
|
## 0.0.113
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 0.0.112
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-react@0.14.18
|
||||||
|
|
||||||
|
## 0.0.111
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-react@0.14.17
|
||||||
|
|
||||||
|
## 0.0.110
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
|
||||||
|
## 0.0.109
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [f9590f9]
|
||||||
|
- jazz-react@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
|
||||||
|
## 0.0.108
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-react@0.14.14
|
||||||
|
|
||||||
|
## 0.0.107
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.13
|
||||||
|
|
||||||
|
## 0.0.106
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.12
|
||||||
|
|
||||||
|
## 0.0.105
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-react@0.14.10
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
|
||||||
## 0.0.104
|
## 0.0.104
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This is an example of how to upload and render images with Jazz.
|
This is an example of how to upload and render images with Jazz.
|
||||||
|
|
||||||
Live version: https://image-upload-demo.jazz.tools
|
Live version: [https://image-upload-demo.jazz.tools](https://image-upload-demo.jazz.tools)
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "image-upload",
|
"name": "image-upload",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.104",
|
"version": "0.0.113",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -13,17 +13,17 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jazz-react": "workspace:*",
|
"jazz-react": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"react": "^18.3.1",
|
"react": "19.0.0",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "19.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "19.0.0",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "19.0.0",
|
||||||
"@vitejs/plugin-react": "^4.3.3",
|
"@vitejs/plugin-react": "^4.5.1",
|
||||||
"globals": "^15.11.0",
|
"globals": "^15.11.0",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"vite": "6.0.11",
|
"vite": "6.3.5",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
"tailwindcss": "^3.4.17"
|
"tailwindcss": "^3.4.17"
|
||||||
|
|||||||
@@ -1,5 +1,72 @@
|
|||||||
# jazz-example-inspector
|
# jazz-example-inspector
|
||||||
|
|
||||||
|
## 0.0.166
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- cojson@0.14.19
|
||||||
|
- cojson-transport-ws@0.14.19
|
||||||
|
- jazz-inspector@0.14.19
|
||||||
|
|
||||||
|
## 0.0.165
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0d5ee3e]
|
||||||
|
- cojson@0.14.18
|
||||||
|
- jazz-inspector@0.14.18
|
||||||
|
- cojson-transport-ws@0.14.18
|
||||||
|
|
||||||
|
## 0.0.164
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.17
|
||||||
|
|
||||||
|
## 0.0.163
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [5e253cc]
|
||||||
|
- cojson@0.14.16
|
||||||
|
- cojson-transport-ws@0.14.16
|
||||||
|
- jazz-inspector@0.14.16
|
||||||
|
|
||||||
|
## 0.0.162
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [23daa7c]
|
||||||
|
- cojson@0.14.15
|
||||||
|
- cojson-transport-ws@0.14.15
|
||||||
|
- jazz-inspector@0.14.15
|
||||||
|
|
||||||
|
## 0.0.161
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.14
|
||||||
|
|
||||||
|
## 0.0.160
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.13
|
||||||
|
|
||||||
|
## 0.0.159
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.12
|
||||||
|
|
||||||
|
## 0.0.158
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- jazz-inspector@0.14.10
|
||||||
|
- hash-slash@0.2.3
|
||||||
|
|
||||||
## 0.0.157
|
## 0.0.157
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Jazz Inspector
|
# Jazz Inspector
|
||||||
|
|
||||||
Live address: https://inspector.jazz.tools
|
Live address: [https://inspector.jazz.tools](https://inspector.jazz.tools)
|
||||||
|
|
||||||
Use this to visually inspect a Jazz account or other CoValue.
|
Use this to visually inspect a Jazz account or other CoValue.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-inspector-app",
|
"name": "jazz-inspector-app",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.157",
|
"version": "0.0.166",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -17,20 +17,20 @@
|
|||||||
"cojson-transport-ws": "workspace:*",
|
"cojson-transport-ws": "workspace:*",
|
||||||
"hash-slash": "workspace:*",
|
"hash-slash": "workspace:*",
|
||||||
"lucide-react": "^0.274.0",
|
"lucide-react": "^0.274.0",
|
||||||
"react": "^18.3.1",
|
"react": "19.0.0",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "19.0.0",
|
||||||
"react-router": "^6.16.0",
|
"react-router": "^6.16.0",
|
||||||
"react-router-dom": "^6.16.0",
|
"react-router-dom": "^6.16.0",
|
||||||
"react-use": "^17.4.0"
|
"react-use": "^17.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "19.0.0",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "19.0.0",
|
||||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
"@vitejs/plugin-react-swc": "^3.10.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"vite": "6.0.11"
|
"vite": "6.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
41
examples/jazz-nextjs/.gitignore
vendored
Normal file
41
examples/jazz-nextjs/.gitignore
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.*
|
||||||
|
.yarn/*
|
||||||
|
!.yarn/patches
|
||||||
|
!.yarn/plugins
|
||||||
|
!.yarn/releases
|
||||||
|
!.yarn/versions
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# env files (can opt-in for committing if needed)
|
||||||
|
.env*
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
49
examples/jazz-nextjs/CHANGELOG.md
Normal file
49
examples/jazz-nextjs/CHANGELOG.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# jazz-nextjs
|
||||||
|
|
||||||
|
## 0.1.6
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 0.1.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-react@0.14.18
|
||||||
|
|
||||||
|
## 0.1.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-react@0.14.17
|
||||||
|
|
||||||
|
## 0.1.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
|
||||||
|
## 0.1.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [f9590f9]
|
||||||
|
- jazz-react@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
|
||||||
|
## 0.1.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-react@0.14.14
|
||||||
36
examples/jazz-nextjs/README.md
Normal file
36
examples/jazz-nextjs/README.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
First, run the development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or
|
||||||
|
yarn dev
|
||||||
|
# or
|
||||||
|
pnpm dev
|
||||||
|
# or
|
||||||
|
bun dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||||
|
|
||||||
|
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||||
|
|
||||||
|
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
To learn more about Next.js, take a look at the following resources:
|
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||||
|
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||||
|
|
||||||
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||||
|
|
||||||
|
## Deploy on Vercel
|
||||||
|
|
||||||
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||||
|
|
||||||
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||||
7
examples/jazz-nextjs/next.config.ts
Normal file
7
examples/jazz-nextjs/next.config.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
|
const nextConfig: NextConfig = {
|
||||||
|
/* config options here */
|
||||||
|
};
|
||||||
|
|
||||||
|
export default nextConfig;
|
||||||
26
examples/jazz-nextjs/package.json
Normal file
26
examples/jazz-nextjs/package.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "jazz-nextjs",
|
||||||
|
"version": "0.1.6",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev --turbopack",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0",
|
||||||
|
"next": "15.3.2",
|
||||||
|
"jazz-react": "workspace:*",
|
||||||
|
"jazz-tools": "workspace:*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5",
|
||||||
|
"@types/node": "^20",
|
||||||
|
"@types/react": "^19",
|
||||||
|
"@types/react-dom": "^19",
|
||||||
|
"@tailwindcss/postcss": "^4",
|
||||||
|
"tailwindcss": "^4"
|
||||||
|
}
|
||||||
|
}
|
||||||
5
examples/jazz-nextjs/postcss.config.mjs
Normal file
5
examples/jazz-nextjs/postcss.config.mjs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
const config = {
|
||||||
|
plugins: ["@tailwindcss/postcss"],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
26
examples/jazz-nextjs/src/app/globals.css
Normal file
26
examples/jazz-nextjs/src/app/globals.css
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--background: #ffffff;
|
||||||
|
--foreground: #171717;
|
||||||
|
}
|
||||||
|
|
||||||
|
@theme inline {
|
||||||
|
--color-background: var(--background);
|
||||||
|
--color-foreground: var(--foreground);
|
||||||
|
--font-sans: var(--font-geist-sans);
|
||||||
|
--font-mono: var(--font-geist-mono);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--background: #0a0a0a;
|
||||||
|
--foreground: #ededed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: var(--background);
|
||||||
|
color: var(--foreground);
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
35
examples/jazz-nextjs/src/app/layout.tsx
Normal file
35
examples/jazz-nextjs/src/app/layout.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import type { Metadata } from "next";
|
||||||
|
import { Geist, Geist_Mono } from "next/font/google";
|
||||||
|
import "./globals.css";
|
||||||
|
import { Jazz } from "../jazz";
|
||||||
|
|
||||||
|
const geistSans = Geist({
|
||||||
|
variable: "--font-geist-sans",
|
||||||
|
subsets: ["latin"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const geistMono = Geist_Mono({
|
||||||
|
variable: "--font-geist-mono",
|
||||||
|
subsets: ["latin"],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Create Next App",
|
||||||
|
description: "Generated by create next app",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: Readonly<{
|
||||||
|
children: React.ReactNode;
|
||||||
|
}>) {
|
||||||
|
return (
|
||||||
|
<html lang="en">
|
||||||
|
<body
|
||||||
|
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
||||||
|
>
|
||||||
|
<Jazz>{children}</Jazz>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
46
examples/jazz-nextjs/src/app/page.tsx
Normal file
46
examples/jazz-nextjs/src/app/page.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useAccount } from "jazz-react";
|
||||||
|
import { Account } from "jazz-tools";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
const { me } = useAccount(Account, {
|
||||||
|
resolve: {
|
||||||
|
profile: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center h-screen gap-4">
|
||||||
|
<h1 className="text-2xl font-bold">SSR rendering example with Jazz</h1>
|
||||||
|
<div className="text-sm text-gray-500 w-1/2 text-center">
|
||||||
|
Data is still loaded only on the client, the components are rendered on
|
||||||
|
the server with all the CoValues as null
|
||||||
|
</div>
|
||||||
|
<label>
|
||||||
|
<div className="text-sm">
|
||||||
|
Your profile name{" "}
|
||||||
|
<span className="text-xs">(only loaded on the client)</span>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
className="border-2 border-gray-300 rounded-md p-2 w-full"
|
||||||
|
value={me?.profile.name ?? ""}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (!me) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
me.profile.name = e.target.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<Link
|
||||||
|
href={`/profile/${me?.profile.id}`}
|
||||||
|
className="bg-blue-500 text-white px-4 py-2 rounded-md"
|
||||||
|
>
|
||||||
|
Your profile name in a Server Component
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
23
examples/jazz-nextjs/src/app/profile/[profileId]/page.tsx
Normal file
23
examples/jazz-nextjs/src/app/profile/[profileId]/page.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { jazzSSR } from "@/jazzSSR";
|
||||||
|
import { Profile } from "jazz-tools";
|
||||||
|
|
||||||
|
export default async function ServerSidePage(props: {
|
||||||
|
params: Promise<{ profileId: string }>;
|
||||||
|
}) {
|
||||||
|
const { profileId } = await props.params;
|
||||||
|
const profile = await Profile.load(profileId, {
|
||||||
|
loadAs: jazzSSR,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center h-screen gap-4">
|
||||||
|
<h1 className="text-2xl font-bold">SSR rendering example with Jazz</h1>
|
||||||
|
<div className="text-sm text-gray-500 w-1/2 text-center">
|
||||||
|
This is a server component!
|
||||||
|
</div>
|
||||||
|
<label>
|
||||||
|
<div className="text-sm">Your profile name "{profile?.name}"</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
16
examples/jazz-nextjs/src/jazz.tsx
Normal file
16
examples/jazz-nextjs/src/jazz.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { JazzProvider } from "jazz-react";
|
||||||
|
|
||||||
|
export function Jazz({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<JazzProvider
|
||||||
|
experimental_enableSSR
|
||||||
|
sync={{
|
||||||
|
peer: `wss://cloud.jazz.tools/`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</JazzProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
5
examples/jazz-nextjs/src/jazzSSR.ts
Normal file
5
examples/jazz-nextjs/src/jazzSSR.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { createSSRJazzAgent } from "jazz-react/ssr";
|
||||||
|
|
||||||
|
export const jazzSSR = createSSRJazzAgent({
|
||||||
|
peer: "wss://cloud.jazz.tools/",
|
||||||
|
});
|
||||||
27
examples/jazz-nextjs/tsconfig.json
Normal file
27
examples/jazz-nextjs/tsconfig.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2017",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
@@ -27,20 +27,20 @@
|
|||||||
"jazz-react": "workspace:*",
|
"jazz-react": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"lucide-react": "^0.485.0",
|
"lucide-react": "^0.485.0",
|
||||||
"react": "^18.3.1",
|
"react": "19.0.0",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "19.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.17",
|
"tailwindcss": "^4.0.17",
|
||||||
"tw-animate-css": "^1.2.5"
|
"tw-animate-css": "^1.2.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "19.0.0",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "19.0.0",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"jazz-run": "workspace:*",
|
"jazz-run": "workspace:*",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"tsx": "^4.19.3",
|
"tsx": "^4.19.3",
|
||||||
"typescript": "~5.6.2",
|
"typescript": "~5.6.2",
|
||||||
"vite": "6.0.11"
|
"vite": "6.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,75 @@
|
|||||||
# multi-cursors
|
# multi-cursors
|
||||||
|
|
||||||
|
## 0.0.109
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 0.0.108
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-react@0.14.18
|
||||||
|
|
||||||
|
## 0.0.107
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-react@0.14.17
|
||||||
|
|
||||||
|
## 0.0.106
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
|
||||||
|
## 0.0.105
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [f9590f9]
|
||||||
|
- jazz-react@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
|
||||||
|
## 0.0.104
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-react@0.14.14
|
||||||
|
|
||||||
|
## 0.0.103
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.13
|
||||||
|
|
||||||
|
## 0.0.102
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.12
|
||||||
|
|
||||||
|
## 0.0.101
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-react@0.14.10
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
|
||||||
## 0.0.100
|
## 0.0.100
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# Jazz Multi-Cursors Example
|
# Jazz Multi-Cursors Example
|
||||||
|
|
||||||
Track user presence on a canvas with multiple cursors and out of bounds indicators.
|
Track user presence on a canvas with multiple cursors and out of bounds indicators.
|
||||||
|
Live version: [https://multi-cursors-demo.jazz.tools/](https://multi-cursors-demo.jazz.tools/)
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "multi-cursors",
|
"name": "multi-cursors",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.100",
|
"version": "0.0.109",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -15,22 +15,22 @@
|
|||||||
"@react-spring/web": "^9.7.5",
|
"@react-spring/web": "^9.7.5",
|
||||||
"jazz-react": "workspace:*",
|
"jazz-react": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"react": "^18.3.1",
|
"react": "19.0.0",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "19.0.0",
|
||||||
"zod": "3.25.0-beta.20250518T002810"
|
"zod": "3.25.28"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "19.0.0",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "19.0.0",
|
||||||
"@vitejs/plugin-react": "^4.3.3",
|
"@vitejs/plugin-react": "^4.5.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"globals": "^15.11.0",
|
"globals": "^15.11.0",
|
||||||
"is-ci": "^3.0.1",
|
"is-ci": "^3.0.1",
|
||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"vite": "6.0.11",
|
"vite": "6.3.5",
|
||||||
"vitest": "3.1.1"
|
"vitest": "3.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ export function Cursor({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{/* @ts-expect-error - TODO: invalid after the React 19 upgrade */}
|
||||||
<animated.g
|
<animated.g
|
||||||
transform={to(
|
transform={to(
|
||||||
[springs.x, springs.y],
|
[springs.x, springs.y],
|
||||||
@@ -113,6 +114,7 @@ export function Cursor({
|
|||||||
isOutOfBounds={isStrictlyOutOfBounds}
|
isOutOfBounds={isStrictlyOutOfBounds}
|
||||||
/>
|
/>
|
||||||
{isStrictlyOutOfBounds ? (
|
{isStrictlyOutOfBounds ? (
|
||||||
|
// @ts-expect-error - TODO: invalid after the React 19 upgrade
|
||||||
<animated.g
|
<animated.g
|
||||||
transform={to(
|
transform={to(
|
||||||
[intersectionSprings.x, intersectionSprings.y],
|
[intersectionSprings.x, intersectionSprings.y],
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ export function CursorLabel({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{/* @ts-expect-error - TODO: invalid after the React 19 upgrade */}
|
||||||
<animated.text
|
<animated.text
|
||||||
ref={textRef}
|
ref={textRef}
|
||||||
x={to([labelSprings.x], (x) => x)}
|
x={to([labelSprings.x], (x) => x)}
|
||||||
|
|||||||
@@ -1,5 +1,84 @@
|
|||||||
# multiauth
|
# multiauth
|
||||||
|
|
||||||
|
## 0.0.57
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.19
|
||||||
|
- jazz-react-auth-clerk@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 0.0.56
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-react@0.14.18
|
||||||
|
- jazz-react-auth-clerk@0.14.18
|
||||||
|
|
||||||
|
## 0.0.55
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-react@0.14.17
|
||||||
|
- jazz-react-auth-clerk@0.14.17
|
||||||
|
|
||||||
|
## 0.0.54
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.16
|
||||||
|
- jazz-react-auth-clerk@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
|
||||||
|
## 0.0.53
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [f9590f9]
|
||||||
|
- jazz-react@0.14.15
|
||||||
|
- jazz-react-auth-clerk@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
|
||||||
|
## 0.0.52
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-react@0.14.14
|
||||||
|
- jazz-react-auth-clerk@0.14.14
|
||||||
|
|
||||||
|
## 0.0.51
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.13
|
||||||
|
- jazz-react-auth-clerk@0.14.13
|
||||||
|
|
||||||
|
## 0.0.50
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.14.12
|
||||||
|
- jazz-react-auth-clerk@0.14.12
|
||||||
|
|
||||||
|
## 0.0.49
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-react-auth-clerk@0.14.10
|
||||||
|
- jazz-react@0.14.10
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
|
||||||
## 0.0.48
|
## 0.0.48
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "multiauth",
|
"name": "multiauth",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.48",
|
"version": "0.0.57",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -15,16 +15,16 @@
|
|||||||
"jazz-react": "workspace:*",
|
"jazz-react": "workspace:*",
|
||||||
"jazz-react-auth-clerk": "workspace:*",
|
"jazz-react-auth-clerk": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"react": "^18.3.1",
|
"react": "19.0.0",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "19.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "19.0.0",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "19.0.0",
|
||||||
"@vitejs/plugin-react": "^4.3.3",
|
"@vitejs/plugin-react": "^4.5.1",
|
||||||
"globals": "^15.11.0",
|
"globals": "^15.11.0",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"vite": "6.0.11"
|
"vite": "6.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,84 @@
|
|||||||
# jazz-example-musicplayer
|
# jazz-example-musicplayer
|
||||||
|
|
||||||
|
## 0.0.138
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.19
|
||||||
|
- jazz-react@0.14.19
|
||||||
|
- jazz-tools@0.14.19
|
||||||
|
|
||||||
|
## 0.0.137
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [4b950bc]
|
||||||
|
- Updated dependencies [d6d9c0a]
|
||||||
|
- Updated dependencies [c559054]
|
||||||
|
- jazz-tools@0.14.18
|
||||||
|
- jazz-inspector@0.14.18
|
||||||
|
- jazz-react@0.14.18
|
||||||
|
|
||||||
|
## 0.0.136
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e512df4]
|
||||||
|
- jazz-tools@0.14.17
|
||||||
|
- jazz-inspector@0.14.17
|
||||||
|
- jazz-react@0.14.17
|
||||||
|
|
||||||
|
## 0.0.135
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.16
|
||||||
|
- jazz-react@0.14.16
|
||||||
|
- jazz-tools@0.14.16
|
||||||
|
|
||||||
|
## 0.0.134
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [f9590f9]
|
||||||
|
- jazz-react@0.14.15
|
||||||
|
- jazz-inspector@0.14.15
|
||||||
|
- jazz-tools@0.14.15
|
||||||
|
|
||||||
|
## 0.0.133
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e32a1f7]
|
||||||
|
- jazz-tools@0.14.14
|
||||||
|
- jazz-inspector@0.14.14
|
||||||
|
- jazz-react@0.14.14
|
||||||
|
|
||||||
|
## 0.0.132
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.13
|
||||||
|
- jazz-react@0.14.13
|
||||||
|
|
||||||
|
## 0.0.131
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-inspector@0.14.12
|
||||||
|
- jazz-react@0.14.12
|
||||||
|
|
||||||
|
## 0.0.130
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dc746a2]
|
||||||
|
- Updated dependencies [f869d9a]
|
||||||
|
- Updated dependencies [3fe6832]
|
||||||
|
- jazz-inspector@0.14.10
|
||||||
|
- jazz-react@0.14.10
|
||||||
|
- jazz-tools@0.14.10
|
||||||
|
|
||||||
## 0.0.129
|
## 0.0.129
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Music player example with Jazz and React
|
# Music player example with Jazz and React
|
||||||
|
|
||||||
Live version: https://music-demo.jazz.tools
|
Live version: [https://music-demo.jazz.tools](https://music-demo.jazz.tools)
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"rsc": false,
|
"rsc": false,
|
||||||
"tsx": true,
|
"tsx": true,
|
||||||
"tailwind": {
|
"tailwind": {
|
||||||
"config": "tailwind.config.js",
|
"config": "tailwind.config.ts",
|
||||||
"css": "src/index.css",
|
"css": "src/index.css",
|
||||||
"baseColor": "stone",
|
"baseColor": "stone",
|
||||||
"cssVariables": true
|
"cssVariables": true
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-example-music-player",
|
"name": "jazz-example-music-player",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.129",
|
"version": "0.0.138",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -16,17 +16,18 @@
|
|||||||
"@radix-ui/react-dialog": "^1.1.4",
|
"@radix-ui/react-dialog": "^1.1.4",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.1",
|
"@radix-ui/react-dropdown-menu": "^2.1.1",
|
||||||
"@radix-ui/react-label": "^2.1.1",
|
"@radix-ui/react-label": "^2.1.1",
|
||||||
|
"@radix-ui/react-separator": "^1.1.2",
|
||||||
"@radix-ui/react-slot": "^1.1.1",
|
"@radix-ui/react-slot": "^1.1.1",
|
||||||
"@radix-ui/react-toast": "^1.1.4",
|
"@radix-ui/react-toast": "^1.1.4",
|
||||||
"@radix-ui/react-tooltip": "^1.1.6",
|
"@radix-ui/react-tooltip": "^1.1.6",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"jazz-inspector": "workspace:*",
|
"jazz-inspector": "workspace:*",
|
||||||
"jazz-react": "workspace:*",
|
"jazz-react": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"lucide-react": "^0.274.0",
|
"lucide-react": "^0.274.0",
|
||||||
"react": "^18.3.1",
|
"react": "19.0.0",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "19.0.0",
|
||||||
"react-router": "^6.16.0",
|
"react-router": "^6.16.0",
|
||||||
"react-router-dom": "^6.16.0",
|
"react-router-dom": "^6.16.0",
|
||||||
"tailwind-merge": "^1.14.0",
|
"tailwind-merge": "^1.14.0",
|
||||||
@@ -34,13 +35,13 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.50.1",
|
"@playwright/test": "^1.50.1",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "19.0.0",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "19.0.0",
|
||||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
"@vitejs/plugin-react-swc": "^3.10.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "5.6.2",
|
"typescript": "5.6.2",
|
||||||
"vite": "6.0.11"
|
"vite": "6.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,14 @@ import { RouterProvider, createHashRouter } from "react-router-dom";
|
|||||||
import { HomePage } from "./3_HomePage";
|
import { HomePage } from "./3_HomePage";
|
||||||
import { useMediaPlayer } from "./5_useMediaPlayer";
|
import { useMediaPlayer } from "./5_useMediaPlayer";
|
||||||
import { InvitePage } from "./6_InvitePage";
|
import { InvitePage } from "./6_InvitePage";
|
||||||
import { PlayerControls } from "./components/PlayerControls";
|
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
|
|
||||||
import { MusicaAccount } from "@/1_schema";
|
import { MusicaAccount } from "@/1_schema";
|
||||||
import { apiKey } from "@/apiKey.ts";
|
import { apiKey } from "@/apiKey.ts";
|
||||||
|
import { SidebarProvider } from "@/components/ui/sidebar";
|
||||||
import { JazzProvider } from "jazz-react";
|
import { JazzProvider } from "jazz-react";
|
||||||
import { onAnonymousAccountDiscarded } from "./4_actions";
|
import { onAnonymousAccountDiscarded } from "./4_actions";
|
||||||
|
import { KeyboardListener } from "./components/PlayerControls";
|
||||||
import { useUploadExampleData } from "./lib/useUploadExampleData";
|
import { useUploadExampleData } from "./lib/useUploadExampleData";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,7 +51,7 @@ function Main() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
<PlayerControls mediaPlayer={mediaPlayer} />
|
<KeyboardListener mediaPlayer={mediaPlayer} />
|
||||||
<Toaster />
|
<Toaster />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -72,8 +73,10 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
|
|||||||
defaultProfileName="Anonymous unicorn"
|
defaultProfileName="Anonymous unicorn"
|
||||||
onAnonymousAccountDiscarded={onAnonymousAccountDiscarded}
|
onAnonymousAccountDiscarded={onAnonymousAccountDiscarded}
|
||||||
>
|
>
|
||||||
<Main />
|
<SidebarProvider>
|
||||||
<JazzInspector />
|
<Main />
|
||||||
|
<JazzInspector />
|
||||||
|
</SidebarProvider>
|
||||||
</JazzProvider>
|
</JazzProvider>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,16 +5,16 @@ import {
|
|||||||
useCoState,
|
useCoState,
|
||||||
useIsAuthenticated,
|
useIsAuthenticated,
|
||||||
} from "jazz-react";
|
} from "jazz-react";
|
||||||
import { useNavigate, useParams } from "react-router";
|
import { useParams } from "react-router";
|
||||||
import { MusicaAccount, Playlist } from "./1_schema";
|
import { MusicaAccount, Playlist } from "./1_schema";
|
||||||
import { createNewPlaylist, uploadMusicTracks } from "./4_actions";
|
import { uploadMusicTracks } from "./4_actions";
|
||||||
import { MediaPlayer } from "./5_useMediaPlayer";
|
import { MediaPlayer } from "./5_useMediaPlayer";
|
||||||
import { AuthButton } from "./components/AuthButton";
|
|
||||||
import { FileUploadButton } from "./components/FileUploadButton";
|
import { FileUploadButton } from "./components/FileUploadButton";
|
||||||
import { MusicTrackRow } from "./components/MusicTrackRow";
|
import { MusicTrackRow } from "./components/MusicTrackRow";
|
||||||
import { PlaylistTitleInput } from "./components/PlaylistTitleInput";
|
import { PlaylistTitleInput } from "./components/PlaylistTitleInput";
|
||||||
import { SidePanel } from "./components/SidePanel";
|
import { SidePanel } from "./components/SidePanel";
|
||||||
import { Button } from "./components/ui/button";
|
import { Button } from "./components/ui/button";
|
||||||
|
import { SidebarInset, SidebarTrigger } from "./components/ui/sidebar";
|
||||||
import { usePlayState } from "./lib/audio/usePlayState";
|
import { usePlayState } from "./lib/audio/usePlayState";
|
||||||
|
|
||||||
export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
||||||
@@ -26,7 +26,6 @@ export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
|||||||
resolve: { root: { rootPlaylist: true, playlists: true } },
|
resolve: { root: { rootPlaylist: true, playlists: true } },
|
||||||
});
|
});
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const playState = usePlayState();
|
const playState = usePlayState();
|
||||||
const isPlaying = playState.value === "play";
|
const isPlaying = playState.value === "play";
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
@@ -39,12 +38,6 @@ export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
|||||||
await uploadMusicTracks(files);
|
await uploadMusicTracks(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleCreatePlaylist() {
|
|
||||||
const playlist = await createNewPlaylist();
|
|
||||||
|
|
||||||
navigate(`/playlist/${playlist.id}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = useParams<{ playlistId: string }>();
|
const params = useParams<{ playlistId: string }>();
|
||||||
const playlistId = params.playlistId ?? me?.root._refs.rootPlaylist.id;
|
const playlistId = params.playlistId ?? me?.root._refs.rootPlaylist.id;
|
||||||
|
|
||||||
@@ -71,10 +64,11 @@ export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
|||||||
const isAuthenticated = useIsAuthenticated();
|
const isAuthenticated = useIsAuthenticated();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-screen text-gray-800 bg-blue-50">
|
<SidebarInset className="flex flex-col h-screen text-gray-800 bg-blue-50">
|
||||||
<div className="flex flex-1 overflow-hidden">
|
<div className="flex flex-1 overflow-hidden">
|
||||||
<SidePanel />
|
<SidePanel mediaPlayer={mediaPlayer} />
|
||||||
<main className="flex-1 p-6 overflow-y-auto">
|
<main className="flex-1 p-6 overflow-y-auto overflow-x-hidden">
|
||||||
|
<SidebarTrigger />
|
||||||
<div className="flex items-center justify-between mb-6">
|
<div className="flex items-center justify-between mb-6">
|
||||||
{isRootPlaylist ? (
|
{isRootPlaylist ? (
|
||||||
<h1 className="text-2xl font-bold text-blue-800">All tracks</h1>
|
<h1 className="text-2xl font-bold text-blue-800">All tracks</h1>
|
||||||
@@ -87,7 +81,6 @@ export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
|||||||
<FileUploadButton onFileLoad={handleFileLoad}>
|
<FileUploadButton onFileLoad={handleFileLoad}>
|
||||||
Add file
|
Add file
|
||||||
</FileUploadButton>
|
</FileUploadButton>
|
||||||
<Button onClick={handleCreatePlaylist}>New playlist</Button>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{!isRootPlaylist && isAuthenticated && (
|
{!isRootPlaylist && isAuthenticated && (
|
||||||
@@ -95,10 +88,9 @@ export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
|||||||
Share playlist
|
Share playlist
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<AuthButton />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul className="flex flex-col">
|
<ul className="flex flex-col max-w-full">
|
||||||
{playlist?.tracks?.map(
|
{playlist?.tracks?.map(
|
||||||
(track) =>
|
(track) =>
|
||||||
track && (
|
track && (
|
||||||
@@ -121,6 +113,6 @@ export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
|||||||
</ul>
|
</ul>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</SidebarInset>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export function AuthButton() {
|
|||||||
|
|
||||||
if (isAuthenticated) {
|
if (isAuthenticated) {
|
||||||
return (
|
return (
|
||||||
<Button variant="outline" onClick={handleSignOut}>
|
<Button variant="ghost" onClick={handleSignOut}>
|
||||||
Sign out
|
Sign out
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
@@ -28,10 +28,7 @@ export function AuthButton() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button onClick={() => setOpen(true)} variant="ghost">
|
||||||
onClick={() => setOpen(true)}
|
|
||||||
className="bg-white text-black hover:bg-gray-100"
|
|
||||||
>
|
|
||||||
Sign up
|
Sign up
|
||||||
</Button>
|
</Button>
|
||||||
<AuthModal open={open} onOpenChange={setOpen} />
|
<AuthModal open={open} onOpenChange={setOpen} />
|
||||||
|
|||||||
@@ -62,9 +62,7 @@ export function MusicTrackRow({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className={
|
className={"flex gap-1 hover:bg-slate-200 group py-2 px-2 cursor-pointer"}
|
||||||
"flex gap-1 hover:bg-slate-200 group py-2 px-2 cursor-pointer"
|
|
||||||
}
|
|
||||||
onClick={handleTrackClick}
|
onClick={handleTrackClick}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export function MusicTrackTitleInput({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="relative flex-grow"
|
className="relative flex-grow max-w-64"
|
||||||
onClick={(evt) => evt.stopPropagation()}
|
onClick={(evt) => evt.stopPropagation()}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -15,13 +15,6 @@ export function PlayerControls({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
|||||||
resolve: { root: { activePlaylist: true } },
|
resolve: { root: { activePlaylist: true } },
|
||||||
}).me?.root.activePlaylist;
|
}).me?.root.activePlaylist;
|
||||||
|
|
||||||
useMediaEndListener(mediaPlayer.playNextTrack);
|
|
||||||
useKeyboardListener("Space", () => {
|
|
||||||
if (document.activeElement !== document.body) return;
|
|
||||||
|
|
||||||
playState.toggle();
|
|
||||||
});
|
|
||||||
|
|
||||||
const activeTrack = useCoState(MusicTrack, mediaPlayer.activeTrackId, {
|
const activeTrack = useCoState(MusicTrack, mediaPlayer.activeTrackId, {
|
||||||
resolve: { waveform: true },
|
resolve: { waveform: true },
|
||||||
});
|
});
|
||||||
@@ -73,3 +66,18 @@ export function PlayerControls({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
|||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function KeyboardListener({
|
||||||
|
mediaPlayer,
|
||||||
|
}: { mediaPlayer: MediaPlayer }) {
|
||||||
|
const playState = usePlayState();
|
||||||
|
|
||||||
|
useMediaEndListener(mediaPlayer.playNextTrack);
|
||||||
|
useKeyboardListener("Space", () => {
|
||||||
|
if (document.activeElement !== document.body) return;
|
||||||
|
|
||||||
|
playState.toggle();
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,27 +1,40 @@
|
|||||||
import { MusicaAccount } from "@/1_schema";
|
import { MusicTrack, MusicaAccount } from "@/1_schema";
|
||||||
import { deletePlaylist } from "@/4_actions";
|
import { createNewPlaylist, deletePlaylist } from "@/4_actions";
|
||||||
import { useAccount } from "jazz-react";
|
import { MediaPlayer } from "@/5_useMediaPlayer";
|
||||||
import { Trash2 } from "lucide-react";
|
import {
|
||||||
|
Sidebar,
|
||||||
|
SidebarContent,
|
||||||
|
SidebarFooter,
|
||||||
|
SidebarGroup,
|
||||||
|
SidebarGroupContent,
|
||||||
|
SidebarGroupLabel,
|
||||||
|
SidebarHeader,
|
||||||
|
SidebarMenu,
|
||||||
|
SidebarMenuAction,
|
||||||
|
SidebarMenuButton,
|
||||||
|
SidebarMenuItem,
|
||||||
|
} from "@/components/ui/sidebar";
|
||||||
|
import { usePlayState } from "@/lib/audio/usePlayState";
|
||||||
|
import { useAccount, useCoState } from "jazz-react";
|
||||||
|
import { Home, Music, Pause, Play, Plus, Trash2 } from "lucide-react";
|
||||||
import { useNavigate, useParams } from "react-router";
|
import { useNavigate, useParams } from "react-router";
|
||||||
import { LocalOnlyTag } from "./LocalOnlyTag";
|
import { AuthButton } from "./AuthButton";
|
||||||
|
|
||||||
export function SidePanel() {
|
export function SidePanel({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
||||||
const { playlistId } = useParams();
|
const { playlistId } = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { me } = useAccount(MusicaAccount, {
|
const { me } = useAccount(MusicaAccount, {
|
||||||
resolve: { root: { playlists: { $each: true } } },
|
resolve: { root: { playlists: { $each: true } } },
|
||||||
});
|
});
|
||||||
|
|
||||||
function handleAllTracksClick(evt: React.MouseEvent<HTMLAnchorElement>) {
|
const playState = usePlayState();
|
||||||
evt.preventDefault();
|
const isPlaying = playState.value === "play";
|
||||||
|
|
||||||
|
function handleAllTracksClick() {
|
||||||
navigate(`/`);
|
navigate(`/`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePlaylistClick(
|
function handlePlaylistClick(playlistId: string) {
|
||||||
evt: React.MouseEvent<HTMLAnchorElement>,
|
|
||||||
playlistId: string,
|
|
||||||
) {
|
|
||||||
evt.preventDefault();
|
|
||||||
navigate(`/playlist/${playlistId}`);
|
navigate(`/playlist/${playlistId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,73 +45,121 @@ export function SidePanel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleCreatePlaylist() {
|
||||||
|
const playlist = await createNewPlaylist();
|
||||||
|
navigate(`/playlist/${playlist.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const activeTrack = useCoState(MusicTrack, mediaPlayer.activeTrackId, {
|
||||||
|
resolve: { waveform: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
const activeTrackTitle = activeTrack?.title;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className="w-64 p-6 bg-white overflow-y-auto">
|
<Sidebar>
|
||||||
<div className="flex items-center mb-1">
|
<SidebarHeader>
|
||||||
<svg
|
<SidebarMenu>
|
||||||
className="w-8 h-8 mr-2"
|
<SidebarMenuItem className="flex items-center gap-2">
|
||||||
viewBox="0 0 24 24"
|
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-blue-600 text-white">
|
||||||
fill="none"
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
className="size-4"
|
||||||
>
|
viewBox="0 0 24 24"
|
||||||
<path
|
fill="none"
|
||||||
d="M9 18V5l12-2v13"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
stroke="#3b82f6"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M6 15H3c-1.1 0-2 .9-2 2v4c0 1.1.9 2 2 2h3c1.1 0 2-.9 2-2v-4c0-1.1-.9-2-2-2zM18 13h-3c-1.1 0-2 .9-2 2v4c0 1.1.9 2 2 2h3c1.1 0 2-.9 2-2v-4c0-1.1-.9-2-2-2z"
|
|
||||||
fill="#3b82f6"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<span className="text-xl font-bold text-blue-600">Music Player</span>
|
|
||||||
</div>
|
|
||||||
<div className="mb-6">
|
|
||||||
<LocalOnlyTag />
|
|
||||||
</div>
|
|
||||||
<nav>
|
|
||||||
<h2 className="mb-2 text-sm font-semibold text-gray-600">Playlists</h2>
|
|
||||||
<ul className="space-y-1">
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
className={`block px-2 py-1 text-sm rounded ${
|
|
||||||
!playlistId ? "bg-blue-100 text-blue-600" : "hover:bg-blue-100"
|
|
||||||
}`}
|
|
||||||
onClick={handleAllTracksClick}
|
|
||||||
>
|
|
||||||
All tracks
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{me?.root.playlists.map((playlist, index) => (
|
|
||||||
<li
|
|
||||||
key={index}
|
|
||||||
className={`px-2 py-1 flex transition-all duration-300 rounded items-center justify-between ${
|
|
||||||
playlist.id === playlistId ? "bg-blue-100" : ""
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
className={`w-full text-sm`}
|
|
||||||
onClick={(evt) => handlePlaylistClick(evt, playlist.id)}
|
|
||||||
>
|
>
|
||||||
{playlist.title}
|
<path
|
||||||
</a>
|
d="M9 18V5l12-2v13"
|
||||||
{playlist.id === playlistId && (
|
stroke="currentColor"
|
||||||
<button
|
strokeWidth="2"
|
||||||
onClick={() => handleDeletePlaylist(playlist.id)}
|
strokeLinecap="round"
|
||||||
className="ml-2 text-red-600 hover:text-red-800 animate-in fade-in scale-in duration-200"
|
strokeLinejoin="round"
|
||||||
aria-label={`Delete ${playlist.title}`}
|
/>
|
||||||
>
|
<path
|
||||||
<Trash2 size={16} />
|
d="M6 15H3c-1.1 0-2 .9-2 2v4c0 1.1.9 2 2 2h3c1.1 0 2-.9 2-2v-4c0-1.1-.9-2-2-2zM18 13h-3c-1.1 0-2 .9-2 2v4c0 1.1.9 2 2 2h3c1.1 0 2-.9 2-2v-4c0-1.1-.9-2-2-2z"
|
||||||
</button>
|
fill="currentColor"
|
||||||
)}
|
/>
|
||||||
</li>
|
</svg>
|
||||||
))}
|
</div>
|
||||||
</ul>
|
<div className="grid flex-1 text-left text-sm leading-tight">
|
||||||
</nav>
|
<span className="truncate font-semibold">Music Player</span>
|
||||||
</aside>
|
</div>
|
||||||
|
<AuthButton />
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</SidebarMenu>
|
||||||
|
</SidebarHeader>
|
||||||
|
<SidebarContent>
|
||||||
|
<SidebarGroup>
|
||||||
|
<SidebarGroupContent>
|
||||||
|
<SidebarMenu>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton onClick={handleAllTracksClick}>
|
||||||
|
<Home className="size-4" />
|
||||||
|
<span>Go to all tracks</span>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</SidebarMenu>
|
||||||
|
</SidebarGroupContent>
|
||||||
|
</SidebarGroup>
|
||||||
|
<SidebarGroup>
|
||||||
|
<SidebarGroupLabel>Playlists</SidebarGroupLabel>
|
||||||
|
<SidebarGroupContent>
|
||||||
|
<SidebarMenu>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton onClick={handleCreatePlaylist}>
|
||||||
|
<Plus className="size-4" />
|
||||||
|
<span>Add a new playlist</span>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
{me?.root.playlists.map((playlist) => (
|
||||||
|
<SidebarMenuItem key={playlist.id}>
|
||||||
|
<SidebarMenuButton
|
||||||
|
onClick={() => handlePlaylistClick(playlist.id)}
|
||||||
|
isActive={playlist.id === playlistId}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Music className="size-4" />
|
||||||
|
<span>{playlist.title}</span>
|
||||||
|
</div>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
{playlist.id === playlistId && (
|
||||||
|
<SidebarMenuAction
|
||||||
|
onClick={() => handleDeletePlaylist(playlist.id)}
|
||||||
|
className="text-red-600 hover:text-red-800"
|
||||||
|
>
|
||||||
|
<Trash2 className="size-4" />
|
||||||
|
<span className="sr-only">Delete {playlist.title}</span>
|
||||||
|
</SidebarMenuAction>
|
||||||
|
)}
|
||||||
|
</SidebarMenuItem>
|
||||||
|
))}
|
||||||
|
</SidebarMenu>
|
||||||
|
</SidebarGroupContent>
|
||||||
|
</SidebarGroup>
|
||||||
|
</SidebarContent>
|
||||||
|
{activeTrack && (
|
||||||
|
<SidebarFooter>
|
||||||
|
<SidebarMenu>
|
||||||
|
<SidebarMenuItem className="flex justify-end">
|
||||||
|
<SidebarMenuButton
|
||||||
|
onClick={playState.toggle}
|
||||||
|
aria-label={
|
||||||
|
isPlaying ? "Pause active track" : "Play active track"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="w-[28px] h-[28px] flex items-center justify-center bg-blue-600 rounded-full text-white hover:bg-blue-700">
|
||||||
|
{isPlaying ? (
|
||||||
|
<Pause size={16} fill="currentColor" />
|
||||||
|
) : (
|
||||||
|
<Play size={16} fill="currentColor" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<span>{activeTrackTitle}</span>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</SidebarMenu>
|
||||||
|
</SidebarFooter>
|
||||||
|
)}
|
||||||
|
</Sidebar>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import * as React from "react";
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
@@ -53,5 +53,4 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|||||||
);
|
);
|
||||||
Button.displayName = "Button";
|
Button.displayName = "Button";
|
||||||
|
|
||||||
// eslint-disable-next-line react-refresh/only-export-components
|
|
||||||
export { Button, buttonVariants };
|
export { Button, buttonVariants };
|
||||||
|
|||||||
29
examples/music-player/src/components/ui/separator.tsx
Normal file
29
examples/music-player/src/components/ui/separator.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const Separator = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
||||||
|
>(
|
||||||
|
(
|
||||||
|
{ className, orientation = "horizontal", decorative = true, ...props },
|
||||||
|
ref,
|
||||||
|
) => (
|
||||||
|
<SeparatorPrimitive.Root
|
||||||
|
ref={ref}
|
||||||
|
decorative={decorative}
|
||||||
|
orientation={orientation}
|
||||||
|
className={cn(
|
||||||
|
"shrink-0 bg-border",
|
||||||
|
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
||||||
|
|
||||||
|
export { Separator };
|
||||||
140
examples/music-player/src/components/ui/sheet.tsx
Normal file
140
examples/music-player/src/components/ui/sheet.tsx
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
||||||
|
import { type VariantProps, cva } from "class-variance-authority";
|
||||||
|
import { X } from "lucide-react";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const Sheet = SheetPrimitive.Root;
|
||||||
|
|
||||||
|
const SheetTrigger = SheetPrimitive.Trigger;
|
||||||
|
|
||||||
|
const SheetClose = SheetPrimitive.Close;
|
||||||
|
|
||||||
|
const SheetPortal = SheetPrimitive.Portal;
|
||||||
|
|
||||||
|
const SheetOverlay = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SheetPrimitive.Overlay>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<SheetPrimitive.Overlay
|
||||||
|
className={cn(
|
||||||
|
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
ref={ref}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
||||||
|
|
||||||
|
const sheetVariants = cva(
|
||||||
|
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
side: {
|
||||||
|
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
||||||
|
bottom:
|
||||||
|
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
||||||
|
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
||||||
|
right:
|
||||||
|
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
side: "right",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
interface SheetContentProps
|
||||||
|
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
||||||
|
VariantProps<typeof sheetVariants> {}
|
||||||
|
|
||||||
|
const SheetContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SheetPrimitive.Content>,
|
||||||
|
SheetContentProps
|
||||||
|
>(({ side = "right", className, children, ...props }, ref) => (
|
||||||
|
<SheetPortal>
|
||||||
|
<SheetOverlay />
|
||||||
|
<SheetPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
className={cn(sheetVariants({ side }), className)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
<span className="sr-only">Close</span>
|
||||||
|
</SheetPrimitive.Close>
|
||||||
|
</SheetPrimitive.Content>
|
||||||
|
</SheetPortal>
|
||||||
|
));
|
||||||
|
SheetContent.displayName = SheetPrimitive.Content.displayName;
|
||||||
|
|
||||||
|
const SheetHeader = ({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex flex-col space-y-2 text-center sm:text-left",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
SheetHeader.displayName = "SheetHeader";
|
||||||
|
|
||||||
|
const SheetFooter = ({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
SheetFooter.displayName = "SheetFooter";
|
||||||
|
|
||||||
|
const SheetTitle = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SheetPrimitive.Title>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<SheetPrimitive.Title
|
||||||
|
ref={ref}
|
||||||
|
className={cn("text-lg font-semibold text-foreground", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
||||||
|
|
||||||
|
const SheetDescription = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SheetPrimitive.Description>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<SheetPrimitive.Description
|
||||||
|
ref={ref}
|
||||||
|
className={cn("text-sm text-muted-foreground", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
||||||
|
|
||||||
|
export {
|
||||||
|
Sheet,
|
||||||
|
SheetPortal,
|
||||||
|
SheetOverlay,
|
||||||
|
SheetTrigger,
|
||||||
|
SheetClose,
|
||||||
|
SheetContent,
|
||||||
|
SheetHeader,
|
||||||
|
SheetFooter,
|
||||||
|
SheetTitle,
|
||||||
|
SheetDescription,
|
||||||
|
};
|
||||||
779
examples/music-player/src/components/ui/sidebar.tsx
Normal file
779
examples/music-player/src/components/ui/sidebar.tsx
Normal file
@@ -0,0 +1,779 @@
|
|||||||
|
import { Slot } from "@radix-ui/react-slot";
|
||||||
|
import { VariantProps, cva } from "class-variance-authority";
|
||||||
|
import { PanelLeft } from "lucide-react";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import {
|
||||||
|
Sheet,
|
||||||
|
SheetContent,
|
||||||
|
SheetDescription,
|
||||||
|
SheetHeader,
|
||||||
|
SheetTitle,
|
||||||
|
} from "@/components/ui/sheet";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip";
|
||||||
|
import { useIsMobile } from "@/hooks/use-mobile";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const SIDEBAR_COOKIE_NAME = "sidebar_state";
|
||||||
|
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
||||||
|
const SIDEBAR_WIDTH = "16rem";
|
||||||
|
const SIDEBAR_WIDTH_MOBILE = "18rem";
|
||||||
|
const SIDEBAR_WIDTH_ICON = "3rem";
|
||||||
|
const SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
||||||
|
|
||||||
|
type SidebarContextProps = {
|
||||||
|
state: "expanded" | "collapsed";
|
||||||
|
open: boolean;
|
||||||
|
setOpen: (open: boolean) => void;
|
||||||
|
openMobile: boolean;
|
||||||
|
setOpenMobile: (open: boolean) => void;
|
||||||
|
isMobile: boolean;
|
||||||
|
toggleSidebar: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SidebarContext = React.createContext<SidebarContextProps | null>(null);
|
||||||
|
|
||||||
|
function useSidebar() {
|
||||||
|
const context = React.useContext(SidebarContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useSidebar must be used within a SidebarProvider.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SidebarProvider = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.ComponentProps<"div"> & {
|
||||||
|
defaultOpen?: boolean;
|
||||||
|
open?: boolean;
|
||||||
|
onOpenChange?: (open: boolean) => void;
|
||||||
|
}
|
||||||
|
>(
|
||||||
|
(
|
||||||
|
{
|
||||||
|
defaultOpen = true,
|
||||||
|
open: openProp,
|
||||||
|
onOpenChange: setOpenProp,
|
||||||
|
className,
|
||||||
|
style,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
},
|
||||||
|
ref,
|
||||||
|
) => {
|
||||||
|
const isMobile = useIsMobile();
|
||||||
|
const [openMobile, setOpenMobile] = React.useState(false);
|
||||||
|
|
||||||
|
// This is the internal state of the sidebar.
|
||||||
|
// We use openProp and setOpenProp for control from outside the component.
|
||||||
|
const [_open, _setOpen] = React.useState(defaultOpen);
|
||||||
|
const open = openProp ?? _open;
|
||||||
|
const setOpen = React.useCallback(
|
||||||
|
(value: boolean | ((value: boolean) => boolean)) => {
|
||||||
|
const openState = typeof value === "function" ? value(open) : value;
|
||||||
|
if (setOpenProp) {
|
||||||
|
setOpenProp(openState);
|
||||||
|
} else {
|
||||||
|
_setOpen(openState);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This sets the cookie to keep the sidebar state.
|
||||||
|
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
||||||
|
},
|
||||||
|
[setOpenProp, open],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Helper to toggle the sidebar.
|
||||||
|
const toggleSidebar = React.useCallback(() => {
|
||||||
|
return isMobile
|
||||||
|
? setOpenMobile((open) => !open)
|
||||||
|
: setOpen((open) => !open);
|
||||||
|
}, [isMobile, setOpen, setOpenMobile]);
|
||||||
|
|
||||||
|
// Adds a keyboard shortcut to toggle the sidebar.
|
||||||
|
React.useEffect(() => {
|
||||||
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
|
if (
|
||||||
|
event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
|
||||||
|
(event.metaKey || event.ctrlKey)
|
||||||
|
) {
|
||||||
|
event.preventDefault();
|
||||||
|
toggleSidebar();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("keydown", handleKeyDown);
|
||||||
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||||
|
}, [toggleSidebar]);
|
||||||
|
|
||||||
|
// We add a state so that we can do data-state="expanded" or "collapsed".
|
||||||
|
// This makes it easier to style the sidebar with Tailwind classes.
|
||||||
|
const state = open ? "expanded" : "collapsed";
|
||||||
|
|
||||||
|
const contextValue = React.useMemo<SidebarContextProps>(
|
||||||
|
() => ({
|
||||||
|
state,
|
||||||
|
open,
|
||||||
|
setOpen,
|
||||||
|
isMobile,
|
||||||
|
openMobile,
|
||||||
|
setOpenMobile,
|
||||||
|
toggleSidebar,
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
state,
|
||||||
|
open,
|
||||||
|
setOpen,
|
||||||
|
isMobile,
|
||||||
|
openMobile,
|
||||||
|
setOpenMobile,
|
||||||
|
toggleSidebar,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SidebarContext.Provider value={contextValue}>
|
||||||
|
<TooltipProvider delayDuration={0}>
|
||||||
|
<div
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--sidebar-width": SIDEBAR_WIDTH,
|
||||||
|
"--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
|
||||||
|
...style,
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
className={cn(
|
||||||
|
"group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</TooltipProvider>
|
||||||
|
</SidebarContext.Provider>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
SidebarProvider.displayName = "SidebarProvider";
|
||||||
|
|
||||||
|
const Sidebar = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.ComponentProps<"div"> & {
|
||||||
|
side?: "left" | "right";
|
||||||
|
variant?: "sidebar" | "floating" | "inset";
|
||||||
|
collapsible?: "offcanvas" | "icon" | "none";
|
||||||
|
}
|
||||||
|
>(
|
||||||
|
(
|
||||||
|
{
|
||||||
|
side = "left",
|
||||||
|
variant = "sidebar",
|
||||||
|
collapsible = "offcanvas",
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
},
|
||||||
|
ref,
|
||||||
|
) => {
|
||||||
|
const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
|
||||||
|
|
||||||
|
if (collapsible === "none") {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMobile) {
|
||||||
|
return (
|
||||||
|
<Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
|
||||||
|
<SheetContent
|
||||||
|
data-sidebar="sidebar"
|
||||||
|
data-mobile="true"
|
||||||
|
className="w-[--sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--sidebar-width": SIDEBAR_WIDTH_MOBILE,
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
side={side}
|
||||||
|
>
|
||||||
|
<SheetHeader className="sr-only">
|
||||||
|
<SheetTitle>Sidebar</SheetTitle>
|
||||||
|
<SheetDescription>Displays the mobile sidebar.</SheetDescription>
|
||||||
|
</SheetHeader>
|
||||||
|
<div className="flex h-full w-full flex-col">{children}</div>
|
||||||
|
</SheetContent>
|
||||||
|
</Sheet>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className="group peer hidden text-sidebar-foreground md:block"
|
||||||
|
data-state={state}
|
||||||
|
data-collapsible={state === "collapsed" ? collapsible : ""}
|
||||||
|
data-variant={variant}
|
||||||
|
data-side={side}
|
||||||
|
>
|
||||||
|
{/* This is what handles the sidebar gap on desktop */}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"relative w-[--sidebar-width] bg-transparent transition-[width] duration-200 ease-linear",
|
||||||
|
"group-data-[collapsible=offcanvas]:w-0",
|
||||||
|
"group-data-[side=right]:rotate-180",
|
||||||
|
variant === "floating" || variant === "inset"
|
||||||
|
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]"
|
||||||
|
: "group-data-[collapsible=icon]:w-[--sidebar-width-icon]",
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"fixed inset-y-0 z-10 hidden h-svh w-[--sidebar-width] transition-[left,right,width] duration-200 ease-linear md:flex",
|
||||||
|
side === "left"
|
||||||
|
? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
|
||||||
|
: "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
|
||||||
|
// Adjust the padding for floating and inset variants.
|
||||||
|
variant === "floating" || variant === "inset"
|
||||||
|
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]"
|
||||||
|
: "group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-sidebar="sidebar"
|
||||||
|
className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow"
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
Sidebar.displayName = "Sidebar";
|
||||||
|
|
||||||
|
const SidebarTrigger = React.forwardRef<
|
||||||
|
React.ElementRef<typeof Button>,
|
||||||
|
React.ComponentProps<typeof Button>
|
||||||
|
>(({ className, onClick, ...props }, ref) => {
|
||||||
|
const { toggleSidebar } = useSidebar();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="trigger"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className={cn("h-7 w-7", className)}
|
||||||
|
onClick={(event) => {
|
||||||
|
onClick?.(event);
|
||||||
|
toggleSidebar();
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<PanelLeft />
|
||||||
|
<span className="sr-only">Toggle Sidebar</span>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarTrigger.displayName = "SidebarTrigger";
|
||||||
|
|
||||||
|
const SidebarRail = React.forwardRef<
|
||||||
|
HTMLButtonElement,
|
||||||
|
React.ComponentProps<"button">
|
||||||
|
>(({ className, ...props }, ref) => {
|
||||||
|
const { toggleSidebar } = useSidebar();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="rail"
|
||||||
|
aria-label="Toggle Sidebar"
|
||||||
|
tabIndex={-1}
|
||||||
|
onClick={toggleSidebar}
|
||||||
|
title="Toggle Sidebar"
|
||||||
|
className={cn(
|
||||||
|
"absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex",
|
||||||
|
"[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize",
|
||||||
|
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
|
||||||
|
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar",
|
||||||
|
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
|
||||||
|
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarRail.displayName = "SidebarRail";
|
||||||
|
|
||||||
|
const SidebarInset = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.ComponentProps<"main">
|
||||||
|
>(({ className, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<main
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"relative flex w-full flex-1 flex-col bg-background",
|
||||||
|
"md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarInset.displayName = "SidebarInset";
|
||||||
|
|
||||||
|
const SidebarInput = React.forwardRef<
|
||||||
|
React.ElementRef<typeof Input>,
|
||||||
|
React.ComponentProps<typeof Input>
|
||||||
|
>(({ className, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="input"
|
||||||
|
className={cn(
|
||||||
|
"h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarInput.displayName = "SidebarInput";
|
||||||
|
|
||||||
|
const SidebarHeader = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.ComponentProps<"div">
|
||||||
|
>(({ className, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="header"
|
||||||
|
className={cn("flex flex-col gap-2 p-2", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarHeader.displayName = "SidebarHeader";
|
||||||
|
|
||||||
|
const SidebarFooter = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.ComponentProps<"div">
|
||||||
|
>(({ className, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="footer"
|
||||||
|
className={cn("flex flex-col gap-2 p-2", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarFooter.displayName = "SidebarFooter";
|
||||||
|
|
||||||
|
const SidebarSeparator = React.forwardRef<
|
||||||
|
React.ElementRef<typeof Separator>,
|
||||||
|
React.ComponentProps<typeof Separator>
|
||||||
|
>(({ className, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<Separator
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="separator"
|
||||||
|
className={cn("mx-2 w-auto bg-sidebar-border", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarSeparator.displayName = "SidebarSeparator";
|
||||||
|
|
||||||
|
const SidebarContent = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.ComponentProps<"div">
|
||||||
|
>(({ className, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="content"
|
||||||
|
className={cn(
|
||||||
|
"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarContent.displayName = "SidebarContent";
|
||||||
|
|
||||||
|
const SidebarGroup = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.ComponentProps<"div">
|
||||||
|
>(({ className, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="group"
|
||||||
|
className={cn("relative flex w-full min-w-0 flex-col p-2", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarGroup.displayName = "SidebarGroup";
|
||||||
|
|
||||||
|
const SidebarGroupLabel = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.ComponentProps<"div"> & { asChild?: boolean }
|
||||||
|
>(({ className, asChild = false, ...props }, ref) => {
|
||||||
|
const Comp = asChild ? Slot : "div";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Comp
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="group-label"
|
||||||
|
className={cn(
|
||||||
|
"flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||||
|
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarGroupLabel.displayName = "SidebarGroupLabel";
|
||||||
|
|
||||||
|
const SidebarGroupAction = React.forwardRef<
|
||||||
|
HTMLButtonElement,
|
||||||
|
React.ComponentProps<"button"> & { asChild?: boolean }
|
||||||
|
>(({ className, asChild = false, ...props }, ref) => {
|
||||||
|
const Comp = asChild ? Slot : "button";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Comp
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="group-action"
|
||||||
|
className={cn(
|
||||||
|
"absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||||
|
// Increases the hit area of the button on mobile.
|
||||||
|
"after:absolute after:-inset-2 after:md:hidden",
|
||||||
|
"group-data-[collapsible=icon]:hidden",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarGroupAction.displayName = "SidebarGroupAction";
|
||||||
|
|
||||||
|
const SidebarGroupContent = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.ComponentProps<"div">
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="group-content"
|
||||||
|
className={cn("w-full text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
SidebarGroupContent.displayName = "SidebarGroupContent";
|
||||||
|
|
||||||
|
const SidebarMenu = React.forwardRef<
|
||||||
|
HTMLUListElement,
|
||||||
|
React.ComponentProps<"ul">
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<ul
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="menu"
|
||||||
|
className={cn("flex w-full min-w-0 flex-col gap-1", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
SidebarMenu.displayName = "SidebarMenu";
|
||||||
|
|
||||||
|
const SidebarMenuItem = React.forwardRef<
|
||||||
|
HTMLLIElement,
|
||||||
|
React.ComponentProps<"li">
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<li
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="menu-item"
|
||||||
|
className={cn("group/menu-item relative", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
SidebarMenuItem.displayName = "SidebarMenuItem";
|
||||||
|
|
||||||
|
const sidebarMenuButtonVariants = cva(
|
||||||
|
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
||||||
|
outline:
|
||||||
|
"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]",
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
default: "h-8 text-sm",
|
||||||
|
sm: "h-7 text-xs",
|
||||||
|
lg: "h-12 text-sm group-data-[collapsible=icon]:!p-0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: "default",
|
||||||
|
size: "default",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const SidebarMenuButton = React.forwardRef<
|
||||||
|
HTMLButtonElement,
|
||||||
|
React.ComponentProps<"button"> & {
|
||||||
|
asChild?: boolean;
|
||||||
|
isActive?: boolean;
|
||||||
|
tooltip?: string | React.ComponentProps<typeof TooltipContent>;
|
||||||
|
} & VariantProps<typeof sidebarMenuButtonVariants>
|
||||||
|
>(
|
||||||
|
(
|
||||||
|
{
|
||||||
|
asChild = false,
|
||||||
|
isActive = false,
|
||||||
|
variant = "default",
|
||||||
|
size = "default",
|
||||||
|
tooltip,
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
},
|
||||||
|
ref,
|
||||||
|
) => {
|
||||||
|
const Comp = asChild ? Slot : "button";
|
||||||
|
const { isMobile, state } = useSidebar();
|
||||||
|
|
||||||
|
const button = (
|
||||||
|
<Comp
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="menu-button"
|
||||||
|
data-size={size}
|
||||||
|
data-active={isActive}
|
||||||
|
className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!tooltip) {
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof tooltip === "string") {
|
||||||
|
tooltip = {
|
||||||
|
children: tooltip,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>{button}</TooltipTrigger>
|
||||||
|
<TooltipContent
|
||||||
|
side="right"
|
||||||
|
align="center"
|
||||||
|
hidden={state !== "collapsed" || isMobile}
|
||||||
|
{...tooltip}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
SidebarMenuButton.displayName = "SidebarMenuButton";
|
||||||
|
|
||||||
|
const SidebarMenuAction = React.forwardRef<
|
||||||
|
HTMLButtonElement,
|
||||||
|
React.ComponentProps<"button"> & {
|
||||||
|
asChild?: boolean;
|
||||||
|
showOnHover?: boolean;
|
||||||
|
}
|
||||||
|
>(({ className, asChild = false, showOnHover = false, ...props }, ref) => {
|
||||||
|
const Comp = asChild ? Slot : "button";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Comp
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="menu-action"
|
||||||
|
className={cn(
|
||||||
|
"absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0",
|
||||||
|
// Increases the hit area of the button on mobile.
|
||||||
|
"after:absolute after:-inset-2 after:md:hidden",
|
||||||
|
"peer-data-[size=sm]/menu-button:top-1",
|
||||||
|
"peer-data-[size=default]/menu-button:top-1.5",
|
||||||
|
"peer-data-[size=lg]/menu-button:top-2.5",
|
||||||
|
"group-data-[collapsible=icon]:hidden",
|
||||||
|
showOnHover &&
|
||||||
|
"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarMenuAction.displayName = "SidebarMenuAction";
|
||||||
|
|
||||||
|
const SidebarMenuBadge = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.ComponentProps<"div">
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="menu-badge"
|
||||||
|
className={cn(
|
||||||
|
"pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground",
|
||||||
|
"peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground",
|
||||||
|
"peer-data-[size=sm]/menu-button:top-1",
|
||||||
|
"peer-data-[size=default]/menu-button:top-1.5",
|
||||||
|
"peer-data-[size=lg]/menu-button:top-2.5",
|
||||||
|
"group-data-[collapsible=icon]:hidden",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
SidebarMenuBadge.displayName = "SidebarMenuBadge";
|
||||||
|
|
||||||
|
const SidebarMenuSkeleton = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.ComponentProps<"div"> & {
|
||||||
|
showIcon?: boolean;
|
||||||
|
}
|
||||||
|
>(({ className, showIcon = false, ...props }, ref) => {
|
||||||
|
// Random width between 50 to 90%.
|
||||||
|
const width = React.useMemo(() => {
|
||||||
|
return `${Math.floor(Math.random() * 40) + 50}%`;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="menu-skeleton"
|
||||||
|
className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{showIcon && (
|
||||||
|
<Skeleton
|
||||||
|
className="size-4 rounded-md"
|
||||||
|
data-sidebar="menu-skeleton-icon"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Skeleton
|
||||||
|
className="h-4 max-w-[--skeleton-width] flex-1"
|
||||||
|
data-sidebar="menu-skeleton-text"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--skeleton-width": width,
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarMenuSkeleton.displayName = "SidebarMenuSkeleton";
|
||||||
|
|
||||||
|
const SidebarMenuSub = React.forwardRef<
|
||||||
|
HTMLUListElement,
|
||||||
|
React.ComponentProps<"ul">
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<ul
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="menu-sub"
|
||||||
|
className={cn(
|
||||||
|
"mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5",
|
||||||
|
"group-data-[collapsible=icon]:hidden",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
SidebarMenuSub.displayName = "SidebarMenuSub";
|
||||||
|
|
||||||
|
const SidebarMenuSubItem = React.forwardRef<
|
||||||
|
HTMLLIElement,
|
||||||
|
React.ComponentProps<"li">
|
||||||
|
>(({ ...props }, ref) => <li ref={ref} {...props} />);
|
||||||
|
SidebarMenuSubItem.displayName = "SidebarMenuSubItem";
|
||||||
|
|
||||||
|
const SidebarMenuSubButton = React.forwardRef<
|
||||||
|
HTMLAnchorElement,
|
||||||
|
React.ComponentProps<"a"> & {
|
||||||
|
asChild?: boolean;
|
||||||
|
size?: "sm" | "md";
|
||||||
|
isActive?: boolean;
|
||||||
|
}
|
||||||
|
>(({ asChild = false, size = "md", isActive, className, ...props }, ref) => {
|
||||||
|
const Comp = asChild ? Slot : "a";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Comp
|
||||||
|
ref={ref}
|
||||||
|
data-sidebar="menu-sub-button"
|
||||||
|
data-size={size}
|
||||||
|
data-active={isActive}
|
||||||
|
className={cn(
|
||||||
|
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
|
||||||
|
"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
|
||||||
|
size === "sm" && "text-xs",
|
||||||
|
size === "md" && "text-sm",
|
||||||
|
"group-data-[collapsible=icon]:hidden",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
SidebarMenuSubButton.displayName = "SidebarMenuSubButton";
|
||||||
|
|
||||||
|
export {
|
||||||
|
Sidebar,
|
||||||
|
SidebarContent,
|
||||||
|
SidebarFooter,
|
||||||
|
SidebarGroup,
|
||||||
|
SidebarGroupAction,
|
||||||
|
SidebarGroupContent,
|
||||||
|
SidebarGroupLabel,
|
||||||
|
SidebarHeader,
|
||||||
|
SidebarInput,
|
||||||
|
SidebarInset,
|
||||||
|
SidebarMenu,
|
||||||
|
SidebarMenuAction,
|
||||||
|
SidebarMenuBadge,
|
||||||
|
SidebarMenuButton,
|
||||||
|
SidebarMenuItem,
|
||||||
|
SidebarMenuSkeleton,
|
||||||
|
SidebarMenuSub,
|
||||||
|
SidebarMenuSubButton,
|
||||||
|
SidebarMenuSubItem,
|
||||||
|
SidebarProvider,
|
||||||
|
SidebarRail,
|
||||||
|
SidebarSeparator,
|
||||||
|
SidebarTrigger,
|
||||||
|
useSidebar,
|
||||||
|
};
|
||||||
15
examples/music-player/src/components/ui/skeleton.tsx
Normal file
15
examples/music-player/src/components/ui/skeleton.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
function Skeleton({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLDivElement>) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn("animate-pulse rounded-md bg-muted", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Skeleton };
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
@@ -19,7 +17,7 @@ const TooltipContent = React.forwardRef<
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-tooltip-content-transform-origin]",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user