svelte-p5 0.2.2 → 0.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/README.md +40 -1
- package/dist/P5Canvas.svelte +9 -6
- package/dist/P5Canvas.svelte.d.ts +23 -2
- package/dist/createP5Bridge.svelte.d.ts +1 -1
- package/dist/createP5Bridge.svelte.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/types.d.ts +27 -6
- package/dist/utils/colorCache.d.ts +2 -2
- package/dist/utils/fontAtlas.d.ts +2 -2
- package/dist/utils/fontAtlas.js +2 -2
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -8,6 +8,14 @@ Svelte 5 bindings for p5.js. This package is the primitive layer: a canvas wrapp
|
|
|
8
8
|
pnpm add svelte-p5 p5
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
To test a change that's merged on `main` but not yet released — or any specific commit — install the preview build from [pkg.pr.new](https://pkg.pr.new/):
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add https://pkg.pr.new/edw1nzhao/svelte-p5/svelte-p5@main
|
|
15
|
+
# or pin an exact SHA:
|
|
16
|
+
pnpm add https://pkg.pr.new/edw1nzhao/svelte-p5/svelte-p5@<commit-sha>
|
|
17
|
+
```
|
|
18
|
+
|
|
11
19
|
## `<P5Canvas>`
|
|
12
20
|
|
|
13
21
|
Mounts a p5 sketch in instance mode, cleans it up on unmount.
|
|
@@ -91,11 +99,42 @@ What each does and when to reach for it lives in the [performance recipe](../../
|
|
|
91
99
|
## Type exports
|
|
92
100
|
|
|
93
101
|
```ts
|
|
94
|
-
import type { SketchFn, P5CanvasProps, P5Bridge } from 'svelte-p5';
|
|
102
|
+
import type { SketchFn, ExtendedP5, P5CanvasProps, P5Bridge } from 'svelte-p5';
|
|
95
103
|
```
|
|
96
104
|
|
|
97
105
|
`SketchFn` is `(p: p5) => void`. `SketchFn`, not `Sketch`, because the components package exports a `<Sketch>` component and the collision would force aliased imports.
|
|
98
106
|
|
|
107
|
+
### Typed instance extensions
|
|
108
|
+
|
|
109
|
+
Sketches that install custom members on the instance (`p.myHelper = ...`) can type
|
|
110
|
+
them instead of casting. `SketchFn<Ext>` types the instance inside the sketch as
|
|
111
|
+
`p5 & Ext`, and `ExtendedP5<Ext>` names that same intersection for stores and
|
|
112
|
+
variables that hold the bound instance:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
interface AppSketchExt {
|
|
116
|
+
resetView(): void;
|
|
117
|
+
zoomLevel: number;
|
|
118
|
+
}
|
|
119
|
+
type AppP5 = ExtendedP5<AppSketchExt>;
|
|
120
|
+
|
|
121
|
+
const sketch: SketchFn<AppSketchExt> = (p) => {
|
|
122
|
+
p.resetView = () => {
|
|
123
|
+
/* ... */
|
|
124
|
+
};
|
|
125
|
+
p.draw = () => {
|
|
126
|
+
/* p.zoomLevel is typed */
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
let instance: AppP5 | null = $state(null);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```svelte
|
|
134
|
+
<P5Canvas {sketch} bind:instance />
|
|
135
|
+
<!-- instance is inferred as AppP5 | null; instance?.resetView() type-checks -->
|
|
136
|
+
```
|
|
137
|
+
|
|
99
138
|
## License
|
|
100
139
|
|
|
101
140
|
MIT
|
package/dist/P5Canvas.svelte
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<script lang="ts">
|
|
1
|
+
<script lang="ts" generics="Ext = unknown">
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
3
|
import type p5Type from 'p5';
|
|
4
|
-
import type { P5CanvasProps } from './types.js';
|
|
4
|
+
import type { ExtendedP5, P5CanvasProps } from './types.js';
|
|
5
5
|
|
|
6
6
|
let {
|
|
7
7
|
sketch,
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
class: className = '',
|
|
10
10
|
style = 'display: block; width: 100%; height: 100%;',
|
|
11
11
|
onReady
|
|
12
|
-
}: P5CanvasProps = $props();
|
|
12
|
+
}: P5CanvasProps<Ext> = $props();
|
|
13
13
|
|
|
14
14
|
let container: HTMLDivElement | null = null;
|
|
15
15
|
|
|
@@ -24,9 +24,12 @@
|
|
|
24
24
|
if (cancelled || !container) return;
|
|
25
25
|
|
|
26
26
|
const p5Ctor = mod.default;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
// The sketch installs its Ext members during construction (p5 calls the
|
|
28
|
+
// sketch function synchronously inside the constructor), so by the time
|
|
29
|
+
// the instance is observable it is already the extended type.
|
|
30
|
+
local = new p5Ctor((p: p5Type) => sketch(p as ExtendedP5<Ext>), container);
|
|
31
|
+
instance = local as ExtendedP5<Ext>;
|
|
32
|
+
onReady?.(local as ExtendedP5<Ext>);
|
|
30
33
|
})();
|
|
31
34
|
|
|
32
35
|
return () => {
|
|
@@ -1,4 +1,25 @@
|
|
|
1
1
|
import type { P5CanvasProps } from './types.js';
|
|
2
|
-
declare
|
|
3
|
-
|
|
2
|
+
declare function $$render<Ext = unknown>(): {
|
|
3
|
+
props: P5CanvasProps<Ext>;
|
|
4
|
+
exports: {};
|
|
5
|
+
bindings: "instance";
|
|
6
|
+
slots: {};
|
|
7
|
+
events: {};
|
|
8
|
+
};
|
|
9
|
+
declare class __sveltets_Render<Ext = unknown> {
|
|
10
|
+
props(): ReturnType<typeof $$render<Ext>>['props'];
|
|
11
|
+
events(): ReturnType<typeof $$render<Ext>>['events'];
|
|
12
|
+
slots(): ReturnType<typeof $$render<Ext>>['slots'];
|
|
13
|
+
bindings(): "instance";
|
|
14
|
+
exports(): {};
|
|
15
|
+
}
|
|
16
|
+
interface $$IsomorphicComponent {
|
|
17
|
+
new <Ext = unknown>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Ext>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Ext>['props']>, ReturnType<__sveltets_Render<Ext>['events']>, ReturnType<__sveltets_Render<Ext>['slots']>> & {
|
|
18
|
+
$$bindings?: ReturnType<__sveltets_Render<Ext>['bindings']>;
|
|
19
|
+
} & ReturnType<__sveltets_Render<Ext>['exports']>;
|
|
20
|
+
<Ext = unknown>(internal: unknown, props: ReturnType<__sveltets_Render<Ext>['props']> & {}): ReturnType<__sveltets_Render<Ext>['exports']>;
|
|
21
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
22
|
+
}
|
|
23
|
+
declare const P5Canvas: $$IsomorphicComponent;
|
|
24
|
+
type P5Canvas<Ext = unknown> = InstanceType<typeof P5Canvas<Ext>>;
|
|
4
25
|
export default P5Canvas;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Bridge reactive Svelte state into a p5 sketch closure.
|
|
3
3
|
*
|
|
4
4
|
* Mutations from either side are seen by the other. Because p5's draw loop
|
|
5
|
-
* reads fields on every frame, you don't need effects or subscriptions
|
|
5
|
+
* reads fields on every frame, you don't need effects or subscriptions -
|
|
6
6
|
* just read `bridge.state.foo` inside your sketch and write to it from
|
|
7
7
|
* Svelte UI.
|
|
8
8
|
*
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Bridge reactive Svelte state into a p5 sketch closure.
|
|
3
3
|
*
|
|
4
4
|
* Mutations from either side are seen by the other. Because p5's draw loop
|
|
5
|
-
* reads fields on every frame, you don't need effects or subscriptions
|
|
5
|
+
* reads fields on every frame, you don't need effects or subscriptions -
|
|
6
6
|
* just read `bridge.state.foo` inside your sketch and write to it from
|
|
7
7
|
* Svelte UI.
|
|
8
8
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as P5Canvas } from './P5Canvas.svelte';
|
|
2
2
|
export { createP5Bridge, type P5Bridge } from './createP5Bridge.svelte.js';
|
|
3
|
-
export type { SketchFn, P5CanvasProps } from './types.js';
|
|
3
|
+
export type { SketchFn, ExtendedP5, P5CanvasProps } from './types.js';
|
|
4
4
|
export * from './utils/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { default as P5Canvas } from './P5Canvas.svelte';
|
|
2
2
|
export { createP5Bridge } from './createP5Bridge.svelte.js';
|
|
3
|
-
// Re-export utils from the main entry for convenience
|
|
3
|
+
// Re-export utils from the main entry for convenience - users doing
|
|
4
4
|
// `import { disableFES } from 'svelte-p5'` get the same
|
|
5
5
|
// helpers they'd get from `.../utils`. Tree-shakeable via `sideEffects: false`.
|
|
6
6
|
export * from './utils/index.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -2,20 +2,41 @@ import type p5 from 'p5';
|
|
|
2
2
|
/**
|
|
3
3
|
* A p5 sketch function in instance mode. Called with the p5 instance;
|
|
4
4
|
* the function should assign `p.setup`, `p.draw`, etc. on it.
|
|
5
|
+
*
|
|
6
|
+
* `Ext` types the members your sketch installs onto the instance
|
|
7
|
+
* (`p.myHelper = ...`). Inside the sketch the instance is typed as
|
|
8
|
+
* already-extended, because the sketch itself is what installs those
|
|
9
|
+
* members before anyone else can observe them:
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* interface MyExt {
|
|
13
|
+
* resetView(): void;
|
|
14
|
+
* }
|
|
15
|
+
* const sketch: SketchFn<MyExt> = (p) => {
|
|
16
|
+
* p.resetView = () => { ... };
|
|
17
|
+
* p.draw = () => { ... };
|
|
18
|
+
* };
|
|
19
|
+
* ```
|
|
5
20
|
*/
|
|
6
|
-
export type SketchFn = (p: p5) => void;
|
|
21
|
+
export type SketchFn<Ext = unknown> = (p: p5 & Ext) => void;
|
|
22
|
+
/**
|
|
23
|
+
* A p5 instance decorated with app-specific members (see {@link SketchFn}).
|
|
24
|
+
* Useful for typing stores or variables that hold the bound instance:
|
|
25
|
+
* `let instance: ExtendedP5<MyExt> | null`.
|
|
26
|
+
*/
|
|
27
|
+
export type ExtendedP5<Ext> = p5 & Ext;
|
|
7
28
|
/**
|
|
8
29
|
* Props accepted by the `<P5Canvas>` component.
|
|
9
30
|
*/
|
|
10
|
-
export interface P5CanvasProps {
|
|
11
|
-
/** Your sketch function
|
|
12
|
-
sketch: SketchFn
|
|
31
|
+
export interface P5CanvasProps<Ext = unknown> {
|
|
32
|
+
/** Your sketch function - assigns p.setup, p.draw, etc. */
|
|
33
|
+
sketch: SketchFn<Ext>;
|
|
13
34
|
/** Bindable: the p5 instance, available after mount. `null` before mount or after unmount. */
|
|
14
|
-
instance?:
|
|
35
|
+
instance?: ExtendedP5<Ext> | null;
|
|
15
36
|
/** Optional class applied to the container div. */
|
|
16
37
|
class?: string;
|
|
17
38
|
/** Optional inline style on the container div. Defaults to `display: block; width: 100%; height: 100%;`. */
|
|
18
39
|
style?: string;
|
|
19
40
|
/** Called once, synchronously, when the p5 instance has been created and the sketch function has returned. */
|
|
20
|
-
onReady?: (instance:
|
|
41
|
+
onReady?: (instance: ExtendedP5<Ext>) => void;
|
|
21
42
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Lazy cache for CSS color strings.
|
|
3
3
|
*
|
|
4
4
|
* p5.color() allocates a p5.Color instance on every call (object + typed
|
|
5
|
-
* arrays + regex parse). Calling it in a draw loop
|
|
6
|
-
* speaker or per data-point
|
|
5
|
+
* arrays + regex parse). Calling it in a draw loop - e.g. to colorize per
|
|
6
|
+
* speaker or per data-point - leaks a lot of garbage. Use a ColorCache to
|
|
7
7
|
* compute each color once and reuse the CSS string.
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
@@ -19,11 +19,11 @@ export interface FontAtlas {
|
|
|
19
19
|
* Pre-render a fixed set of strings to an offscreen buffer **once**, then
|
|
20
20
|
* composite them each frame with `p5.image()`. This bypasses the OpenType.js
|
|
21
21
|
* path-rendering slow path that fires for every `p5.text()` call when you've
|
|
22
|
-
* `loadFont()`'d an OTF/TTF file
|
|
22
|
+
* `loadFont()`'d an OTF/TTF file - typically a 10-100× speedup for text-heavy
|
|
23
23
|
* sketches (word clouds, axis labels, small-multiples titles).
|
|
24
24
|
*
|
|
25
25
|
* Use for a fixed vocabulary (speaker names, category labels, axis ticks).
|
|
26
|
-
* Don't use for per-frame dynamic text
|
|
26
|
+
* Don't use for per-frame dynamic text - that defeats the point.
|
|
27
27
|
*
|
|
28
28
|
* @see https://github.com/processing/p5.js/blob/main/src/core/p5.Renderer2D.js
|
|
29
29
|
*/
|
package/dist/utils/fontAtlas.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* Pre-render a fixed set of strings to an offscreen buffer **once**, then
|
|
3
3
|
* composite them each frame with `p5.image()`. This bypasses the OpenType.js
|
|
4
4
|
* path-rendering slow path that fires for every `p5.text()` call when you've
|
|
5
|
-
* `loadFont()`'d an OTF/TTF file
|
|
5
|
+
* `loadFont()`'d an OTF/TTF file - typically a 10-100× speedup for text-heavy
|
|
6
6
|
* sketches (word clouds, axis labels, small-multiples titles).
|
|
7
7
|
*
|
|
8
8
|
* Use for a fixed vocabulary (speaker names, category labels, axis ticks).
|
|
9
|
-
* Don't use for per-frame dynamic text
|
|
9
|
+
* Don't use for per-frame dynamic text - that defeats the point.
|
|
10
10
|
*
|
|
11
11
|
* @see https://github.com/processing/p5.js/blob/main/src/core/p5.Renderer2D.js
|
|
12
12
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-p5",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Svelte 5 + p5.js integration primitives — <P5Canvas> wrapper, rune bridge, and performance utilities",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"svelte",
|
|
@@ -44,6 +44,9 @@
|
|
|
44
44
|
"README.md",
|
|
45
45
|
"LICENSE"
|
|
46
46
|
],
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
47
50
|
"sideEffects": false,
|
|
48
51
|
"scripts": {
|
|
49
52
|
"build": "svelte-package -o dist && publint",
|