diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..7d74fe2
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,9 @@
+# Package Managers
+package-lock.json
+pnpm-lock.yaml
+yarn.lock
+bun.lock
+bun.lockb
+
+# Miscellaneous
+/static/
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..3f7802c
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,15 @@
+{
+ "useTabs": true,
+ "singleQuote": true,
+ "trailingComma": "none",
+ "printWidth": 100,
+ "plugins": ["prettier-plugin-svelte"],
+ "overrides": [
+ {
+ "files": "*.svelte",
+ "options": {
+ "parser": "svelte"
+ }
+ }
+ ]
+}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 28d1e67..38f928a 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -1,3 +1,3 @@
{
- "recommendations": ["svelte.svelte-vscode"]
+ "recommendations": ["svelte.svelte-vscode", "esbenp.prettier-vscode"]
}
diff --git a/AGENTS.md b/AGENTS.md
index 3a524df..2140b9b 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1 +1 @@
-- Non modificare mai i file direttamente, proponi la soluzione nella chat.
\ No newline at end of file
+- Puoi modificare direttamente i tag e lo stile di componenti e pagine.
diff --git a/package-lock.json b/package-lock.json
index fe7167f..68f2455 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,6 +21,8 @@
"better-auth": "~1.4.21",
"drizzle-kit": "^0.31.8",
"drizzle-orm": "^0.45.1",
+ "prettier": "^3.8.1",
+ "prettier-plugin-svelte": "^3.4.1",
"svelte": "^5.51.0",
"svelte-check": "^4.4.2",
"typescript": "^5.9.3",
@@ -4658,6 +4660,17 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
+ "node_modules/prettier-plugin-svelte": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.5.1.tgz",
+ "integrity": "sha512-65+fr5+cgIKWKiqM1Doum4uX6bY8iFCdztvvp2RcF+AJoieaw9kJOFMNcJo/bkmKYsxFaM9OsVZK/gWauG/5mg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "prettier": "^3.0.0",
+ "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
+ }
+ },
"node_modules/process-warning": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz",
diff --git a/package.json b/package.json
index 9f84605..9dcc865 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,9 @@
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:studio": "drizzle-kit studio",
- "auth:schema": "better-auth generate --config src/lib/server/auth.ts --output src/lib/server/db/auth.schema.ts --yes"
+ "auth:schema": "better-auth generate --config src/lib/server/auth.ts --output src/lib/server/db/auth.schema.ts --yes",
+ "lint": "prettier --check .",
+ "format": "prettier --write ."
},
"devDependencies": {
"@better-auth/cli": "~1.4.21",
@@ -26,6 +28,8 @@
"better-auth": "~1.4.21",
"drizzle-kit": "^0.31.8",
"drizzle-orm": "^0.45.1",
+ "prettier": "^3.8.1",
+ "prettier-plugin-svelte": "^3.4.1",
"svelte": "^5.51.0",
"svelte-check": "^4.4.2",
"typescript": "^5.9.3",
diff --git a/src/app.d.ts b/src/app.d.ts
index 87f8dbd..2ae6f13 100644
--- a/src/app.d.ts
+++ b/src/app.d.ts
@@ -4,7 +4,10 @@ import type { User, Session } from 'better-auth/minimal';
// for information about these interfaces
declare global {
namespace App {
- interface Locals { user?: User; session?: Session }
+ interface Locals {
+ user?: User;
+ session?: Session;
+ }
// interface Error {}
// interface PageData {}
diff --git a/src/app.html b/src/app.html
index f273cc5..19689b3 100644
--- a/src/app.html
+++ b/src/app.html
@@ -3,6 +3,12 @@
+
+
+
%sveltekit.head%
diff --git a/src/hooks.server.ts b/src/hooks.server.ts
index 85a772e..2c6220d 100644
--- a/src/hooks.server.ts
+++ b/src/hooks.server.ts
@@ -4,8 +4,6 @@ import { auth } from '$lib/server/auth';
import { svelteKitHandler } from 'better-auth/svelte-kit';
import { sequence } from '@sveltejs/kit/hooks';
-
-
const handleBetterAuth: Handle = async ({ event, resolve }) => {
const session = await auth.api.getSession({ headers: event.request.headers });
@@ -29,6 +27,6 @@ const handleRouting: Handle = async ({ event, resolve }) => {
}
return resolve(event);
-}
+};
export const handle: Handle = sequence(handleBetterAuth, handleRouting);
diff --git a/src/lib/assets/composer/palette.svg b/src/lib/assets/composer/palette.svg
new file mode 100644
index 0000000..77a1f56
--- /dev/null
+++ b/src/lib/assets/composer/palette.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/src/lib/components/Note.svelte b/src/lib/components/Note.svelte
deleted file mode 100644
index df9fff7..0000000
--- a/src/lib/components/Note.svelte
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/src/lib/components/NoteEditor.svelte b/src/lib/components/NoteEditor.svelte
deleted file mode 100644
index f53080b..0000000
--- a/src/lib/components/NoteEditor.svelte
+++ /dev/null
@@ -1,34 +0,0 @@
-
\ No newline at end of file
diff --git a/src/lib/components/NoteNavbar.svelte b/src/lib/components/NoteNavbar.svelte
deleted file mode 100644
index 9ec367a..0000000
--- a/src/lib/components/NoteNavbar.svelte
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
- {
- if (e.key === "n" && e.metaKey) {
- expanded = true;
- return;
- }
- if( e.key === "Escape") {
- expanded = false;
- return;
- }
- }}
-/>
-
-{#if !expanded}
- Scrivi una nota...
-{:else}
-
-
-
-{/if}
\ No newline at end of file
diff --git a/src/lib/components/board/BoardCanvas.svelte b/src/lib/components/board/BoardCanvas.svelte
new file mode 100644
index 0000000..d91a1d1
--- /dev/null
+++ b/src/lib/components/board/BoardCanvas.svelte
@@ -0,0 +1,61 @@
+
+
+
+ {#each notes as note (note.id)}
+ {
+ event.stopPropagation();
+ onStartDrag(event, note.id);
+ }}
+ >
+
+
+ {/each}
+
+
+
diff --git a/src/lib/components/board/Note.svelte b/src/lib/components/board/Note.svelte
new file mode 100644
index 0000000..68f66bf
--- /dev/null
+++ b/src/lib/components/board/Note.svelte
@@ -0,0 +1,65 @@
+
+
+
+ {#if note.title.trim().length > 0}
+ {note.title}
+ {/if}
+
+ {#if note.content.trim().length > 0}
+ {note.content}
+ {:else}
+ Nota senza contenuto
+ {/if}
+
+ {note.date.toLocaleString('it-IT')}
+
+
+
diff --git a/src/lib/components/board/script/constants.ts b/src/lib/components/board/script/constants.ts
new file mode 100644
index 0000000..eaddb6f
--- /dev/null
+++ b/src/lib/components/board/script/constants.ts
@@ -0,0 +1,9 @@
+export const BOARD_WIDTH = 5400;
+export const BOARD_HEIGHT = 5400;
+
+export const BOARD_GRID_SIZE = 16;
+
+export const NOTE_CARD_WIDTH = 280;
+export const NOTE_CARD_MIN_HEIGHT = 140;
+
+export const MINIMAP_WIDTH = 220;
diff --git a/src/lib/components/board/script/types.ts b/src/lib/components/board/script/types.ts
new file mode 100644
index 0000000..d7bfe59
--- /dev/null
+++ b/src/lib/components/board/script/types.ts
@@ -0,0 +1,31 @@
+import type { Note } from '$lib/components/editor/script/editor';
+
+export type BoardNote = Note & {
+ x: number;
+ y: number;
+ z: number;
+};
+
+export type DragState =
+ | {
+ id: string;
+ offsetX: number;
+ offsetY: number;
+ }
+ | null;
+
+export type PanState =
+ | {
+ startX: number;
+ startY: number;
+ scrollLeft: number;
+ scrollTop: number;
+ }
+ | null;
+
+export type ViewportState = {
+ scrollLeft: number;
+ scrollTop: number;
+ width: number;
+ height: number;
+};
diff --git a/src/lib/components/board/script/utils.ts b/src/lib/components/board/script/utils.ts
new file mode 100644
index 0000000..99267f8
--- /dev/null
+++ b/src/lib/components/board/script/utils.ts
@@ -0,0 +1,18 @@
+import {
+ BOARD_HEIGHT,
+ BOARD_WIDTH,
+ NOTE_CARD_MIN_HEIGHT,
+ NOTE_CARD_WIDTH
+} from '$lib/components/board/script/constants';
+
+export const clamp = (value: number, min: number, max: number) =>
+ Math.min(max, Math.max(min, value));
+
+export const getRandomPosition = (idx: number) => ({
+ x: 200 + ((idx * 420) % (BOARD_WIDTH - NOTE_CARD_WIDTH - 260)),
+ y: 140 + Math.floor(idx / 8) * 260
+});
+
+export const clampNoteX = (x: number) => clamp(x, 0, BOARD_WIDTH - NOTE_CARD_WIDTH);
+
+export const clampNoteY = (y: number) => clamp(y, 0, BOARD_HEIGHT - NOTE_CARD_MIN_HEIGHT);
diff --git a/src/lib/components/editor/ColorSelector.svelte b/src/lib/components/editor/ColorSelector.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/src/lib/components/editor/NoteEditor.svelte b/src/lib/components/editor/NoteEditor.svelte
new file mode 100644
index 0000000..f896292
--- /dev/null
+++ b/src/lib/components/editor/NoteEditor.svelte
@@ -0,0 +1,193 @@
+
+
+
+
+{#if note}
+
+{/if}
+
+
diff --git a/src/lib/components/editor/script/types.ts b/src/lib/components/editor/script/types.ts
new file mode 100644
index 0000000..cada5ab
--- /dev/null
+++ b/src/lib/components/editor/script/types.ts
@@ -0,0 +1,23 @@
+export type Note = {
+ id: string;
+
+ title: string;
+ content: string;
+ color: string;
+ date: Date;
+
+ images: ImageAttachment[];
+ files: FileAttachment[];
+};
+
+export type ImageAttachment = NoteAttachment & { kind: 'image' };
+export type FileAttachment = NoteAttachment & { kind: 'file' };
+
+interface NoteAttachment {
+ id: string;
+
+ name: string;
+ size: number;
+ mimeType: string;
+ previewUrl?: string;
+}
diff --git a/src/lib/components/editor/script/utils.ts b/src/lib/components/editor/script/utils.ts
new file mode 100644
index 0000000..e69de29
diff --git a/src/lib/components/ui/Minimap.svelte b/src/lib/components/ui/Minimap.svelte
new file mode 100644
index 0000000..a9ac2ad
--- /dev/null
+++ b/src/lib/components/ui/Minimap.svelte
@@ -0,0 +1,112 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/Navbar.svelte b/src/lib/components/ui/Navbar.svelte
new file mode 100644
index 0000000..17f03b6
--- /dev/null
+++ b/src/lib/components/ui/Navbar.svelte
@@ -0,0 +1,62 @@
+
+
+ {
+ if (e.key === 'Escape') {
+ expanded = false;
+ return;
+ }
+ }}
+/>
+
+{#if !expanded}
+
+{:else}
+
+ (expanded = false)} />
+
+{/if}
+
+
diff --git a/src/lib/editor.ts b/src/lib/editor.ts
deleted file mode 100644
index 2f585e9..0000000
--- a/src/lib/editor.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export type Note = {
- id: string;
-
- title: string;
- content: string;
- color: string;
- date: Date;
-
- images: ImageAttachment[];
- files: FileAttachment[];
-};
-
-
-export type ImageAttachment = NoteAttachment & { kind: "image" };
-export type FileAttachment = NoteAttachment & { kind: "file" };
-
-interface NoteAttachment {
- id: string;
-
- name: string;
- size: number;
- mimeType: string;
- previewUrl?: string;
-}
-
diff --git a/src/lib/media.ts b/src/lib/media.ts
deleted file mode 100644
index 98e048c..0000000
--- a/src/lib/media.ts
+++ /dev/null
@@ -1 +0,0 @@
-export type MediaProvider = 'youtube' | 'youtube-music' | 'spotify';
diff --git a/src/lib/server/db/auth.schema.ts b/src/lib/server/db/auth.schema.ts
index 66fc633..4fb0524 100644
--- a/src/lib/server/db/auth.schema.ts
+++ b/src/lib/server/db/auth.schema.ts
@@ -1,107 +1,105 @@
-import { relations, sql } from "drizzle-orm";
-import { sqliteTable, text, integer, index } from "drizzle-orm/sqlite-core";
+import { relations, sql } from 'drizzle-orm';
+import { sqliteTable, text, integer, index } from 'drizzle-orm/sqlite-core';
-export const user = sqliteTable("user", {
- id: text("id").primaryKey(),
- name: text("name").notNull(),
- email: text("email").notNull().unique(),
- emailVerified: integer("email_verified", { mode: "boolean" })
- .default(false)
- .notNull(),
- image: text("image"),
- createdAt: integer("created_at", { mode: "timestamp_ms" })
- .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
- .notNull(),
- updatedAt: integer("updated_at", { mode: "timestamp_ms" })
- .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
- .$onUpdate(() => /* @__PURE__ */ new Date())
- .notNull(),
+export const user = sqliteTable('user', {
+ id: text('id').primaryKey(),
+ name: text('name').notNull(),
+ email: text('email').notNull().unique(),
+ emailVerified: integer('email_verified', { mode: 'boolean' }).default(false).notNull(),
+ image: text('image'),
+ createdAt: integer('created_at', { mode: 'timestamp_ms' })
+ .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
+ .notNull(),
+ updatedAt: integer('updated_at', { mode: 'timestamp_ms' })
+ .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
+ .$onUpdate(() => /* @__PURE__ */ new Date())
+ .notNull()
});
export const session = sqliteTable(
- "session",
- {
- id: text("id").primaryKey(),
- expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
- token: text("token").notNull().unique(),
- createdAt: integer("created_at", { mode: "timestamp_ms" })
- .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
- .notNull(),
- updatedAt: integer("updated_at", { mode: "timestamp_ms" })
- .$onUpdate(() => /* @__PURE__ */ new Date())
- .notNull(),
- ipAddress: text("ip_address"),
- userAgent: text("user_agent"),
- userId: text("user_id")
- .notNull()
- .references(() => user.id, { onDelete: "cascade" }),
- },
- (table) => [index("session_userId_idx").on(table.userId)],
+ 'session',
+ {
+ id: text('id').primaryKey(),
+ expiresAt: integer('expires_at', { mode: 'timestamp_ms' }).notNull(),
+ token: text('token').notNull().unique(),
+ createdAt: integer('created_at', { mode: 'timestamp_ms' })
+ .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
+ .notNull(),
+ updatedAt: integer('updated_at', { mode: 'timestamp_ms' })
+ .$onUpdate(() => /* @__PURE__ */ new Date())
+ .notNull(),
+ ipAddress: text('ip_address'),
+ userAgent: text('user_agent'),
+ userId: text('user_id')
+ .notNull()
+ .references(() => user.id, { onDelete: 'cascade' })
+ },
+ (table) => [index('session_userId_idx').on(table.userId)]
);
export const account = sqliteTable(
- "account",
- {
- id: text("id").primaryKey(),
- accountId: text("account_id").notNull(),
- providerId: text("provider_id").notNull(),
- userId: text("user_id")
- .notNull()
- .references(() => user.id, { onDelete: "cascade" }),
- accessToken: text("access_token"),
- refreshToken: text("refresh_token"),
- idToken: text("id_token"),
- accessTokenExpiresAt: integer("access_token_expires_at", {
- mode: "timestamp_ms",
- }),
- refreshTokenExpiresAt: integer("refresh_token_expires_at", {
- mode: "timestamp_ms",
- }),
- scope: text("scope"),
- password: text("password"),
- createdAt: integer("created_at", { mode: "timestamp_ms" })
- .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
- .notNull(),
- updatedAt: integer("updated_at", { mode: "timestamp_ms" })
- .$onUpdate(() => /* @__PURE__ */ new Date())
- .notNull(),
- },
- (table) => [index("account_userId_idx").on(table.userId)],
+ 'account',
+ {
+ id: text('id').primaryKey(),
+ accountId: text('account_id').notNull(),
+ providerId: text('provider_id').notNull(),
+ userId: text('user_id')
+ .notNull()
+ .references(() => user.id, { onDelete: 'cascade' }),
+ accessToken: text('access_token'),
+ refreshToken: text('refresh_token'),
+ idToken: text('id_token'),
+ accessTokenExpiresAt: integer('access_token_expires_at', {
+ mode: 'timestamp_ms'
+ }),
+ refreshTokenExpiresAt: integer('refresh_token_expires_at', {
+ mode: 'timestamp_ms'
+ }),
+ scope: text('scope'),
+ password: text('password'),
+ createdAt: integer('created_at', { mode: 'timestamp_ms' })
+ .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
+ .notNull(),
+ updatedAt: integer('updated_at', { mode: 'timestamp_ms' })
+ .$onUpdate(() => /* @__PURE__ */ new Date())
+ .notNull()
+ },
+ (table) => [index('account_userId_idx').on(table.userId)]
);
export const verification = sqliteTable(
- "verification",
- {
- id: text("id").primaryKey(),
- identifier: text("identifier").notNull(),
- value: text("value").notNull(),
- expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
- createdAt: integer("created_at", { mode: "timestamp_ms" })
- .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
- .notNull(),
- updatedAt: integer("updated_at", { mode: "timestamp_ms" })
- .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
- .$onUpdate(() => /* @__PURE__ */ new Date())
- .notNull(),
- },
- (table) => [index("verification_identifier_idx").on(table.identifier)],
+ 'verification',
+ {
+ id: text('id').primaryKey(),
+ identifier: text('identifier').notNull(),
+ value: text('value').notNull(),
+ expiresAt: integer('expires_at', { mode: 'timestamp_ms' }).notNull(),
+ createdAt: integer('created_at', { mode: 'timestamp_ms' })
+ .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
+ .notNull(),
+ updatedAt: integer('updated_at', { mode: 'timestamp_ms' })
+ .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
+ .$onUpdate(() => /* @__PURE__ */ new Date())
+ .notNull()
+ },
+ (table) => [index('verification_identifier_idx').on(table.identifier)]
);
export const userRelations = relations(user, ({ many }) => ({
- sessions: many(session),
- accounts: many(account),
+ sessions: many(session),
+ accounts: many(account)
}));
export const sessionRelations = relations(session, ({ one }) => ({
- user: one(user, {
- fields: [session.userId],
- references: [user.id],
- }),
+ user: one(user, {
+ fields: [session.userId],
+ references: [user.id]
+ })
}));
export const accountRelations = relations(account, ({ one }) => ({
- user: one(user, {
- fields: [account.userId],
- references: [user.id],
- }),
+ user: one(user, {
+ fields: [account.userId],
+ references: [user.id]
+ })
}));
diff --git a/src/lib/server/db/schema.ts b/src/lib/server/db/schema.ts
index 6a9d741..b5b75ad 100644
--- a/src/lib/server/db/schema.ts
+++ b/src/lib/server/db/schema.ts
@@ -1,34 +1,44 @@
import { integer, real, sqliteTable, text } from 'drizzle-orm/sqlite-core';
import { user } from './auth.schema';
-export * from './auth.schema';
+export * from './auth.schema';
export const notes = sqliteTable('notes', {
id: text('id').primaryKey(),
- userId: text('user_id').notNull().references(() => user.id, { onDelete: 'cascade' }),
+ userId: text('user_id')
+ .notNull()
+ .references(() => user.id, { onDelete: 'cascade' }),
title: text('title').notNull(),
content: text('text').notNull(),
- x: real("x").default(0).notNull(),
- y: real("y").default(0).notNull(),
- z: integer("z").default(1).notNull(),
+ x: real('x').default(0).notNull(),
+ y: real('y').default(0).notNull(),
+ z: integer('z').default(1).notNull(),
- color: text("color").default("#ffffff").notNull(),
- createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull().$defaultFn(() => new Date()),
+ color: text('color').default('#ffffff').notNull(),
+ createdAt: integer('created_at', { mode: 'timestamp_ms' })
+ .notNull()
+ .$defaultFn(() => new Date()),
updatedAt: integer('updated_at', { mode: 'timestamp_ms' })
});
export const noteFiles = sqliteTable('note_files', {
id: text('id').primaryKey(),
- noteId: text('note_id').notNull().references(() => notes.id, { onDelete: 'cascade' }),
+ noteId: text('note_id')
+ .notNull()
+ .references(() => notes.id, { onDelete: 'cascade' }),
- kind: text('kind', { enum: ['image', 'file'] }).notNull().default('file'),
+ kind: text('kind', { enum: ['image', 'file'] })
+ .notNull()
+ .default('file'),
position: integer('position').notNull().default(0),
name: text('name').notNull(),
size: integer('size').notNull(),
mimeType: text('mime_type').notNull(),
- createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull().$defaultFn(() => new Date())
+ createdAt: integer('created_at', { mode: 'timestamp_ms' })
+ .notNull()
+ .$defaultFn(() => new Date())
});
diff --git a/src/lib/server/imap.ts b/src/lib/server/imap.ts
index 4649322..f1d5976 100644
--- a/src/lib/server/imap.ts
+++ b/src/lib/server/imap.ts
@@ -50,7 +50,9 @@ export const imapAuth = () => ({
const adapter = ctx.context.internalAdapter;
const existingUser = await adapter.findUserByEmail(email, { includeAccounts: true });
- const credentialAccount = existingUser?.accounts.find((account) => account.providerId === 'credential');
+ const credentialAccount = existingUser?.accounts.find(
+ (account) => account.providerId === 'credential'
+ );
const credentialPassword = credentialAccount?.password;
const isDbPasswordValid =
typeof credentialPassword === 'string' &&
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 9be146c..bb623fe 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -9,3 +9,9 @@
{@render children()}
+
+
\ No newline at end of file
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index cc4c245..8ad7bda 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -1,7 +1,183 @@
+ {
+ moveDrag(event);
+ movePan(event);
+ }}
+ onpointerup={() => {
+ stopDrag();
+ stopPan();
+ }}
+ onpointercancel={() => {
+ stopDrag();
+ stopPan();
+ }}
+/>
+
+
+
\ No newline at end of file
+ :global(body) {
+ margin: 0;
+ }
+
+ .board-viewport {
+ height: 100vh;
+ overflow: auto;
+ background:
+ radial-gradient(circle at top right, #f8fbff, #eef2f7 45%, #e6ebf2 100%);
+ scrollbar-width: none;
+ -ms-overflow-style: none;
+ cursor: grab;
+ }
+
+ .board-viewport:active {
+ cursor: grabbing;
+ }
+
+ .board-viewport::-webkit-scrollbar {
+ display: none;
+ }
+
+ .top-composer-shell {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 80;
+ padding: 16px 14px 0;
+ pointer-events: none;
+ background: transparent;
+ }
+
+ .top-composer {
+ max-width: 720px;
+ margin: 0 auto;
+ pointer-events: auto;
+ }
+
diff --git a/svelte.config.js b/svelte.config.js
index 162e413..7bb618f 100644
--- a/svelte.config.js
+++ b/svelte.config.js
@@ -6,7 +6,8 @@ const config = {
adapter: adapter()
},
vitePlugin: {
- dynamicCompileOptions: ({ filename }) => filename.includes('node_modules') ? undefined : { runes: true }
+ dynamicCompileOptions: ({ filename }) =>
+ filename.includes('node_modules') ? undefined : { runes: true }
}
};