Compare commits

...

80 Commits

Author SHA1 Message Date
Guido D'Orsi
8d7d62d64f Merge pull request #2194 from garden-co/changeset-release/main
Version Packages
2025-05-12 19:09:18 +02:00
github-actions[bot]
65a8227b2b Version Packages 2025-05-12 14:58:57 +00:00
Guido D'Orsi
a846e0730e fix: block load of invalid ids on a lower level and do not break sync when getting invalid ids 2025-05-12 16:56:32 +02:00
Trisha Lim
e9c0e65170 Merge pull request #2190 from garden-co/improvement/homepage-cta
homepage: improve CTA, move problem section down
2025-05-12 15:53:55 +01:00
Trisha Lim
14636606bd homepage: improve CTA, move problem section down 2025-05-12 14:59:31 +01:00
Guido D'Orsi
5118ff6585 chore: remove unused typecheck clause 2025-05-12 14:34:45 +02:00
Guido D'Orsi
51a0f86b99 test: add tests on the load API for unavailable retry 2025-05-12 14:34:45 +02:00
Guido D'Orsi
fa61ab4eb5 chore: make the retries use CO_VALUE_LOADING_CONFIG 2025-05-12 14:34:45 +02:00
Trisha Lim
d4cdd43cf7 Merge pull request #2173 from garden-co/docs/change-role
add docs for changing roles and removing members in a Group
2025-05-12 10:05:48 +01:00
Anselm Eickhoff
c5d5fb25f7 Merge pull request #2183 from garden-co/jmsv/jazz-tiptap
jazz-richtext-tiptap
2025-05-10 12:27:18 +01:00
James Vickery
38f2276fdd version example app 2025-05-10 12:19:48 +01:00
James Vickery
b92bfce041 jazz-richtext-tiptap 2025-05-10 12:18:27 +01:00
Benjamin S. Leveritt
e3fd7bf6e3 Merge pull request #2154 from garden-co/1816-update-examples-to-coplaintext
Update examples to CoPlainText
2025-05-09 20:18:30 +01:00
Benjamin S. Leveritt
7526e444d6 Merge origin/main into 1816-update-examples-to-coplaintext 2025-05-09 20:00:59 +01:00
Benjamin S. Leveritt
28522bd062 Merge origin/main into 1816-update-examples-to-coplaintext 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
824be82f94 Adds a note for React use of CoText 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
8a9ef8ac78 Update chat-rn-expo-clerk with shorthands 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
5fb2f959f1 Fix comment 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
7a900d43f3 Fix formatting 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
c8624d56d2 Updates richtext with shorthands 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
8ed7c3947d Updates version-history with shorthands 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
ec0e61a442 Updates todo with shorthands 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
824d417d4e Updates form with shorthands 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
9f1ce81e09 Updates chat-vue with shorthands 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
48b32b6a72 Updates chat-rn with shorthands 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
03fec5f1b3 Updates chat with new CoPlainText shorthands 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
cdd7ac98cc Update examples/form/src/OrderForm.tsx
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
8218a272ee Update chat-rn-expo-clerk to CoPlainText 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
25d146ead8 Update chat-vue to CoPlainText 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
3f4d493286 Update chat-rn to CoPlainText 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
d476b06d0e Update version-history to CoPlainText 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
22baf1f547 Update todo to CoPlainText
Replace text with CoPlainText in todo
2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
d6ec873b1e Update form to CoPlainText 2025-05-09 20:00:38 +01:00
Benjamin S. Leveritt
160b30406b Update chat to CoPlainText 2025-05-09 20:00:38 +01:00
Guido D'Orsi
3e473eff50 chore: skip flaky test 2025-05-09 18:44:36 +02:00
Guido D'Orsi
47ad35085e Merge pull request #2179 from garden-co/changeset-release/main
Version Packages
2025-05-09 18:42:53 +02:00
github-actions[bot]
0b0d06ea44 Version Packages 2025-05-09 16:40:20 +00:00
Guido D'Orsi
ec546b4cd6 fix(svelte): fix return type of the id callback to accept undefined values 2025-05-09 18:38:24 +02:00
Guido D'Orsi
cadc5ef913 Merge pull request #2177 from garden-co/changeset-release/main
Version Packages
2025-05-09 18:14:32 +02:00
github-actions[bot]
f961dedbd0 Version Packages 2025-05-09 16:11:48 +00:00
Guido D'Orsi
c7b27e902b Merge pull request #2110 from garden-co/filestream-metadata
feat(FileStream): add getMetadata to easily get file metadata without having to process all the file chunks
2025-05-09 18:07:15 +02:00
Guido D'Orsi
b1cbc9283a Merge pull request #2174 from garden-co/feat/svelte-classes
feat(svelte):  new CoState and AccountCoState APIs
2025-05-09 18:05:02 +02:00
Guido D'Orsi
f2c7c20a75 Merge pull request #2176 from garden-co/changeset-release/main
Version Packages
2025-05-09 17:58:47 +02:00
Guido D'Orsi
53705d0ac1 test: fix file-share-svelte e2e test 2025-05-09 17:47:35 +02:00
github-actions[bot]
4031b7532f Version Packages 2025-05-09 15:41:11 +00:00
Guido D'Orsi
5ac43c300d Merge pull request #2123 from garden-co/repro-rnquickcrypto-chat-signature-issue
Fix the InvalidSignature issues on RNQuickCrypto
2025-05-09 17:39:16 +02:00
Guido D'Orsi
064174501e Merge remote-tracking branch 'origin/main' into repro-rnquickcrypto-chat-signature-issue 2025-05-09 17:21:32 +02:00
Guido D'Orsi
b0c2a5a53f changeset 2025-05-09 17:20:09 +02:00
Guido D'Orsi
24d9a6b7e1 chore: cleanup 2025-05-09 17:16:24 +02:00
Guido D'Orsi
e270295387 chore: add comments to ignore binding_property_non_reactive 2025-05-09 17:13:13 +02:00
Guido D'Orsi
67fa7be0d4 feat(svelte): react to id changes b accepting an id callback, remove the version state 2025-05-09 16:40:17 +02:00
Guido D'Orsi
3431076350 feat: add CoState and AccountCoState class APIs to subscribe CoValues for better integration with Svelte runes 2025-05-09 15:51:35 +02:00
Guido D'Orsi
e8092141e8 Merge pull request #2175 from garden-co/improvement/inspector-in-starter
embed inspector component in react starter app
2025-05-09 15:29:25 +02:00
Guido D'Orsi
a2aac6791d Merge pull request #2171 from garden-co/docs/vanilla-inspector
update inspector docs to include vanilla, vue, svelte
2025-05-09 15:29:14 +02:00
Trisha Lim
aebd1519c3 embed inspector component in react starter app 2025-05-09 14:00:29 +01:00
Trisha Lim
a9cf6da27a add docs for changing roles and removing members in a Group 2025-05-09 13:47:00 +01:00
Guido D'Orsi
2e0378639c fix env access 2025-05-09 14:42:19 +02:00
Trisha Lim
5ba76eeab5 update inspector docs to include vanilla, vue, svelte 2025-05-09 13:31:04 +01:00
Guido D'Orsi
279fc1c390 test: skip flaky test on CI 2025-05-08 21:32:44 +02:00
Brad Anderson
865b0e81a7 chore: remove debug stuffs 2025-05-08 15:32:07 -04:00
Guido D'Orsi
829ab08873 Merge pull request #2165 from garden-co/changeset-release/main
Version Packages
2025-05-08 21:28:50 +02:00
github-actions[bot]
2c9b08a080 Version Packages 2025-05-08 19:27:22 +00:00
Guido D'Orsi
48bda8854f Merge pull request #2163 from garden-co/vanilla-inspector
feat: package jazz-inspector as custom element
2025-05-08 21:24:59 +02:00
Brad Anderson
2858db7419 fix: bump RNQC to version with verify fix 2025-05-08 15:18:40 -04:00
Guido D'Orsi
96ed9adf59 Merge pull request #2142 from garden-co/feat/simplify-accept-invite
feat: simplified the acceptInvite method and cleaned the coValue transfer methods
2025-05-08 18:21:03 +02:00
Guido D'Orsi
5e4905ca99 test: add sync invite tests 2025-05-08 18:18:03 +02:00
Guido D'Orsi
1d4949b70c Merge remote-tracking branch 'origin/main' into feat/simplify-accept-invite 2025-05-08 18:08:02 +02:00
Guido D'Orsi
7dacfd03f9 Merge remote-tracking branch 'origin/main' into vanilla-inspector 2025-05-08 18:05:55 +02:00
Guido D'Orsi
bd4191520e Merge pull request #2164 from garden-co/fix/sync-browser-flaky-test
test: fix the flakiness on a browser integration test
2025-05-08 18:05:19 +02:00
Guido D'Orsi
e3dfb1b06e test: fix the flakiness on a browser integration test 2025-05-08 18:05:06 +02:00
Guido D'Orsi
7de210f225 feat: package jazz-inspector as custom element 2025-05-08 17:48:49 +02:00
Brad Anderson
d456a8c124 fix: regex to stop dupes (for realz) 2025-05-08 10:58:51 -04:00
Guido D'Orsi
1676ff852a fix: remove a broken JSON.stringify from expectCoValueLoaded error 2025-05-08 16:14:24 +02:00
Guido D'Orsi
2217e12ba6 clearUserCredentials 2025-05-08 10:08:27 -04:00
Guido D'Orsi
519eda0ac2 fix: skip profileID check 2025-05-08 09:59:30 -04:00
Brad Anderson
a8725abfb4 fix: XCode 16.3 bug fix, RNQuickCrypto remove dead code 2025-05-08 09:40:19 -04:00
Guido D'Orsi
2229e5a64f Create a repro for the InvalidSignature issues on RNQuickCrypto 2025-05-08 09:40:18 -04:00
Guido D'Orsi
e14e61f7d9 feat: simplified the acceptInvite method and cleaned the coValue transfer methods 2025-05-07 16:23:57 +02:00
Guido D'Orsi
02a240ce75 feat(FileStream): add getMetadata to easily get file metadata 2025-05-05 11:20:10 +02:00
Guido D'Orsi
6b781cf4a6 feat(RawBinaryCoStreamView): add getBinaryStreamInfo to retrieve file info without processing all the chunks 2025-05-05 11:18:42 +02:00
214 changed files with 4443 additions and 438 deletions

