codeforge-dev 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devcontainer/.env +22 -0
- package/.devcontainer/CHANGELOG.md +197 -0
- package/.devcontainer/CLAUDE.md +117 -0
- package/.devcontainer/README.md +222 -0
- package/.devcontainer/config/main-system-prompt.md +502 -0
- package/.devcontainer/config/settings.json +47 -0
- package/.devcontainer/devcontainer.json +94 -0
- package/.devcontainer/features/README.md +113 -0
- package/.devcontainer/features/agent-browser/README.md +65 -0
- package/.devcontainer/features/agent-browser/devcontainer-feature.json +23 -0
- package/.devcontainer/features/agent-browser/install.sh +79 -0
- package/.devcontainer/features/ast-grep/README.md +24 -0
- package/.devcontainer/features/ast-grep/devcontainer-feature.json +24 -0
- package/.devcontainer/features/ast-grep/install.sh +51 -0
- package/.devcontainer/features/ccstatusline/README.md +296 -0
- package/.devcontainer/features/ccstatusline/devcontainer-feature.json +19 -0
- package/.devcontainer/features/ccstatusline/install.sh +290 -0
- package/.devcontainer/features/ccusage/README.md +205 -0
- package/.devcontainer/features/ccusage/devcontainer-feature.json +38 -0
- package/.devcontainer/features/ccusage/install.sh +132 -0
- package/.devcontainer/features/claude-code/README.md +498 -0
- package/.devcontainer/features/claude-code/config/settings.json +36 -0
- package/.devcontainer/features/claude-code/config/system-prompt.md +118 -0
- package/.devcontainer/features/claude-code/config/world-building-sp.md +1432 -0
- package/.devcontainer/features/claude-code/devcontainer-feature.json +42 -0
- package/.devcontainer/features/claude-code/install.sh +466 -0
- package/.devcontainer/features/claude-monitor/README.md +74 -0
- package/.devcontainer/features/claude-monitor/devcontainer-feature.json +38 -0
- package/.devcontainer/features/claude-monitor/install.sh +99 -0
- package/.devcontainer/features/lsp-servers/README.md +85 -0
- package/.devcontainer/features/lsp-servers/devcontainer-feature.json +40 -0
- package/.devcontainer/features/lsp-servers/install.sh +116 -0
- package/.devcontainer/features/mcp-qdrant/CHANGES.md +399 -0
- package/.devcontainer/features/mcp-qdrant/README.md +474 -0
- package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +57 -0
- package/.devcontainer/features/mcp-qdrant/install.sh +295 -0
- package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +129 -0
- package/.devcontainer/features/mcp-reasoner/README.md +177 -0
- package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +20 -0
- package/.devcontainer/features/mcp-reasoner/install.sh +177 -0
- package/.devcontainer/features/mcp-reasoner/poststart-hook.sh +67 -0
- package/.devcontainer/features/notify-hook/README.md +86 -0
- package/.devcontainer/features/notify-hook/devcontainer-feature.json +23 -0
- package/.devcontainer/features/notify-hook/install.sh +38 -0
- package/.devcontainer/features/splitrail/README.md +140 -0
- package/.devcontainer/features/splitrail/devcontainer-feature.json +34 -0
- package/.devcontainer/features/splitrail/install.sh +129 -0
- package/.devcontainer/features/tree-sitter/README.md +138 -0
- package/.devcontainer/features/tree-sitter/devcontainer-feature.json +52 -0
- package/.devcontainer/features/tree-sitter/install.sh +173 -0
- package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +106 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-file.py +101 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/lint-file.py +137 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/.claude-plugin/plugin.json +8 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/SKILL.md +387 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/cli-flags-and-output.md +312 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/sdk-and-mcp.md +569 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/SKILL.md +309 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/compose-services.md +438 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/dockerfile-patterns.md +340 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/SKILL.md +412 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/container-lifecycle.md +388 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/resources-and-security.md +444 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/SKILL.md +344 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/middleware-and-lifespan.md +254 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/pydantic-models.md +245 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/routing-and-dependencies.md +255 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/sse-and-streaming.md +318 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/SKILL.md +345 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/agents-and-tools.md +271 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/models-and-streaming.md +422 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/SKILL.md +220 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/cross-vendor-principles.md +139 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/patterns-and-antipatterns.md +376 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/skill-authoring-patterns.md +356 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/SKILL.md +329 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/advanced-queries.md +314 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/javascript-patterns.md +323 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/python-patterns.md +354 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/schema-and-pragmas.md +326 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/SKILL.md +356 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/ai-sdk-svelte.md +128 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/component-patterns.md +332 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/layercake.md +203 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/migration-guide.md +350 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/runes-and-reactivity.md +328 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/spa-and-routing.md +262 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/svelte-dnd-action.md +181 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/SKILL.md +414 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/fastapi-testing.md +411 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/svelte-testing.md +538 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codeforge-lsp/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +110 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +108 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272create-pr.md +337 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272new.md +166 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272review-commit.md +290 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272work.md +257 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/plugin.json +8 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/system-prompt.md +184 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/.claude-plugin/plugin.json +6 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/config/planning-instructions.md +14 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/functional-conjuring-map.md +989 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/hooks/hooks.json +33 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/__pycache__/post-enhance-task.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhance-planning.py +71 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-plan.sh +68 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-task.sh +120 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-plan.py +133 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-task.py +253 -0
- package/.devcontainer/scripts/setup-aliases.sh +80 -0
- package/.devcontainer/scripts/setup-config.sh +28 -0
- package/.devcontainer/scripts/setup-irie-claude.sh +32 -0
- package/.devcontainer/scripts/setup-plugins.sh +80 -0
- package/.devcontainer/scripts/setup.sh +58 -0
- package/LICENSE.txt +674 -0
- package/README.md +267 -0
- package/package.json +44 -0
- package/setup.js +83 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# SPA and Routing — Deep Dive
|
|
2
|
+
|
|
3
|
+
## 1. SPA Configuration
|
|
4
|
+
|
|
5
|
+
### Core Setup
|
|
6
|
+
|
|
7
|
+
Three changes convert a SvelteKit project to a single-page application:
|
|
8
|
+
|
|
9
|
+
**1. Install adapter-static:**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install -D @sveltejs/adapter-static
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**2. Configure svelte.config.js:**
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import adapter from '@sveltejs/adapter-static';
|
|
19
|
+
|
|
20
|
+
export default {
|
|
21
|
+
kit: {
|
|
22
|
+
adapter: adapter({
|
|
23
|
+
fallback: '200.html' // Serves the SPA shell for all unmatched routes
|
|
24
|
+
}),
|
|
25
|
+
prerender: {
|
|
26
|
+
entries: [] // Disable automatic prerendering
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**3. Disable SSR globally:**
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
// src/routes/+layout.js
|
|
36
|
+
export const ssr = false;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The `fallback` page name depends on the hosting platform:
|
|
40
|
+
- `200.html` — Surge, many static hosts
|
|
41
|
+
- `index.html` — GitHub Pages, Netlify (with `_redirects` file)
|
|
42
|
+
- `404.html` — GitHub Pages alternative (handles as custom 404)
|
|
43
|
+
|
|
44
|
+
### Why ssr = false in +layout.js
|
|
45
|
+
|
|
46
|
+
Setting `ssr = false` at the root layout propagates to all routes. Every page renders exclusively on the client. This means:
|
|
47
|
+
|
|
48
|
+
- No server-side rendering step
|
|
49
|
+
- No `+page.server.js` or `+layout.server.js` files (server load functions are unavailable)
|
|
50
|
+
- All data fetching occurs in `+page.js` load functions or in component effects
|
|
51
|
+
- `$app/environment` reports `browser` as always `true`
|
|
52
|
+
|
|
53
|
+
## 2. File-Based Routing
|
|
54
|
+
|
|
55
|
+
SvelteKit uses the filesystem for routing. Each directory under `src/routes/` maps to a URL path:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
src/routes/
|
|
59
|
+
├── +layout.svelte → root layout (wraps all pages)
|
|
60
|
+
├── +page.svelte → /
|
|
61
|
+
├── about/
|
|
62
|
+
│ └── +page.svelte → /about
|
|
63
|
+
├── blog/
|
|
64
|
+
│ ├── +page.svelte → /blog
|
|
65
|
+
│ └── [slug]/
|
|
66
|
+
│ └── +page.svelte → /blog/:slug
|
|
67
|
+
└── (app)/
|
|
68
|
+
├── +layout.svelte → shared layout for grouped routes
|
|
69
|
+
├── dashboard/
|
|
70
|
+
│ └── +page.svelte → /dashboard
|
|
71
|
+
└── settings/
|
|
72
|
+
└── +page.svelte → /settings
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Dynamic Parameters
|
|
76
|
+
|
|
77
|
+
Square brackets define dynamic route segments:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
[slug] → single parameter (required)
|
|
81
|
+
[...rest] → catch-all (zero or more segments)
|
|
82
|
+
[[optional]] → optional parameter
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Access parameters in load functions or via the `$page` store:
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
// src/routes/blog/[slug]/+page.js
|
|
89
|
+
export function load({ params }) {
|
|
90
|
+
return { slug: params.slug };
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Route Groups
|
|
95
|
+
|
|
96
|
+
Parenthesized directories like `(app)` create layout groups without affecting the URL. Routes inside `(app)/` share a layout but the URL does not include `(app)`.
|
|
97
|
+
|
|
98
|
+
Use route groups to:
|
|
99
|
+
- Apply different layouts to different sections
|
|
100
|
+
- Separate authenticated and public routes
|
|
101
|
+
- Share a sidebar or navigation across a subset of pages
|
|
102
|
+
|
|
103
|
+
## 3. Load Functions in SPA Mode
|
|
104
|
+
|
|
105
|
+
In SPA mode, only `+page.js` and `+layout.js` load functions are available (no `.server.js` variants).
|
|
106
|
+
|
|
107
|
+
### Client-Only Load Function
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
// src/routes/dashboard/+page.js
|
|
111
|
+
export async function load({ fetch, params, url }) {
|
|
112
|
+
const res = await fetch('/api/dashboard');
|
|
113
|
+
const data = await res.json();
|
|
114
|
+
return { dashboard: data };
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The `fetch` provided by SvelteKit adds relative URL resolution and cookie forwarding. Prefer it over the global `fetch`.
|
|
119
|
+
|
|
120
|
+
### Accessing Load Data
|
|
121
|
+
|
|
122
|
+
Load function return values are available as `data` in the corresponding `+page.svelte`:
|
|
123
|
+
|
|
124
|
+
```svelte
|
|
125
|
+
<!-- src/routes/dashboard/+page.svelte -->
|
|
126
|
+
<script>
|
|
127
|
+
let { data } = $props();
|
|
128
|
+
</script>
|
|
129
|
+
<h1>Dashboard</h1>
|
|
130
|
+
<pre>{JSON.stringify(data.dashboard, null, 2)}</pre>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Invalidation and Re-running Loads
|
|
134
|
+
|
|
135
|
+
Force a load function to re-run using `invalidate` or `invalidateAll`:
|
|
136
|
+
|
|
137
|
+
```js
|
|
138
|
+
import { invalidate, invalidateAll } from '$app/navigation';
|
|
139
|
+
|
|
140
|
+
// Re-run load functions that depend on a specific URL
|
|
141
|
+
invalidate('/api/dashboard');
|
|
142
|
+
|
|
143
|
+
// Re-run all active load functions
|
|
144
|
+
invalidateAll();
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Load functions re-run when their dependencies change (URL parameters, `fetch` URLs, or `depends` keys).
|
|
148
|
+
|
|
149
|
+
Register custom dependency keys with `depends`:
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
export async function load({ fetch, depends }) {
|
|
153
|
+
depends('app:dashboard');
|
|
154
|
+
const res = await fetch('/api/dashboard');
|
|
155
|
+
return { dashboard: await res.json() };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Later: invalidate('app:dashboard');
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 4. Prerendering in SPA Mode
|
|
162
|
+
|
|
163
|
+
Even with `ssr = false`, specific routes can be prerendered as static HTML:
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
// src/routes/about/+page.js
|
|
167
|
+
export const prerender = true;
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
This generates a static `about/index.html` at build time. Useful for:
|
|
171
|
+
- Marketing pages that benefit from instant load
|
|
172
|
+
- SEO-critical pages (search engines see full HTML)
|
|
173
|
+
- Pages with no dynamic data
|
|
174
|
+
|
|
175
|
+
The rest of the application still uses the SPA fallback for client-side routing.
|
|
176
|
+
|
|
177
|
+
### Prerender Configuration
|
|
178
|
+
|
|
179
|
+
Control prerender behavior in `svelte.config.js`:
|
|
180
|
+
|
|
181
|
+
```js
|
|
182
|
+
export default {
|
|
183
|
+
kit: {
|
|
184
|
+
prerender: {
|
|
185
|
+
entries: ['/about', '/pricing'], // Explicitly list pages to prerender
|
|
186
|
+
handleHttpError: 'warn' // Warn instead of fail on broken links
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## 5. Navigation
|
|
193
|
+
|
|
194
|
+
### Programmatic Navigation
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
import { goto } from '$app/navigation';
|
|
198
|
+
|
|
199
|
+
// Navigate to a route
|
|
200
|
+
goto('/dashboard');
|
|
201
|
+
|
|
202
|
+
// Replace history entry (no back button)
|
|
203
|
+
goto('/login', { replaceState: true });
|
|
204
|
+
|
|
205
|
+
// Keep current scroll position
|
|
206
|
+
goto('/page', { noScroll: true });
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Navigation Lifecycle
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
import { beforeNavigate, afterNavigate, onNavigate } from '$app/navigation';
|
|
213
|
+
|
|
214
|
+
// Runs before leaving current page — can cancel navigation
|
|
215
|
+
beforeNavigate(({ cancel, to }) => {
|
|
216
|
+
if (hasUnsavedChanges && !confirm('Leave without saving?')) {
|
|
217
|
+
cancel();
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// Runs after navigation completes — useful for analytics
|
|
222
|
+
afterNavigate(({ from, to }) => {
|
|
223
|
+
trackPageView(to?.url.pathname);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// Runs when navigation starts — returns a promise for view transitions
|
|
227
|
+
onNavigate((navigation) => {
|
|
228
|
+
// Optionally return a promise to delay navigation
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Page Store
|
|
233
|
+
|
|
234
|
+
Access the current URL, params, and route info via the `$page` store:
|
|
235
|
+
|
|
236
|
+
```svelte
|
|
237
|
+
<script>
|
|
238
|
+
import { page } from '$app/stores';
|
|
239
|
+
</script>
|
|
240
|
+
<nav>
|
|
241
|
+
<a href="/" class:active={$page.url.pathname === '/'}>Home</a>
|
|
242
|
+
<a href="/about" class:active={$page.url.pathname === '/about'}>About</a>
|
|
243
|
+
</nav>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Link Options
|
|
247
|
+
|
|
248
|
+
Control SvelteKit link behavior with `data-sveltekit-*` attributes:
|
|
249
|
+
|
|
250
|
+
```html
|
|
251
|
+
<!-- Preload on hover (default behavior) -->
|
|
252
|
+
<a href="/about">About</a>
|
|
253
|
+
|
|
254
|
+
<!-- Preload immediately when link enters viewport -->
|
|
255
|
+
<a href="/about" data-sveltekit-preload-data="eager">About</a>
|
|
256
|
+
|
|
257
|
+
<!-- Disable SvelteKit handling (full page navigation) -->
|
|
258
|
+
<a href="/external" data-sveltekit-reload>External</a>
|
|
259
|
+
|
|
260
|
+
<!-- Replace history entry -->
|
|
261
|
+
<a href="/step2" data-sveltekit-replacestate>Next Step</a>
|
|
262
|
+
```
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# svelte-dnd-action — Reference
|
|
2
|
+
|
|
3
|
+
## Mental Model
|
|
4
|
+
|
|
5
|
+
`svelte-dnd-action` is an action-based drag-and-drop library. The `use:dndzone` action transforms any container element into a drag-and-drop zone. Items are plain arrays managed with `$state`; the library emits events when the user drags (consider) and drops (finalize), and the component reassigns its items array in response. There is no separate state store or provider — the action reads items from its options and communicates changes through DOM events.
|
|
6
|
+
|
|
7
|
+
> Official documentation and examples: <https://github.com/isaacHagworthy/svelte-dnd-action>
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Core API
|
|
12
|
+
|
|
13
|
+
### The dndzone Action
|
|
14
|
+
|
|
15
|
+
Apply `use:dndzone` to a container element. The action accepts an options object and emits two events:
|
|
16
|
+
|
|
17
|
+
```svelte
|
|
18
|
+
<script>
|
|
19
|
+
import { dndzone } from 'svelte-dnd-action';
|
|
20
|
+
|
|
21
|
+
let items = $state([
|
|
22
|
+
{ id: 1, name: 'Item A' },
|
|
23
|
+
{ id: 2, name: 'Item B' },
|
|
24
|
+
{ id: 3, name: 'Item C' }
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
function handleSort(e) {
|
|
28
|
+
items = e.detail.items;
|
|
29
|
+
}
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<div
|
|
33
|
+
use:dndzone={{ items }}
|
|
34
|
+
onconsider={handleSort}
|
|
35
|
+
onfinalize={handleSort}
|
|
36
|
+
>
|
|
37
|
+
{#each items as item (item.id)}
|
|
38
|
+
<div>{item.name}</div>
|
|
39
|
+
{/each}
|
|
40
|
+
</div>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Events
|
|
44
|
+
|
|
45
|
+
| Event | When | Purpose |
|
|
46
|
+
|-------|------|---------|
|
|
47
|
+
| `consider` | During drag (hover, reorder) | Preview the tentative new order; update items for visual feedback |
|
|
48
|
+
| `finalize` | On drop | Commit the final order; update items to persist the result |
|
|
49
|
+
|
|
50
|
+
Both events provide `e.detail.items` (the reordered array) and `e.detail.info` (metadata about the drag operation including `trigger` and `source`).
|
|
51
|
+
|
|
52
|
+
### Options
|
|
53
|
+
|
|
54
|
+
| Option | Type | Default | Description |
|
|
55
|
+
|--------|------|---------|-------------|
|
|
56
|
+
| `items` | array | required | The array of items. Each must have a unique `id` property |
|
|
57
|
+
| `type` | string | internal ID | Zone type identifier. Only zones with matching types accept drops |
|
|
58
|
+
| `flipDurationMs` | number | 0 | Animation duration in ms for reorder transitions. Set to ~200 for smooth animations |
|
|
59
|
+
| `dragDisabled` | boolean | false | Disable dragging from this zone |
|
|
60
|
+
| `morphDisabled` | boolean | false | Disable morph animation when items move between zones |
|
|
61
|
+
| `dropFromOthersDisabled` | boolean | false | Prevent items from being dropped into this zone from other zones |
|
|
62
|
+
| `dropTargetStyle` | object | `{outline: ...}` | CSS styles applied to the zone when a dragged item hovers over it |
|
|
63
|
+
| `dropTargetClasses` | array | `[]` | CSS classes applied to the zone during hover |
|
|
64
|
+
| `transformDraggedElement` | function | undefined | Callback to modify the dragged element's appearance |
|
|
65
|
+
| `autoAriaDisabled` | boolean | false | Disable automatic ARIA attribute management |
|
|
66
|
+
| `centreDraggedOnCursor` | boolean | false | Center the dragged element on the cursor |
|
|
67
|
+
| `zoneTabIndex` | number | 0 | Tab index for the zone container |
|
|
68
|
+
| `minItems` | number | undefined | Minimum items the zone must retain |
|
|
69
|
+
| `maxItems` | number | undefined | Maximum items the zone accepts |
|
|
70
|
+
| `itemsOrientation` | string | inferred | `"vertical"`, `"horizontal"`, or `"grid"`. Usually auto-detected |
|
|
71
|
+
| `multiDrag` | boolean | false | Enable selecting and dragging multiple items |
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Drag Handle Pattern
|
|
76
|
+
|
|
77
|
+
Use `dragHandleZone` and `dragHandle` when only a specific element within each item should initiate dragging:
|
|
78
|
+
|
|
79
|
+
```svelte
|
|
80
|
+
<script>
|
|
81
|
+
import { dragHandleZone, dragHandle } from 'svelte-dnd-action';
|
|
82
|
+
|
|
83
|
+
let items = $state([
|
|
84
|
+
{ id: 1, name: 'Task A' },
|
|
85
|
+
{ id: 2, name: 'Task B' }
|
|
86
|
+
]);
|
|
87
|
+
|
|
88
|
+
function handleSort(e) {
|
|
89
|
+
items = e.detail.items;
|
|
90
|
+
}
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<div
|
|
94
|
+
use:dragHandleZone={{ items }}
|
|
95
|
+
onconsider={handleSort}
|
|
96
|
+
onfinalize={handleSort}
|
|
97
|
+
>
|
|
98
|
+
{#each items as item (item.id)}
|
|
99
|
+
<div>
|
|
100
|
+
<span use:dragHandle aria-label="drag handle">☰</span>
|
|
101
|
+
<span>{item.name}</span>
|
|
102
|
+
</div>
|
|
103
|
+
{/each}
|
|
104
|
+
</div>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`dragHandleZone` replaces `dndzone` on the container. `dragHandle` marks the grip element inside each item. All options and events remain the same.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Svelte 5 Integration
|
|
112
|
+
|
|
113
|
+
### Event Syntax
|
|
114
|
+
|
|
115
|
+
Svelte 5 uses `onconsider` and `onfinalize` (no colon). The Svelte 4 syntax `on:consider` and `on:finalize` does not work in runes mode:
|
|
116
|
+
|
|
117
|
+
```svelte
|
|
118
|
+
<!-- Correct (Svelte 5) -->
|
|
119
|
+
<div use:dndzone={{ items }} onconsider={handleSort} onfinalize={handleSort}>
|
|
120
|
+
|
|
121
|
+
<!-- Wrong (Svelte 4 syntax) -->
|
|
122
|
+
<div use:dndzone={{ items }} on:consider={handleSort} on:finalize={handleSort}>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### State Management
|
|
126
|
+
|
|
127
|
+
Store items with `$state()` and reassign in event handlers. The library checks reference equality, so always reassign the entire array — never use `splice` or other in-place mutations in the handler:
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
let items = $state([...]);
|
|
131
|
+
|
|
132
|
+
function handleSort(e) {
|
|
133
|
+
items = e.detail.items; // full reassignment
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Version Requirement
|
|
138
|
+
|
|
139
|
+
Version **0.9.59+** is required for `$state` compatibility. Earlier versions do not correctly detect Svelte 5's reactive proxies and may fail silently or throw during drag operations.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Shadow Item Handling
|
|
144
|
+
|
|
145
|
+
During a drag operation, the library inserts a shadow placeholder item into the items array to represent the drop position. This shadow item is visible to `$derived` computations over the items array.
|
|
146
|
+
|
|
147
|
+
Filter shadow items when computing derived values to avoid counting or displaying the placeholder:
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
import { SHADOW_ITEM_MARKER_PROPERTY_NAME } from 'svelte-dnd-action';
|
|
151
|
+
|
|
152
|
+
let items = $state([...]);
|
|
153
|
+
let realCount = $derived(
|
|
154
|
+
items.filter(i => !i[SHADOW_ITEM_MARKER_PROPERTY_NAME]).length
|
|
155
|
+
);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The shadow item carries the `SHADOW_ITEM_MARKER_PROPERTY_NAME` property set to `true`. The companion constant `SHADOW_PLACEHOLDER_ITEM_ID` holds the shadow's `id` value for identity-based filtering.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Exported Constants
|
|
163
|
+
|
|
164
|
+
| Constant | Purpose |
|
|
165
|
+
|----------|---------|
|
|
166
|
+
| `TRIGGERS` | Enum of drag trigger types (e.g., `DRAG_STARTED`, `DROPPED_INTO_ZONE`) |
|
|
167
|
+
| `SOURCES` | Enum of event sources (e.g., `POINTER`, `KEYBOARD`) |
|
|
168
|
+
| `SHADOW_ITEM_MARKER_PROPERTY_NAME` | Property name on shadow placeholder items |
|
|
169
|
+
| `SHADOW_PLACEHOLDER_ITEM_ID` | The `id` value assigned to shadow items |
|
|
170
|
+
|
|
171
|
+
Access trigger and source info from `e.detail.info`:
|
|
172
|
+
|
|
173
|
+
```js
|
|
174
|
+
import { TRIGGERS, SOURCES } from 'svelte-dnd-action';
|
|
175
|
+
|
|
176
|
+
function handleFinalize(e) {
|
|
177
|
+
if (e.detail.info.trigger === TRIGGERS.DROPPED_INTO_ZONE) {
|
|
178
|
+
saveOrder(e.detail.items);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|