@sealpixel/svelte 1.0.0-rc.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 +5 -0
- package/dist/store.d.ts +11 -0
- package/dist/store.js +18 -0
- package/dist/store.js.map +1 -0
- package/package.json +48 -0
- package/src/SealpixelEditor.svelte +141 -0
- package/src/index.d.ts +2 -0
- package/src/index.js +2 -0
- package/src/store.ts +27 -0
package/README.md
ADDED
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type EditorSession, type SessionOptions, type SessionState } from '@sealpixel/core';
|
|
2
|
+
/**
|
|
3
|
+
* Headless use in Svelte 5: a store-contract object (`subscribe`) plus the
|
|
4
|
+
* session. Works with `$store` auto-subscription and with runes via
|
|
5
|
+
* `fromStore`. Call `dispose()` in `onDestroy`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createSealpixelStore(options: SessionOptions): {
|
|
8
|
+
session: EditorSession;
|
|
9
|
+
subscribe: (run: (state: SessionState) => void) => () => void;
|
|
10
|
+
dispose: () => void;
|
|
11
|
+
};
|
package/dist/store.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createEditorSession, } from '@sealpixel/core';
|
|
2
|
+
/**
|
|
3
|
+
* Headless use in Svelte 5: a store-contract object (`subscribe`) plus the
|
|
4
|
+
* session. Works with `$store` auto-subscription and with runes via
|
|
5
|
+
* `fromStore`. Call `dispose()` in `onDestroy`.
|
|
6
|
+
*/
|
|
7
|
+
export function createSealpixelStore(options) {
|
|
8
|
+
const session = createEditorSession(options);
|
|
9
|
+
return {
|
|
10
|
+
session,
|
|
11
|
+
subscribe(run) {
|
|
12
|
+
run(session.getState());
|
|
13
|
+
return session.subscribe(run);
|
|
14
|
+
},
|
|
15
|
+
dispose: () => session.dispose(),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,GAIpB,MAAM,iBAAiB,CAAC;AAEzB;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAuB;IAK1D,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7C,OAAO;QACL,OAAO;QACP,SAAS,CAAC,GAAG;YACX,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxB,OAAO,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;KACjC,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sealpixel/svelte",
|
|
3
|
+
"version": "1.0.0-rc.0",
|
|
4
|
+
"description": "Svelte 5 bindings for the Sealpixel image editor: <SealpixelEditor> with a bindable editLog and createSealpixelStore for headless use.",
|
|
5
|
+
"license": "BUSL-1.1",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/9feet/sealpixel.git",
|
|
9
|
+
"directory": "packages/svelte"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://docs.sealpixel.dev",
|
|
12
|
+
"bugs": "https://github.com/9feet/sealpixel/issues",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"sideEffects": false,
|
|
15
|
+
"files": [
|
|
16
|
+
"src",
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"svelte": "./src/index.js",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./src/index.d.ts",
|
|
24
|
+
"svelte": "./src/index.js",
|
|
25
|
+
"default": "./src/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./package.json": "./package.json"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc -p tsconfig.build.json",
|
|
31
|
+
"typecheck": "svelte-check --tsconfig ./tsconfig.json --fail-on-warnings"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@sealpixel/core": "workspace:*",
|
|
35
|
+
"@sealpixel/element": "workspace:*",
|
|
36
|
+
"@sealpixel/ui": "workspace:*"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"svelte": "^5.0.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@sealpixel/config": "workspace:*",
|
|
43
|
+
"@types/node": "^24.0.0",
|
|
44
|
+
"svelte": "^5.0.0",
|
|
45
|
+
"svelte-check": "^4.0.0",
|
|
46
|
+
"typescript": "^5.9.0"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import '@sealpixel/element';
|
|
3
|
+
import type {
|
|
4
|
+
AnyPlugin,
|
|
5
|
+
AssetResolver,
|
|
6
|
+
ExportResult,
|
|
7
|
+
OutputOptions,
|
|
8
|
+
PluginOptionsMap,
|
|
9
|
+
Renderer,
|
|
10
|
+
SealpixelError,
|
|
11
|
+
SessionOptions,
|
|
12
|
+
SourceDescriptor,
|
|
13
|
+
} from '@sealpixel/core';
|
|
14
|
+
import type { SealpixelEditor as SealpixelEditorElement } from '@sealpixel/element';
|
|
15
|
+
|
|
16
|
+
interface EditLogState {
|
|
17
|
+
log: unknown;
|
|
18
|
+
index: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
src = null,
|
|
23
|
+
editLog = $bindable(undefined),
|
|
24
|
+
defaultEditLog = undefined,
|
|
25
|
+
plugins = null,
|
|
26
|
+
pluginOptions = null,
|
|
27
|
+
renderer = null,
|
|
28
|
+
assets = null,
|
|
29
|
+
server = null,
|
|
30
|
+
output = { format: 'image/png' },
|
|
31
|
+
theme = 'dark',
|
|
32
|
+
locale = 'en',
|
|
33
|
+
dictionary = null,
|
|
34
|
+
activeTool = null,
|
|
35
|
+
showExport = 'auto',
|
|
36
|
+
showDownload = 'always',
|
|
37
|
+
showHistory = 'all',
|
|
38
|
+
downloadLabel = null,
|
|
39
|
+
onprocess,
|
|
40
|
+
onerror,
|
|
41
|
+
onload,
|
|
42
|
+
onready,
|
|
43
|
+
class: className = '',
|
|
44
|
+
style = '',
|
|
45
|
+
}: {
|
|
46
|
+
src?: File | Blob | Uint8Array | string | null;
|
|
47
|
+
editLog?: EditLogState | undefined;
|
|
48
|
+
defaultEditLog?: EditLogState | undefined;
|
|
49
|
+
plugins?: readonly AnyPlugin[] | null;
|
|
50
|
+
pluginOptions?: PluginOptionsMap | null;
|
|
51
|
+
renderer?: Renderer | null;
|
|
52
|
+
assets?: AssetResolver | null;
|
|
53
|
+
server?: SessionOptions['server'] | null;
|
|
54
|
+
output?: OutputOptions;
|
|
55
|
+
theme?: 'dark' | 'light' | 'auto';
|
|
56
|
+
locale?: string;
|
|
57
|
+
dictionary?: Record<string, string> | null;
|
|
58
|
+
activeTool?: string | null;
|
|
59
|
+
showExport?: 'auto' | 'always' | 'never';
|
|
60
|
+
showDownload?: 'always' | 'never';
|
|
61
|
+
showHistory?: 'all' | 'buttons' | 'none';
|
|
62
|
+
downloadLabel?: string | null;
|
|
63
|
+
onprocess?: (result: ExportResult) => void;
|
|
64
|
+
onerror?: (error: SealpixelError) => void;
|
|
65
|
+
onload?: (descriptor: SourceDescriptor) => void;
|
|
66
|
+
onready?: () => void;
|
|
67
|
+
class?: string;
|
|
68
|
+
style?: string;
|
|
69
|
+
} = $props();
|
|
70
|
+
|
|
71
|
+
let el: SealpixelEditorElement | undefined = $state();
|
|
72
|
+
|
|
73
|
+
export function getSession() {
|
|
74
|
+
return el?.getSession();
|
|
75
|
+
}
|
|
76
|
+
export function getEditLog() {
|
|
77
|
+
return el?.getEditLog();
|
|
78
|
+
}
|
|
79
|
+
export function undo() {
|
|
80
|
+
el?.undo();
|
|
81
|
+
}
|
|
82
|
+
export function redo() {
|
|
83
|
+
el?.redo();
|
|
84
|
+
}
|
|
85
|
+
export function download(options?: Parameters<SealpixelEditorElement['download']>[0]) {
|
|
86
|
+
return el?.download(options);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Property assignments: custom-element properties are objects, not attributes.
|
|
90
|
+
$effect(() => {
|
|
91
|
+
if (!el) return;
|
|
92
|
+
el.plugins = plugins;
|
|
93
|
+
el.pluginOptions = pluginOptions;
|
|
94
|
+
el.renderer = renderer;
|
|
95
|
+
el.assets = assets;
|
|
96
|
+
el.server = server;
|
|
97
|
+
el.output = output;
|
|
98
|
+
el.locale = locale;
|
|
99
|
+
el.dictionary = dictionary;
|
|
100
|
+
el.activeTool = activeTool;
|
|
101
|
+
el.setAttribute('show-export', showExport);
|
|
102
|
+
el.setAttribute('show-download', showDownload);
|
|
103
|
+
el.setAttribute('show-history', showHistory);
|
|
104
|
+
if (downloadLabel === null) el.removeAttribute('download-label');
|
|
105
|
+
else el.setAttribute('download-label', downloadLabel);
|
|
106
|
+
el.defaultEditLog = defaultEditLog;
|
|
107
|
+
});
|
|
108
|
+
$effect(() => {
|
|
109
|
+
if (el) el.src = src;
|
|
110
|
+
});
|
|
111
|
+
$effect(() => {
|
|
112
|
+
if (el && editLog !== undefined) el.editLog = editLog;
|
|
113
|
+
});
|
|
114
|
+
// Custom event names contain a colon, which Svelte attributes cannot express.
|
|
115
|
+
$effect(() => {
|
|
116
|
+
const node = el;
|
|
117
|
+
if (!node) return;
|
|
118
|
+
const onChange = (e: Event) => {
|
|
119
|
+
editLog = (e as CustomEvent<EditLogState>).detail;
|
|
120
|
+
};
|
|
121
|
+
const onProcess = (e: Event) => onprocess?.((e as CustomEvent<ExportResult>).detail);
|
|
122
|
+
const onError = (e: Event) => onerror?.((e as CustomEvent<SealpixelError>).detail);
|
|
123
|
+
const onLoad = (e: Event) => onload?.((e as CustomEvent<SourceDescriptor>).detail);
|
|
124
|
+
const onReady = () => onready?.();
|
|
125
|
+
node.addEventListener('sealpixel:change', onChange);
|
|
126
|
+
// Only attach when the host handles results: the editor shows Export while someone listens.
|
|
127
|
+
if (onprocess) node.addEventListener('sealpixel:process', onProcess);
|
|
128
|
+
node.addEventListener('sealpixel:error', onError);
|
|
129
|
+
node.addEventListener('sealpixel:load', onLoad);
|
|
130
|
+
node.addEventListener('sealpixel:ready', onReady);
|
|
131
|
+
return () => {
|
|
132
|
+
node.removeEventListener('sealpixel:change', onChange);
|
|
133
|
+
if (onprocess) node.removeEventListener('sealpixel:process', onProcess);
|
|
134
|
+
node.removeEventListener('sealpixel:error', onError);
|
|
135
|
+
node.removeEventListener('sealpixel:load', onLoad);
|
|
136
|
+
node.removeEventListener('sealpixel:ready', onReady);
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
</script>
|
|
140
|
+
|
|
141
|
+
<sealpixel-editor bind:this={el} {theme} class={className} {style}></sealpixel-editor>
|
package/src/index.d.ts
ADDED
package/src/index.js
ADDED
package/src/store.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createEditorSession,
|
|
3
|
+
type EditorSession,
|
|
4
|
+
type SessionOptions,
|
|
5
|
+
type SessionState,
|
|
6
|
+
} from '@sealpixel/core';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Headless use in Svelte 5: a store-contract object (`subscribe`) plus the
|
|
10
|
+
* session. Works with `$store` auto-subscription and with runes via
|
|
11
|
+
* `fromStore`. Call `dispose()` in `onDestroy`.
|
|
12
|
+
*/
|
|
13
|
+
export function createSealpixelStore(options: SessionOptions): {
|
|
14
|
+
session: EditorSession;
|
|
15
|
+
subscribe: (run: (state: SessionState) => void) => () => void;
|
|
16
|
+
dispose: () => void;
|
|
17
|
+
} {
|
|
18
|
+
const session = createEditorSession(options);
|
|
19
|
+
return {
|
|
20
|
+
session,
|
|
21
|
+
subscribe(run) {
|
|
22
|
+
run(session.getState());
|
|
23
|
+
return session.subscribe(run);
|
|
24
|
+
},
|
|
25
|
+
dispose: () => session.dispose(),
|
|
26
|
+
};
|
|
27
|
+
}
|