Skip to content

Update to Svelte 5 with runes #176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 56 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
ffe40f2
Update to Svelte v5 preview
TeyKey1 Mar 3, 2024
a3ca8df
Rewrite everything to Svelte runes (examples do not work)
TeyKey1 Mar 3, 2024
e38d014
Export handle as const prop to prevent overwriting, unify props type …
TeyKey1 Mar 3, 2024
e5bbb24
Stage component handle has fallback value workaround so it can be bou…
TeyKey1 Mar 17, 2024
cc3b26b
Prevent Stage handle from being overwritten from outside the component
TeyKey1 Mar 17, 2024
5f4e11c
Update to Svelte v5 next.80
TeyKey1 Mar 17, 2024
be572b9
Update Svelte and testing library for v5 support
TeyKey1 Apr 24, 2024
d1d28f5
Update SvelteKit & prettier plugin, Mark bindable props as bindable, …
TeyKey1 Apr 24, 2024
2a18b63
removed deprecated svelte event dispatcher, moved to Svelte 5 event h…
TeyKey1 Apr 24, 2024
6135245
Improve event propagation in responsive stage component
TeyKey1 Apr 24, 2024
21bef37
Expose handle via props using a shadow variable to prevent overwritin…
TeyKey1 Apr 25, 2024
a55b88f
Update eslint and svelte check
TeyKey1 Apr 26, 2024
7ebe1ea
Update svelte-persistent-store for svelte 5 compatibility
TeyKey1 Apr 26, 2024
9c314f1
Fix wrong import
TeyKey1 Apr 26, 2024
632d661
Fix optional config prop and clean up props
TeyKey1 Apr 26, 2024
1b04a01
Fix rest props in combination with konva event hooks
TeyKey1 Apr 26, 2024
ed79335
Fix event hook registering in stage component
TeyKey1 Apr 26, 2024
5ec3240
Do not use state as static value for other states
TeyKey1 Apr 26, 2024
3384c82
Fix test config
TeyKey1 May 3, 2024
e989756
format
TeyKey1 May 3, 2024
47aabcb
Update to svelte next 121
TeyKey1 May 3, 2024
2f16d13
Export handle as const prop to better match Svelte 5 paradigms and ea…
TeyKey1 May 3, 2024
5f9cb21
Update vitest, update test cases to Svelte 5
TeyKey1 May 3, 2024
d05fee0
Corrections on examples for new handle location and runes
TeyKey1 May 3, 2024
46acec9
Update svelte due to bug that broke svelte-konva context (sveltejs/sv…
TeyKey1 May 3, 2024
717cb8f
Dep update, fix free drawing example
TeyKey1 May 26, 2024
7e3a670
Fix bound config tests
TeyKey1 May 26, 2024
c8a084f
Remove unaltered context tests on components without children as svel…
TeyKey1 May 26, 2024
9a47ab9
Fix context tests for svelte v5, all tests working again
TeyKey1 May 26, 2024
5c8c1f1
Fix transform example, update +Layout.svelte to runes and svelte v5
TeyKey1 May 26, 2024
d7a755d
Move getting started guide of svelte-konva v0 into own file (legacy),…
TeyKey1 May 26, 2024
7eae45b
Fix non reactive in stage due to _handle not being
TeyKey1 Jun 1, 2024
cfe0f85
update svelte
TeyKey1 Jun 7, 2024
fb9cb56
Fix: transformer config prop was not optional
TeyKey1 Jun 10, 2024
b6003b3
Update Svelte & Kit
TeyKey1 Jul 15, 2024
c901334
Update daisyUI
TeyKey1 Jul 15, 2024
4e005c0
Split config prop properties into individual props
TeyKey1 Jul 25, 2024
93fafac
Update Svelte, Force runes only in lib
TeyKey1 Jul 27, 2024
07c2d57
Fix wrong bindings in group example
TeyKey1 Jul 27, 2024
9d27277
Fix wrong bindings and missing state rune in transformer example
TeyKey1 Jul 27, 2024
ec43668
Fix most tests to use split config props
TeyKey1 Jul 27, 2024
839841e
Fix binding tests to work with new split config props
TeyKey1 Jul 31, 2024
3ffb059
Make stage x and y props bindable. Fix stage bindable tests
TeyKey1 Jul 31, 2024
7d76fae
New divWrapperId prop to expose stage div id to user (id prop already…
TeyKey1 Jul 31, 2024
3a4cfbb
Forward all stage wrapper div props through prop, cleanup messy stag…
TeyKey1 Jul 31, 2024
1d1126b
Update migration guide with split config props and divWrapperProps
TeyKey1 Jul 31, 2024
ca4b716
make divWrapperProps optional
TeyKey1 Jul 31, 2024
da6b181
Fix linter dep issue
TeyKey1 Jul 31, 2024
3d26262
Remove unused function
TeyKey1 Jul 31, 2024
b0931c6
Fix or ignore most linter errors
TeyKey1 Jul 31, 2024
8fc8c6a
Update svelte testing library & svelte
TeyKey1 Aug 1, 2024
6bbcab5
Update build configs and deps. Fix Omit type on props type to map opt…
TeyKey1 Aug 2, 2024
1dbf811
Update ts docs to match new API and functions
TeyKey1 Aug 2, 2024
e2ba060
Fix missing reactive declarations in transformer example
TeyKey1 Aug 2, 2024
9724246
Add reactivity changes to migration guide, add Svelte 5 release candi…
TeyKey1 Aug 2, 2024
028b373
Update changelog
TeyKey1 Aug 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ module.exports = {
'@typescript-eslint/no-unused-vars': [
'warn',
{
varsIgnorePattern: '\\$\\$Events'
varsIgnorePattern: '^_',
argsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_'
}
]
}
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# Unreleased

# v1.0.0-next.0

**breaking changes** please refer to the [migration guide](./docs/svelte-konva-v1-migration.md) for detailed examples on how to update.

- Breaking: `config` prop is now splitted into individual props
- Breaking: Deprecated Svelte `on:event` syntax is no longer supported and replaced by event hooks named `on<konva event name>`
- Breaking: The Konva event object is now directly provided as payload on the new event hooks instead of being provided under the `detail` property of the payload
- Breaking: Changes in how reactivity works on dragend and transformend events with `staticConfig = false`. State changes are now only propagated if the corresponding prop is bound.
- Breaking: The Konva handle is now a component property that can be accessed directly on the component instance (read only)
- Improved handle prop safety by preventing the user from overwriting the internal handle of the svelte-konva components (see #136)
- Breaking: Passing restProps to the wrapper div of the `Stage` component is no longer supported. Instead props can be passed to the wrapper div using the new `divWrapperProps` prop on the `Stage` component.
- svelte-konva is now a runes-only library and fully compatible with Svelte 5 runes-only projects
- Update to SvelteKit v2
- Various dependency updates

Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ svelte-konva is a component-based svelte wrapper for the [Konva HTML5 2D canvas

Currently compatible with Svelte v3 & 4, SvelteKit v1 and Konva v8 & 9.

### Experimental Svelte 5 support

There is now experimental support for Svelte v5. It is not production-ready and should be used for testing purposes only. Svelte 5 support is currently published under the `v1.0.0-next` tag. To use it simply add the following dependency to your package.json in your Svelte 5 project:

```
"svelte-konva": "^1.0.0-next.0"
```

Please see the [migration guide](./docs/svelte-konva-v1-migration.md) for all relevant (and breaking) changes.

If you encounter bugs or difficulties while migrating/testing please open an issue.

## Install

```npm
Expand Down
207 changes: 207 additions & 0 deletions docs/svelte-konva-v0-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
# svelte-konva v0 getting started guide (legacy)

This guide covers the basics of svelte-konva v0. For the newer svelte-konva v1 supporting Svelte v5, please consult the [README](../README.md).

## Compatibility

svelte-konva v0 is compatible with Svelte v3 & 4, SvelteKit v1 and Konva v8 & 9.

## Install

```npm
npm i svelte-konva@0 konva
```

## Quick start

```svelte
<script>
import { Stage, Layer, Rect } from 'svelte-konva';
</script>
<Stage config={{ width: 1000, height: 1000 }}>
<Layer>
<Rect config={{ x: 100, y: 100, width: 400, height: 200, fill: 'blue' }} />
</Layer>
</Stage>
```

### Events

You can listen to Konva events by using the Svelte `on:event` Syntax. All [Konva events](https://konvajs.org/docs/events/Binding_Events.html) are supported.

```svelte
<script>
import { Stage, Layer, Rect } from 'svelte-konva';
function handleClick(e) {
const konvaEvent = e.detail;
window.alert(`Clicked on rectangle: ${konvaEvent.type}`);
}
</script>
<Stage config={{ width: 1000, height: 1000 }}>
<Layer>
<Rect
config={{ x: 100, y: 100, width: 400, height: 200, fill: 'blue' }}
on:pointerclick={handleClick}
/>
</Layer>
</Stage>
```

### Accessing the underlying Konva node

In various cases it is useful and required to be able to access the underlying Konva node object. In svelte-konva you can do this by binding the `handle` prop.

```svelte
<script>
import { onMount, tick } from 'svelte';
import { Stage, Layer, Rect } from 'svelte-konva';
let rectangle;
onMount(async () => {
// Wait for dom update so the rectangle handle becomes defined
await tick();
const json = rectangle.toJSON();
window.alert(`Rectangle as JSON: ${json}`);
});
</script>
<Stage config={{ width: 1000, height: 1000 }}>
<Layer>
<Rect
config={{ x: 100, y: 100, width: 400, height: 200, fill: 'blue' }}
bind:handle={rectangle}
/>
</Layer>
</Stage>
```

### Binding the config prop

By default svelte-konva keeps your config in sync (position, rotation, scale, etc.) with the Konva node after `dragend` and `transformend` events. If you bind the config prop any reactive blocks depending on the config will also be triggered once such changes happen. In case you don't want svelte-konva to sync those changes you can pass the `staticConfig` prop to the component.

```svelte
<script>
import { Stage, Layer, Rect } from 'svelte-konva';
let rectangleConfig = {
x: 100,
y: 100,
width: 400,
height: 200,
fill: 'blue',
draggable: true
};
$: console.log(
`Rectangle was dragged. New x: ${rectangleConfig.x}. New y: ${rectangleConfig.y}.`
);
</script>
<Stage config={{ width: 1000, height: 1000 }}>
<Layer>
<Rect bind:config={rectangleConfig} />
</Layer>
</Stage>
```

### Usage with SvelteKit

Generally svelte-konva is a client-side only library. When using SvelteKit, special care needs to be taken if svelte-konva/Konva functionality is used on prerendered and server side rendered (SSR) components. Prerendering and SSR happens in a Node.js environment which causes Konva to require the [canvas](https://www.npmjs.com/package/canvas) library as Konva can also be used in Node.js environments. When you use svelte-konva in such conditions you'll likely run into the following error:

> Error: Cannot find module 'canvas'
There are multiple solutions to this problem:

**Installing canvas:**

Simplest solution is to install canvas:

```npm
npm i canvas
```

This will satisfy the canvas dependency of Konva and you can use svelte-konva components in prerendered and SSR SvelteKit pages. The solution is a bit messy though, as you now have installed a package you don't really need which adds unnecessary overhead. Alternatively use one of the following solutions:

**Dynamically import your svelte-konva stage:**

A better approach is to dynamically import your svelte-konva canvas on the client-side only. Suppose you have a Svelte component containing your stage with various svelte-konva components:

_MyCanvas.svelte_

```svelte
<script>
import { Stage, Layer, Rect } from 'svelte-konva';
import OtherComponentUsingSvelteKonva from './OtherComponentUsingSvelteKonva.svelte';
const rectangleConfig = {
/*...*/
};
</script>
<Stage config={{ width: 1000, height: 1000 }}>
<Layer>
<Rect bind:config={rectangleConfig} />
<OtherComponentUsingSvelteKonva />
</Layer>
</Stage>
```

To use this component inside a SvelteKit prerendered/SSR page you can dynamically import it inside `onMount()` and render it using `<svelte:component>`:

_+page.svelte_

```svelte
<script>
import { onMount } from 'svelte';
// typescript:
// import type MyCanvasComponent from '$lib/MyCanvas.svelte';
let MyCanvas;
// typescript:
// let MyCanvas: typeof MyCanvasComponent;
onMount(async () => {
// Dynamically import your canvas component encapsulating all svelte-konva functionality inside onMount()
MyCanvas = (await import('$lib/MyCanvas.svelte')).default;
});
</script>
<div>
<p>This is my fancy server side rendered (or prerendered) page.</p>
<!-- Use your dynamically imported svelte-konva canvas component with a svelte:component block, you can pass any component props as usual -->
<svelte:component this={MyCanvas} someProp="SomeString" />
</div>
```

**Dynamically import svelte-konva using vite:**

The [vite-plugin-iso-import](https://www.npmjs.com/package/vite-plugin-iso-import) allows you to make client-side only imports without needing the manual approach in `onMount()` described above. Please follow the installation instructions in the [README](https://www.npmjs.com/package/vite-plugin-iso-import) then you can dynamically import your component like so:

_+page.svelte_

```svelte
<script>
import MyCanvasComponent from '$lib/MyCanvas.svelte?client'; // Client-side only import
// Set component variable to null if page is rendered in SSR, otherwise use client-side only import
let MyCanvas = import.meta.env.SSR ? null : MyCanvasComponent;
</script>
<div>
<p>This is my fancy server side rendered (or prerendered) page.</p>
<!-- Use your dynamically imported svelte-konva canvas component with a svelte:component block, you can pass any component props as usual -->
<svelte:component this={MyCanvas} someProp="SomeString" />
</div>
```

Currently vite-plugin-iso-import cannot automatically fix intellisense inside .svelte files with TypeScript. Consult the [README](https://www.npmjs.com/package/vite-plugin-iso-import) for a workaround to this problem.

For further examples please consult the [docs](https://konvajs.org/docs/svelte) or clone the repo and run `npm i && npm run examples`.
Loading
Loading