View File

@@ -15,6 +15,7 @@
"jazz-browser-media-images",
"jazz-expo",
"jazz-inspector",
"jazz-inspector-element",
"jazz-nodejs",
"jazz-react",
"jazz-react-core",

View File

@@ -1,5 +1,36 @@
# chat-rn-expo-clerk
## 1.0.116
### Patch Changes
- jazz-expo@0.13.25
- jazz-tools@0.13.25
- jazz-react-native-media-images@0.13.25
## 1.0.115
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-expo@0.13.23
- jazz-react-native-media-images@0.13.23
## 1.0.114
### Patch Changes
- jazz-expo@0.13.22
## 1.0.113
### Patch Changes
- jazz-expo@0.13.21
- jazz-tools@0.13.21
- jazz-react-native-media-images@0.13.21
## 1.0.112
### Patch Changes

View File

@@ -7,7 +7,7 @@ import { useLocalSearchParams } from "expo-router";
import { useAccount, useCoState } from "jazz-expo";
import { ProgressiveImg } from "jazz-expo";
import { createImage } from "jazz-react-native-media-images";
import { Group, ID } from "jazz-tools";
import { CoPlainText, Group, ID } from "jazz-tools";
import { useEffect, useLayoutEffect, useState } from "react";
import React, {
SafeAreaView,
@@ -71,8 +71,8 @@ export default function Conversation() {
const loadChat = async (chatId: ID<Chat>) => {
try {
const chat = await Chat.load(chatId, me);
setChat(chat);
const chat = await Chat.load(chatId);
if (chat) setChat(chat);
} catch (error) {
console.log("Error loading chat", error);
Alert.alert("Error", `Error loading chat: ${error}`);
@@ -82,7 +82,12 @@ export default function Conversation() {
const sendMessage = () => {
if (!chat) return;
if (message.trim()) {
chat.push(Message.create({ text: message }, { owner: chat._owner }));
chat.push(
Message.create(
{ text: CoPlainText.create(message, chat._owner) },
chat._owner,
),
);
setMessage("");
}
};
@@ -104,7 +109,12 @@ export default function Conversation() {
maxSize: 2048,
});
chat.push(Message.create({ text: "", image }, { owner: chat._owner }));
chat.push(
Message.create(
{ text: CoPlainText.create("", chat._owner), image },
chat._owner,
),
);
}
} catch (error) {
Alert.alert("Error", "Failed to upload image");

View File

@@ -1,7 +1,7 @@
{
"name": "chat-rn-expo-clerk",
"main": "index.js",
"version": "1.0.112",
"version": "1.0.116",
"scripts": {
"build": "expo export -p ios",
"start": "expo start",

View File

@@ -1,7 +1,7 @@
import { CoList, CoMap, ImageDefinition, co } from "jazz-tools";
import { CoList, CoMap, CoPlainText, ImageDefinition, co } from "jazz-tools";
export class Message extends CoMap {
text = co.string;
text = co.ref(CoPlainText);
image = co.optional.ref(ImageDefinition);
}

View File

@@ -1,5 +1,33 @@
# chat-rn-expo
## 1.0.103
### Patch Changes
- jazz-expo@0.13.25
- jazz-tools@0.13.25
## 1.0.102
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-expo@0.13.23
## 1.0.101
### Patch Changes
- jazz-expo@0.13.22
## 1.0.100
### Patch Changes
- jazz-expo@0.13.21
- jazz-tools@0.13.21
## 1.0.99
### Patch Changes

View File

@@ -0,0 +1,55 @@
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);
};

View File

@@ -1,6 +1,6 @@
{
"name": "chat-rn-expo",
"version": "1.0.99",
"version": "1.0.103",
"main": "index.js",
"scripts": {
"build": "expo export -p ios",
@@ -36,6 +36,8 @@
"react-dom": "18.3.1",
"react-native": "0.76.7",
"react-native-get-random-values": "^1.11.0",
"react-native-nitro-modules": "0.25.2",
"react-native-quick-crypto": "1.0.0-beta.15",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "4.4.0",
"react-native-url-polyfill": "^2.0.0",

View File

@@ -6,6 +6,7 @@ import {
} 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";
@@ -46,6 +47,7 @@ function App() {
return (
<StrictMode>
<JazzProvider
CryptoProvider={RNQuickCrypto}
sync={{
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
}}

View File

@@ -1,5 +1,42 @@
# chat-rn
## 1.0.111
### Patch Changes
- Updated dependencies [a846e07]
- cojson@0.13.25
- cojson-transport-ws@0.13.25
- jazz-react-native@0.13.25
- jazz-tools@0.13.25
## 1.0.110
### Patch Changes
- Updated dependencies [6b781cf]
- Updated dependencies [02a240c]
- cojson@0.13.23
- jazz-tools@0.13.23
- cojson-transport-ws@0.13.23
- jazz-react-native@0.13.23
## 1.0.109
### Patch Changes
- jazz-react-native@0.13.22
## 1.0.108
### Patch Changes
- Updated dependencies [e14e61f]
- cojson@0.13.21
- cojson-transport-ws@0.13.21
- jazz-react-native@0.13.21
- jazz-tools@0.13.21
## 1.0.107
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-rn",
"version": "1.0.107",
"version": "1.0.111",
"main": "index.js",
"scripts": {
"android": "react-native run-android",

View File

@@ -1,6 +1,6 @@
import Clipboard from "@react-native-clipboard/clipboard";
import { useAccount, useCoState } from "jazz-react-native";
import { Group, ID, Profile } from "jazz-tools";
import { CoPlainText, Group, ID, Profile } from "jazz-tools";
import { useEffect, useState } from "react";
import {
Alert,
@@ -83,7 +83,10 @@ export function ChatScreen({ navigation }: { navigation: any }) {
if (!loadedChat) return;
if (message.trim()) {
loadedChat.push(
Message.create({ text: message }, { owner: loadedChat?._owner }),
Message.create(
{ text: CoPlainText.create(message, loadedChat?._owner) },
loadedChat?._owner,
),
);
setMessage("");
}

View File

@@ -1,7 +1,7 @@
import { CoList, CoMap, co } from "jazz-tools";
import { CoList, CoMap, CoPlainText, co } from "jazz-tools";
export class Message extends CoMap {
text = co.string;
text = co.ref(CoPlainText);
}
export class Chat extends CoList.Of(co.ref(Message)) {}

View File

@@ -1,5 +1,30 @@
# chat-vue
## 0.0.94
### Patch Changes
- jazz-browser@0.13.25
- jazz-tools@0.13.25
- jazz-vue@0.13.25
## 0.0.93
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-browser@0.13.23
- jazz-vue@0.13.23
## 0.0.92
### Patch Changes
- jazz-browser@0.13.21
- jazz-tools@0.13.21
- jazz-vue@0.13.21
## 0.0.91
### Patch Changes

View File

@@ -1,11 +1,11 @@
{
"name": "chat-vue",
"version": "0.0.91",
"version": "0.0.94",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build-type-check": "run-p type-check \"build-only {@}\" --",
"build-type-check": "run-p type-check \"build {@}\" --",
"preview": "vite preview",
"build": "vite build",
"type-check": "vue-tsc --build --force",

View File

@@ -1,9 +1,9 @@
<template>
<BubbleContainer :fromMe="lastEdit.by?.isMe">
<BubbleBody>{{ msg.text }}</BubbleBody>
<BubbleInfo :by="lastEdit.by?.profile?.name" :madeAt="lastEdit.madeAt" />
</BubbleContainer>
</template>
<BubbleContainer :fromMe="lastEdit.by?.isMe">
<BubbleBody>{{ msg.text }}</BubbleBody>
<BubbleInfo :by="lastEdit.by?.profile?.name" :madeAt="lastEdit.madeAt" />
</BubbleContainer>
</template>
<script lang="ts">
import { computed, defineComponent } from "vue";

View File

@@ -1,7 +1,7 @@
import { CoList, CoMap, co } from "jazz-tools";
import { CoList, CoMap, CoPlainText, co } from "jazz-tools";
export class Message extends CoMap {
text = co.string;
text = co.ref(CoPlainText);
}
export class Chat extends CoList.Of(co.ref(Message)) {}

View File

@@ -25,7 +25,7 @@
</template>
<script lang="ts">
import type { ID } from "jazz-tools";
import { CoPlainText, type ID } from "jazz-tools";
import { useCoState } from "jazz-vue";
import { type PropType, computed, defineComponent, ref } from "vue";
import ChatBody from "../components/ChatBody.vue";
@@ -61,7 +61,12 @@ export default defineComponent({
}
function handleSubmit(text: string) {
chat?.value?.push(Message.create({ text }, { owner: chat.value._owner }));
chat?.value?.push(
Message.create(
{ text: CoPlainText.create(text, chat.value._owner) },
chat.value._owner,
),
);
}
return {

View File

@@ -1,5 +1,31 @@
# jazz-example-chat
## 0.0.192
### Patch Changes
- jazz-inspector@0.13.25
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.191
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-inspector@0.13.23
- jazz-react@0.13.23
## 0.0.190
### Patch Changes
- Updated dependencies [7de210f]
- jazz-inspector@0.13.21
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.189
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-chat",
"private": true,
"version": "0.0.189",
"version": "0.0.192",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,5 @@
import { createImage, useAccount, useCoState } from "jazz-react";
import { Account, ID } from "jazz-tools";
import { Account, CoPlainText, ID } from "jazz-tools";
import { useState } from "react";
import { Chat, Message } from "./schema.ts";
import {
@@ -36,7 +36,15 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
}
createImage(file, { owner: chat._owner }).then((image) => {
chat.push(Message.create({ text: file.name, image: image }, chat._owner));
chat.push(
Message.create(
{
text: CoPlainText.create(file.name, chat._owner),
image: image,
},
chat._owner,
),
);
});
};
@@ -66,7 +74,12 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
<TextInput
onSubmit={(text) => {
chat.push(Message.create({ text }, { owner: chat._owner }));
chat.push(
Message.create(
{ text: CoPlainText.create(text, chat._owner) },
chat._owner,
),
);
}}
/>
</InputBar>
@@ -75,7 +88,7 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
}
function ChatBubble(props: { me: Account; msg: Message }) {
if (!props.me.canRead(props.msg)) {
if (!props.me.canRead(props.msg) || !props.msg.text?.toString()) {
return (
<BubbleContainer fromMe={false}>
<BubbleBody fromMe={false}>

View File

@@ -1,7 +1,7 @@
import { CoList, CoMap, ImageDefinition, co } from "jazz-tools";
import { CoList, CoMap, CoPlainText, ImageDefinition, co } from "jazz-tools";
export class Message extends CoMap {
text = co.string;
text = co.ref(CoPlainText);
image = co.optional.ref(ImageDefinition);
}

View File

@@ -1,6 +1,6 @@
import clsx from "clsx";
import { ProgressiveImg } from "jazz-react";
import { ImageDefinition } from "jazz-tools";
import { CoPlainText, ImageDefinition } from "jazz-tools";
import { ImageIcon } from "lucide-react";
import { useId, useRef } from "react";
@@ -70,7 +70,10 @@ export function BubbleBody(props: {
);
}
export function BubbleText(props: { text: string; className?: string }) {
export function BubbleText(props: {
text: CoPlainText | string;
className?: string;
}) {
return (
<p className={clsx("px-2 leading-relaxed", props.className)}>
{props.text}

View File

@@ -1,5 +1,30 @@
# minimal-auth-clerk
## 0.0.91
### Patch Changes
- jazz-react@0.13.25
- jazz-react-auth-clerk@0.13.25
- jazz-tools@0.13.25
## 0.0.90
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
- jazz-react-auth-clerk@0.13.23
## 0.0.89
### Patch Changes
- jazz-react@0.13.21
- jazz-react-auth-clerk@0.13.21
- jazz-tools@0.13.21
## 0.0.88
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "clerk",
"private": true,
"version": "0.0.88",
"version": "0.0.91",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,38 @@
# file-share-svelte
## 0.0.75
### Patch Changes
- jazz-svelte@0.13.25
- jazz-tools@0.13.25
- jazz-inspector-element@0.13.25
## 0.0.74
### Patch Changes
- Updated dependencies [ec546b4]
- jazz-svelte@0.13.24
## 0.0.73
### Patch Changes
- Updated dependencies [3431076]
- Updated dependencies [02a240c]
- jazz-svelte@0.13.23
- jazz-tools@0.13.23
- jazz-inspector-element@0.13.23
## 0.0.72
### Patch Changes
- jazz-inspector-element@0.13.21
- jazz-svelte@0.13.21
- jazz-tools@0.13.21
## 0.0.71
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "file-share-svelte",
"version": "0.0.71",
"version": "0.0.75",
"private": true,
"type": "module",
"scripts": {
@@ -39,6 +39,7 @@
},
"dependencies": {
"@tailwindcss/typography": "^0.5.15",
"jazz-inspector-element": "workspace:*",
"jazz-svelte": "workspace:*",
"jazz-tools": "workspace:*",
"lucide-svelte": "^0.463.0",

View File

@@ -3,9 +3,8 @@
import { SharedFile } from '$lib/schema';
import { FileStream } from 'jazz-tools';
import { File, FileDown, Trash2, Link2 } from 'lucide-svelte';
import { useAccount } from 'jazz-svelte';
import { toast } from 'svelte-sonner';
import { formatFileSize } from '$lib/utils';
import { downloadFileBlob, formatFileSize } from '$lib/utils';
const {
file,
@@ -17,32 +16,22 @@
onDelete: (file: SharedFile) => void;
} = $props();
const { me } = useAccount();
const isAdmin = $derived(me && file._owner?.myRole() === 'admin');
const isAdmin = $derived(file._owner?.myRole() === 'admin');
const fileStreamId = $derived(file._refs.file?.id);
async function downloadFile() {
if (!file._refs.file?.id || !me) {
if (!fileStreamId) {
toast.error('Failed to download file');
return;
}
try {
const fileId = file._refs.file.id;
// Load the file as a blob, can take a while
const blob = await FileStream.loadAsBlob(fileId);
const blob = await FileStream.loadAsBlob(fileStreamId);
if (!blob) {
toast.error('Failed to download file');
return;
}
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = file.name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
downloadFileBlob(blob, file.name);
toast.success('File downloaded successfully');
} catch (error) {
console.error('Error downloading file:', error);
@@ -66,14 +55,19 @@
class="flex items-center justify-between rounded-lg border border-gray-200 bg-white p-4"
transition:slide={{ duration: 200 }}
>
<div class="flex items-center space-x-4">
<div class="flex items-center space-x-4 flex-grow">
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-blue-600">
<File class="h-6 w-6" />
</div>
<div>
<a href="/file/{file.id}" class="hover:text-blue-600 hover:underline">
<div class="flex-grow">
{#if isAdmin}
<label class="sr-only" for={`file-name-${file.id}`}>File name</label>
<!-- Jazz values are reactive, but they are not recognized as reactive by Svelte -->
<!-- svelte-ignore binding_property_non_reactive -->
<input class="font-medium text-gray-900 w-full py-1" type="text" bind:value={file.name} id={`file-name-${file.id}`} />
{:else}
<h3 class="font-medium text-gray-900">{file.name}</h3>
</a>
{/if}
<p class="text-sm text-gray-500">
{isAdmin ? 'Owned by you' : ''} • Uploaded {new Date(
file.createdAt || 0

View File

@@ -15,9 +15,8 @@ export class FileShareProfile extends Profile {
export class ListOfSharedFiles extends CoList.Of(co.ref(SharedFile)) {}
export class FileShareAccountRoot extends CoMap {
type = co.string;
type = co.literal('file-share-account');
sharedFiles = co.ref(ListOfSharedFiles);
publicGroup = co.ref(Group);
}
export class FileShareAccount extends Account {
@@ -31,7 +30,7 @@ export class FileShareAccount extends Account {
await this._refs.root?.load();
// Initialize root if it doesn't exist
if (!this.root || this.root.type !== 'file-share-account') {
if (this.root === undefined || this.root?.type !== 'file-share-account') {
// Create a group that will own all shared files
const publicGroup = Group.create({ owner: this });
publicGroup.addMember('everyone', 'reader');
@@ -40,9 +39,7 @@ export class FileShareAccount extends Account {
{
type: 'file-share-account',
sharedFiles: ListOfSharedFiles.create([], { owner: publicGroup }),
publicGroup
},
{ owner: this }
);
}
}

View File

@@ -20,3 +20,13 @@ export function formatFileSize(bytes: number): string {
export function generateTempFileId(fileName: string | undefined, createdAt: Date | undefined): string {
return `file-${fileName ?? 'unknown'}-${createdAt?.getTime() ?? 0}`;
}
export function downloadFileBlob(blob: Blob, fileName: string) {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}

View File

@@ -8,7 +8,8 @@
<script lang="ts">
import { JazzProvider } from 'jazz-svelte';
import { PasskeyAuthBasicUI, usePasskeyAuth } from 'jazz-svelte';
import "jazz-inspector-element"
import { PasskeyAuthBasicUI } from 'jazz-svelte';
import { Toaster } from 'svelte-sonner';
import '../app.css';
import { FileShareAccount } from '$lib/schema';
@@ -29,6 +30,7 @@
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
}}
>
<jazz-inspector></jazz-inspector>
<PasskeyAuthBasicUI appName="File Share">
<div class="min-h-screen bg-gray-100">
{@render children()}

View File

@@ -1,14 +1,22 @@
<script lang="ts">
import { useAccount, useCoState } from 'jazz-svelte';
import { SharedFile, ListOfSharedFiles } from '$lib/schema';
import { AccountCoState } from 'jazz-svelte';
import { SharedFile } from '$lib/schema';
import { FileStream } from 'jazz-tools';
import FileItem from '$lib/components/FileItem.svelte';
import { CloudUpload } from 'lucide-svelte';
const { me, logOut } = useAccount();
const me = new AccountCoState({
resolve: {
profile: true,
root: {
sharedFiles: {
$each: true
},
}
}
});
const mySharedFilesId = me?.root?._refs.sharedFiles.id;
const sharedFiles = $derived(useCoState(ListOfSharedFiles, mySharedFilesId));
const sharedFiles = $derived(me.current?.root.sharedFiles);
let fileInput: HTMLInputElement;
@@ -16,17 +24,15 @@
const input = event.target as HTMLInputElement;
const files = input.files;
if (!files || !files.length || !me?.root?.sharedFiles || !me?.root?.publicGroup) return;
if (!files?.length || !sharedFiles) return;
const file = files[0];
const fileName = file.name;
const createdAt = new Date();
try {
const ownership = { owner: me.root.publicGroup };
// Create a FileStream from the uploaded file
const fileStream = await FileStream.createFromBlob(file, ownership);
const fileStream = await FileStream.createFromBlob(file, sharedFiles._owner);
// Create the shared file entry
const sharedFile = SharedFile.create(
@@ -37,22 +43,22 @@
uploadedAt: new Date(),
size: file.size
},
ownership
sharedFiles._owner
);
// Add the file to the user's files list
me.root.sharedFiles.push(sharedFile);
sharedFiles.push(sharedFile);
} finally {
fileInput.value = ''; // reset input
}
}
async function deleteFile(file: SharedFile) {
if (!me?.root?.sharedFiles || !sharedFiles.current) return;
if (!sharedFiles) return;
const index = sharedFiles.current.indexOf(file);
const index = sharedFiles.indexOf(file);
if (index > -1) {
me.root.sharedFiles.splice(index, 1);
sharedFiles.splice(index, 1);
}
}
</script>
@@ -62,11 +68,11 @@
<div class="mb-12 flex items-center justify-between">
<div>
<h1 class="mb-2 text-4xl font-bold text-gray-900">File Share</h1>
<h2 class="text-xl text-gray-600">Welcome back, {me?.profile?.name}</h2>
<h2 class="text-xl text-gray-600">Welcome back, {me.current?.profile.name}</h2>
</div>
<button
onclick={logOut}
onclick={me.logOut}
class="rounded-lg bg-red-500 px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
>
Log Out
@@ -97,9 +103,9 @@
<!-- Files List -->
<div class="space-y-4">
{#if sharedFiles.current}
{#if !(sharedFiles.current.length === 0)}
{#each sharedFiles.current as file}
{#if sharedFiles}
{#if sharedFiles.length}
{#each sharedFiles as file}
{#if file}
<FileItem
{file}

View File

@@ -1,39 +1,33 @@
<script lang="ts">
import { page } from '$app/stores';
import { useAccount, useCoState } from 'jazz-svelte';
import { CoState } from 'jazz-svelte';
import { SharedFile } from '$lib/schema';
import { File, FileDown, Link2 } from 'lucide-svelte';
import type { ID } from 'jazz-tools';
import { FileStream } from 'jazz-tools';
import { toast } from 'svelte-sonner';
import { downloadFileBlob } from '$lib/utils';
const { me } = useAccount();
const fileId = $page.params.fileId;
const file = $state(useCoState(SharedFile, fileId as ID<SharedFile>, {}));
const isAdmin = $derived(me && file.current?._owner?.myRole() === 'admin');
const file = $derived(new CoState(SharedFile, fileId as ID<SharedFile>));
const isAdmin = $derived(file.current?._owner?.myRole() === 'admin');
const fileStreamId = $derived(file.current?._refs.file?.id);
async function downloadFile() {
if (!file.current?._refs.file?.id || !me) {
if (!fileStreamId || !file.current) {
toast.error('Failed to download file');
return;
}
try {
const fileId = file.current._refs.file.id;
const blob = await FileStream.loadAsBlob(fileId, me, {});
const blob = await FileStream.loadAsBlob(fileStreamId);
if (!blob) {
toast.error('Failed to download file');
return;
}
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = file.current.name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
downloadFileBlob(blob, file.current.name);
toast.success('File downloaded successfully');
} catch (error) {
console.error('Error downloading file:', error);

View File

@@ -59,7 +59,7 @@ test('can login with passkey and upload file', async ({ page, browser }) => {
await fileChooser.setFiles(filePath);
// Verify the uploaded file appears in the list
await expect(page.getByText('test-file.txt')).toBeVisible();
await expect(page.getByRole("textbox", { name: "File name" })).toHaveValue("test-file.txt");
await page.getByRole('button', { name: 'Share file' }).click();
const inviteLink = await page.evaluate(() => navigator.clipboard.readText());

View File

@@ -1,5 +1,31 @@
# jazz-tailwind-demo-auth-starter
## 0.0.31
### Patch Changes
- jazz-inspector@0.13.25
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.30
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-inspector@0.13.23
- jazz-react@0.13.23
## 0.0.29
### Patch Changes
- Updated dependencies [7de210f]
- jazz-inspector@0.13.21
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.28
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "filestream",
"private": true,
"version": "0.0.28",
"version": "0.0.31",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -189,7 +189,7 @@ export function FileWidget() {
);
}
const fileData = me?.profile?.file?.getChunks();
const fileData = me?.profile?.file?.getMetadata();
const mimeType = fileData?.mimeType || "unknown";
return (

View File

@@ -1,5 +1,27 @@
# form
## 0.1.32
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.1.31
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
## 0.1.30
### Patch Changes
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.1.29
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "form",
"private": true,
"version": "0.1.29",
"version": "0.1.32",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -62,7 +62,7 @@ function CreateOrderForm({
onSave: (draft: DraftBubbleTeaOrder) => void;
}) {
const draft = useCoState(DraftBubbleTeaOrder, id, {
resolve: { addOns: true },
resolve: { addOns: true, instructions: true },
});
if (!draft) return;

View File

@@ -1,3 +1,4 @@
import { CoPlainText } from "jazz-tools";
import {
BubbleTeaAddOnTypes,
BubbleTeaBaseTeaTypes,
@@ -12,6 +13,18 @@ export function OrderForm({
order: BubbleTeaOrder | DraftBubbleTeaOrder;
onSave?: (e: React.FormEvent<HTMLFormElement>) => void;
}) {
// Handles updates to the instructions field of the order.
// If instructions already exist, applyDiff updates them incrementally.
// Otherwise, creates a new CoPlainText instance for the instructions.
const handleInstructionsChange = (
e: React.ChangeEvent<HTMLTextAreaElement>,
) => {
if (order.instructions) {
return order.instructions.applyDiff(e.target.value);
}
order.instructions = CoPlainText.create(e.target.value, order._owner);
};
return (
<form onSubmit={onSave} className="grid gap-5">
<div className="flex flex-col gap-2">
@@ -88,9 +101,9 @@ export function OrderForm({
<textarea
name="instructions"
id="instructions"
value={order.instructions}
value={`${order.instructions}`}
className="dark:bg-transparent"
onChange={(e) => (order.instructions = e.target.value)}
onChange={handleInstructionsChange}
></textarea>
</div>

View File

@@ -1,4 +1,4 @@
import { Account, CoList, CoMap, co } from "jazz-tools";
import { Account, CoList, CoMap, CoPlainText, co } from "jazz-tools";
export const BubbleTeaAddOnTypes = [
"Pearl",
@@ -28,7 +28,7 @@ export class BubbleTeaOrder extends CoMap {
addOns = co.ref(ListOfBubbleTeaAddOns);
deliveryDate = co.Date;
withMilk = co.boolean;
instructions = co.optional.string;
instructions = co.optional.ref(CoPlainText);
}
export class DraftBubbleTeaOrder extends CoMap {
@@ -36,7 +36,7 @@ export class DraftBubbleTeaOrder extends CoMap {
addOns = co.optional.ref(ListOfBubbleTeaAddOns);
deliveryDate = co.optional.Date;
withMilk = co.optional.boolean;
instructions = co.optional.string;
instructions = co.optional.ref(CoPlainText);
get hasChanges() {
return Object.keys(this._edits).length > 1 || this.addOns?.hasChanges;

View File

@@ -1,5 +1,27 @@
# image-upload
## 0.0.88
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.87
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
## 0.0.86
### Patch Changes
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.85
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "image-upload",
"private": true,
"version": "0.0.85",
"version": "0.0.88",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,33 @@
# jazz-example-inspector
## 0.0.142
### Patch Changes
- Updated dependencies [a846e07]
- cojson@0.13.25
- cojson-transport-ws@0.13.25
- jazz-inspector@0.13.25
## 0.0.141
### Patch Changes
- Updated dependencies [6b781cf]
- cojson@0.13.23
- cojson-transport-ws@0.13.23
- jazz-inspector@0.13.23
## 0.0.140
### Patch Changes
- Updated dependencies [7de210f]
- Updated dependencies [e14e61f]
- jazz-inspector@0.13.21
- cojson@0.13.21
- cojson-transport-ws@0.13.21
## 0.0.139
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-inspector-app",
"private": true,
"version": "0.0.139",
"version": "0.0.142",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,27 @@
# multi-cursors
## 0.0.84
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.83
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
## 0.0.82
### Patch Changes
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.81
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "multi-cursors",
"private": true,
"version": "0.0.81",
"version": "0.0.84",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,30 @@
# multiauth
## 0.0.32
### Patch Changes
- jazz-react@0.13.25
- jazz-react-auth-clerk@0.13.25
- jazz-tools@0.13.25
## 0.0.31
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
- jazz-react-auth-clerk@0.13.23
## 0.0.30
### Patch Changes
- jazz-react@0.13.21
- jazz-react-auth-clerk@0.13.21
- jazz-tools@0.13.21
## 0.0.29
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "multiauth",
"private": true,
"version": "0.0.29",
"version": "0.0.32",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,31 @@
# jazz-example-musicplayer
## 0.0.113
### Patch Changes
- jazz-inspector@0.13.25
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.112
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-inspector@0.13.23
- jazz-react@0.13.23
## 0.0.111
### Patch Changes
- Updated dependencies [7de210f]
- jazz-inspector@0.13.21
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.110
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-music-player",
"private": true,
"version": "0.0.110",
"version": "0.0.113",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,27 @@
# organization
## 0.0.84
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.83
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
## 0.0.82
### Patch Changes
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.81
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "organization",
"private": true,
"version": "0.0.81",
"version": "0.0.84",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,35 @@
# passkey-svelte
## 0.0.79
### Patch Changes
- jazz-svelte@0.13.25
- jazz-tools@0.13.25
## 0.0.78
### Patch Changes
- Updated dependencies [ec546b4]
- jazz-svelte@0.13.24
## 0.0.77
### Patch Changes
- Updated dependencies [3431076]
- Updated dependencies [02a240c]
- jazz-svelte@0.13.23
- jazz-tools@0.13.23
## 0.0.76
### Patch Changes
- jazz-svelte@0.13.21
- jazz-tools@0.13.21
## 0.0.75
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "passkey-svelte",
"version": "0.0.75",
"version": "0.0.79",
"type": "module",
"private": true,
"scripts": {

View File

@@ -1,5 +1,27 @@
# minimal-auth-passkey
## 0.0.89
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.88
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
## 0.0.87
### Patch Changes
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.86
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "passkey",
"private": true,
"version": "0.0.86",
"version": "0.0.89",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,27 @@
# passphrase
## 0.0.86
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.85
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
## 0.0.84
### Patch Changes
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.83
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "passphrase",
"private": true,
"version": "0.0.83",
"version": "0.0.86",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,27 @@
# jazz-password-manager
## 0.0.110
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.109
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
## 0.0.108
### Patch Changes
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.107
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-password-manager",
"private": true,
"version": "0.0.107",
"version": "0.0.110",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,27 @@
# jazz-example-pets
## 0.0.208
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.207
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
## 0.0.206
### Patch Changes
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.205
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-pets",
"private": true,
"version": "0.0.205",
"version": "0.0.208",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,27 @@
# reactions
## 0.0.88
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.87
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
## 0.0.86
### Patch Changes
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.85
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "reactions",
"private": true,
"version": "0.0.85",
"version": "0.0.88",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -0,0 +1,13 @@
# richtext-tiptap
## 0.1.1
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
- jazz-richtext-tiptap@0.1.1
## 0.1.0
Initial release.

View File

@@ -0,0 +1,124 @@
# Jazz RichText Tiptap Example
A demonstration of collaborative rich text editing with Jazz, React, and Tiptap.
Live version: [https://richtext-tiptap-demo.jazz.tools](https://richtext-tiptap-demo.jazz.tools)
## Overview
This example shows how to implement collaborative rich text editing using:
- **Jazz** for real-time synchronization
- **CoRichText** for collaborative rich text data structures
- **Tiptap** for the rich text editor UI
- **React** for the component framework
The example features:
- Side-by-side plaintext and rich text editors
- Real-time collaboration across devices
- Persistent document storage
## Getting started
You can either
1. Clone the jazz repository, and run the app within the monorepo.
2. Or create a new Jazz project using this example as a template.
### Using the example as a template
Create a new Jazz project, and use this example as a template.
```bash
npx create-jazz-app@latest richtext-tiptap-app --example richtext-tiptap
```
Go to the new project directory.
```bash
cd richtext-tiptap-app
```
Run the dev server.
```bash
npm run dev
```
### Using the monorepo
This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation).
Clone the jazz repository.
```bash
git clone https://github.com/garden-co/jazz.git
```
Install and build dependencies.
```bash
pnpm i && npx turbo build
```
Go to the example directory.
```bash
cd jazz/examples/richtext-tiptap/
```
Start the dev server.
```bash
pnpm dev
```
Open [http://localhost:5173](http://localhost:5173) with your browser to see the result.
## How it works
This example demonstrates two key functionalities:
1. **CoRichText** - Jazz's collaborative rich text data structure
2. **Rich text integration** - Using Tiptap with Jazz
### Key components
- `src/schema.ts` - Defines the data model, including the `bio` field using CoRichText
- `src/Editor.tsx` - Implements both plaintext and rich text editor views
- `jazz-richtext-tiptap` - Provides the plugin that connects Jazz to Tiptap
### Implementation details
The example shows how to:
- Create and store CoRichText values
- Set up a plaintext editor with CoRichText
- Set up a Tiptap editor with a Jazz plugin
## Extending this example
You can extend this example by:
- Adding formatting options to the rich text toolbar
- Adding multiple collaborative documents
- Building document history or versioning
## Configuration: sync server
By default, the app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<Jazz.Provider>` provider component in [./src/main.tsx](./src/main.tsx).
## Learn more
To learn more about Jazz's collaborative text capabilities:
- [Jazz documentation](https://jazz.tools/docs)
- [CoText documentation](https://jazz.tools/docs/using-covalues/cotext)
- [Tiptap documentation](https://tiptap.dev/docs)
## Questions / problems / feedback
If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or open an issue or PR to fix something that seems wrong.

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en" class="h-full">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Rich text Tiptap example app | Jazz</title>
</head>
<body class="h-full flex flex-col">
<div id="root" class="align-self-center flex-1"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

View File

@@ -0,0 +1,45 @@
{
"name": "richtext-tiptap",
"private": true,
"version": "0.1.1",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"format-and-lint": "biome check .",
"format-and-lint:fix": "biome check . --write"
},
"dependencies": {
"@tiptap/core": "^2.12.0",
"@tiptap/extension-color": "^2.12.0",
"@tiptap/extension-list-item": "^2.12.0",
"@tiptap/extension-text-style": "^2.12.0",
"@tiptap/pm": "^2.12.0",
"@tiptap/react": "^2.12.0",
"@tiptap/starter-kit": "^2.12.0",
"clsx": "^2.1.1",
"jazz-react": "workspace:*",
"jazz-richtext-tiptap": "workspace:*",
"jazz-tools": "workspace:*",
"lucide-react": "^0.509.0",
"react": "18.3.1",
"react-dom": "18.3.1"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@playwright/test": "^1.50.1",
"@types/react": "~18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"autoprefixer": "^10.4.20",
"globals": "^15.11.0",
"is-ci": "^3.0.1",
"postcss": "^8.4.27",
"tailwindcss": "^3.4.17",
"typescript": "5.6.2",
"vite": "6.0.11"
}
}

View File

@@ -0,0 +1,46 @@
import { defineConfig, devices } from "@playwright/test";
import isCI from "is-ci";
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./tests",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: isCI,
/* Retry on CI only */
retries: isCI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: isCI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "http://localhost:5173/",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
permissions: ["clipboard-read", "clipboard-write"],
},
/* Configure projects for major browsers */
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
],
/* Run your local dev server before starting the tests */
webServer: [
{
command: "pnpm preview --port 5173",
url: "http://localhost:5173/",
reuseExistingServer: !isCI,
},
],
});

View File

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

View File

@@ -0,0 +1,41 @@
import { useAccount, useIsAuthenticated } from "jazz-react";
import { AuthButton } from "./AuthButton.tsx";
import { Editor } from "./Editor.tsx";
import { Logo } from "./Logo.tsx";
function App() {
const { me } = useAccount({
resolve: { profile: { bio: true }, root: true },
});
const isAuthenticated = useIsAuthenticated();
return (
<>
<header>
<nav className="container flex justify-between items-center py-3">
{isAuthenticated ? (
<span>You're logged in.</span>
) : (
<span>Authenticate to share the data with another device.</span>
)}
<AuthButton />
</nav>
</header>
<main className="container mt-16 flex flex-col gap-8">
<Logo />
<div className="text-center">
<h1>
Welcome{me?.profile.firstName ? <>, {me?.profile.firstName}</> : ""}
!
</h1>
</div>
{me ? <Editor value={me.profile.bio} /> : null}
</main>
</>
);
}
export default App;

View File

@@ -0,0 +1,45 @@
"use client";
import { useAccount, usePasskeyAuth } from "jazz-react";
import { APPLICATION_NAME } from "./main";
export function AuthButton() {
const { logOut } = useAccount();
const auth = usePasskeyAuth({
appName: APPLICATION_NAME,
});
function handleLogOut() {
logOut();
window.history.pushState({}, "", "/");
}
if (auth.state === "signedIn") {
return (
<button
className="bg-stone-100 py-1.5 px-3 text-sm rounded-md"
onClick={handleLogOut}
>
Log out
</button>
);
}
return (
<div className="flex gap-2">
<button
className="bg-stone-100 py-1.5 px-3 text-sm rounded-md"
onClick={() => auth.signUp("")}
>
Sign up
</button>
<button
onClick={() => auth.logIn()}
className="bg-stone-100 py-1.5 px-3 text-sm rounded-md"
>
Log in
</button>
</div>
);
}

View File

@@ -0,0 +1,72 @@
import { EditorContent, useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import clsx from "clsx";
import { JazzSyncExtension } from "jazz-richtext-tiptap";
import { CoRichText } from "jazz-tools";
import { BoldIcon, ItalicIcon, type LucideIcon } from "lucide-react";
import { useCallback } from "react";
export function Editor({ value }: { value: CoRichText }) {
const extensions = [
StarterKit,
// Jazz sync!
JazzSyncExtension.configure({ coRichText: value }),
];
const editor = useEditor({ extensions });
const toggleBold = useCallback(() => {
editor?.chain().focus().toggleBold().run();
}, [editor]);
const toggleItalic = useCallback(() => {
editor?.chain().focus().toggleItalic().run();
}, [editor]);
const isBold = editor?.isActive("bold");
const isItalic = editor?.isActive("italic");
return (
<div className="max-w-2xl bg-white rounded-xl shadow-md border border-black/10 w-full">
<div className="flex p-4 gap-2 border-b border-black/10">
<EditorMenuToggleButton
onClick={toggleBold}
isActive={isBold}
icon={BoldIcon}
/>
<EditorMenuToggleButton
onClick={toggleItalic}
isActive={isItalic}
icon={ItalicIcon}
/>
</div>
<EditorContent
editor={editor}
className="prose prose-sm sm:prose lg:prose-lg xl:prose-xl [&>.ProseMirror]:active:ring-0 [&>.ProseMirror]:p-4"
/>
</div>
);
}
function EditorMenuToggleButton({
onClick,
isActive,
icon: Icon,
}: {
onClick: () => void;
isActive: boolean | undefined;
icon: LucideIcon;
}) {
return (
<button
onClick={onClick}
className={clsx(
"w-8 h-8 flex items-center justify-center rounded-md text-sm font-medium",
isActive ? "bg-black text-white" : "bg-gray-100 text-black/70",
)}
>
<Icon size="1.25em" />
</button>
);
}

View File

@@ -0,0 +1,21 @@
export function Logo() {
return (
<svg
viewBox="0 0 386 146"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="text-black w-48 mx-auto"
>
<path
d="M176.725 33.865H188.275V22.7H176.725V33.865ZM164.9 129.4H172.875C182.72 129.4 188.275 123.9 188.275 114.22V43.6H176.725V109.545C176.725 115.65 173.975 118.51 167.925 118.51H164.9V129.4ZM245.298 53.28C241.613 45.47 233.363 41.95 222.748 41.95C208.998 41.95 200.748 48.44 197.888 58.615L208.613 61.915C210.648 55.315 216.368 52.565 222.638 52.565C231.933 52.565 235.673 56.415 236.058 64.61C226.433 65.93 216.643 67.195 209.768 69.23C200.583 72.145 195.743 77.865 195.743 86.83C195.743 96.51 202.673 104.65 215.818 104.65C225.443 104.65 232.318 101.35 237.213 94.365V103H247.388V66.425C247.388 61.475 247.168 57.185 245.298 53.28ZM217.853 95.245C210.483 95.245 207.128 91.34 207.128 86.72C207.128 82.045 210.593 79.515 215.323 77.92C220.328 76.435 226.983 75.5 235.948 74.18C235.893 76.93 235.673 80.725 234.738 83.475C233.418 89.25 227.643 95.245 217.853 95.245ZM251.22 103H301.545V92.715H269.535L303.195 45.47V43.6H254.3V53.885H284.935L251.22 101.185V103ZM304.815 103H355.14V92.715H323.13L356.79 45.47V43.6H307.895V53.885H338.53L304.815 101.185V103Z"
fill="currentColor"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M136.179 44.8277C136.179 44.8277 136.179 44.8277 136.179 44.8276V21.168C117.931 28.5527 97.9854 32.6192 77.0897 32.6192C65.1466 32.6192 53.5138 31.2908 42.331 28.7737V51.4076C42.331 51.4076 42.331 51.4076 42.331 51.4076V81.1508C41.2955 80.4385 40.1568 79.8458 38.9405 79.3915C36.1732 78.358 33.128 78.0876 30.1902 78.6145C27.2524 79.1414 24.5539 80.4419 22.4358 82.3516C20.3178 84.2613 18.8754 86.6944 18.291 89.3433C17.7066 91.9921 18.0066 94.7377 19.1528 97.2329C20.2991 99.728 22.2403 101.861 24.7308 103.361C27.2214 104.862 30.1495 105.662 33.1448 105.662H33.1455C33.6061 105.662 33.8365 105.662 34.0314 105.659C44.5583 105.449 53.042 96.9656 53.2513 86.4386C53.2534 86.3306 53.2544 86.2116 53.2548 86.0486H53.2552V85.7149L53.2552 85.5521V82.0762L53.2552 53.1993C61.0533 54.2324 69.0092 54.7656 77.0897 54.7656C77.6696 54.7656 78.2489 54.7629 78.8276 54.7574V110.696C77.792 109.983 76.6533 109.391 75.437 108.936C72.6697 107.903 69.6246 107.632 66.6867 108.159C63.7489 108.686 61.0504 109.987 58.9323 111.896C56.8143 113.806 55.3719 116.239 54.7875 118.888C54.2032 121.537 54.5031 124.283 55.6494 126.778C56.7956 129.273 58.7368 131.405 61.2273 132.906C63.7179 134.406 66.646 135.207 69.6414 135.207C70.1024 135.207 70.3329 135.207 70.5279 135.203C81.0548 134.994 89.5385 126.51 89.7478 115.983C89.7517 115.788 89.7517 115.558 89.7517 115.097V111.621L89.7517 54.3266C101.962 53.4768 113.837 51.4075 125.255 48.2397V80.9017C124.219 80.1894 123.081 79.5966 121.864 79.1424C119.097 78.1089 116.052 77.8384 113.114 78.3653C110.176 78.8922 107.478 80.1927 105.36 82.1025C103.242 84.0122 101.799 86.4453 101.215 89.0941C100.631 91.743 100.931 94.4886 102.077 96.9837C103.223 99.4789 105.164 101.612 107.655 103.112C110.145 104.612 113.073 105.413 116.069 105.413C116.53 105.413 116.76 105.413 116.955 105.409C127.482 105.2 135.966 96.7164 136.175 86.1895C136.179 85.9945 136.179 85.764 136.179 85.3029V81.8271L136.179 44.8277Z"
fill="#3313F7"
/>
</svg>
);
}

View File

@@ -0,0 +1 @@
export const apiKey = "richtext-tiptap-example@garden.co";

View File

@@ -0,0 +1,84 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
.ProseMirror {
min-height: 12rem;
}
.ProseMirror:focus {
outline: none;
box-shadow: none;
}
.tiptap :first-child {
margin-top: 0;
}
.tiptap ul,
.tiptap ol {
padding: 0 1rem;
margin: 1.25rem 1rem 1.25rem 0.4rem;
}
.tiptap ul li p,
.tiptap ol li p {
margin-top: 0.25em;
margin-bottom: 0.25em;
}
.tiptap h1,
.tiptap h2,
.tiptap h3,
.tiptap h4,
.tiptap h5,
.tiptap h6 {
line-height: 1.1;
margin-top: 2.5rem;
text-wrap: pretty;
}
.tiptap h1,
.tiptap h2 {
margin-top: 3.5rem;
margin-bottom: 1.5rem;
}
.tiptap h1 {
font-size: 1.4rem;
}
.tiptap h2 {
font-size: 1.2rem;
}
.tiptap h3 {
font-size: 1.1rem;
}
.tiptap h4,
.tiptap h5,
.tiptap h6 {
font-size: 1rem;
}
.tiptap code {
background-color: var(--purple-light);
border-radius: 0.4rem;
color: var(--black);
font-size: 0.85rem;
padding: 0.25em 0.3em;
}
.tiptap pre {
background: var(--black);
border-radius: 0.5rem;
color: var(--white);
font-family: "JetBrainsMono", monospace;
margin: 1.5rem 0;
padding: 0.75rem 1rem;
}
.tiptap pre code {
background: none;
color: inherit;
font-size: 0.8rem;
padding: 0;
}
.tiptap blockquote {
border-left: 3px solid var(--gray-3);
margin: 1.5rem 0;
padding-left: 1rem;
}
.tiptap hr {
border: none;
border-top: 1px solid var(--gray-2);
margin: 2rem 0;
}

View File

@@ -0,0 +1,32 @@
import { JazzProvider } from "jazz-react";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
import "prosemirror-example-setup/style/style.css";
import "prosemirror-view/style/prosemirror.css";
import "prosemirror-menu/style/menu.css";
import { apiKey } from "./apiKey.ts";
import { JazzAccount } from "./schema.ts";
// We use this to identify the app in the passkey auth
export const APPLICATION_NAME = "Jazz richtext Tiptap example";
declare module "jazz-react" {
export interface Register {
Account: JazzAccount;
}
}
createRoot(document.getElementById("root")!).render(
<StrictMode>
<JazzProvider
sync={{
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
}}
AccountSchema={JazzAccount}
>
<App />
</JazzProvider>
</StrictMode>,
);

View File

@@ -0,0 +1,68 @@
/**
* Learn about schemas here:
* https://jazz.tools/docs/react/schemas/covalues
*/
import { Account, CoMap, CoRichText, Group, Profile, co } from "jazz-tools";
/** The account profile is an app-specific per-user public `CoMap`
* where you can store top-level objects for that user */
export class JazzProfile extends Profile {
/**
* Learn about CoValue field/item types here:
* https://jazz.tools/docs/react/schemas/covalues#covalue-fielditem-types
*/
firstName = co.string;
bio = co.ref(CoRichText);
// Add public fields here
}
/** The account root is an app-specific per-user private `CoMap`
* where you can store top-level objects for that user */
export class AccountRoot extends CoMap {
dateOfBirth = co.Date;
// Add private fields here
get age() {
if (!this.dateOfBirth) return null;
return new Date().getFullYear() - this.dateOfBirth.getFullYear();
}
}
export class JazzAccount extends Account {
profile = co.ref(JazzProfile);
root = co.ref(AccountRoot);
/** The account migration is run on account creation and on every log-in.
* You can use it to set up the account root and any other initial CoValues you need.
*/
migrate(this: JazzAccount) {
if (this.root === undefined) {
const group = Group.create();
this.root = AccountRoot.create(
{ dateOfBirth: new Date("1/1/1990") },
group,
);
}
if (this.profile === undefined) {
const group = Group.create();
group.addMember("everyone", "reader"); // The profile info is visible to everyone
this.profile = JazzProfile.create(
{
name: "Anonymous user",
firstName: "",
bio: CoRichText.create("<p>A <strong>hu<em>man</strong></em>.</p>", {
owner: group,
}),
},
group,
);
}
}
}

View File

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

View File

@@ -0,0 +1,23 @@
import type { Config } from "tailwindcss";
const config: Config = {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
container: {
center: true,
padding: {
DEFAULT: "0.75rem",
sm: "1rem",
},
screens: {
lg: "600px",
xl: "600px",
},
},
},
},
plugins: [],
} as const;
export default config;

View File

@@ -0,0 +1,24 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2023", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

View File

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

View File

@@ -0,0 +1,22 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -0,0 +1,8 @@
{
"build": {
"env": {
"APP_NAME": "richtext-tiptap"
}
},
"ignoreCommand": "node ../../ignore-vercel-build.js"
}

View File

@@ -0,0 +1,7 @@
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
});

View File

@@ -1,5 +1,30 @@
# richtext
## 0.0.78
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
- jazz-richtext-prosemirror@0.1.12
## 0.0.77
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
- jazz-richtext-prosemirror@0.1.11
## 0.0.76
### Patch Changes
- jazz-react@0.13.21
- jazz-tools@0.13.21
- jazz-richtext-prosemirror@0.1.10
## 0.0.75
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "richtext",
"private": true,
"version": "0.0.75",
"version": "0.0.78",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -9,7 +9,9 @@ import { EditorView } from "prosemirror-view";
import { useEffect, useRef } from "react";
export function Editor() {
const { me } = useAccount({ resolve: { profile: true, root: true } });
const { me } = useAccount({
resolve: { profile: { bio: true }, root: true },
});
const editorRef = useRef<HTMLDivElement>(null);
const viewRef = useRef<EditorView | null>(null);
@@ -53,7 +55,7 @@ export function Editor() {
</label>
<textarea
className="flex-1 border border-stone-200 dark:border-stone-700 rounded shadow-sm py-2 px-3 font-mono text-sm bg-stone-50 dark:bg-stone-900 text-stone-900 dark:text-stone-100 whitespace-pre-wrap break-words resize-none"
value={me.profile.bio?.toString()}
value={`${me.profile.bio}`}
onChange={(e) => me.profile.bio?.applyDiff(e.target.value)}
rows={10}
/>

View File

@@ -59,9 +59,10 @@ export class JazzAccount extends Account {
{
name: "Anonymous user",
firstName: "",
bio: CoRichText.create("<p>A <strong>hu<em>man</strong></em>.</p>", {
owner: group,
}),
bio: CoRichText.create(
"<p>A <strong>hu<em>man</strong></em>.</p>",
group,
),
},
group,
);

View File

@@ -1,5 +1,30 @@
# todo-vue
## 0.0.92
### Patch Changes
- jazz-browser@0.13.25
- jazz-tools@0.13.25
- jazz-vue@0.13.25
## 0.0.91
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-browser@0.13.23
- jazz-vue@0.13.23
## 0.0.90
### Patch Changes
- jazz-browser@0.13.21
- jazz-tools@0.13.21
- jazz-vue@0.13.21
## 0.0.89
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "todo-vue",
"version": "0.0.89",
"version": "0.0.92",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,5 +1,27 @@
# jazz-example-todo
## 0.0.207
### Patch Changes
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.206
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-react@0.13.23
## 0.0.205
### Patch Changes
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.204
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-todo",
"private": true,
"version": "0.0.204",
"version": "0.0.207",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,4 +1,4 @@
import { Account, CoList, CoMap, Profile, co } from "jazz-tools";
import { Account, CoList, CoMap, CoPlainText, Profile, co } from "jazz-tools";
/** Walkthrough: Defining the data model with CoJSON
*
@@ -13,7 +13,7 @@ import { Account, CoList, CoMap, Profile, co } from "jazz-tools";
/** An individual task which collaborators can tick or rename */
export class Task extends CoMap {
done = co.boolean;
text = co.string;
text = co.ref(CoPlainText);
}
export class ListOfTasks extends CoList.Of(co.ref(Task)) {}

View File

@@ -15,7 +15,7 @@ import {
} from "./basicComponents";
import { useCoState } from "jazz-react";
import { ID } from "jazz-tools";
import { CoPlainText, ID } from "jazz-tools";
import { useParams } from "react-router";
import uniqolor from "uniqolor";
import { InviteButton } from "./components/InviteButton";
@@ -50,9 +50,9 @@ export function ProjectTodoTable() {
const task = Task.create(
{
done: false,
text,
text: CoPlainText.create(text, project._owner),
},
{ owner: project._owner },
project._owner,
);
// push will cause useCoState to rerender this component, both here and on other devices

View File

@@ -1,4 +1,5 @@
import { faker } from "@faker-js/faker";
import { CoPlainText } from "jazz-tools";
import { ListOfTasks, Task, TodoProject } from "./1_schema";
export function generateRandomProject(numTasks: number): TodoProject {
@@ -12,7 +13,10 @@ export function generateRandomProject(numTasks: number): TodoProject {
for (let i = 0; i < numTasks; i++) {
const task = Task.create({
done: faker.datatype.boolean(),
text: faker.lorem.sentence({ min: 3, max: 8 }),
text: CoPlainText.create(
faker.lorem.sentence({ min: 3, max: 8 }),
tasks._owner,
),
});
tasks.push(task);
}

View File

@@ -1,5 +1,31 @@
# version-history
## 0.0.86
### Patch Changes
- jazz-inspector@0.13.25
- jazz-react@0.13.25
- jazz-tools@0.13.25
## 0.0.85
### Patch Changes
- Updated dependencies [02a240c]
- jazz-tools@0.13.23
- jazz-inspector@0.13.23
- jazz-react@0.13.23
## 0.0.84
### Patch Changes
- Updated dependencies [7de210f]
- jazz-inspector@0.13.21
- jazz-react@0.13.21
- jazz-tools@0.13.21
## 0.0.83
### Patch Changes

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