Compare commits
45 Commits
copy/meta-
...
jazz-react
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dda9672dcb | ||
|
|
a86cd0e74e | ||
|
|
95e84a2ca7 | ||
|
|
e7c85b7575 | ||
|
|
8ad57f9d50 | ||
|
|
4a0f70692f | ||
|
|
51db96e8d0 | ||
|
|
4b0b27bde7 | ||
|
|
29a177224d | ||
|
|
63ccdaa3b2 | ||
|
|
8ed144e857 | ||
|
|
c9e2ab69bf | ||
|
|
4263c30753 | ||
|
|
416dd79b50 | ||
|
|
11da4d1366 | ||
|
|
6e794c3fed | ||
|
|
080a718c4d | ||
|
|
e5891f77ca | ||
|
|
e141c8779b | ||
|
|
868c49d096 | ||
|
|
bdc78c55fc | ||
|
|
2dbe990c22 | ||
|
|
60b8dbc33c | ||
|
|
5337edf717 | ||
|
|
fe60a88de9 | ||
|
|
939e1d7a3c | ||
|
|
19871690e4 | ||
|
|
064900d5f9 | ||
|
|
8e44caaebc | ||
|
|
c95f344c41 | ||
|
|
7320adc58d | ||
|
|
57a92f4aa0 | ||
|
|
c9b2b01928 | ||
|
|
5b97ac3b92 | ||
|
|
09f0a98eef | ||
|
|
3d8babdbb6 | ||
|
|
f10004c6bc | ||
|
|
33ecca3d10 | ||
|
|
bc601d809b | ||
|
|
cc8462f071 | ||
|
|
02fe68d207 | ||
|
|
0f87cfbbb0 | ||
|
|
cc1eb6da90 | ||
|
|
f7b91b7ce1 | ||
|
|
e2b1247969 |
@@ -1,18 +0,0 @@
|
||||
---
|
||||
"jazz-tailwind-demo-auth-starter": patch
|
||||
"file-share-svelte": patch
|
||||
"jazz-password-manager": patch
|
||||
"version-history": patch
|
||||
"passkey-svelte": patch
|
||||
"chat-rn-clerk": patch
|
||||
"jazz-example-music-player": patch
|
||||
"passphrase": patch
|
||||
"multiauth": patch
|
||||
"reactions": patch
|
||||
"passkey": patch
|
||||
"clerk": patch
|
||||
"jazz-example-pets": patch
|
||||
"jazz-example-todo": patch
|
||||
---
|
||||
|
||||
Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"create-jazz-app": patch
|
||||
---
|
||||
|
||||
add directory param to create-jazz-app
|
||||
@@ -1,5 +1,16 @@
|
||||
# chat-rn-clerk
|
||||
|
||||
## 1.0.87
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-react-native@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-react-native-auth-clerk@0.11.6
|
||||
- jazz-react-native-media-images@0.11.6
|
||||
|
||||
## 1.0.86
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "chat-rn-clerk",
|
||||
"main": "index.js",
|
||||
"version": "1.0.86",
|
||||
"version": "1.0.87",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
"start": "expo start",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# chat-rn
|
||||
|
||||
## 1.0.83
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-react-native@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
|
||||
## 1.0.82
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn",
|
||||
"version": "1.0.82",
|
||||
"version": "1.0.83",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# chat-vue
|
||||
|
||||
## 0.0.68
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-vue@0.11.6
|
||||
- jazz-browser@0.11.6
|
||||
|
||||
## 0.0.67
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-vue",
|
||||
"version": "0.0.67",
|
||||
"version": "0.0.68",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.165
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e7c85b7]
|
||||
- Updated dependencies [09f0a98]
|
||||
- Updated dependencies [11da4d1]
|
||||
- Updated dependencies [8ed144e]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-inspector@0.11.6
|
||||
- jazz-browser-media-images@0.11.6
|
||||
|
||||
## 0.0.164
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat",
|
||||
"private": true,
|
||||
"version": "0.0.164",
|
||||
"version": "0.0.165",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# minimal-auth-clerk
|
||||
|
||||
## 0.0.64
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-react-auth-clerk@0.11.6
|
||||
|
||||
## 0.0.63
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "clerk",
|
||||
"private": true,
|
||||
"version": "0.0.63",
|
||||
"version": "0.0.64",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -13,7 +13,7 @@
|
||||
"dependencies": {
|
||||
"@clerk/clerk-react": "^5.4.1",
|
||||
"jazz-react": "workspace:*",
|
||||
"jazz-react-auth-clerk": "workspace:0.11.5",
|
||||
"jazz-react-auth-clerk": "workspace:0.11.6",
|
||||
"jazz-tools": "workspace:*",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# file-share-svelte
|
||||
|
||||
## 0.0.48
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-svelte@0.11.6
|
||||
|
||||
## 0.0.47
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "file-share-svelte",
|
||||
"version": "0.0.47",
|
||||
"version": "0.0.48",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# jazz-tailwind-demo-auth-starter
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "filestream",
|
||||
"private": true,
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# form
|
||||
|
||||
## 0.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e7c85b7]
|
||||
- Updated dependencies [8ed144e]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-browser-media-images@0.11.6
|
||||
|
||||
## 0.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "form",
|
||||
"private": true,
|
||||
"version": "0.1.5",
|
||||
"version": "0.1.6",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# image-upload
|
||||
|
||||
## 0.0.62
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e7c85b7]
|
||||
- Updated dependencies [8ed144e]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-browser-media-images@0.11.6
|
||||
|
||||
## 0.0.61
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "image-upload",
|
||||
"private": true,
|
||||
"version": "0.0.61",
|
||||
"version": "0.0.62",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -24,6 +24,9 @@
|
||||
"@vitejs/plugin-react": "^4.3.3",
|
||||
"globals": "^15.11.0",
|
||||
"typescript": "~5.6.2",
|
||||
"vite": "^6.0.11"
|
||||
"vite": "^6.0.11",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"postcss": "^8.4.27",
|
||||
"tailwindcss": "^3.4.17"
|
||||
}
|
||||
}
|
||||
|
||||
6
examples/image-upload/postcss.config.js
Normal file
6
examples/image-upload/postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
@@ -3,7 +3,7 @@ import ImageUpload from "./ImageUpload.tsx";
|
||||
function App() {
|
||||
return (
|
||||
<>
|
||||
<main className="container">
|
||||
<main className="container py-16">
|
||||
<ImageUpload />
|
||||
</main>
|
||||
</>
|
||||
|
||||
@@ -1,60 +1,97 @@
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
import { ProgressiveImg, useAccount } from "jazz-react";
|
||||
import { ImageDefinition } from "jazz-tools";
|
||||
import { ChangeEvent, useRef } from "react";
|
||||
|
||||
function Image({ image }: { image: ImageDefinition }) {
|
||||
return (
|
||||
<ProgressiveImg image={image}>
|
||||
{({ src }) => <img src={src} />}
|
||||
</ProgressiveImg>
|
||||
);
|
||||
}
|
||||
import { ChangeEvent, useEffect, useRef, useState } from "react";
|
||||
|
||||
export default function ImageUpload() {
|
||||
const { me } = useAccount();
|
||||
|
||||
const [imagePreviewUrl, setImagePreviewUrl] = useState<string | null>(null);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
|
||||
if (imagePreviewUrl) {
|
||||
e.preventDefault();
|
||||
return "Upload in progress. Are you sure you want to leave?";
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("beforeunload", handleBeforeUnload);
|
||||
return () => {
|
||||
window.removeEventListener("beforeunload", handleBeforeUnload);
|
||||
|
||||
if (imagePreviewUrl) {
|
||||
URL.revokeObjectURL(imagePreviewUrl);
|
||||
}
|
||||
};
|
||||
}, [imagePreviewUrl]);
|
||||
|
||||
const onImageChange = async (event: ChangeEvent<HTMLInputElement>) => {
|
||||
if (!me?.profile) return;
|
||||
|
||||
const file = event.currentTarget.files?.[0];
|
||||
|
||||
if (file) {
|
||||
me.profile.image = await createImage(file, {
|
||||
owner: me.profile._owner,
|
||||
});
|
||||
const objectUrl = URL.createObjectURL(file);
|
||||
setImagePreviewUrl(objectUrl);
|
||||
|
||||
try {
|
||||
me.profile.image = await createImage(file, {
|
||||
owner: me.profile._owner,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error uploading image:", error);
|
||||
} finally {
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
setImagePreviewUrl(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const deleteImage = () => {
|
||||
if (!me?.profile) return;
|
||||
|
||||
me.profile.image = null;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>{me?.profile?.image && <Image image={me.profile.image} />}</div>
|
||||
if (me?.profile?.image) {
|
||||
return (
|
||||
<>
|
||||
<ProgressiveImg image={me.profile.image}>
|
||||
{({ src }) => <img alt="" src={src} className="w-full h-auto" />}
|
||||
</ProgressiveImg>
|
||||
|
||||
<div>
|
||||
{me?.profile?.image ? (
|
||||
<button type="button" onClick={deleteImage}>
|
||||
Delete image
|
||||
</button>
|
||||
) : (
|
||||
<div>
|
||||
<label>Upload image</label>
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="file"
|
||||
accept="image/png, image/jpeg, image/gif"
|
||||
onChange={onImageChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<button type="button" onClick={deleteImage} className="mt-5">
|
||||
Delete image
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (imagePreviewUrl) {
|
||||
return (
|
||||
<div className="relative">
|
||||
<p className="z-10 absolute font-semibold text-gray-900 inset-0 flex items-center justify-center">
|
||||
Uploading image...
|
||||
</p>
|
||||
<img
|
||||
src={imagePreviewUrl}
|
||||
alt="Preview"
|
||||
className="opacity-50 w-full h-auto"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<label htmlFor="image">Image</label>
|
||||
<input
|
||||
id="image"
|
||||
name="image"
|
||||
ref={inputRef}
|
||||
type="file"
|
||||
accept="image/png, image/jpeg, image/gif, image/bmp"
|
||||
onChange={onImageChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,82 +1,3 @@
|
||||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
--border-color: #2f2e2d;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 0;
|
||||
padding: 0.6em 1.2em;
|
||||
font-weight: 500;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--border-color: #e5e5e5;
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
|
||||
header,
|
||||
main {
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
header {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
padding: 2rem 0.75rem;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
18
examples/image-upload/tailwind.config.ts
Normal file
18
examples/image-upload/tailwind.config.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
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",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export default config;
|
||||
@@ -1,5 +1,18 @@
|
||||
# jazz-example-inspector
|
||||
|
||||
## 0.0.115
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 09f0a98: UI and JSON display improvements
|
||||
- 11da4d1: isolate class name hashing on inspector
|
||||
- Updated dependencies [09f0a98]
|
||||
- Updated dependencies [11da4d1]
|
||||
- Updated dependencies [8ed144e]
|
||||
- jazz-inspector@0.11.6
|
||||
- cojson@0.11.6
|
||||
- cojson-transport-ws@0.11.6
|
||||
|
||||
## 0.0.114
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-inspector-app",
|
||||
"private": true,
|
||||
"version": "0.0.114",
|
||||
"version": "0.0.115",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -13,8 +13,8 @@
|
||||
"dependencies": {
|
||||
"jazz-inspector": "workspace:*",
|
||||
"clsx": "^2.0.0",
|
||||
"cojson": "workspace:0.11.5",
|
||||
"cojson-transport-ws": "workspace:0.11.5",
|
||||
"cojson": "workspace:0.11.6",
|
||||
"cojson-transport-ws": "workspace:0.11.6",
|
||||
"hash-slash": "workspace:0.2.2",
|
||||
"lucide-react": "^0.274.0",
|
||||
"react": "^18.3.1",
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import { clsx } from "clsx";
|
||||
import { forwardRef } from "react";
|
||||
|
||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
variant?: "primary" | "secondary" | "tertiary" | "destructive" | "plain";
|
||||
size?: "sm" | "md" | "lg";
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
children,
|
||||
size = "md",
|
||||
variant = "primary",
|
||||
disabled,
|
||||
type = "button",
|
||||
...buttonProps
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const sizeClasses = {
|
||||
sm: "text-sm py-1 px-2",
|
||||
md: "py-1.5 px-3",
|
||||
lg: "md:text-lg py-2 px-3 md:px-8 md:py-3",
|
||||
};
|
||||
|
||||
const variantClasses = {
|
||||
primary:
|
||||
"bg-blue border-blue text-white font-medium bg-blue hover:bg-blue-800 hover:border-blue-800",
|
||||
secondary:
|
||||
"text-stone-900 border font-medium hover:border-stone-300 hover:dark:border-stone-700 dark:text-white",
|
||||
tertiary: "text-blue underline underline-offset-4",
|
||||
destructive:
|
||||
"bg-red-600 border-red-600 text-white font-medium hover:bg-red-700 hover:border-red-700",
|
||||
};
|
||||
|
||||
const classNames =
|
||||
variant === "plain"
|
||||
? clsx(className, "text-left")
|
||||
: clsx(
|
||||
className,
|
||||
"inline-flex items-center justify-center gap-2 rounded-lg text-center transition-colors",
|
||||
"disabled:pointer-events-none disabled:opacity-70",
|
||||
sizeClasses[size],
|
||||
variantClasses[variant],
|
||||
disabled && "opacity-50 cursor-not-allowed pointer-events-none",
|
||||
);
|
||||
|
||||
return (
|
||||
<button
|
||||
ref={ref}
|
||||
{...buttonProps}
|
||||
disabled={disabled}
|
||||
className={classNames}
|
||||
type={type}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -9,8 +9,14 @@ import {
|
||||
} from "cojson";
|
||||
import { createWebSocketPeer } from "cojson-transport-ws";
|
||||
import { WasmCrypto } from "cojson/crypto/WasmCrypto";
|
||||
import { Breadcrumbs, PageStack } from "jazz-inspector";
|
||||
import { Trash2 } from "lucide-react";
|
||||
import {
|
||||
Breadcrumbs,
|
||||
Button,
|
||||
Icon,
|
||||
Input,
|
||||
PageStack,
|
||||
Select,
|
||||
} from "jazz-inspector";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { usePagePath } from "./use-page-path";
|
||||
import { resolveCoValue, useResolvedCoValue } from "./use-resolve-covalue";
|
||||
@@ -120,15 +126,23 @@ export default function CoJsonViewerApp() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full h-screen bg-white p-4 overflow-hidden flex flex-col">
|
||||
<div className="flex items-center mb-4 gap-4">
|
||||
<div
|
||||
className={clsx(
|
||||
"h-screen overflow-hidden flex flex-col",
|
||||
" text-stone-700 bg-white",
|
||||
"dark:text-stone-300 dark:bg-stone-950",
|
||||
)}
|
||||
>
|
||||
<header className="flex items-center gap-4 p-3">
|
||||
<Breadcrumbs path={path} onBreadcrumbClick={goToIndex} />
|
||||
<div className="flex-1">
|
||||
<form onSubmit={handleCoValueIdSubmit}>
|
||||
{path.length !== 0 && (
|
||||
<input
|
||||
className="border p-2 rounded-lg min-w-[21rem] font-mono"
|
||||
<Input
|
||||
className="min-w-[21rem] font-mono"
|
||||
placeholder="co_z1234567890abcdef123456789"
|
||||
label="CoValue ID"
|
||||
hideLabel
|
||||
value={coValueId}
|
||||
onChange={(e) =>
|
||||
setCoValueId(e.target.value as CoID<RawCoValue>)
|
||||
@@ -144,7 +158,7 @@ export default function CoJsonViewerApp() {
|
||||
deleteCurrentAccount={deleteCurrentAccount}
|
||||
localNode={localNode}
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<PageStack
|
||||
path={path}
|
||||
@@ -152,49 +166,39 @@ export default function CoJsonViewerApp() {
|
||||
goBack={goBack}
|
||||
addPages={addPages}
|
||||
>
|
||||
{!currentAccount ? (
|
||||
<AddAccountForm addAccount={addAccount} />
|
||||
) : (
|
||||
{!currentAccount && <AddAccountForm addAccount={addAccount} />}
|
||||
|
||||
{currentAccount && path.length <= 0 && (
|
||||
<form
|
||||
onSubmit={handleCoValueIdSubmit}
|
||||
aria-hidden={path.length !== 0}
|
||||
className={clsx(
|
||||
"flex flex-col justify-center items-center gap-2 h-full w-full mb-20 ",
|
||||
"transition-all duration-150",
|
||||
path.length > 0
|
||||
? "opacity-0 -translate-y-2 scale-95"
|
||||
: "opacity-100",
|
||||
)}
|
||||
className="flex flex-col relative -top-6 justify-center gap-2 h-full w-full max-w-sm mx-auto"
|
||||
>
|
||||
<fieldset className="flex flex-col gap-2 text-sm">
|
||||
<h2 className="text-3xl font-medium text-gray-950 text-center mb-4">
|
||||
Jazz CoValue Inspector
|
||||
</h2>
|
||||
<input
|
||||
className="border p-4 rounded-lg min-w-[21rem] font-mono"
|
||||
placeholder="co_z1234567890abcdef123456789"
|
||||
value={coValueId}
|
||||
onChange={(e) =>
|
||||
setCoValueId(e.target.value as CoID<RawCoValue>)
|
||||
}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-indigo-500 hover:bg-indigo-500/80 text-white px-4 py-2 rounded-md"
|
||||
>
|
||||
Inspect
|
||||
</button>
|
||||
<hr />
|
||||
<button
|
||||
type="button"
|
||||
className="border inline-block px-2 py-1.5 text-black rounded"
|
||||
onClick={() => {
|
||||
setPage(currentAccount.id);
|
||||
}}
|
||||
>
|
||||
Inspect My Account
|
||||
</button>
|
||||
</fieldset>
|
||||
<h1 className="text-lg text-center font-medium mb-4 text-stone-900 dark:text-white">
|
||||
Jazz CoValue Inspector
|
||||
</h1>
|
||||
<Input
|
||||
label="CoValue ID"
|
||||
className="font-mono"
|
||||
hideLabel
|
||||
placeholder="co_z1234567890abcdef123456789"
|
||||
value={coValueId}
|
||||
onChange={(e) => setCoValueId(e.target.value as CoID<RawCoValue>)}
|
||||
/>
|
||||
<Button type="submit" variant="primary">
|
||||
Inspect CoValue
|
||||
</Button>
|
||||
|
||||
<p className="text-center">or</p>
|
||||
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
setPage(currentAccount.id);
|
||||
}}
|
||||
>
|
||||
Inspect my account
|
||||
</Button>
|
||||
</form>
|
||||
)}
|
||||
</PageStack>
|
||||
@@ -216,8 +220,11 @@ function AccountSwitcher({
|
||||
localNode: LocalNode | null;
|
||||
}) {
|
||||
return (
|
||||
<div className="relative flex items-center gap-1">
|
||||
<select
|
||||
<div className="relative flex items-stretch gap-1">
|
||||
<Select
|
||||
label="Account to inspect"
|
||||
hideLabel
|
||||
className="label:sr-only max-w-96"
|
||||
value={currentAccount?.id || "add-account"}
|
||||
onChange={(e) => {
|
||||
if (e.target.value === "add-account") {
|
||||
@@ -227,7 +234,6 @@ function AccountSwitcher({
|
||||
setCurrentAccount(account || null);
|
||||
}
|
||||
}}
|
||||
className="p-2 px-4 bg-gray-100/50 border border-indigo-500/10 backdrop-blur-sm rounded-md text-indigo-700 appearance-none"
|
||||
>
|
||||
{accounts.map((account) => (
|
||||
<option key={account.id} value={account.id}>
|
||||
@@ -239,15 +245,16 @@ function AccountSwitcher({
|
||||
</option>
|
||||
))}
|
||||
<option value="add-account">Add account</option>
|
||||
</select>
|
||||
</Select>
|
||||
{currentAccount && (
|
||||
<button
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={deleteCurrentAccount}
|
||||
className="p-3 rounded hover:bg-gray-200 transition-colors"
|
||||
title="Delete Account"
|
||||
className="rounded-md p-2 ml-1"
|
||||
aria-label="Remove account"
|
||||
>
|
||||
<Trash2 size={16} className="text-gray-500" />
|
||||
</button>
|
||||
<Icon name="delete" className="text-gray-500" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@@ -271,30 +278,34 @@ function AddAccountForm({
|
||||
return (
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className="flex flex-col gap-2 max-w-md mx-auto h-full justify-center"
|
||||
className="flex flex-col gap-3 max-w-md mx-auto h-full justify-center"
|
||||
>
|
||||
<h2 className="text-2xl font-medium text-gray-900 mb-3">
|
||||
Add an Account to Inspect
|
||||
<h2 className="text-2xl font-medium text-gray-900 dark:text-white">
|
||||
Add an account to inspect
|
||||
</h2>
|
||||
<input
|
||||
className="border py-2 px-3 rounded-md"
|
||||
placeholder="Account ID"
|
||||
<p className="leading-relaxed mb-5">
|
||||
Use the{" "}
|
||||
<code className="whitespace-nowrap text-stone-900 dark:text-white font-semibold">
|
||||
jazz-logged-in-secret
|
||||
</code>{" "}
|
||||
local storage key from within your Jazz app for your account
|
||||
credentials.
|
||||
</p>
|
||||
<Input
|
||||
label="Account ID"
|
||||
value={id}
|
||||
placeholder="co_z1234567890abcdef123456789"
|
||||
onChange={(e) => setId(e.target.value)}
|
||||
/>
|
||||
<input
|
||||
<Input
|
||||
label="Account secret"
|
||||
type="password"
|
||||
className="border py-2 px-3 rounded-md"
|
||||
placeholder="Account Secret"
|
||||
value={secret}
|
||||
onChange={(e) => setSecret(e.target.value)}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-indigo-500 text-white px-4 py-2 rounded-md"
|
||||
>
|
||||
Add Account
|
||||
</button>
|
||||
<Button className="mt-3" type="submit">
|
||||
Add account
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Config } from "tailwindcss";
|
||||
import plugin from "tailwindcss/plugin";
|
||||
|
||||
const stonePalette = {
|
||||
50: "oklch(0.988281 0.002 75)",
|
||||
@@ -61,6 +62,7 @@ const config: Config = {
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [plugin(({ addVariant }) => addVariant("label", "& :is(label)"))],
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# multiauth
|
||||
|
||||
## 0.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-react-auth-clerk@0.11.6
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "multiauth",
|
||||
"private": true,
|
||||
"version": "0.0.4",
|
||||
"version": "0.0.5",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# jazz-example-musicplayer
|
||||
|
||||
## 0.0.86
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- Updated dependencies [09f0a98]
|
||||
- Updated dependencies [11da4d1]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-inspector@0.11.6
|
||||
|
||||
## 0.0.85
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-music-player",
|
||||
"private": true,
|
||||
"version": "0.0.85",
|
||||
"version": "0.0.86",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -22,8 +22,8 @@
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-inspector": "workspace:*",
|
||||
"jazz-react": "workspace:0.11.5",
|
||||
"jazz-tools": "workspace:0.11.5",
|
||||
"jazz-react": "workspace:0.11.6",
|
||||
"jazz-tools": "workspace:0.11.6",
|
||||
"lucide-react": "^0.274.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# organization
|
||||
|
||||
## 0.0.58
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
|
||||
## 0.0.57
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "organization",
|
||||
"private": true,
|
||||
"version": "0.0.57",
|
||||
"version": "0.0.58",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# passkey-svelte
|
||||
|
||||
## 0.0.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- jazz-svelte@0.11.6
|
||||
|
||||
## 0.0.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "passkey-svelte",
|
||||
"version": "0.0.51",
|
||||
"version": "0.0.52",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# minimal-auth-passkey
|
||||
|
||||
## 0.0.63
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
|
||||
## 0.0.62
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passkey",
|
||||
"private": true,
|
||||
"version": "0.0.62",
|
||||
"version": "0.0.63",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# passphrase
|
||||
|
||||
## 0.0.60
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
|
||||
## 0.0.59
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passphrase",
|
||||
"private": true,
|
||||
"version": "0.0.59",
|
||||
"version": "0.0.60",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# jazz-password-manager
|
||||
|
||||
## 0.0.84
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
|
||||
## 0.0.83
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-password-manager",
|
||||
"private": true,
|
||||
"version": "0.0.83",
|
||||
"version": "0.0.84",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -12,8 +12,8 @@
|
||||
"clean-install": "rm -rf node_modules pnpm-lock.yaml && pnpm install"
|
||||
},
|
||||
"dependencies": {
|
||||
"jazz-react": "workspace:0.11.5",
|
||||
"jazz-tools": "workspace:0.11.5",
|
||||
"jazz-react": "workspace:0.11.6",
|
||||
"jazz-tools": "workspace:0.11.6",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-hook-form": "^7.41.5",
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# jazz-example-pets
|
||||
|
||||
## 0.0.182
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- Updated dependencies [8ed144e]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-browser-media-images@0.11.6
|
||||
|
||||
## 0.0.181
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-pets",
|
||||
"private": true,
|
||||
"version": "0.0.181",
|
||||
"version": "0.0.182",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -19,9 +19,9 @@
|
||||
"@radix-ui/react-toast": "^1.1.4",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-browser-media-images": "workspace:0.11.5",
|
||||
"jazz-react": "workspace:0.11.5",
|
||||
"jazz-tools": "workspace:0.11.5",
|
||||
"jazz-browser-media-images": "workspace:0.11.6",
|
||||
"jazz-react": "workspace:0.11.6",
|
||||
"jazz-tools": "workspace:0.11.6",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "^18.3.1",
|
||||
@@ -41,7 +41,7 @@
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"is-ci": "^3.0.1",
|
||||
"jazz-run": "workspace:0.11.5",
|
||||
"jazz-run": "workspace:0.11.6",
|
||||
"postcss": "^8.4.27",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "~5.6.2",
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# reactions
|
||||
|
||||
## 0.0.62
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- Updated dependencies [8ed144e]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-browser-media-images@0.11.6
|
||||
|
||||
## 0.0.61
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "reactions",
|
||||
"private": true,
|
||||
"version": "0.0.61",
|
||||
"version": "0.0.62",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# todo-vue
|
||||
|
||||
## 0.0.66
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-vue@0.11.6
|
||||
- jazz-browser@0.11.6
|
||||
|
||||
## 0.0.65
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "todo-vue",
|
||||
"version": "0.0.65",
|
||||
"version": "0.0.66",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# jazz-example-todo
|
||||
|
||||
## 0.0.181
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
|
||||
## 0.0.180
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-todo",
|
||||
"private": true,
|
||||
"version": "0.0.180",
|
||||
"version": "0.0.181",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -16,8 +16,8 @@
|
||||
"@radix-ui/react-toast": "^1.1.4",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-react": "workspace:0.11.5",
|
||||
"jazz-tools": "workspace:0.11.5",
|
||||
"jazz-react": "workspace:0.11.6",
|
||||
"jazz-tools": "workspace:0.11.6",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "^18.3.1",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# version-history
|
||||
|
||||
## 0.0.59
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
|
||||
- Updated dependencies [e7c85b7]
|
||||
- Updated dependencies [09f0a98]
|
||||
- Updated dependencies [11da4d1]
|
||||
- jazz-react@0.11.6
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-inspector@0.11.6
|
||||
|
||||
## 0.0.58
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "version-history",
|
||||
"private": true,
|
||||
"version": "0.0.58",
|
||||
"version": "0.0.59",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
37
homepage/gcmp/app/api/rss/route.ts
Normal file
37
homepage/gcmp/app/api/rss/route.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { metaTags } from "@/app/layout";
|
||||
import { posts } from "@/lib/posts";
|
||||
import { Feed } from "feed";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function GET() {
|
||||
const feed = new Feed({
|
||||
title: "Garden Computing Blog",
|
||||
description: "News from Garden Computing",
|
||||
id: metaTags.url,
|
||||
link: `${metaTags.url}/news`,
|
||||
language: "en",
|
||||
image: `${metaTags.url}/social-image.png`,
|
||||
favicon: `${metaTags.url}/favicon.ico`,
|
||||
copyright: `${new Date().getFullYear()} Garden Computing, Inc.`,
|
||||
});
|
||||
|
||||
posts.forEach((post) => {
|
||||
feed.addItem({
|
||||
title: post.meta.title,
|
||||
description: post.meta.subtitle,
|
||||
id: post.meta.slug,
|
||||
link: `${metaTags.url}/news/${post.meta.slug}`,
|
||||
date: new Date(post.meta.date),
|
||||
author: [{ name: post.meta.author.name }],
|
||||
guid: post.meta.slug,
|
||||
image: `${metaTags.url}${post.meta.coverImage}`,
|
||||
});
|
||||
});
|
||||
|
||||
return new NextResponse(feed.rss2(), {
|
||||
headers: {
|
||||
"Content-Type": "application/xml",
|
||||
"Cache-Control": "public, s-maxage=3600, stale-while-revalidate=86400",
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -41,7 +41,7 @@ const commitMono = localFont({
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
const metaTags = {
|
||||
export const metaTags = {
|
||||
title: "garden computing",
|
||||
description:
|
||||
"Computers are magic. So why do we put up with so much complexity? We believe just a few new ideas can make all the difference.",
|
||||
@@ -70,6 +70,16 @@ export const metadata: Metadata = {
|
||||
},
|
||||
],
|
||||
},
|
||||
alternates: {
|
||||
canonical: metaTags.url,
|
||||
types: {
|
||||
"application/rss+xml": `${
|
||||
process.env.VERCEL_URL
|
||||
? `https://${process.env.VERCEL_URL}`
|
||||
: "http://localhost:3000"
|
||||
}/api/rss`,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"@vercel/analytics": "^1.3.1",
|
||||
"@vercel/speed-insights": "^1.0.12",
|
||||
"clsx": "^2.1.1",
|
||||
"feed": "^4.2.2",
|
||||
"gcmp-design-system": "workspace:*",
|
||||
"lucide-react": "^0.436.0",
|
||||
"mdast-util-from-markdown": "^2.0.0",
|
||||
|
||||
@@ -26,14 +26,9 @@ export function SideNav({
|
||||
footer?: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className={clsx(className, "text-sm space-y-5 px-2")}>
|
||||
<div className={clsx(className, "text-sm space-y-4 px-2")}>
|
||||
{children}
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="inline-block size-2 rounded-full bg-yellow-400"></span>{" "}
|
||||
Documentation coming soon
|
||||
</div>
|
||||
|
||||
{items.map(({ name, href, items }) => (
|
||||
<div key={name}>
|
||||
<SideNavHeader href={href}>{name}</SideNavHeader>
|
||||
@@ -42,10 +37,6 @@ export function SideNav({
|
||||
<ul key={name}>
|
||||
<li>
|
||||
<SideNavItem href={href}>
|
||||
{done == 0 && (
|
||||
<span className="mr-1.5 inline-block size-2 rounded-full bg-yellow-400"></span>
|
||||
)}
|
||||
|
||||
<span
|
||||
className={
|
||||
done === 0 ? "text-stone-400 dark:text-stone-600" : ""
|
||||
|
||||
@@ -17,7 +17,7 @@ export function SideNavItem({
|
||||
}) {
|
||||
const classes = clsx(
|
||||
className,
|
||||
"py-1.5 px-2 -mx-2 group rounded-md flex items-center transition-colors",
|
||||
"py-1 px-2 -mx-2 group rounded-md flex items-center transition-colors",
|
||||
);
|
||||
const path = usePathname();
|
||||
|
||||
|
||||
@@ -21,17 +21,7 @@ export const docNavigationItems = [
|
||||
href: "/examples",
|
||||
done: 30,
|
||||
},
|
||||
{
|
||||
name: "AI tools",
|
||||
href: "/docs/ai-tools",
|
||||
done: 100,
|
||||
},
|
||||
{
|
||||
name: "Inspector",
|
||||
href: "/docs/inspector",
|
||||
done: 100,
|
||||
},
|
||||
{ name: "FAQ", href: "/docs/faq", done: 100 },
|
||||
{ name: "FAQs", href: "/docs/faq", done: 100 },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -60,6 +50,21 @@ export const docNavigationItems = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Tools",
|
||||
items: [
|
||||
{
|
||||
name: "AI tools",
|
||||
href: "/docs/ai-tools",
|
||||
done: 100,
|
||||
},
|
||||
{
|
||||
name: "Inspector",
|
||||
href: "/docs/inspector",
|
||||
done: 100,
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Upgrade guides",
|
||||
items: [
|
||||
|
||||
@@ -12,4 +12,11 @@ export const products = [
|
||||
url: "https://invoiceradar.com",
|
||||
description: "Automatically gather invoices from mail and cloud providers.",
|
||||
},
|
||||
{
|
||||
name: "Hend",
|
||||
description: "Learn languages naturally with interesting, compelling content tailored just for you.",
|
||||
url: "https://hendapp.com",
|
||||
imageUrl: "/hend.png",
|
||||
|
||||
}
|
||||
];
|
||||
|
||||
BIN
homepage/homepage/public/hend.png
Normal file
BIN
homepage/homepage/public/hend.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
24
homepage/pnpm-lock.yaml
generated
24
homepage/pnpm-lock.yaml
generated
@@ -102,6 +102,9 @@ importers:
|
||||
clsx:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
feed:
|
||||
specifier: ^4.2.2
|
||||
version: 4.2.2
|
||||
gcmp-design-system:
|
||||
specifier: workspace:*
|
||||
version: link:../design-system
|
||||
@@ -1952,6 +1955,10 @@ packages:
|
||||
fastq@1.17.1:
|
||||
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
|
||||
|
||||
feed@4.2.2:
|
||||
resolution: {integrity: sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
fenceparser@1.1.1:
|
||||
resolution: {integrity: sha512-VdkTsK7GWLT0VWMK5S5WTAPn61wJ98WPFwJiRHumhg4ESNUO/tnkU8bzzzc62o6Uk1SVhuZFLnakmDA4SGV7wA==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -2793,6 +2800,9 @@ packages:
|
||||
safe-buffer@5.2.1:
|
||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||
|
||||
sax@1.4.1:
|
||||
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
|
||||
|
||||
scheduler@0.23.2:
|
||||
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
|
||||
|
||||
@@ -3165,6 +3175,10 @@ packages:
|
||||
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
xml-js@1.6.11:
|
||||
resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
|
||||
hasBin: true
|
||||
|
||||
y18n@4.0.3:
|
||||
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
|
||||
|
||||
@@ -5468,6 +5482,10 @@ snapshots:
|
||||
dependencies:
|
||||
reusify: 1.0.4
|
||||
|
||||
feed@4.2.2:
|
||||
dependencies:
|
||||
xml-js: 1.6.11
|
||||
|
||||
fenceparser@1.1.1: {}
|
||||
|
||||
fill-range@7.0.1:
|
||||
@@ -6687,6 +6705,8 @@ snapshots:
|
||||
|
||||
safe-buffer@5.2.1: {}
|
||||
|
||||
sax@1.4.1: {}
|
||||
|
||||
scheduler@0.23.2:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
@@ -7136,6 +7156,10 @@ snapshots:
|
||||
string-width: 5.1.2
|
||||
strip-ansi: 7.1.0
|
||||
|
||||
xml-js@1.6.11:
|
||||
dependencies:
|
||||
sax: 1.4.1
|
||||
|
||||
y18n@4.0.3: {}
|
||||
|
||||
yaml@2.4.2: {}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# cojson-storage-indexeddb
|
||||
|
||||
## 0.11.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8ed144e]
|
||||
- cojson@0.11.6
|
||||
- cojson-storage@0.11.6
|
||||
|
||||
## 0.11.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cojson-storage-indexeddb",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# cojson-storage-sqlite
|
||||
|
||||
## 0.11.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8ed144e]
|
||||
- cojson@0.11.6
|
||||
- cojson-storage@0.11.6
|
||||
|
||||
## 0.11.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "cojson-storage-rn-sqlite",
|
||||
"type": "module",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# cojson-storage-sqlite
|
||||
|
||||
## 0.11.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8ed144e]
|
||||
- cojson@0.11.6
|
||||
- cojson-storage@0.11.6
|
||||
|
||||
## 0.11.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "cojson-storage-sqlite",
|
||||
"type": "module",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^11.7.0",
|
||||
"cojson": "workspace:0.11.5",
|
||||
"cojson": "workspace:0.11.6",
|
||||
"cojson-storage": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# cojson-storage
|
||||
|
||||
## 0.11.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8ed144e]
|
||||
- cojson@0.11.6
|
||||
|
||||
## 0.11.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cojson-storage",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# cojson-transport-nodejs-ws
|
||||
|
||||
## 0.11.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [8ed144e]
|
||||
- cojson@0.11.6
|
||||
|
||||
## 0.11.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "cojson-transport-ws",
|
||||
"type": "module",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# cojson
|
||||
|
||||
## 0.11.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8ed144e: Fix transaction sorting when the timestamps are equal
|
||||
|
||||
## 0.11.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"devDependencies": {
|
||||
"@opentelemetry/sdk-metrics": "^1.29.0",
|
||||
"typescript": "~5.6.2",
|
||||
|
||||
@@ -573,7 +573,11 @@ export class CoValueCore {
|
||||
) {
|
||||
return (
|
||||
a.madeAt - b.madeAt ||
|
||||
(a.txID.sessionID < b.txID.sessionID ? -1 : 1) ||
|
||||
(a.txID.sessionID === b.txID.sessionID
|
||||
? 0
|
||||
: a.txID.sessionID < b.txID.sessionID
|
||||
? -1
|
||||
: 1) ||
|
||||
a.txID.txIndex - b.txID.txIndex
|
||||
);
|
||||
}
|
||||
|
||||
@@ -79,6 +79,22 @@ export class RawCoStreamView<
|
||||
throw new Error("Not yet implemented");
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
protected compareStreamItems(
|
||||
a: CoStreamItem<Item>,
|
||||
b: CoStreamItem<Item>,
|
||||
): number {
|
||||
return (
|
||||
a.madeAt - b.madeAt ||
|
||||
(a.tx.sessionID === b.tx.sessionID
|
||||
? 0
|
||||
: a.tx.sessionID < b.tx.sessionID
|
||||
? -1
|
||||
: 1) ||
|
||||
a.tx.txIndex - b.tx.txIndex
|
||||
);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
protected processNewTransactions() {
|
||||
const changeEntries = new Set<CoStreamItem<Item>[]>();
|
||||
@@ -104,12 +120,7 @@ export class RawCoStreamView<
|
||||
}
|
||||
|
||||
for (const entries of changeEntries) {
|
||||
entries.sort(
|
||||
(a, b) =>
|
||||
a.madeAt - b.madeAt ||
|
||||
(a.tx.sessionID < b.tx.sessionID ? -1 : 1) ||
|
||||
a.tx.txIndex - b.tx.txIndex,
|
||||
);
|
||||
entries.sort(this.compareStreamItems);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { expectStream } from "../coValue.js";
|
||||
import { MAX_RECOMMENDED_TX_SIZE } from "../coValueCore.js";
|
||||
import { RawBinaryCoStream } from "../coValues/coStream.js";
|
||||
import {
|
||||
BinaryStreamItem,
|
||||
CoStreamItem,
|
||||
RawBinaryCoStream,
|
||||
RawCoStreamView,
|
||||
} from "../coValues/coStream.js";
|
||||
import { WasmCrypto } from "../crypto/WasmCrypto.js";
|
||||
import { SessionID } from "../ids.js";
|
||||
import { LocalNode } from "../localNode.js";
|
||||
import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
|
||||
|
||||
@@ -299,3 +305,114 @@ describe("isBinaryStreamEnded", () => {
|
||||
expect(stream.isBinaryStreamEnded()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Binary stream order", () => {
|
||||
class TestStreamView extends RawCoStreamView<BinaryStreamItem> {
|
||||
public testCompareItems(
|
||||
a: CoStreamItem<BinaryStreamItem>,
|
||||
b: CoStreamItem<BinaryStreamItem>,
|
||||
): number {
|
||||
return this.compareStreamItems(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
test("sorts by madeAt timestamp first", () => {
|
||||
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
|
||||
const coValue = node.createCoValue({
|
||||
type: "costream",
|
||||
ruleset: { type: "unsafeAllowAll" },
|
||||
meta: { type: "binary" },
|
||||
...Crypto.createdNowUnique(),
|
||||
});
|
||||
|
||||
const content = coValue.getCurrentContent();
|
||||
if (!(content instanceof RawBinaryCoStream)) {
|
||||
throw new Error("Expected binary stream");
|
||||
}
|
||||
|
||||
const testView = new TestStreamView(content.core);
|
||||
|
||||
const itemA: CoStreamItem<BinaryStreamItem> = {
|
||||
value: { type: "start", mimeType: "text/plain" },
|
||||
madeAt: 100,
|
||||
tx: { sessionID: node.currentSessionID, txIndex: 0 },
|
||||
};
|
||||
|
||||
const itemB: CoStreamItem<BinaryStreamItem> = {
|
||||
value: { type: "chunk", chunk: "binary_UAwECAQ" },
|
||||
madeAt: 200,
|
||||
tx: { sessionID: node.currentSessionID, txIndex: 1 },
|
||||
};
|
||||
|
||||
expect(testView.testCompareItems(itemA, itemB)).toBeLessThan(0);
|
||||
expect(testView.testCompareItems(itemB, itemA)).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test("sorts by sessionID when timestamps are equal", () => {
|
||||
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
|
||||
const coValue = node.createCoValue({
|
||||
type: "costream",
|
||||
ruleset: { type: "unsafeAllowAll" },
|
||||
meta: { type: "binary" },
|
||||
...Crypto.createdNowUnique(),
|
||||
});
|
||||
|
||||
const content = coValue.getCurrentContent();
|
||||
if (!(content instanceof RawBinaryCoStream)) {
|
||||
throw new Error("Expected binary stream");
|
||||
}
|
||||
|
||||
const testView = new TestStreamView(content.core);
|
||||
const timestamp = Date.now();
|
||||
|
||||
const itemA: CoStreamItem<BinaryStreamItem> = {
|
||||
value: { type: "start", mimeType: "text/plain" },
|
||||
madeAt: timestamp,
|
||||
tx: { sessionID: "a" as SessionID, txIndex: 0 },
|
||||
};
|
||||
|
||||
const itemB: CoStreamItem<BinaryStreamItem> = {
|
||||
value: { type: "chunk", chunk: "binary_UAwECAQ" },
|
||||
madeAt: timestamp,
|
||||
tx: { sessionID: "b" as SessionID, txIndex: 0 },
|
||||
};
|
||||
|
||||
expect(testView.testCompareItems(itemA, itemB)).toBeLessThan(0);
|
||||
expect(testView.testCompareItems(itemB, itemA)).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test("sorts by txIndex when timestamps and sessionIDs are equal", () => {
|
||||
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
|
||||
const coValue = node.createCoValue({
|
||||
type: "costream",
|
||||
ruleset: { type: "unsafeAllowAll" },
|
||||
meta: { type: "binary" },
|
||||
...Crypto.createdNowUnique(),
|
||||
});
|
||||
|
||||
const content = coValue.getCurrentContent();
|
||||
if (!(content instanceof RawBinaryCoStream)) {
|
||||
throw new Error("Expected binary stream");
|
||||
}
|
||||
|
||||
const testView = new TestStreamView(content.core);
|
||||
const timestamp = Date.now();
|
||||
const sessionID = node.currentSessionID;
|
||||
|
||||
const itemA: CoStreamItem<BinaryStreamItem> = {
|
||||
value: { type: "start", mimeType: "text/plain" },
|
||||
madeAt: timestamp,
|
||||
tx: { sessionID, txIndex: 0 },
|
||||
};
|
||||
|
||||
const itemB: CoStreamItem<BinaryStreamItem> = {
|
||||
value: { type: "chunk", chunk: "binary_UAwECAQ" },
|
||||
madeAt: timestamp,
|
||||
tx: { sessionID, txIndex: 1 },
|
||||
};
|
||||
|
||||
// Expect itemA to be before itemB
|
||||
expect(testView.testCompareItems(itemA, itemB)).toBeLessThan(0);
|
||||
expect(testView.testCompareItems(itemB, itemA)).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# create-jazz-app
|
||||
|
||||
## 0.1.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 7e945b5: add directory param to create-jazz-app
|
||||
|
||||
## 0.1.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"types": "src/index.ts",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "0.1.14",
|
||||
"version": "0.1.15",
|
||||
"bin": {
|
||||
"create-jazz-app": "./dist/index.js"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.11.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e7c85b7]
|
||||
- Updated dependencies [8ed144e]
|
||||
- jazz-tools@0.11.6
|
||||
- cojson@0.11.6
|
||||
- jazz-browser@0.11.6
|
||||
|
||||
## 0.11.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "jazz-auth-clerk",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.11.5",
|
||||
"jazz-browser": "workspace:0.11.5",
|
||||
"jazz-tools": "workspace:0.11.5"
|
||||
"cojson": "workspace:0.11.6",
|
||||
"jazz-browser": "workspace:0.11.6",
|
||||
"jazz-tools": "workspace:0.11.6"
|
||||
},
|
||||
"scripts": {
|
||||
"format-and-lint": "biome check .",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.11.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8ed144e: Resolve the promise when the resolutions are processed and mark the package as side-effect free
|
||||
- Updated dependencies [e7c85b7]
|
||||
- jazz-tools@0.11.6
|
||||
- jazz-browser@0.11.6
|
||||
|
||||
## 0.11.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-browser-media-images",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@@ -8,8 +8,8 @@
|
||||
"dependencies": {
|
||||
"@types/image-blob-reduce": "^4.1.1",
|
||||
"image-blob-reduce": "^4.1.0",
|
||||
"jazz-browser": "workspace:0.11.5",
|
||||
"jazz-tools": "workspace:0.11.5",
|
||||
"jazz-browser": "workspace:0.11.6",
|
||||
"jazz-tools": "workspace:0.11.6",
|
||||
"pica": "^9.0.1",
|
||||
"typescript": "~5.6.2"
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@ import ImageBlobReduce from "image-blob-reduce";
|
||||
import { Account, FileStream, Group, ImageDefinition } from "jazz-tools";
|
||||
import Pica from "pica";
|
||||
|
||||
const pica = new Pica();
|
||||
let pica: Pica.Pica | undefined;
|
||||
|
||||
/** @category Image creation */
|
||||
export async function createImage(
|
||||
@@ -12,6 +12,11 @@ export async function createImage(
|
||||
maxSize?: 256 | 1024 | 2048;
|
||||
},
|
||||
): Promise<ImageDefinition> {
|
||||
// Inizialize Pica here to not have module side effects
|
||||
if (!pica) {
|
||||
pica = new Pica();
|
||||
}
|
||||
|
||||
const owner = options?.owner;
|
||||
|
||||
let originalWidth!: number;
|
||||
@@ -40,7 +45,8 @@ export async function createImage(
|
||||
},
|
||||
owner,
|
||||
);
|
||||
setTimeout(async () => {
|
||||
|
||||
const fillImageResolutions = async () => {
|
||||
const max256 = await Reducer.toBlob(imageBlobOrFile, { max: 256 });
|
||||
|
||||
if (originalWidth > 256 || originalHeight > 256) {
|
||||
@@ -55,7 +61,6 @@ export async function createImage(
|
||||
|
||||
const binaryStream = await FileStream.createFromBlob(max256, owner);
|
||||
|
||||
console.log(`${width}x${height}`);
|
||||
imageDefinition[`${width}x${height}`] = binaryStream;
|
||||
}
|
||||
|
||||
@@ -112,7 +117,9 @@ export async function createImage(
|
||||
|
||||
imageDefinition[`${originalWidth}x${originalHeight}`] =
|
||||
originalBinaryStream;
|
||||
}, 0);
|
||||
};
|
||||
|
||||
await fillImageResolutions();
|
||||
|
||||
return imageDefinition;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# jazz-browser
|
||||
|
||||
## 0.11.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e7c85b7]
|
||||
- Updated dependencies [8ed144e]
|
||||
- jazz-tools@0.11.6
|
||||
- cojson@0.11.6
|
||||
- cojson-storage-indexeddb@0.11.6
|
||||
- cojson-transport-ws@0.11.6
|
||||
|
||||
## 0.11.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-browser",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# jazz-inspector
|
||||
|
||||
## 0.11.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 09f0a98: UI and JSON display improvements
|
||||
- 11da4d1: isolate class name hashing on inspector
|
||||
- Updated dependencies [e7c85b7]
|
||||
- Updated dependencies [8ed144e]
|
||||
- jazz-tools@0.11.6
|
||||
- cojson@0.11.6
|
||||
- jazz-react-core@0.11.6
|
||||
|
||||
## 0.11.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-inspector",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"type": "module",
|
||||
"main": "./dist/app.js",
|
||||
"types": "./dist/app.d.ts",
|
||||
@@ -21,7 +21,8 @@
|
||||
"@twind/preset-tailwind": "^1.1.4",
|
||||
"cojson": "workspace:*",
|
||||
"jazz-react-core": "workspace:*",
|
||||
"jazz-tools": "workspace:*"
|
||||
"jazz-tools": "workspace:*",
|
||||
"lucide-react": "^0.274.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
|
||||
@@ -5,4 +5,9 @@ export { JazzInspector } from "./viewer/new-app.js";
|
||||
export { PageStack } from "./viewer/page-stack.js";
|
||||
export { Breadcrumbs } from "./viewer/breadcrumbs.js";
|
||||
|
||||
export { Button } from "./ui/button.js";
|
||||
export { Input } from "./ui/input.js";
|
||||
export { Select } from "./ui/select.js";
|
||||
export { Icon } from "./ui/icon.js";
|
||||
|
||||
export type { PageInfo } from "./viewer/types.js";
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { classNames } from "./utils.js";
|
||||
|
||||
export function LinkIcon() {
|
||||
return (
|
||||
<svg
|
||||
@@ -6,7 +8,7 @@ export function LinkIcon() {
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className="w-3 h-3"
|
||||
className={classNames("w-3 h-3")}
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
|
||||
@@ -28,6 +28,7 @@ Object.keys(stonePalette).forEach((key) => {
|
||||
});
|
||||
|
||||
export default defineConfig({
|
||||
hash: true,
|
||||
presets: [presetAutoprefix(), presetTailwind()],
|
||||
theme: {
|
||||
extend: {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { install } from "@twind/core";
|
||||
import { setup } from "@twind/core";
|
||||
import config from "./twind.config";
|
||||
|
||||
install(config);
|
||||
export const tw = setup(
|
||||
config,
|
||||
undefined,
|
||||
document.getElementById("__jazz_inspector")!,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { clsx } from "clsx";
|
||||
import { forwardRef } from "react";
|
||||
import { classNames } from "../utils.js";
|
||||
|
||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
variant?: "primary" | "secondary" | "tertiary" | "destructive" | "plain";
|
||||
@@ -38,10 +38,10 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
"bg-red-600 border-red-600 text-white font-medium hover:bg-red-700 hover:border-red-700",
|
||||
};
|
||||
|
||||
const classNames =
|
||||
const classes =
|
||||
variant === "plain"
|
||||
? className
|
||||
: clsx(
|
||||
: classNames(
|
||||
className,
|
||||
"inline-flex items-center justify-center gap-2 rounded-lg text-center transition-colors",
|
||||
"disabled:pointer-events-none disabled:opacity-70",
|
||||
@@ -55,7 +55,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
ref={ref}
|
||||
{...buttonProps}
|
||||
disabled={disabled}
|
||||
className={classNames}
|
||||
className={classes}
|
||||
type={type}
|
||||
>
|
||||
{children}
|
||||
89
packages/jazz-inspector/src/ui/icon.tsx
Normal file
89
packages/jazz-inspector/src/ui/icon.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
CheckIcon,
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
ClipboardIcon,
|
||||
LinkIcon,
|
||||
type LucideIcon,
|
||||
TrashIcon,
|
||||
UserIcon,
|
||||
XIcon,
|
||||
} from "lucide-react";
|
||||
import { classNames } from "../utils.js";
|
||||
|
||||
const icons = {
|
||||
auth: UserIcon,
|
||||
check: CheckIcon,
|
||||
chevronRight: ChevronRight,
|
||||
chevronDown: ChevronDown,
|
||||
close: XIcon,
|
||||
copy: ClipboardIcon,
|
||||
delete: TrashIcon,
|
||||
link: LinkIcon,
|
||||
};
|
||||
|
||||
// copied from tailwind line height https://tailwindcss.com/docs/font-size
|
||||
const sizes = {
|
||||
"2xs": 14,
|
||||
xs: 16,
|
||||
sm: 20,
|
||||
md: 24,
|
||||
lg: 28,
|
||||
xl: 28,
|
||||
"2xl": 32,
|
||||
"3xl": 36,
|
||||
"4xl": 40,
|
||||
"5xl": 48,
|
||||
"6xl": 60,
|
||||
"7xl": 72,
|
||||
"8xl": 96,
|
||||
"9xl": 128,
|
||||
};
|
||||
|
||||
const strokeWidths = {
|
||||
"2xs": 2.5,
|
||||
xs: 2,
|
||||
sm: 2,
|
||||
md: 1.5,
|
||||
lg: 1.5,
|
||||
xl: 1.5,
|
||||
"2xl": 1.25,
|
||||
"3xl": 1.25,
|
||||
"4xl": 1.25,
|
||||
"5xl": 1,
|
||||
"6xl": 1,
|
||||
"7xl": 1,
|
||||
"8xl": 1,
|
||||
"9xl": 1,
|
||||
};
|
||||
|
||||
export function Icon({
|
||||
name,
|
||||
icon,
|
||||
size = "md",
|
||||
className,
|
||||
...svgProps
|
||||
}: {
|
||||
name?: string;
|
||||
icon?: LucideIcon;
|
||||
size?: keyof typeof sizes;
|
||||
className?: string;
|
||||
} & React.SVGProps<SVGSVGElement>) {
|
||||
if (!icon && (!name || !icons.hasOwnProperty(name))) {
|
||||
throw new Error(`Icon not found: ${name}`);
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const IconComponent = icons?.hasOwnProperty(name) ? icons[name] : icon;
|
||||
|
||||
return (
|
||||
<IconComponent
|
||||
aria-hidden="true"
|
||||
size={sizes[size]}
|
||||
strokeWidth={strokeWidths[size]}
|
||||
strokeLinecap="round"
|
||||
className={classNames(className)}
|
||||
{...svgProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { clsx } from "clsx";
|
||||
import { forwardRef, useId } from "react";
|
||||
|
||||
import { classNames } from "../utils.js";
|
||||
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
||||
// label can be hidden with a "label:sr-only" className
|
||||
label: string;
|
||||
@@ -13,19 +13,19 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(
|
||||
const generatedId = useId();
|
||||
const id = customId || generatedId;
|
||||
|
||||
const inputClassName = clsx(
|
||||
const inputClassName = classNames(
|
||||
"w-full rounded-md border px-3.5 py-2 shadow-sm",
|
||||
"font-medium text-stone-900",
|
||||
"dark:text-white dark:bg-stone-925",
|
||||
);
|
||||
|
||||
const containerClassName = clsx("grid gap-1", className);
|
||||
const containerClassName = classNames("grid gap-1", className);
|
||||
|
||||
return (
|
||||
<div className={containerClassName}>
|
||||
<label
|
||||
htmlFor={id}
|
||||
className={clsx(
|
||||
className={classNames(
|
||||
"text-stone-600 dark:text-stone-300",
|
||||
hideLabel && "sr-only",
|
||||
)}
|
||||
51
packages/jazz-inspector/src/ui/select.tsx
Normal file
51
packages/jazz-inspector/src/ui/select.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import { useId } from "react";
|
||||
import { classNames } from "../utils.js";
|
||||
import { Icon } from "./icon.js";
|
||||
|
||||
export function Select(
|
||||
props: React.SelectHTMLAttributes<HTMLSelectElement> & {
|
||||
label: string;
|
||||
hideLabel?: boolean;
|
||||
},
|
||||
) {
|
||||
const { label, hideLabel, id: customId, className } = props;
|
||||
const generatedId = useId();
|
||||
const id = customId || generatedId;
|
||||
|
||||
const containerClassName = classNames("grid gap-1", className);
|
||||
|
||||
const selectClassName = classNames(
|
||||
"w-full rounded-md border pl-3.5 py-2 pr-8 shadow-sm",
|
||||
"font-medium text-stone-900",
|
||||
"dark:text-white dark:bg-stone-925",
|
||||
"appearance-none",
|
||||
"truncate",
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={classNames(containerClassName)}>
|
||||
<label
|
||||
htmlFor={id}
|
||||
className={classNames("text-stone-600 dark:text-stone-300", {
|
||||
"sr-only": hideLabel,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
|
||||
<div className={classNames("relative flex items-center")}>
|
||||
<select {...props} id={id} className={selectClassName}>
|
||||
{props.children}
|
||||
</select>
|
||||
|
||||
<Icon
|
||||
name="chevronDown"
|
||||
className={classNames(
|
||||
"absolute right-[0.5em] text-stone-400 dark:text-stone-600",
|
||||
)}
|
||||
size="sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
6
packages/jazz-inspector/src/utils.ts
Normal file
6
packages/jazz-inspector/src/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { ClassValue, clsx } from "clsx";
|
||||
import { tw } from "./twind.js";
|
||||
|
||||
export const classNames = (...inputs: ClassValue[]) => {
|
||||
return tw(clsx(inputs));
|
||||
};
|
||||
@@ -1,7 +1,9 @@
|
||||
import React from "react";
|
||||
import { Button } from "./button.js";
|
||||
import { Button } from "../ui/button.js";
|
||||
import { PageInfo } from "./types.js";
|
||||
|
||||
import { classNames } from "../utils.js";
|
||||
|
||||
interface BreadcrumbsProps {
|
||||
path: PageInfo[];
|
||||
onBreadcrumbClick: (index: number) => void;
|
||||
@@ -12,25 +14,33 @@ export const Breadcrumbs: React.FC<BreadcrumbsProps> = ({
|
||||
onBreadcrumbClick,
|
||||
}) => {
|
||||
return (
|
||||
<div className="relative z-20 flex-1 flex gap-2 items-center">
|
||||
<Button variant="plain" onClick={() => onBreadcrumbClick(-1)}>
|
||||
<div className={classNames("relative z-20 flex-1 flex items-center")}>
|
||||
<Button
|
||||
variant="plain"
|
||||
className={classNames("text-blue px-1 dark:text-blue-400")}
|
||||
onClick={() => onBreadcrumbClick(-1)}
|
||||
>
|
||||
Home
|
||||
</Button>
|
||||
{path.map((page, index) => {
|
||||
return (
|
||||
<span
|
||||
key={index}
|
||||
className={`inline-block ${index === 0 ? "pl-1" : "pl-0"} ${
|
||||
index === path.length - 1 ? "pr-1" : "pr-0"
|
||||
}`}
|
||||
>
|
||||
{index === 0 ? null : (
|
||||
<span className="text-blue-600/30">{" / "}</span>
|
||||
)}
|
||||
<Button variant="tertiary" onClick={() => onBreadcrumbClick(index)}>
|
||||
<React.Fragment key={page.coId}>
|
||||
<span
|
||||
aria-hidden
|
||||
className={classNames(
|
||||
"text-stone-400 dark:text-stone-600 px-0.5",
|
||||
)}
|
||||
>
|
||||
/
|
||||
</span>
|
||||
<Button
|
||||
variant="plain"
|
||||
className={classNames("text-blue px-1 dark:text-blue-400")}
|
||||
onClick={() => onBreadcrumbClick(index)}
|
||||
>
|
||||
{index === 0 ? page.name || "Root" : page.name}
|
||||
</Button>
|
||||
</span>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -9,10 +9,12 @@ import { base64URLtoBytes } from "cojson";
|
||||
import { BinaryStreamItem, BinaryStreamStart, CoStreamItem } from "cojson";
|
||||
import type { JsonObject, JsonValue } from "cojson";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Button } from "./button.js";
|
||||
import { Button } from "../ui/button.js";
|
||||
import { PageInfo } from "./types.js";
|
||||
import { AccountOrGroupPreview } from "./value-renderer.js";
|
||||
|
||||
import { classNames } from "../utils.js";
|
||||
|
||||
// typeguard for BinaryStreamStart
|
||||
function isBinaryStreamStart(item: unknown): item is BinaryStreamStart {
|
||||
return (
|
||||
@@ -162,7 +164,7 @@ const LabelContentPair = ({
|
||||
content: React.ReactNode;
|
||||
}) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<div className={classNames("flex flex-col gap-1.5")}>
|
||||
<span>{label}</span>
|
||||
<span>{content}</span>
|
||||
</div>
|
||||
@@ -220,12 +222,16 @@ function RenderCoBinaryStream({
|
||||
const sizeInKB = (file.totalSize || 0) / 1024;
|
||||
|
||||
return (
|
||||
<div className="mt-8 flex flex-col gap-8">
|
||||
<div className="grid grid-cols-3 gap-2 max-w-3xl">
|
||||
<div className={classNames("mt-8 flex flex-col gap-8")}>
|
||||
<div className={classNames("grid grid-cols-3 gap-2 max-w-3xl")}>
|
||||
<LabelContentPair
|
||||
label="Mime Type"
|
||||
content={
|
||||
<span className="font-mono bg-gray-100 rounded px-2 py-1 text-sm dark:bg-stone-900">
|
||||
<span
|
||||
className={classNames(
|
||||
"font-mono bg-gray-100 rounded px-2 py-1 text-sm dark:bg-stone-900",
|
||||
)}
|
||||
>
|
||||
{mimeType || "No mime type"}
|
||||
</span>
|
||||
}
|
||||
@@ -254,7 +260,9 @@ function RenderCoBinaryStream({
|
||||
<LabelContentPair
|
||||
label="Preview"
|
||||
content={
|
||||
<div className="bg-gray-50 dark:bg-gray-925 p-3 rounded">
|
||||
<div
|
||||
className={classNames("bg-gray-50 dark:bg-gray-925 p-3 rounded")}
|
||||
>
|
||||
<RenderBlobImage blob={blob} />
|
||||
</div>
|
||||
}
|
||||
@@ -275,10 +283,12 @@ function RenderCoStream({
|
||||
const userCoIds = streamPerUser.map((stream) => stream.split("_session")[0]);
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<div className={classNames("grid grid-cols-3 gap-2")}>
|
||||
{userCoIds.map((id, idx) => (
|
||||
<div
|
||||
className="p-3 rounded-lg overflow-hidden border border-gray-200 cursor-pointer shadow-sm hover:bg-gray-100/5"
|
||||
className={classNames(
|
||||
"p-3 rounded-lg overflow-hidden border border-gray-200 cursor-pointer shadow-sm hover:bg-gray-100/5",
|
||||
)}
|
||||
key={id}
|
||||
>
|
||||
<AccountOrGroupPreview coId={id as CoID<RawCoValue>} node={node} />
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user