Compare commits
10 Commits
jazz-auth-
...
feat/form-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
998927f752 | ||
|
|
1da5f9c150 | ||
|
|
ef242d9a7b | ||
|
|
ca4551b044 | ||
|
|
9cd8c407d2 | ||
|
|
88d393ac91 | ||
|
|
f04b11572d | ||
|
|
3cbd4eae3b | ||
|
|
63ab6abd4f | ||
|
|
52243161a3 |
@@ -10,6 +10,7 @@
|
||||
"format-and-lint:fix": "biome check . --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tanstack/react-form": "^0.33.0",
|
||||
"hash-slash": "workspace:*",
|
||||
"jazz-tools": "workspace:*",
|
||||
"react": "19.0.0",
|
||||
@@ -30,4 +31,4 @@
|
||||
"typescript": "5.6.2",
|
||||
"vite": "^6.3.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
import { useCoState } from "jazz-tools/react";
|
||||
import { LinkToHome } from "./LinkToHome.tsx";
|
||||
import { OrderForm } from "./OrderForm.tsx";
|
||||
import { OrderFormWithSaveButton } from "./OrderFormWithSaveButton.tsx";
|
||||
import { OrderThumbnail } from "./OrderThumbnail.tsx";
|
||||
import { BubbleTeaOrder } from "./schema.ts";
|
||||
|
||||
export function EditOrder(props: { id: string }) {
|
||||
const order = useCoState(BubbleTeaOrder, props.id);
|
||||
const order = useCoState(BubbleTeaOrder, props.id, {
|
||||
resolve: { addOns: true, instructions: true },
|
||||
});
|
||||
|
||||
if (!order) return;
|
||||
|
||||
@@ -13,13 +15,17 @@ export function EditOrder(props: { id: string }) {
|
||||
<>
|
||||
<LinkToHome />
|
||||
|
||||
<OrderThumbnail order={order} />
|
||||
<div>
|
||||
<p>Saved order:</p>
|
||||
|
||||
<OrderThumbnail order={order} />
|
||||
</div>
|
||||
|
||||
<h1 className="text-lg">
|
||||
<strong>Edit your bubble tea order 🧋</strong>
|
||||
</h1>
|
||||
|
||||
<OrderForm order={order} />
|
||||
<OrderFormWithSaveButton order={order} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
214
examples/form/src/OrderFormWithSaveButton.tsx
Normal file
214
examples/form/src/OrderFormWithSaveButton.tsx
Normal file
@@ -0,0 +1,214 @@
|
||||
import { CoPlainText, Loaded } from "jazz-tools";
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import {
|
||||
BubbleTeaAddOnTypes,
|
||||
BubbleTeaBaseTeaTypes,
|
||||
BubbleTeaOrder,
|
||||
} from "./schema.ts";
|
||||
import { OrderThumbnail } from "./OrderThumbnail.tsx";
|
||||
|
||||
type LoadedBubbleTeaOrder = Loaded<
|
||||
typeof BubbleTeaOrder,
|
||||
{ addOns: { $each: true }; instructions: true }
|
||||
>;
|
||||
|
||||
// Would be great to derive this type from the CoValue schema
|
||||
export type OrderFormData = {
|
||||
id: string;
|
||||
baseTea: (typeof BubbleTeaBaseTeaTypes)[number];
|
||||
addOns: (typeof BubbleTeaAddOnTypes)[number][];
|
||||
deliveryDate: Date;
|
||||
withMilk: boolean;
|
||||
instructions?: string;
|
||||
};
|
||||
|
||||
export function OrderFormWithSaveButton({
|
||||
order: originalOrder,
|
||||
}: {
|
||||
order: LoadedBubbleTeaOrder;
|
||||
}) {
|
||||
const defaultValues = originalOrder.toJSON();
|
||||
// Convert timestamp to Date
|
||||
defaultValues.deliveryDate = new Date(defaultValues.deliveryDate);
|
||||
|
||||
const form = useForm<OrderFormData>({
|
||||
defaultValues,
|
||||
onSubmit: async ({ value }: { value: OrderFormData }) => {
|
||||
console.log("submit form", value);
|
||||
|
||||
// Apply changes to the original Jazz order
|
||||
originalOrder.baseTea = value.baseTea;
|
||||
originalOrder.addOns.applyDiff(value.addOns);
|
||||
originalOrder.deliveryDate = new Date(value.deliveryDate);
|
||||
originalOrder.withMilk = value.withMilk;
|
||||
|
||||
// `applyDiff` requires nested objects to be CoValues as well
|
||||
const instructions = originalOrder.instructions ?? CoPlainText.create("");
|
||||
if (value.instructions) {
|
||||
instructions.applyDiff(value.instructions);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
className="grid gap-5"
|
||||
>
|
||||
{/* TODO refactor OrderThumbnail to support receiving a plain JSON object */}
|
||||
<div>
|
||||
<p>Unsaved order preview:</p>
|
||||
<form.Subscribe
|
||||
selector={(state) => [state.values]}
|
||||
children={([values]) => <OrderThumbnail order={values} />}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label htmlFor="baseTea">Base tea</label>
|
||||
<form.Field
|
||||
name="baseTea"
|
||||
validators={{
|
||||
onChange: ({ value }) =>
|
||||
!value ? "Please select your preferred base tea" : undefined,
|
||||
}}
|
||||
children={(field) => (
|
||||
<>
|
||||
<select
|
||||
id="baseTea"
|
||||
className="dark:bg-transparent"
|
||||
value={field.state.value}
|
||||
onChange={(e) =>
|
||||
field.handleChange(e.target.value as typeof field.state.value)
|
||||
}
|
||||
onBlur={field.handleBlur}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Please select your preferred base tea
|
||||
</option>
|
||||
{BubbleTeaBaseTeaTypes.map((teaType) => (
|
||||
<option key={teaType} value={teaType}>
|
||||
{teaType}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{field.state.meta.errors.length > 0 && (
|
||||
<span className="text-red-500 text-sm">
|
||||
{field.state.meta.errors[0]}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<fieldset>
|
||||
<legend className="mb-2">Add-ons</legend>
|
||||
<form.Field
|
||||
name="addOns"
|
||||
mode="array"
|
||||
children={(field) => (
|
||||
<>
|
||||
{BubbleTeaAddOnTypes.map((addOn) => (
|
||||
<div key={addOn} className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={addOn}
|
||||
checked={field.state.value.includes(addOn)}
|
||||
onChange={(e) => {
|
||||
const currentValue = field.state.value;
|
||||
if (e.target.checked) {
|
||||
field.handleChange([...currentValue, addOn]);
|
||||
} else {
|
||||
field.handleChange(
|
||||
currentValue.filter((item) => item !== addOn),
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<label htmlFor={addOn}>{addOn}</label>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label htmlFor="deliveryDate">Delivery date</label>
|
||||
<form.Field
|
||||
name="deliveryDate"
|
||||
validators={{
|
||||
onChange: ({ value }) =>
|
||||
!value ? "Delivery date is required" : undefined,
|
||||
}}
|
||||
children={(field) => (
|
||||
<>
|
||||
<input
|
||||
type="date"
|
||||
id="deliveryDate"
|
||||
className="dark:bg-transparent"
|
||||
value={field.state.value.toISOString().split("T")[0]}
|
||||
onChange={(e) => field.handleChange(new Date(e.target.value))}
|
||||
onBlur={field.handleBlur}
|
||||
/>
|
||||
{field.state.meta.errors.length > 0 && (
|
||||
<span className="text-red-500 text-sm">
|
||||
{field.state.meta.errors[0]}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<form.Field
|
||||
name="withMilk"
|
||||
children={(field) => (
|
||||
<input
|
||||
type="checkbox"
|
||||
id="withMilk"
|
||||
checked={field.state.value}
|
||||
onChange={(e) => field.handleChange(e.target.checked)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<label htmlFor="withMilk">With milk?</label>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label htmlFor="instructions">Special instructions</label>
|
||||
<form.Field
|
||||
name="instructions"
|
||||
children={(field) => (
|
||||
<textarea
|
||||
id="instructions"
|
||||
className="dark:bg-transparent"
|
||||
value={field.state.value || ""}
|
||||
onChange={(e) => field.handleChange(e.target.value)}
|
||||
onBlur={field.handleBlur}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<form.Subscribe
|
||||
selector={(state) => [state.canSubmit, state.isSubmitting]}
|
||||
children={([canSubmit, isSubmitting]) => (
|
||||
<button
|
||||
type="submit"
|
||||
disabled={!canSubmit}
|
||||
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:bg-gray-400"
|
||||
>
|
||||
{isSubmitting ? "Submitting..." : "Submit"}
|
||||
</button>
|
||||
)}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Loaded } from "jazz-tools";
|
||||
import { BubbleTeaOrder } from "./schema.ts";
|
||||
import { OrderFormData } from "./OrderFormWithSaveButton.tsx";
|
||||
|
||||
export function OrderThumbnail({
|
||||
order,
|
||||
}: {
|
||||
order: Loaded<typeof BubbleTeaOrder>;
|
||||
order: Loaded<typeof BubbleTeaOrder> | OrderFormData;
|
||||
}) {
|
||||
const { id, baseTea, addOns, instructions, deliveryDate, withMilk } = order;
|
||||
const date = deliveryDate.toLocaleDateString();
|
||||
|
||||
8
examples/tanstack-form/.prettierrc
Normal file
8
examples/tanstack-form/.prettierrc
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
||||
35
examples/tanstack-form/CHANGELOG.md
Normal file
35
examples/tanstack-form/CHANGELOG.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Changelog
|
||||
|
||||
## v0.1.0 - Initial Svelte Migration
|
||||
|
||||
### Added
|
||||
- Complete Svelte implementation of the form example
|
||||
- Native Svelte reactive state management (replacing TanStack Form)
|
||||
- SvelteKit routing with hash router
|
||||
- Tailwind CSS styling
|
||||
- Jazz tools integration for Svelte
|
||||
|
||||
### Changes from React Version
|
||||
- **Form Management**: Replaced TanStack Form with native Svelte `$state` and `$derived` reactives
|
||||
- **Components**: Converted all React components to Svelte components
|
||||
- **Event Handling**: Used Svelte's native event handling instead of React event handlers
|
||||
- **State Management**: Leveraged Svelte's built-in reactivity instead of external form libraries
|
||||
- **Validation**: Implemented custom validation using Svelte reactive patterns
|
||||
|
||||
### Features
|
||||
- ✅ Create new bubble tea orders
|
||||
- ✅ Edit existing orders
|
||||
- ✅ Real-time form preview
|
||||
- ✅ Form validation with error messages
|
||||
- ✅ Date input handling with proper format conversion
|
||||
- ✅ Multiple selection for add-ons
|
||||
- ✅ Jazz CoValue synchronization
|
||||
- ✅ Responsive design with Tailwind CSS
|
||||
|
||||
### Technical Implementation
|
||||
- **Framework**: SvelteKit 2.x with Svelte 5.x
|
||||
- **State**: Native Svelte `$state` runes for reactive state
|
||||
- **Derived State**: `$derived` for computed values like form validity
|
||||
- **Effects**: `$effect` for side effects and lifecycle management
|
||||
- **TypeScript**: Full type safety maintained
|
||||
- **Styling**: Tailwind CSS for consistent design
|
||||
126
examples/tanstack-form/README.md
Normal file
126
examples/tanstack-form/README.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Jazz Form Example - Svelte
|
||||
|
||||
A comprehensive form example built with Svelte and Jazz, demonstrating reactive form handling, validation, and real-time data synchronization.
|
||||
|
||||
## Overview
|
||||
|
||||
This example showcases a bubble tea ordering system with the following features:
|
||||
|
||||
- **Create Orders**: Build new bubble tea orders with base tea, add-ons, delivery date, and special instructions
|
||||
- **Edit Orders**: Modify existing orders with real-time preview
|
||||
- **Form Validation**: Client-side validation with error messages
|
||||
- **Real-time Sync**: Jazz CoValues for real-time data synchronization
|
||||
- **Responsive Design**: Modern UI with Tailwind CSS
|
||||
|
||||
## Key Technologies
|
||||
|
||||
- **Svelte 5.x**: Modern reactive UI framework with runes
|
||||
- **SvelteKit**: Full-stack Svelte framework
|
||||
- **Jazz Tools**: Real-time collaborative data layer
|
||||
- **TypeScript**: Full type safety
|
||||
- **Tailwind CSS**: Utility-first CSS framework
|
||||
|
||||
## Architecture
|
||||
|
||||
### State Management
|
||||
Instead of external form libraries, this example uses Svelte's native reactivity:
|
||||
|
||||
- `$state` - For mutable reactive state
|
||||
- `$derived` - For computed values (like form validity)
|
||||
- `$effect` - For side effects and lifecycle management
|
||||
|
||||
### Form Pattern
|
||||
```svelte
|
||||
<script>
|
||||
// Reactive form state
|
||||
let formData = $state({
|
||||
baseTea: '',
|
||||
addOns: [],
|
||||
deliveryDate: new Date(),
|
||||
withMilk: false,
|
||||
instructions: ''
|
||||
});
|
||||
|
||||
// Derived validation
|
||||
const isValid = $derived(
|
||||
formData.baseTea && formData.deliveryDate
|
||||
);
|
||||
|
||||
// Event handlers
|
||||
function handleSubmit(event) {
|
||||
// Handle form submission
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### Jazz Integration
|
||||
The example demonstrates Jazz CoValues for:
|
||||
- **Account Management**: User authentication and profile
|
||||
- **Data Persistence**: Bubble tea orders stored as CoMaps
|
||||
- **Real-time Sync**: Changes sync across sessions
|
||||
- **Collaborative Features**: Shared data structures
|
||||
|
||||
## Getting Started
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Start development server
|
||||
pnpm dev
|
||||
|
||||
# Build for production
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── lib/
|
||||
│ ├── components/
|
||||
│ │ ├── CreateOrder.svelte # New order creation
|
||||
│ │ ├── EditOrder.svelte # Edit existing orders
|
||||
│ │ ├── Orders.svelte # Order list view
|
||||
│ │ ├── OrderFormWithSaveButton.svelte # Main form component
|
||||
│ │ ├── OrderThumbnail.svelte # Order preview
|
||||
│ │ └── LinkToHome.svelte # Navigation
|
||||
│ ├── schema.ts # Jazz CoValue definitions
|
||||
│ └── apiKey.ts # Jazz API configuration
|
||||
├── routes/
|
||||
│ ├── +layout.svelte # App layout with Jazz provider
|
||||
│ └── +page.svelte # Main app with routing
|
||||
└── app.html # HTML template
|
||||
```
|
||||
|
||||
## Migration from React
|
||||
|
||||
This Svelte version was migrated from a React + TanStack Form implementation. Key differences:
|
||||
|
||||
| React | Svelte |
|
||||
|-------|--------|
|
||||
| `useForm` hook | `$state` runes |
|
||||
| `form.Field` components | Native form elements |
|
||||
| `form.Subscribe` | `$derived` reactives |
|
||||
| Event handlers via props | Native Svelte event handling |
|
||||
| TanStack Form validation | Custom validation functions |
|
||||
|
||||
The Svelte implementation is more concise while maintaining the same functionality and type safety.
|
||||
|
||||
## Features Demonstrated
|
||||
|
||||
- ✅ **Form State Management**: Reactive state with validation
|
||||
- ✅ **Real-time Preview**: Live updates as user types
|
||||
- ✅ **Date Handling**: Proper Date ↔ string conversion for inputs
|
||||
- ✅ **Array Fields**: Dynamic add-on selection
|
||||
- ✅ **Error Handling**: Field-level validation messages
|
||||
- ✅ **Submit State**: Loading states and form submission
|
||||
- ✅ **Jazz Integration**: CoValue creation and updates
|
||||
- ✅ **TypeScript**: Full type safety throughout
|
||||
|
||||
## Learn More
|
||||
|
||||
- [Svelte Documentation](https://svelte.dev/docs)
|
||||
- [SvelteKit Documentation](https://kit.svelte.dev/docs)
|
||||
- [Jazz Documentation](https://jazz.tools/docs)
|
||||
- [Tailwind CSS](https://tailwindcss.com/docs)
|
||||
32
examples/tanstack-form/eslint.config.js
Normal file
32
examples/tanstack-form/eslint.config.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import eslint from "@eslint/js";
|
||||
import prettier from "eslint-config-prettier";
|
||||
import svelte from "eslint-plugin-svelte";
|
||||
import globals from "globals";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
export default tseslint.config(
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
...svelte.configs["flat/recommended"],
|
||||
prettier,
|
||||
...svelte.configs["flat/prettier"],
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["**/*.svelte"],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
parser: tseslint.parser,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ignores: ["build/", ".svelte-kit/", "dist/"],
|
||||
},
|
||||
);
|
||||
43
examples/tanstack-form/package.json
Normal file
43
examples/tanstack-form/package.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "tanstack-form",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "pnpm run check && vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"format": "prettier --write .",
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"format-and-lint": "pnpm run format && pnpm run lint",
|
||||
"format-and-lint:fix": "pnpm run format --write && pnpm run lint --fix",
|
||||
"test:e2e": "playwright test",
|
||||
"test:e2e:ui": "playwright test --ui"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^3.3.1",
|
||||
"@sveltejs/kit": "^2.21.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||
"@tailwindcss/postcss": "^4.1.10",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"eslint": "^9.27.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.46.1",
|
||||
"globals": "^15.15.0",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"svelte": "^5.31.1",
|
||||
"svelte-check": "^4.2.1",
|
||||
"tailwindcss": "^4.1.7",
|
||||
"typescript": "5.6.2",
|
||||
"typescript-eslint": "^8.32.1",
|
||||
"vite": "6.0.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.1.7",
|
||||
"@tanstack/svelte-form": "^1.12.4",
|
||||
"jazz-tools": "workspace:*",
|
||||
"tailwindcss": "^4.1.7"
|
||||
}
|
||||
}
|
||||
1
examples/tanstack-form/src/app.css
Normal file
1
examples/tanstack-form/src/app.css
Normal file
@@ -0,0 +1 @@
|
||||
@import 'tailwindcss';
|
||||
13
examples/tanstack-form/src/app.d.ts
vendored
Normal file
13
examples/tanstack-form/src/app.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// See https://svelte.dev/docs/kit/types#app.d.ts
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface PageState {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
12
examples/tanstack-form/src/app.html
Normal file
12
examples/tanstack-form/src/app.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
1
examples/tanstack-form/src/lib/apiKey.ts
Normal file
1
examples/tanstack-form/src/lib/apiKey.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const apiKey = 'tanstack-form-example_bYRMYEZmBNwE1qKQ';
|
||||
50
examples/tanstack-form/src/lib/components/CreateOrder.svelte
Normal file
50
examples/tanstack-form/src/lib/components/CreateOrder.svelte
Normal file
@@ -0,0 +1,50 @@
|
||||
<script lang="ts">
|
||||
import { AccountCoState } from 'jazz-tools/svelte';
|
||||
import { JazzAccount, BubbleTeaOrder, BubbleTeaBaseTeaTypes, ListOfBubbleTeaAddOns } from '$lib/schema';
|
||||
import OrderFormWithSaveButton from './OrderFormWithSaveButton.svelte';
|
||||
import LinkToHome from './LinkToHome.svelte';
|
||||
import { CoPlainText } from 'jazz-tools';
|
||||
|
||||
const me = new AccountCoState(JazzAccount, {
|
||||
resolve: {
|
||||
profile: true,
|
||||
root: {
|
||||
orders: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const orders = $derived(me.current?.root.orders);
|
||||
|
||||
// Create a new order when component loads
|
||||
let newOrder = $state<any>(null);
|
||||
|
||||
$effect(() => {
|
||||
if (orders && !newOrder) {
|
||||
const order = BubbleTeaOrder.create({
|
||||
baseTea: BubbleTeaBaseTeaTypes[0],
|
||||
addOns: ListOfBubbleTeaAddOns.create([], orders._owner),
|
||||
deliveryDate: new Date(),
|
||||
withMilk: false,
|
||||
instructions: CoPlainText.create(''),
|
||||
}, orders._owner);
|
||||
|
||||
orders.push(order);
|
||||
newOrder = order;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<LinkToHome />
|
||||
|
||||
<h1 class="text-lg mb-4">
|
||||
<strong>Create your bubble tea order 🧋</strong>
|
||||
</h1>
|
||||
|
||||
{#if newOrder}
|
||||
<OrderFormWithSaveButton order={newOrder} />
|
||||
{:else}
|
||||
<p>Creating order...</p>
|
||||
{/if}
|
||||
</div>
|
||||
39
examples/tanstack-form/src/lib/components/EditOrder.svelte
Normal file
39
examples/tanstack-form/src/lib/components/EditOrder.svelte
Normal file
@@ -0,0 +1,39 @@
|
||||
<script lang="ts">
|
||||
import { CoState } from 'jazz-tools/svelte';
|
||||
import LinkToHome from './LinkToHome.svelte';
|
||||
import OrderFormWithSaveButton from './OrderFormWithSaveButton.svelte';
|
||||
import OrderThumbnail from './OrderThumbnail.svelte';
|
||||
import { BubbleTeaOrder } from '$lib/schema';
|
||||
|
||||
type Props = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
let { id }: Props = $props();
|
||||
|
||||
const order = new CoState(BubbleTeaOrder, id, {
|
||||
resolve: { addOns: true, instructions: true },
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if order.current}
|
||||
<div>
|
||||
<LinkToHome />
|
||||
|
||||
<div class="mb-6">
|
||||
<p>Saved order:</p>
|
||||
<OrderThumbnail order={order.current} />
|
||||
</div>
|
||||
|
||||
<h1 class="text-lg mb-4">
|
||||
<strong>Edit your bubble tea order 🧋</strong>
|
||||
</h1>
|
||||
|
||||
<OrderFormWithSaveButton order={order.current} />
|
||||
</div>
|
||||
{:else}
|
||||
<div>
|
||||
<LinkToHome />
|
||||
<p>Loading order...</p>
|
||||
</div>
|
||||
{/if}
|
||||
14
examples/tanstack-form/src/lib/components/LinkToHome.svelte
Normal file
14
examples/tanstack-form/src/lib/components/LinkToHome.svelte
Normal file
@@ -0,0 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
function navigateHome() {
|
||||
goto('#/');
|
||||
}
|
||||
</script>
|
||||
|
||||
<button
|
||||
onclick={navigateHome}
|
||||
class="mb-4 text-blue-500 hover:text-blue-700 underline"
|
||||
>
|
||||
← Back to orders
|
||||
</button>
|
||||
@@ -0,0 +1,194 @@
|
||||
<script lang="ts">
|
||||
import { CoPlainText, type Loaded } from 'jazz-tools';
|
||||
import {
|
||||
BubbleTeaAddOnTypes,
|
||||
BubbleTeaBaseTeaTypes,
|
||||
type BubbleTeaOrder
|
||||
} from '$lib/schema';
|
||||
import { createForm } from '@tanstack/svelte-form';
|
||||
import OrderThumbnail from './OrderThumbnail.svelte';
|
||||
|
||||
type LoadedBubbleTeaOrder = Loaded<
|
||||
typeof BubbleTeaOrder,
|
||||
{ addOns: { $each: true }; instructions: true }
|
||||
>;
|
||||
|
||||
type OrderFormData = {
|
||||
id: string;
|
||||
baseTea: (typeof BubbleTeaBaseTeaTypes)[number];
|
||||
addOns: (typeof BubbleTeaAddOnTypes)[number][];
|
||||
deliveryDate: Date;
|
||||
withMilk: boolean;
|
||||
instructions?: string;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
order: LoadedBubbleTeaOrder;
|
||||
};
|
||||
|
||||
let { order: originalOrder }: Props = $props();
|
||||
|
||||
const defaultValues: OrderFormData = originalOrder.toJSON();
|
||||
defaultValues.deliveryDate = new Date(defaultValues.deliveryDate);
|
||||
|
||||
const form = createForm(() => ({
|
||||
defaultValues,
|
||||
onSubmit: async ({ value }) => {
|
||||
console.log('submit form', value);
|
||||
|
||||
// Apply changes to the original Jazz order
|
||||
originalOrder.baseTea = value.baseTea;
|
||||
originalOrder.addOns.applyDiff(value.addOns);
|
||||
originalOrder.deliveryDate = value.deliveryDate;
|
||||
originalOrder.withMilk = value.withMilk;
|
||||
|
||||
// Handle instructions (CoPlainText)
|
||||
const instructions = originalOrder.instructions ?? CoPlainText.create('');
|
||||
if (value.instructions) {
|
||||
instructions.applyDiff(value.instructions);
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
function handleSubmit(event: Event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
form.handleSubmit();
|
||||
}
|
||||
</script>
|
||||
|
||||
<form onsubmit={handleSubmit} class="grid gap-5">
|
||||
<form.Subscribe selector={(state) => state.values}>
|
||||
{#snippet children(values)}
|
||||
<p>Unsaved order preview:</p>
|
||||
<OrderThumbnail order={values} />
|
||||
{/snippet}
|
||||
</form.Subscribe>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<label for="baseTea">Base tea</label>
|
||||
<form.Field
|
||||
name="baseTea"
|
||||
validators={{
|
||||
onChange: ({ value }) => {
|
||||
if (!value) {
|
||||
return 'Please select your preferred base tea';
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
}}
|
||||
>
|
||||
{#snippet children(field)}
|
||||
<select
|
||||
id="baseTea"
|
||||
class="dark:bg-transparent"
|
||||
value={field.state.value}
|
||||
onchange={(e) => field.handleChange(e.currentTarget.value as typeof BubbleTeaBaseTeaTypes[number])}
|
||||
onblur={field.handleBlur}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Please select your preferred base tea
|
||||
</option>
|
||||
{#each BubbleTeaBaseTeaTypes as teaType}
|
||||
<option value={teaType}>
|
||||
{teaType}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
{#if field.state.meta.errors.length > 0}
|
||||
<span class="text-red-500 text-sm">{field.state.meta.errors[0]}</span>
|
||||
{/if}
|
||||
{/snippet}
|
||||
</form.Field>
|
||||
</div>
|
||||
|
||||
<fieldset>
|
||||
<legend class="mb-2">Add-ons</legend>
|
||||
<form.Field name="addOns">
|
||||
{#snippet children(field)}
|
||||
{#each BubbleTeaAddOnTypes as addOn}
|
||||
<div class="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={addOn}
|
||||
checked={field.state.value.includes(addOn)}
|
||||
onchange={(e) => {
|
||||
const updatedAddons = (e.currentTarget.checked) ? [...field.state.value, addOn] : field.state.value.filter((item: string) => item !== addOn)
|
||||
field.handleChange(updatedAddons)}}
|
||||
/>
|
||||
<label for={addOn}>{addOn}</label>
|
||||
</div>
|
||||
{/each}
|
||||
{/snippet}
|
||||
</form.Field>
|
||||
</fieldset>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<label for="deliveryDate">Delivery date</label>
|
||||
<form.Field
|
||||
name="deliveryDate"
|
||||
validators={{
|
||||
onChange: ({ value }) => {
|
||||
if (!value) {
|
||||
return 'Delivery date is required';
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
}}
|
||||
>
|
||||
{#snippet children(field)}
|
||||
<input
|
||||
type="date"
|
||||
id="deliveryDate"
|
||||
class="dark:bg-transparent"
|
||||
value={field.state.value.toISOString().split('T')[0]}
|
||||
onchange={(e) => field.handleChange(new Date(e.currentTarget.value))}
|
||||
onblur={field.handleBlur}
|
||||
/>
|
||||
{#if field.state.meta.errors.length > 0}
|
||||
<span class="text-red-500 text-sm">{field.state.meta.errors[0]}</span>
|
||||
{/if}
|
||||
{/snippet}
|
||||
</form.Field>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<form.Field name="withMilk">
|
||||
{#snippet children(field)}
|
||||
<input
|
||||
type="checkbox"
|
||||
id="withMilk"
|
||||
checked={field.state.value}
|
||||
onchange={(e) => field.handleChange(e.currentTarget.checked)}
|
||||
/>
|
||||
<label for="withMilk">With milk?</label>
|
||||
{/snippet}
|
||||
</form.Field>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<label for="instructions">Special instructions</label>
|
||||
<form.Field name="instructions">
|
||||
{#snippet children(field)}
|
||||
<textarea
|
||||
id="instructions"
|
||||
class="dark:bg-transparent"
|
||||
value={field.state.value || ''}
|
||||
onchange={(e) => field.handleChange(e.currentTarget.value)}
|
||||
></textarea>
|
||||
{/snippet}
|
||||
</form.Field>
|
||||
</div>
|
||||
|
||||
<form.Subscribe selector={(state) => [state.canSubmit, state.isSubmitting]}>
|
||||
{#snippet children([canSubmit, isSubmitting])}
|
||||
<button
|
||||
type="submit"
|
||||
disabled={!canSubmit}
|
||||
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:bg-gray-400"
|
||||
>
|
||||
{isSubmitting ? 'Submitting...' : 'Submit'}
|
||||
</button>
|
||||
{/snippet}
|
||||
</form.Subscribe>
|
||||
</form>
|
||||
@@ -0,0 +1,39 @@
|
||||
<script lang="ts">
|
||||
import { type Loaded } from 'jazz-tools';
|
||||
import { type BubbleTeaOrder } from '$lib/schema';
|
||||
|
||||
type Props = {
|
||||
order: Loaded<typeof BubbleTeaOrder> | {
|
||||
baseTea: string;
|
||||
addOns: string[];
|
||||
deliveryDate: Date;
|
||||
withMilk: boolean;
|
||||
instructions?: string;
|
||||
};
|
||||
};
|
||||
|
||||
let { order }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="border p-3 bg-gray-50 dark:bg-gray-800 rounded">
|
||||
<strong>
|
||||
{order.baseTea || "(No tea selected)"}
|
||||
{order.withMilk ? " milk " : " "}
|
||||
tea
|
||||
</strong>
|
||||
{#if order.addOns && order.addOns.length > 0}
|
||||
<p class="text-sm text-stone-600">
|
||||
with {order.addOns.join(", ").toLowerCase()}
|
||||
</p>
|
||||
{/if}
|
||||
{#if order.instructions}
|
||||
<p class="text-sm text-stone-600 italic">
|
||||
{order.instructions}
|
||||
</p>
|
||||
{/if}
|
||||
{#if order.deliveryDate}
|
||||
<p class="text-sm text-stone-600">
|
||||
Delivery: {order.deliveryDate.toLocaleDateString()}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
59
examples/tanstack-form/src/lib/components/Orders.svelte
Normal file
59
examples/tanstack-form/src/lib/components/Orders.svelte
Normal file
@@ -0,0 +1,59 @@
|
||||
<script lang="ts">
|
||||
import { AccountCoState } from 'jazz-tools/svelte';
|
||||
import { JazzAccount, type BubbleTeaOrder } from '$lib/schema';
|
||||
import { type Loaded } from 'jazz-tools';
|
||||
import OrderThumbnail from './OrderThumbnail.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
const me = new AccountCoState(JazzAccount, {
|
||||
resolve: {
|
||||
profile: true,
|
||||
root: {
|
||||
orders: {
|
||||
$each: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const orders = $derived(me.current?.root.orders);
|
||||
|
||||
function navigateToCreateOrder() {
|
||||
goto('#/order');
|
||||
}
|
||||
|
||||
function navigateToEditOrder(id: string) {
|
||||
goto(`#/order/${id}`);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<h1 class="text-lg mb-4">
|
||||
<strong>Your bubble tea orders 🧋</strong>
|
||||
</h1>
|
||||
|
||||
{#if orders && orders.length > 0}
|
||||
<div class="space-y-4">
|
||||
{#each orders as order}
|
||||
{#if order}
|
||||
<button
|
||||
type="button"
|
||||
class="border rounded-lg p-4 cursor-pointer hover:bg-gray-50 text-left w-full"
|
||||
onclick={() => navigateToEditOrder(order.id)}
|
||||
>
|
||||
<OrderThumbnail {order} />
|
||||
</button>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<p class="text-gray-500">No orders yet. Create your first order!</p>
|
||||
{/if}
|
||||
|
||||
<button
|
||||
onclick={navigateToCreateOrder}
|
||||
class="mt-6 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
|
||||
>
|
||||
Create New Order
|
||||
</button>
|
||||
</div>
|
||||
86
examples/tanstack-form/src/lib/schema.ts
Normal file
86
examples/tanstack-form/src/lib/schema.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { type Loaded, co, z } from 'jazz-tools';
|
||||
|
||||
export const BubbleTeaAddOnTypes = [
|
||||
'Pearl',
|
||||
'Lychee jelly',
|
||||
'Red bean',
|
||||
'Brown sugar',
|
||||
'Taro'
|
||||
] as const;
|
||||
|
||||
export const BubbleTeaBaseTeaTypes = ['Black', 'Oolong', 'Jasmine', 'Thai'] as const;
|
||||
|
||||
export const ListOfBubbleTeaAddOns = co
|
||||
.list(z.literal([...BubbleTeaAddOnTypes]))
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.withHelpers((Self) => ({
|
||||
hasChanges(list?: Loaded<typeof Self> | null) {
|
||||
return list && Object.entries(list._raw.insertions).length > 0;
|
||||
}
|
||||
}));
|
||||
|
||||
export const BubbleTeaOrder = co.map({
|
||||
baseTea: z.literal([...BubbleTeaBaseTeaTypes]),
|
||||
addOns: ListOfBubbleTeaAddOns,
|
||||
deliveryDate: z.date(),
|
||||
withMilk: z.boolean(),
|
||||
instructions: z.optional(co.plainText())
|
||||
});
|
||||
|
||||
export const DraftBubbleTeaOrder = co
|
||||
.map({
|
||||
baseTea: z.optional(z.literal([...BubbleTeaBaseTeaTypes])),
|
||||
addOns: z.optional(ListOfBubbleTeaAddOns),
|
||||
deliveryDate: z.optional(z.date()),
|
||||
withMilk: z.optional(z.boolean()),
|
||||
instructions: z.optional(co.plainText())
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
.withHelpers((Self) => ({
|
||||
hasChanges(order: Loaded<typeof Self> | undefined) {
|
||||
return (
|
||||
!!order &&
|
||||
(Object.keys(order._edits).length > 1 || ListOfBubbleTeaAddOns.hasChanges(order.addOns))
|
||||
);
|
||||
},
|
||||
|
||||
validate(order: Loaded<typeof Self>) {
|
||||
const errors: string[] = [];
|
||||
|
||||
if (!order.baseTea) {
|
||||
errors.push('Please select your preferred base tea.');
|
||||
}
|
||||
if (!order.deliveryDate) {
|
||||
errors.push('Plese select a delivery date.');
|
||||
}
|
||||
|
||||
return { errors };
|
||||
}
|
||||
}));
|
||||
|
||||
/** The root is an app-specific per-user private `CoMap`
|
||||
* where you can store top-level objects for that user */
|
||||
export const AccountRoot = co.map({
|
||||
draft: DraftBubbleTeaOrder,
|
||||
orders: co.list(BubbleTeaOrder)
|
||||
});
|
||||
|
||||
export const JazzAccount = co
|
||||
.account({
|
||||
root: AccountRoot,
|
||||
profile: co.profile()
|
||||
})
|
||||
.withMigration((account) => {
|
||||
if (!account.root) {
|
||||
const orders = co.list(BubbleTeaOrder).create([], account);
|
||||
const draft = DraftBubbleTeaOrder.create(
|
||||
{
|
||||
addOns: ListOfBubbleTeaAddOns.create([], account),
|
||||
instructions: co.plainText().create('', account)
|
||||
},
|
||||
account
|
||||
);
|
||||
|
||||
account.root = AccountRoot.create({ draft, orders }, account);
|
||||
}
|
||||
});
|
||||
28
examples/tanstack-form/src/routes/+layout.svelte
Normal file
28
examples/tanstack-form/src/routes/+layout.svelte
Normal file
@@ -0,0 +1,28 @@
|
||||
<script lang="ts">
|
||||
import { JazzSvelteProvider } from 'jazz-tools/svelte';
|
||||
import 'jazz-tools/inspector/register-custom-element';
|
||||
import { PasskeyAuthBasicUI } from 'jazz-tools/svelte';
|
||||
import { apiKey } from '$lib/apiKey';
|
||||
import { JazzAccount } from '$lib/schema';
|
||||
import '../app.css';
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Form Example</title>
|
||||
</svelte:head>
|
||||
|
||||
<JazzSvelteProvider
|
||||
AccountSchema={JazzAccount}
|
||||
sync={{
|
||||
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
||||
}}
|
||||
>
|
||||
<jazz-inspector></jazz-inspector>
|
||||
<PasskeyAuthBasicUI appName="Form Example">
|
||||
<div class="min-h-screen bg-gray-100">
|
||||
{@render children()}
|
||||
</div>
|
||||
</PasskeyAuthBasicUI>
|
||||
</JazzSvelteProvider>
|
||||
22
examples/tanstack-form/src/routes/+page.svelte
Normal file
22
examples/tanstack-form/src/routes/+page.svelte
Normal file
@@ -0,0 +1,22 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import CreateOrder from '$lib/components/CreateOrder.svelte';
|
||||
import EditOrder from '$lib/components/EditOrder.svelte';
|
||||
import Orders from '$lib/components/Orders.svelte';
|
||||
|
||||
// Get current route from URL hash or default to '/'
|
||||
const currentRoute = $derived($page.url.hash || '#/');
|
||||
const route = $derived(currentRoute.replace('#', '') || '/');
|
||||
</script>
|
||||
|
||||
<main class="max-w-xl mx-auto px-3 py-8 space-y-8">
|
||||
{#if route === '/'}
|
||||
<Orders />
|
||||
{:else if route === '/order'}
|
||||
<CreateOrder />
|
||||
{:else if route.startsWith('/order/')}
|
||||
{#if route.split('/').length === 3}
|
||||
<EditOrder id={route.split('/')[2]} />
|
||||
{/if}
|
||||
{/if}
|
||||
</main>
|
||||
13
examples/tanstack-form/svelte.config.js
Normal file
13
examples/tanstack-form/svelte.config.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import adapter from "@sveltejs/adapter-auto";
|
||||
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
preprocess: vitePreprocess(),
|
||||
|
||||
kit: {
|
||||
adapter: adapter(),
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
14
examples/tanstack-form/tsconfig.json
Normal file
14
examples/tanstack-form/tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "./.svelte-kit/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"moduleResolution": "bundler"
|
||||
}
|
||||
}
|
||||
10
examples/tanstack-form/vite.config.ts
Normal file
10
examples/tanstack-form/vite.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit(), tailwindcss()],
|
||||
optimizeDeps: {
|
||||
exclude: ['jazz-tools']
|
||||
}
|
||||
});
|
||||
361
pnpm-lock.yaml
generated
361
pnpm-lock.yaml
generated
@@ -129,7 +129,7 @@ importers:
|
||||
version: 0.510.0(react@19.0.0)
|
||||
next:
|
||||
specifier: 15.3.2
|
||||
version: 15.3.2(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
version: 15.3.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
react:
|
||||
specifier: 19.0.0
|
||||
version: 19.0.0
|
||||
@@ -169,7 +169,7 @@ importers:
|
||||
version: 19.0.0
|
||||
react-email:
|
||||
specifier: ^4.0.11
|
||||
version: 4.0.13(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
version: 4.0.13(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
tailwindcss:
|
||||
specifier: ^4
|
||||
version: 4.1.10
|
||||
@@ -667,6 +667,9 @@ importers:
|
||||
|
||||
examples/form:
|
||||
dependencies:
|
||||
'@tanstack/react-form':
|
||||
specifier: ^0.33.0
|
||||
version: 0.33.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.6.2)
|
||||
hash-slash:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/hash-slash
|
||||
@@ -720,6 +723,70 @@ importers:
|
||||
specifier: 6.3.5
|
||||
version: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)
|
||||
|
||||
examples/form-svelte:
|
||||
dependencies:
|
||||
'@tailwindcss/vite':
|
||||
specifier: ^4.1.7
|
||||
version: 4.1.10(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1))
|
||||
'@tanstack/svelte-form':
|
||||
specifier: ^1.12.4
|
||||
version: 1.12.4(svelte@5.34.6)
|
||||
jazz-tools:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/jazz-tools
|
||||
tailwindcss:
|
||||
specifier: ^4.1.7
|
||||
version: 4.1.10
|
||||
devDependencies:
|
||||
'@sveltejs/adapter-auto':
|
||||
specifier: ^3.3.1
|
||||
version: 3.3.1(@sveltejs/kit@2.21.5(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.6)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)))(svelte@5.34.6)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)))
|
||||
'@sveltejs/kit':
|
||||
specifier: ^2.21.1
|
||||
version: 2.21.5(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.6)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)))(svelte@5.34.6)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1))
|
||||
'@sveltejs/vite-plugin-svelte':
|
||||
specifier: ^5.0.3
|
||||
version: 5.1.0(svelte@5.34.6)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1))
|
||||
'@tailwindcss/postcss':
|
||||
specifier: ^4.1.10
|
||||
version: 4.1.10
|
||||
'@types/eslint':
|
||||
specifier: ^9.6.1
|
||||
version: 9.6.1
|
||||
eslint:
|
||||
specifier: ^9.27.0
|
||||
version: 9.28.0(jiti@2.4.2)
|
||||
eslint-config-prettier:
|
||||
specifier: ^9.1.0
|
||||
version: 9.1.0(eslint@9.28.0(jiti@2.4.2))
|
||||
eslint-plugin-svelte:
|
||||
specifier: ^2.46.1
|
||||
version: 2.46.1(eslint@9.28.0(jiti@2.4.2))(svelte@5.34.6)(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.18)(typescript@5.6.2))
|
||||
globals:
|
||||
specifier: ^15.15.0
|
||||
version: 15.15.0
|
||||
prettier:
|
||||
specifier: ^3.5.3
|
||||
version: 3.5.3
|
||||
prettier-plugin-svelte:
|
||||
specifier: ^3.4.0
|
||||
version: 3.4.0(prettier@3.5.3)(svelte@5.34.6)
|
||||
svelte:
|
||||
specifier: ^5.31.1
|
||||
version: 5.34.6
|
||||
svelte-check:
|
||||
specifier: ^4.2.1
|
||||
version: 4.2.1(picomatch@4.0.2)(svelte@5.34.6)(typescript@5.6.2)
|
||||
typescript:
|
||||
specifier: 5.6.2
|
||||
version: 5.6.2
|
||||
typescript-eslint:
|
||||
specifier: ^8.32.1
|
||||
version: 8.34.0(eslint@9.28.0(jiti@2.4.2))(typescript@5.6.2)
|
||||
vite:
|
||||
specifier: 6.3.5
|
||||
version: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)
|
||||
|
||||
examples/image-upload:
|
||||
dependencies:
|
||||
jazz-tools:
|
||||
@@ -825,7 +892,7 @@ importers:
|
||||
version: link:../../packages/jazz-tools
|
||||
next:
|
||||
specifier: 15.3.2
|
||||
version: 15.3.2(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
version: 15.3.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
react:
|
||||
specifier: 19.0.0
|
||||
version: 19.0.0
|
||||
@@ -5282,10 +5349,48 @@ packages:
|
||||
'@remirror/core-constants@3.0.0':
|
||||
resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==}
|
||||
|
||||
'@remix-run/node@2.16.8':
|
||||
resolution: {integrity: sha512-foeYXU3mdaBJZnbtGbM8mNdHowz2+QnVGDRo7P3zgFkmsccMEflArGZNbkACGKd9xwDguTxxMJ6cuXBC4jIfgQ==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
peerDependencies:
|
||||
typescript: ^5.1.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@remix-run/router@1.21.0':
|
||||
resolution: {integrity: sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
'@remix-run/router@1.23.0':
|
||||
resolution: {integrity: sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
'@remix-run/server-runtime@2.16.8':
|
||||
resolution: {integrity: sha512-ZwWOam4GAQTx10t+wK09YuYctd2Koz5Xy/klDgUN3lmTXmwbV0tZU0baiXEqZXrvyD+WDZ4b0ADDW9Df3+dpzA==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
peerDependencies:
|
||||
typescript: ^5.1.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@remix-run/web-blob@3.1.0':
|
||||
resolution: {integrity: sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==}
|
||||
|
||||
'@remix-run/web-fetch@4.4.2':
|
||||
resolution: {integrity: sha512-jgKfzA713/4kAW/oZ4bC3MoLWyjModOVDjFPNseVqcJKSafgIscrYL9G50SurEYLswPuoU3HzSbO0jQCMYWHhA==}
|
||||
engines: {node: ^10.17 || >=12.3}
|
||||
|
||||
'@remix-run/web-file@3.1.0':
|
||||
resolution: {integrity: sha512-dW2MNGwoiEYhlspOAXFBasmLeYshyAyhIdrlXBi06Duex5tDr3ut2LFKVj7tyHLmn8nnNwFf1BjNbkQpygC2aQ==}
|
||||
|
||||
'@remix-run/web-form-data@3.1.0':
|
||||
resolution: {integrity: sha512-NdeohLMdrb+pHxMQ/Geuzdp0eqPbea+Ieo8M8Jx2lGC6TBHsgHzYcBvr0LyPdPVycNRDEpWpiDdCOdCryo3f9A==}
|
||||
|
||||
'@remix-run/web-stream@1.1.0':
|
||||
resolution: {integrity: sha512-KRJtwrjRV5Bb+pM7zxcTJkhIqWWSy+MYsIxHK+0m5atcznsf15YwUBWHWulZerV2+vvHH1Lp1DD7pw6qKW8SgA==}
|
||||
|
||||
'@rnx-kit/console@2.0.0':
|
||||
resolution: {integrity: sha512-8kyM0TUWpawWlaypHKWLgJjPoF5HcsjIxx9LSnYM8VgwBW1gOl2cCDhPYaeS8IG9m0fi4rMtQD8OJqmwpJ2jEg==}
|
||||
engines: {node: '>=16.17'}
|
||||
@@ -5776,10 +5881,25 @@ packages:
|
||||
peerDependencies:
|
||||
vite: 6.3.5
|
||||
|
||||
'@tanstack/form-core@0.33.0':
|
||||
resolution: {integrity: sha512-ouu1JVwLZgfPkIdIq3TWIZs++KpLOo8Bx4tXYOc/1KwA9qUQ0Iv/+Y6GfiC4wMcUzGCtLKOww84eZ8Qdge3ZmQ==}
|
||||
|
||||
'@tanstack/form-core@1.12.4':
|
||||
resolution: {integrity: sha512-BhfNI5sEjI68Im1Vqezf9w68fJL4EB80cqW5w0zb/MV1erHHsXNRwLGmljF88VnCx1t/xd4fmF0D08wNajBauQ==}
|
||||
|
||||
'@tanstack/history@1.115.0':
|
||||
resolution: {integrity: sha512-K7JJNrRVvyjAVnbXOH2XLRhFXDkeP54Kt2P4FR1Kl2KDGlIbkua5VqZQD2rot3qaDrpufyUa63nuLai1kOLTsQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@tanstack/react-form@0.33.0':
|
||||
resolution: {integrity: sha512-+292gWfP67uAu3zYeIQAQYEk6T7IvQUiuKwanCyATROG92FsxQrYeJdqDk4Bkh0MB8uy13CilrdxZOoEMdEKSQ==}
|
||||
peerDependencies:
|
||||
'@tanstack/start': ^1.43.13
|
||||
react: 19.0.0
|
||||
peerDependenciesMeta:
|
||||
'@tanstack/start':
|
||||
optional: true
|
||||
|
||||
'@tanstack/react-router-devtools@1.116.0':
|
||||
resolution: {integrity: sha512-PsJZWPjcmwZGe71kUvH4bI1ozkv1FgBuBEE0hTYlTCSJ3uG+qv3ndGEI+AiFyuF5OStrbfg0otW1OxeNq5vdGQ==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -5795,6 +5915,12 @@ packages:
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0
|
||||
|
||||
'@tanstack/react-store@0.5.8':
|
||||
resolution: {integrity: sha512-G8TFpT/QJv2B2vro4QOUypvMjjSrbLRR8VKNoBByr6gpXAhU7y7mkrsn55Ra6svplVuvF+rAPTvHcUJKtU6geQ==}
|
||||
peerDependencies:
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0
|
||||
|
||||
'@tanstack/react-store@0.7.0':
|
||||
resolution: {integrity: sha512-S/Rq17HaGOk+tQHV/yrePMnG1xbsKZIl/VsNWnNXt4XW+tTY8dTlvpJH2ZQ3GRALsusG5K6Q3unAGJ2pd9W/Ng==}
|
||||
peerDependencies:
|
||||
@@ -5851,9 +5977,25 @@ packages:
|
||||
resolution: {integrity: sha512-Dng4y+uLR9b5zPGg7dHReHOTHQa6x+G6nCoZshsDtWrYsrdCcJEtLyhwZ5wG8OyYS6dVr/Cn+E5Bd2b6BhJ89w==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@tanstack/store@0.5.5':
|
||||
resolution: {integrity: sha512-EOSrgdDAJExbvRZEQ/Xhh9iZchXpMN+ga1Bnk8Nmygzs8TfiE6hbzThF+Pr2G19uHL6+DTDTHhJ8VQiOd7l4tA==}
|
||||
|
||||
'@tanstack/store@0.7.0':
|
||||
resolution: {integrity: sha512-CNIhdoUsmD2NolYuaIs8VfWM467RK6oIBAW4nPEKZhg1smZ+/CwtCdpURgp7nxSqOaV9oKkzdWD80+bC66F/Jg==}
|
||||
|
||||
'@tanstack/store@0.7.1':
|
||||
resolution: {integrity: sha512-PjUQKXEXhLYj2X5/6c1Xn/0/qKY0IVFxTJweopRfF26xfjVyb14yALydJrHupDh3/d+1WKmfEgZPBVCmDkzzwg==}
|
||||
|
||||
'@tanstack/svelte-form@1.12.4':
|
||||
resolution: {integrity: sha512-as8J3wu+GZUIeG1DZSEibF81D8GoalCJvag/OiOjeO28aHZEL3fExtCltzJkCE5odQCrL0QmNUreQ/P3gE7rEA==}
|
||||
peerDependencies:
|
||||
svelte: ^5.0.0
|
||||
|
||||
'@tanstack/svelte-store@0.7.1':
|
||||
resolution: {integrity: sha512-09GSf96YCmwquWVqLbbX0VpO+bXdJFqzxTC7gVR6Q/uqd+3mwZnC3ORVMi25tFQDKNrbAtAzhpEwzOgSUobeyQ==}
|
||||
peerDependencies:
|
||||
svelte: ^5.0.0
|
||||
|
||||
'@tanstack/virtual-file-routes@1.115.0':
|
||||
resolution: {integrity: sha512-XLUh1Py3AftcERrxkxC5Y5m5mfllRH3YR6YVlyjFgI2Tc2Ssy2NKmQFQIafoxfW459UJ8Dn81nWKETEIJifE4g==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -6598,6 +6740,9 @@ packages:
|
||||
resolution: {integrity: sha512-0TcTjBiax1VxtJQ/iQA0ZyYOSHjjX2ARVmEI0AMo9+AuIq+xBfnY561+v8k9GqOMPKsiH/HrK3xwjx8xCVS03g==}
|
||||
engines: {node: ^16.13 || >=18}
|
||||
|
||||
'@web3-storage/multipart-parser@1.0.0':
|
||||
resolution: {integrity: sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==}
|
||||
|
||||
'@xmldom/xmldom@0.7.13':
|
||||
resolution: {integrity: sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
@@ -6635,6 +6780,9 @@ packages:
|
||||
'@zxcvbn-ts/language-common@3.0.4':
|
||||
resolution: {integrity: sha512-viSNNnRYtc7ULXzxrQIVUNwHAPSXRtoIwy/Tq4XQQdIknBzw4vz36lQLF6mvhMlTIlpjoN/Z1GFu/fwiAlUSsw==}
|
||||
|
||||
'@zxing/text-encoding@0.9.0':
|
||||
resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==}
|
||||
|
||||
abbrev@2.0.0:
|
||||
resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==}
|
||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||
@@ -7394,6 +7542,10 @@ packages:
|
||||
convert-source-map@2.0.0:
|
||||
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
||||
|
||||
cookie-signature@1.2.2:
|
||||
resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
|
||||
engines: {node: '>=6.6.0'}
|
||||
|
||||
cookie@0.5.0:
|
||||
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@@ -7511,6 +7663,10 @@ packages:
|
||||
data-uri-to-buffer@2.0.2:
|
||||
resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==}
|
||||
|
||||
data-uri-to-buffer@3.0.1:
|
||||
resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
data-uri-to-buffer@4.0.1:
|
||||
resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
|
||||
engines: {node: '>= 12'}
|
||||
@@ -7587,6 +7743,9 @@ packages:
|
||||
decimal.js@10.4.3:
|
||||
resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
|
||||
|
||||
decode-formdata@0.8.0:
|
||||
resolution: {integrity: sha512-iUzDgnWsw5ToSkFY7VPFA5Gfph6ROoOxOB7Ybna4miUSzLZ4KaSJk6IAB2AdW6+C9vCVWhjjNA4gjT6wF3eZHQ==}
|
||||
|
||||
decode-uri-component@0.2.2:
|
||||
resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==}
|
||||
engines: {node: '>=0.10'}
|
||||
@@ -10012,6 +10171,10 @@ packages:
|
||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
mrmime@1.0.1:
|
||||
resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
mrmime@2.0.0:
|
||||
resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -11747,6 +11910,10 @@ packages:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
source-map@0.7.4:
|
||||
resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
source-map@0.8.0-beta.0:
|
||||
resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -11847,6 +12014,9 @@ packages:
|
||||
resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==}
|
||||
engines: {node: '>= 0.10.0'}
|
||||
|
||||
stream-slice@0.1.2:
|
||||
resolution: {integrity: sha512-QzQxpoacatkreL6jsxnVb7X5R/pGw9OUv2qWTYWnmLpg4NdN31snPy/f3TdQE1ZUXaThRvj1Zw4/OGg0ZkaLMA==}
|
||||
|
||||
streamsearch@1.1.0:
|
||||
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
@@ -12349,6 +12519,9 @@ packages:
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
turbo-stream@2.4.1:
|
||||
resolution: {integrity: sha512-v8kOJXpG3WoTN/+at8vK7erSzo6nW6CIaeOvNOkHQVDajfz1ZVeSxCbc6tOH4hrGZW7VUCV0TOXd8CPzYnYkrw==}
|
||||
|
||||
turbo-windows-64@2.3.3:
|
||||
resolution: {integrity: sha512-O2+BS4QqjK3dOERscXqv7N2GXNcqHr9hXumkMxDj/oGx9oCatIwnnwx34UmzodloSnJpgSqjl8iRWiY65SmYoQ==}
|
||||
cpu: [x64]
|
||||
@@ -12481,6 +12654,10 @@ packages:
|
||||
resolution: {integrity: sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==}
|
||||
engines: {node: '>=18.17'}
|
||||
|
||||
undici@6.21.3:
|
||||
resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==}
|
||||
engines: {node: '>=18.17'}
|
||||
|
||||
unenv@2.0.0-rc.1:
|
||||
resolution: {integrity: sha512-PU5fb40H8X149s117aB4ytbORcCvlASdtF97tfls4BPIyj4PeVxvpSuy1jAptqYHqB0vb2w2sHvzM0XWcp2OKg==}
|
||||
|
||||
@@ -12814,6 +12991,9 @@ packages:
|
||||
wcwidth@1.0.1:
|
||||
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
|
||||
|
||||
web-encoding@1.1.5:
|
||||
resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==}
|
||||
|
||||
web-streams-polyfill@3.3.3:
|
||||
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -17302,8 +17482,62 @@ snapshots:
|
||||
|
||||
'@remirror/core-constants@3.0.0': {}
|
||||
|
||||
'@remix-run/node@2.16.8(typescript@5.6.2)':
|
||||
dependencies:
|
||||
'@remix-run/server-runtime': 2.16.8(typescript@5.6.2)
|
||||
'@remix-run/web-fetch': 4.4.2
|
||||
'@web3-storage/multipart-parser': 1.0.0
|
||||
cookie-signature: 1.2.2
|
||||
source-map-support: 0.5.21
|
||||
stream-slice: 0.1.2
|
||||
undici: 6.21.3
|
||||
optionalDependencies:
|
||||
typescript: 5.6.2
|
||||
|
||||
'@remix-run/router@1.21.0': {}
|
||||
|
||||
'@remix-run/router@1.23.0': {}
|
||||
|
||||
'@remix-run/server-runtime@2.16.8(typescript@5.6.2)':
|
||||
dependencies:
|
||||
'@remix-run/router': 1.23.0
|
||||
'@types/cookie': 0.6.0
|
||||
'@web3-storage/multipart-parser': 1.0.0
|
||||
cookie: 0.7.2
|
||||
set-cookie-parser: 2.7.1
|
||||
source-map: 0.7.4
|
||||
turbo-stream: 2.4.1
|
||||
optionalDependencies:
|
||||
typescript: 5.6.2
|
||||
|
||||
'@remix-run/web-blob@3.1.0':
|
||||
dependencies:
|
||||
'@remix-run/web-stream': 1.1.0
|
||||
web-encoding: 1.1.5
|
||||
|
||||
'@remix-run/web-fetch@4.4.2':
|
||||
dependencies:
|
||||
'@remix-run/web-blob': 3.1.0
|
||||
'@remix-run/web-file': 3.1.0
|
||||
'@remix-run/web-form-data': 3.1.0
|
||||
'@remix-run/web-stream': 1.1.0
|
||||
'@web3-storage/multipart-parser': 1.0.0
|
||||
abort-controller: 3.0.0
|
||||
data-uri-to-buffer: 3.0.1
|
||||
mrmime: 1.0.1
|
||||
|
||||
'@remix-run/web-file@3.1.0':
|
||||
dependencies:
|
||||
'@remix-run/web-blob': 3.1.0
|
||||
|
||||
'@remix-run/web-form-data@3.1.0':
|
||||
dependencies:
|
||||
web-encoding: 1.1.5
|
||||
|
||||
'@remix-run/web-stream@1.1.0':
|
||||
dependencies:
|
||||
web-streams-polyfill: 3.3.3
|
||||
|
||||
'@rnx-kit/console@2.0.0': {}
|
||||
|
||||
'@rnx-kit/metro-config@2.0.1(@react-native/metro-config@0.80.0(@babel/core@7.27.1))(react-native@0.80.0(@babel/core@7.27.1)(@react-native-community/cli@19.0.0(typescript@5.6.2))(@types/react@19.0.0)(react@19.0.0))(react@19.0.0)':
|
||||
@@ -17545,6 +17779,11 @@ snapshots:
|
||||
'@sveltejs/kit': 2.21.5(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.1)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)))(svelte@5.34.1)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1))
|
||||
import-meta-resolve: 4.1.0
|
||||
|
||||
'@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.21.5(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.6)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)))(svelte@5.34.6)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)))':
|
||||
dependencies:
|
||||
'@sveltejs/kit': 2.21.5(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.6)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)))(svelte@5.34.6)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1))
|
||||
import-meta-resolve: 4.1.0
|
||||
|
||||
'@sveltejs/adapter-auto@6.0.1(@sveltejs/kit@2.21.5(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.1)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)))(svelte@5.34.1)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)))':
|
||||
dependencies:
|
||||
'@sveltejs/kit': 2.21.5(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.1)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)))(svelte@5.34.1)(vite@6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1))
|
||||
@@ -17819,8 +18058,27 @@ snapshots:
|
||||
tailwindcss: 4.1.10
|
||||
vite: 6.3.5(@types/node@22.15.18)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)
|
||||
|
||||
'@tanstack/form-core@0.33.0':
|
||||
dependencies:
|
||||
'@tanstack/store': 0.5.5
|
||||
|
||||
'@tanstack/form-core@1.12.4':
|
||||
dependencies:
|
||||
'@tanstack/store': 0.7.1
|
||||
|
||||
'@tanstack/history@1.115.0': {}
|
||||
|
||||
'@tanstack/react-form@0.33.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.6.2)':
|
||||
dependencies:
|
||||
'@remix-run/node': 2.16.8(typescript@5.6.2)
|
||||
'@tanstack/form-core': 0.33.0
|
||||
'@tanstack/react-store': 0.5.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
decode-formdata: 0.8.0
|
||||
react: 19.0.0
|
||||
transitivePeerDependencies:
|
||||
- react-dom
|
||||
- typescript
|
||||
|
||||
'@tanstack/react-router-devtools@1.116.0(@tanstack/react-router@1.116.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@tanstack/router-core@1.115.3)(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(tiny-invariant@1.3.3)':
|
||||
dependencies:
|
||||
'@tanstack/react-router': 1.116.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
@@ -17844,6 +18102,13 @@ snapshots:
|
||||
tiny-invariant: 1.3.3
|
||||
tiny-warning: 1.0.3
|
||||
|
||||
'@tanstack/react-store@0.5.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||
dependencies:
|
||||
'@tanstack/store': 0.5.5
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
use-sync-external-store: 1.5.0(react@19.0.0)
|
||||
|
||||
'@tanstack/react-store@0.7.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||
dependencies:
|
||||
'@tanstack/store': 0.7.0
|
||||
@@ -17908,8 +18173,23 @@ snapshots:
|
||||
ansis: 3.17.0
|
||||
diff: 7.0.0
|
||||
|
||||
'@tanstack/store@0.5.5': {}
|
||||
|
||||
'@tanstack/store@0.7.0': {}
|
||||
|
||||
'@tanstack/store@0.7.1': {}
|
||||
|
||||
'@tanstack/svelte-form@1.12.4(svelte@5.34.6)':
|
||||
dependencies:
|
||||
'@tanstack/form-core': 1.12.4
|
||||
'@tanstack/svelte-store': 0.7.1(svelte@5.34.6)
|
||||
svelte: 5.34.6
|
||||
|
||||
'@tanstack/svelte-store@0.7.1(svelte@5.34.6)':
|
||||
dependencies:
|
||||
'@tanstack/store': 0.7.1
|
||||
svelte: 5.34.6
|
||||
|
||||
'@tanstack/virtual-file-routes@1.115.0': {}
|
||||
|
||||
'@testing-library/dom@10.4.0':
|
||||
@@ -18820,7 +19100,7 @@ snapshots:
|
||||
sirv: 3.0.1
|
||||
tinyglobby: 0.2.14
|
||||
tinyrainbow: 2.0.0
|
||||
vitest: 3.1.3(@types/node@22.15.18)(@vitest/browser@3.1.3)(@vitest/ui@3.1.3)(happy-dom@17.4.4)(jiti@2.4.2)(jsdom@25.0.1)(lightningcss@1.30.1)(msw@2.7.0(@types/node@22.15.18)(typescript@5.6.2))(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)
|
||||
vitest: 3.1.3(@types/node@22.15.18)(@vitest/browser@3.1.3)(@vitest/ui@3.1.3)(happy-dom@17.4.4)(jiti@2.4.2)(jsdom@25.0.1)(lightningcss@1.30.1)(msw@2.7.0(@types/node@22.15.18)(typescript@5.8.3))(terser@5.37.0)(tsx@4.19.3)(yaml@2.6.1)
|
||||
|
||||
'@vitest/utils@3.1.1':
|
||||
dependencies:
|
||||
@@ -18952,6 +19232,8 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@web3-storage/multipart-parser@1.0.0': {}
|
||||
|
||||
'@xmldom/xmldom@0.7.13': {}
|
||||
|
||||
'@xmldom/xmldom@0.8.10': {}
|
||||
@@ -18987,6 +19269,9 @@ snapshots:
|
||||
|
||||
'@zxcvbn-ts/language-common@3.0.4': {}
|
||||
|
||||
'@zxing/text-encoding@0.9.0':
|
||||
optional: true
|
||||
|
||||
abbrev@2.0.0: {}
|
||||
|
||||
abort-controller@3.0.0:
|
||||
@@ -19853,6 +20138,8 @@ snapshots:
|
||||
|
||||
convert-source-map@2.0.0: {}
|
||||
|
||||
cookie-signature@1.2.2: {}
|
||||
|
||||
cookie@0.5.0: {}
|
||||
|
||||
cookie@0.6.0: {}
|
||||
@@ -19989,6 +20276,8 @@ snapshots:
|
||||
|
||||
data-uri-to-buffer@2.0.2: {}
|
||||
|
||||
data-uri-to-buffer@3.0.1: {}
|
||||
|
||||
data-uri-to-buffer@4.0.1: {}
|
||||
|
||||
data-uri-to-buffer@6.0.2: {}
|
||||
@@ -20042,6 +20331,8 @@ snapshots:
|
||||
|
||||
decimal.js@10.4.3: {}
|
||||
|
||||
decode-formdata@0.8.0: {}
|
||||
|
||||
decode-uri-component@0.2.2: {}
|
||||
|
||||
decode-uri-component@0.4.1: {}
|
||||
@@ -20505,6 +20796,25 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- ts-node
|
||||
|
||||
eslint-plugin-svelte@2.46.1(eslint@9.28.0(jiti@2.4.2))(svelte@5.34.6)(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.18)(typescript@5.6.2)):
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@2.4.2))
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
eslint: 9.28.0(jiti@2.4.2)
|
||||
eslint-compat-utils: 0.5.1(eslint@9.28.0(jiti@2.4.2))
|
||||
esutils: 2.0.3
|
||||
known-css-properties: 0.35.0
|
||||
postcss: 8.5.4
|
||||
postcss-load-config: 3.1.4(postcss@8.5.4)(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.18)(typescript@5.6.2))
|
||||
postcss-safe-parser: 6.0.0(postcss@8.5.4)
|
||||
postcss-selector-parser: 6.1.2
|
||||
semver: 7.7.2
|
||||
svelte-eslint-parser: 0.43.0(svelte@5.34.6)
|
||||
optionalDependencies:
|
||||
svelte: 5.34.6
|
||||
transitivePeerDependencies:
|
||||
- ts-node
|
||||
|
||||
eslint-scope@5.1.1:
|
||||
dependencies:
|
||||
esrecurse: 4.3.0
|
||||
@@ -22958,6 +23268,8 @@ snapshots:
|
||||
|
||||
mri@1.2.0: {}
|
||||
|
||||
mrmime@1.0.1: {}
|
||||
|
||||
mrmime@2.0.0: {}
|
||||
|
||||
ms@2.0.0: {}
|
||||
@@ -23071,7 +23383,7 @@ snapshots:
|
||||
|
||||
neverthrow@7.2.0: {}
|
||||
|
||||
next@15.3.2(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
next@15.3.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
dependencies:
|
||||
'@next/env': 15.3.2
|
||||
'@swc/counter': 0.1.3
|
||||
@@ -23081,7 +23393,7 @@ snapshots:
|
||||
postcss: 8.4.31
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
styled-jsx: 5.1.6(react@19.0.0)
|
||||
styled-jsx: 5.1.6(@babel/core@7.27.1)(react@19.0.0)
|
||||
optionalDependencies:
|
||||
'@next/swc-darwin-arm64': 15.3.2
|
||||
'@next/swc-darwin-x64': 15.3.2
|
||||
@@ -23650,6 +23962,11 @@ snapshots:
|
||||
prettier: 3.5.3
|
||||
svelte: 5.34.1
|
||||
|
||||
prettier-plugin-svelte@3.4.0(prettier@3.5.3)(svelte@5.34.6):
|
||||
dependencies:
|
||||
prettier: 3.5.3
|
||||
svelte: 5.34.6
|
||||
|
||||
prettier-plugin-tailwindcss@0.6.9(prettier-plugin-svelte@3.4.0(prettier@3.5.3)(svelte@5.34.1))(prettier@3.5.3):
|
||||
dependencies:
|
||||
prettier: 3.5.3
|
||||
@@ -24040,7 +24357,7 @@ snapshots:
|
||||
react: 19.0.0
|
||||
scheduler: 0.25.0
|
||||
|
||||
react-email@4.0.13(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
react-email@4.0.13(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
dependencies:
|
||||
'@babel/parser': 7.27.2
|
||||
'@babel/traverse': 7.27.1
|
||||
@@ -24052,7 +24369,7 @@ snapshots:
|
||||
glob: 11.0.2
|
||||
log-symbols: 7.0.0
|
||||
mime-types: 3.0.1
|
||||
next: 15.3.2(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
next: 15.3.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
normalize-path: 3.0.0
|
||||
ora: 8.2.0
|
||||
socket.io: 4.8.1
|
||||
@@ -25040,6 +25357,8 @@ snapshots:
|
||||
|
||||
source-map@0.6.1: {}
|
||||
|
||||
source-map@0.7.4: {}
|
||||
|
||||
source-map@0.8.0-beta.0:
|
||||
dependencies:
|
||||
whatwg-url: 7.1.0
|
||||
@@ -25127,6 +25446,8 @@ snapshots:
|
||||
|
||||
stream-buffers@2.2.0: {}
|
||||
|
||||
stream-slice@0.1.2: {}
|
||||
|
||||
streamsearch@1.1.0: {}
|
||||
|
||||
streamx@2.21.1:
|
||||
@@ -25272,10 +25593,12 @@ snapshots:
|
||||
|
||||
structured-headers@0.4.1: {}
|
||||
|
||||
styled-jsx@5.1.6(react@19.0.0):
|
||||
styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.0.0):
|
||||
dependencies:
|
||||
client-only: 0.0.1
|
||||
react: 19.0.0
|
||||
optionalDependencies:
|
||||
'@babel/core': 7.27.1
|
||||
|
||||
stylis@4.2.0: {}
|
||||
|
||||
@@ -25346,6 +25669,16 @@ snapshots:
|
||||
optionalDependencies:
|
||||
svelte: 5.34.1
|
||||
|
||||
svelte-eslint-parser@0.43.0(svelte@5.34.6):
|
||||
dependencies:
|
||||
eslint-scope: 7.2.2
|
||||
eslint-visitor-keys: 3.4.3
|
||||
espree: 9.6.1
|
||||
postcss: 8.5.4
|
||||
postcss-scss: 4.0.9(postcss@8.5.4)
|
||||
optionalDependencies:
|
||||
svelte: 5.34.6
|
||||
|
||||
svelte-sonner@0.3.28(svelte@5.34.1):
|
||||
dependencies:
|
||||
svelte: 5.34.1
|
||||
@@ -25714,6 +26047,8 @@ snapshots:
|
||||
turbo-linux-arm64@2.3.3:
|
||||
optional: true
|
||||
|
||||
turbo-stream@2.4.1: {}
|
||||
|
||||
turbo-windows-64@2.3.3:
|
||||
optional: true
|
||||
|
||||
@@ -25842,6 +26177,8 @@ snapshots:
|
||||
|
||||
undici@6.21.0: {}
|
||||
|
||||
undici@6.21.3: {}
|
||||
|
||||
unenv@2.0.0-rc.1:
|
||||
dependencies:
|
||||
defu: 6.1.4
|
||||
@@ -26293,6 +26630,12 @@ snapshots:
|
||||
dependencies:
|
||||
defaults: 1.0.4
|
||||
|
||||
web-encoding@1.1.5:
|
||||
dependencies:
|
||||
util: 0.12.5
|
||||
optionalDependencies:
|
||||
'@zxing/text-encoding': 0.9.0
|
||||
|
||||
web-streams-polyfill@3.3.3: {}
|
||||
|
||||
webdriver@8.41.0:
|
||||
|
||||
Reference in New Issue
Block a user