@wonderyard/tela 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/dist/brush.d.ts +21 -0
- package/dist/brush.js +84 -0
- package/dist/document.d.ts +50 -0
- package/dist/document.js +105 -0
- package/dist/history.d.ts +16 -0
- package/dist/history.js +38 -0
- package/dist/image.d.ts +41 -0
- package/dist/image.js +94 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +399 -0
- package/dist/input.d.ts +67 -0
- package/dist/input.js +536 -0
- package/dist/internals.d.ts +18 -0
- package/dist/internals.js +3 -0
- package/dist/keymap.d.ts +20 -0
- package/dist/keymap.js +266 -0
- package/dist/mask.d.ts +27 -0
- package/dist/mask.js +96 -0
- package/dist/moving.d.ts +102 -0
- package/dist/moving.js +215 -0
- package/dist/palette.d.ts +21 -0
- package/dist/palette.js +47 -0
- package/dist/react.d.ts +6 -0
- package/dist/react.js +16 -0
- package/dist/selection.d.ts +15 -0
- package/dist/selection.js +76 -0
- package/dist/sprite.d.ts +20 -0
- package/dist/sprite.js +49 -0
- package/dist/store.d.ts +4 -0
- package/dist/store.js +20 -0
- package/dist/tools.d.ts +43 -0
- package/dist/tools.js +113 -0
- package/dist/transactions.d.ts +45 -0
- package/dist/transactions.js +135 -0
- package/dist/types/document.d.ts +2 -0
- package/dist/types/history.d.ts +11 -0
- package/dist/types/image.d.ts +7 -0
- package/dist/types/index.d.ts +371 -0
- package/dist/types/input.d.ts +105 -0
- package/dist/types/keymap.d.ts +26 -0
- package/dist/types/mask.d.ts +11 -0
- package/dist/types/moving.d.ts +26 -0
- package/dist/types/selection.d.ts +1 -0
- package/dist/types/store.d.ts +4 -0
- package/dist/types/tools.d.ts +8 -0
- package/dist/types/view.d.ts +14 -0
- package/dist/view.d.ts +56 -0
- package/dist/view.js +139 -0
- package/package.json +72 -3
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OrangeNote
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/brush.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BrushChange } from './types/image';
|
|
2
|
+
import { Brush, Settings, State } from './types/index';
|
|
3
|
+
import { Mask } from './types/mask';
|
|
4
|
+
export declare function createBrush(store: {
|
|
5
|
+
getState(): State;
|
|
6
|
+
setState(patch: Partial<State>): void;
|
|
7
|
+
},
|
|
8
|
+
/** The brush size +/- stops at. */
|
|
9
|
+
maxBrushSize: number): {
|
|
10
|
+
/** A settings patch as it lands: a custom brush is copied, a Foreground change recolors it. */
|
|
11
|
+
patch(patch: Partial<Settings>): Partial<Settings>;
|
|
12
|
+
/**
|
|
13
|
+
* Increment and Decrement Size, within 1 and the maximum, on a circle or square; the turns and
|
|
14
|
+
* flips on a custom brush. False when nothing changes.
|
|
15
|
+
*/
|
|
16
|
+
change(change: "increment-size" | "decrement-size" | BrushChange): boolean;
|
|
17
|
+
/** Edit > New Brush: the selected pixels `data` in the selection's shape, with the last pattern. */
|
|
18
|
+
fromSelection: (m: Mask, data: Uint8Array) => Brush;
|
|
19
|
+
/** The custom brush's indices follow `f`, as a remap moves them. */
|
|
20
|
+
remap(f: (i: number) => number): void;
|
|
21
|
+
};
|
package/dist/brush.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { turn as e } from "./image.js";
|
|
2
|
+
import { recolour as t } from "./tools.js";
|
|
3
|
+
// lib/brush.ts
|
|
4
|
+
function n(n, r) {
|
|
5
|
+
let i = null, a = "origin";
|
|
6
|
+
return {
|
|
7
|
+
patch(e) {
|
|
8
|
+
if (e.brush?.type === "image") {
|
|
9
|
+
let { image: t, mask: n } = e.brush;
|
|
10
|
+
return i = t.data.slice(), a = e.brush.pattern ?? "none", {
|
|
11
|
+
...e,
|
|
12
|
+
brush: {
|
|
13
|
+
...e.brush,
|
|
14
|
+
image: {
|
|
15
|
+
...t,
|
|
16
|
+
data: t.data.slice()
|
|
17
|
+
},
|
|
18
|
+
mask: n?.slice()
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
if (e.fgColor === void 0) return e;
|
|
23
|
+
let { brush: r, keepBrushIndices: o } = {
|
|
24
|
+
...n.getState(),
|
|
25
|
+
...e
|
|
26
|
+
};
|
|
27
|
+
return r.type !== "image" || !i || o ? e : {
|
|
28
|
+
...e,
|
|
29
|
+
brush: {
|
|
30
|
+
...r,
|
|
31
|
+
image: {
|
|
32
|
+
...r.image,
|
|
33
|
+
data: t(i, r.mask, e.fgColor)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
change(t) {
|
|
39
|
+
let { brush: a } = n.getState();
|
|
40
|
+
if (t !== "increment-size" && t !== "decrement-size") {
|
|
41
|
+
if (a.type !== "image" || !i) return !1;
|
|
42
|
+
let { width: r, height: o } = a.image, s = e(a.image.data, r, o, t);
|
|
43
|
+
i = e(i, r, o, t).data;
|
|
44
|
+
let c = a.mask && e(a.mask, r, o, t).data;
|
|
45
|
+
return n.setState({ brush: {
|
|
46
|
+
...a,
|
|
47
|
+
image: s,
|
|
48
|
+
mask: c
|
|
49
|
+
} }), !0;
|
|
50
|
+
}
|
|
51
|
+
if (a.type === "image") return !1;
|
|
52
|
+
let o = a.size + (t === "increment-size" ? 1 : -1);
|
|
53
|
+
return o < 1 || o > r ? !1 : (n.setState({ brush: {
|
|
54
|
+
...a,
|
|
55
|
+
size: o
|
|
56
|
+
} }), !0);
|
|
57
|
+
},
|
|
58
|
+
fromSelection: (e, t) => ({
|
|
59
|
+
type: "image",
|
|
60
|
+
image: {
|
|
61
|
+
width: e.width,
|
|
62
|
+
height: e.height,
|
|
63
|
+
data: t
|
|
64
|
+
},
|
|
65
|
+
mask: e.data,
|
|
66
|
+
pattern: a,
|
|
67
|
+
patternOrigin: {
|
|
68
|
+
x: e.x,
|
|
69
|
+
y: e.y
|
|
70
|
+
}
|
|
71
|
+
}),
|
|
72
|
+
remap(e) {
|
|
73
|
+
let { brush: t } = n.getState();
|
|
74
|
+
t.type === "image" && (i &&= i.map(e), n.setState({ brush: {
|
|
75
|
+
...t,
|
|
76
|
+
image: {
|
|
77
|
+
...t.image,
|
|
78
|
+
data: t.image.data.map(e)
|
|
79
|
+
}
|
|
80
|
+
} }));
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export { n as createBrush };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Change } from './types/history';
|
|
2
|
+
import { Color, SpriteChange } from './types/index';
|
|
3
|
+
import { Mask } from './types/mask';
|
|
4
|
+
/**
|
|
5
|
+
* The document: pixels, size, palette and selection. Its writers are the only code that changes
|
|
6
|
+
* it and the only code that reports to the host; `show` mirrors it into the editor's state. Its
|
|
7
|
+
* changes hold their data and call the writers, so every undo and redo reports.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createDocument(init: {
|
|
10
|
+
image: Uint8Array;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
palette: readonly Color[];
|
|
14
|
+
}, deps: {
|
|
15
|
+
onChange: (change: SpriteChange) => void;
|
|
16
|
+
/** Whether tela's copy matches the host's, so a span from it is safe to send. */
|
|
17
|
+
fresh: () => boolean;
|
|
18
|
+
show: (patch: {
|
|
19
|
+
width?: number;
|
|
20
|
+
height?: number;
|
|
21
|
+
palette?: readonly Color[];
|
|
22
|
+
selection?: Mask | null;
|
|
23
|
+
}) => void;
|
|
24
|
+
}): {
|
|
25
|
+
readonly image: Uint8Array<ArrayBufferLike>;
|
|
26
|
+
readonly width: number;
|
|
27
|
+
readonly height: number;
|
|
28
|
+
readonly palette: readonly string[];
|
|
29
|
+
readonly sel: Mask | null;
|
|
30
|
+
readonly bits: Uint8Array<ArrayBufferLike> | null;
|
|
31
|
+
write(positions: Uint32Array, values: Uint8Array): void;
|
|
32
|
+
/** A remap's palette and pixels, in one report. */
|
|
33
|
+
remap(next: readonly Color[], positions: Uint32Array, values: Uint8Array): void;
|
|
34
|
+
select(next: Mask | null): void;
|
|
35
|
+
/** A palette as the state's and, when `report`, the host's. */
|
|
36
|
+
setPalette(next: readonly Color[], report?: boolean): void;
|
|
37
|
+
/** Swaps in a whole image, reported as a size change when `report`; the selection is the caller's. */
|
|
38
|
+
replace(next: Uint8Array, w: number, h: number, report?: boolean): void;
|
|
39
|
+
/** Takes the host's same-size image as tela's copy, unreported. */
|
|
40
|
+
load(next: Uint8Array): void;
|
|
41
|
+
/** `before` and `after` at `positions`, not yet done. */
|
|
42
|
+
pixels: (positions: Uint32Array, before: Uint8Array, after: Uint8Array) => Change;
|
|
43
|
+
selChange: (before: Mask | null, after: Mask | null) => Change;
|
|
44
|
+
paletteChange: (before: readonly Color[], after: readonly Color[]) => Change;
|
|
45
|
+
/**
|
|
46
|
+
* The whole image and selection, from now to `next` and `m`, not yet done. It swaps in copies:
|
|
47
|
+
* writes change the image in place, and a stroke during a Run isn't undone on its own.
|
|
48
|
+
*/
|
|
49
|
+
imageChange(next: Uint8Array, w: number, h: number, m: Mask | null): Change;
|
|
50
|
+
};
|
package/dist/document.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { tight as e, toBits as t } from "./mask.js";
|
|
2
|
+
// lib/document.ts
|
|
3
|
+
function n(n, r) {
|
|
4
|
+
let { onChange: i, fresh: a, show: o } = r, { image: s, width: c, height: l, palette: u } = n, d = null, f = null, p = (e, t) => {
|
|
5
|
+
let [n, r] = [Infinity, -1];
|
|
6
|
+
for (let i = 0; i < e.length; i++) s[e[i]] = t[i], n = Math.min(n, e[i]), r = Math.max(r, e[i]);
|
|
7
|
+
return {
|
|
8
|
+
positions: e,
|
|
9
|
+
values: t,
|
|
10
|
+
span: e.length && a() ? {
|
|
11
|
+
start: n,
|
|
12
|
+
values: s.subarray(n, r + 1)
|
|
13
|
+
} : void 0
|
|
14
|
+
};
|
|
15
|
+
}, m = {
|
|
16
|
+
get image() {
|
|
17
|
+
return s;
|
|
18
|
+
},
|
|
19
|
+
get width() {
|
|
20
|
+
return c;
|
|
21
|
+
},
|
|
22
|
+
get height() {
|
|
23
|
+
return l;
|
|
24
|
+
},
|
|
25
|
+
get palette() {
|
|
26
|
+
return u;
|
|
27
|
+
},
|
|
28
|
+
get sel() {
|
|
29
|
+
return d;
|
|
30
|
+
},
|
|
31
|
+
get bits() {
|
|
32
|
+
return f;
|
|
33
|
+
},
|
|
34
|
+
write(e, t) {
|
|
35
|
+
e.length && i({
|
|
36
|
+
type: "pixels",
|
|
37
|
+
...p(e, t)
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
remap(e, t, n) {
|
|
41
|
+
u = e, o({ palette: u }), i({
|
|
42
|
+
type: "remap",
|
|
43
|
+
palette: u,
|
|
44
|
+
...p(t, n)
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
select(n) {
|
|
48
|
+
d = n && e(n), f = d && t(d, c, l), o({ selection: d });
|
|
49
|
+
},
|
|
50
|
+
setPalette(e, t = !0) {
|
|
51
|
+
u = e, o({ palette: u }), t && i({
|
|
52
|
+
type: "palette",
|
|
53
|
+
palette: u
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
replace(e, t, n, r = !0) {
|
|
57
|
+
s = e, c = t, l = n, o({
|
|
58
|
+
width: c,
|
|
59
|
+
height: l
|
|
60
|
+
}), r && i({
|
|
61
|
+
type: "size",
|
|
62
|
+
width: c,
|
|
63
|
+
height: l,
|
|
64
|
+
image: s
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
load(e) {
|
|
68
|
+
s = e;
|
|
69
|
+
},
|
|
70
|
+
pixels: (e, t, n) => ({
|
|
71
|
+
size: e.byteLength + t.byteLength + n.byteLength,
|
|
72
|
+
undo: () => m.write(e, t),
|
|
73
|
+
redo: () => m.write(e, n)
|
|
74
|
+
}),
|
|
75
|
+
selChange: (e, t) => ({
|
|
76
|
+
size: (e?.data.byteLength ?? 0) + (t?.data.byteLength ?? 0),
|
|
77
|
+
undo: () => m.select(e),
|
|
78
|
+
redo: () => m.select(t)
|
|
79
|
+
}),
|
|
80
|
+
paletteChange: (e, t) => ({
|
|
81
|
+
size: (e.length + t.length) * 8,
|
|
82
|
+
undo: () => m.setPalette(e),
|
|
83
|
+
redo: () => m.setPalette(t)
|
|
84
|
+
}),
|
|
85
|
+
imageChange(e, t, n, r) {
|
|
86
|
+
let [i, a, o, u] = [
|
|
87
|
+
s.slice(),
|
|
88
|
+
c,
|
|
89
|
+
l,
|
|
90
|
+
d
|
|
91
|
+
];
|
|
92
|
+
return {
|
|
93
|
+
size: i.byteLength + e.byteLength,
|
|
94
|
+
undo: () => {
|
|
95
|
+
m.replace(i.slice(), a, o), m.select(u);
|
|
96
|
+
},
|
|
97
|
+
redo: () => {
|
|
98
|
+
m.replace(e.slice(), t, n), m.select(r);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
return m;
|
|
104
|
+
}
|
|
105
|
+
export { n as createDocument };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Change } from './types/history';
|
|
2
|
+
/** Changes as one: undone newest first, redone in order. */
|
|
3
|
+
export declare function group(changes: (Change | null)[]): Change;
|
|
4
|
+
/** Tela's linear undo history: `done` steps sit below the cursor, the rest can be redone. */
|
|
5
|
+
export declare function createHistory(): {
|
|
6
|
+
/** Records a step, clearing redo, then drops the oldest past `limit` bytes (0: none); the newest stays. */
|
|
7
|
+
record(label: string, changes: Change[], limit: number): void;
|
|
8
|
+
undo(): boolean;
|
|
9
|
+
redo(): boolean;
|
|
10
|
+
readonly state: {
|
|
11
|
+
undoSteps: number;
|
|
12
|
+
redoSteps: number;
|
|
13
|
+
undoLabel: string;
|
|
14
|
+
redoLabel: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
package/dist/history.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// lib/history.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
let t = e.filter((e) => e !== null);
|
|
4
|
+
return {
|
|
5
|
+
size: t.reduce((e, t) => e + t.size, 0),
|
|
6
|
+
undo: () => [...t].reverse().forEach((e) => e.undo()),
|
|
7
|
+
redo: () => t.forEach((e) => e.redo())
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function t() {
|
|
11
|
+
let t = [], n = 0, r = (e) => e.changes.reduce((e, t) => e + t.size, 0);
|
|
12
|
+
return {
|
|
13
|
+
record(e, i, a) {
|
|
14
|
+
t.splice(n, Infinity, {
|
|
15
|
+
label: e,
|
|
16
|
+
changes: i
|
|
17
|
+
});
|
|
18
|
+
let o = t.reduce((e, t) => e + r(t), 0);
|
|
19
|
+
for (; a && o > a && t.length > 1;) o -= r(t.shift());
|
|
20
|
+
n = t.length;
|
|
21
|
+
},
|
|
22
|
+
undo() {
|
|
23
|
+
return n ? (e(t[--n].changes).undo(), !0) : !1;
|
|
24
|
+
},
|
|
25
|
+
redo() {
|
|
26
|
+
return n !== t.length && (e(t[n++].changes).redo(), !0);
|
|
27
|
+
},
|
|
28
|
+
get state() {
|
|
29
|
+
return {
|
|
30
|
+
undoSteps: n,
|
|
31
|
+
redoSteps: t.length - n,
|
|
32
|
+
undoLabel: t[n - 1]?.label ?? null,
|
|
33
|
+
redoLabel: t[n]?.label ?? null
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export { t as createHistory, e as group };
|
package/dist/image.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BrushChange, Image } from './types/image';
|
|
2
|
+
import { Mask, Rect } from './types/mask';
|
|
3
|
+
/**
|
|
4
|
+
* A `width`×`height` image whose cell (x, y) is `src`'s cell at `from(x, y)`, or `outside`
|
|
5
|
+
* where that lies off `src`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resample(src: Image, width: number, height: number, from: (x: number, y: number) => [number, number], outside?: number): Image;
|
|
8
|
+
export declare function turn(data: Uint8Array, w: number, h: number, change: BrushChange): Image;
|
|
9
|
+
/** Flip and Rotate Canvas: each turn on the image and on the selection, cell for cell. */
|
|
10
|
+
export declare function turnImage(image: Image, sel: Mask | null, changes: BrushChange[]): {
|
|
11
|
+
image: {
|
|
12
|
+
data: Uint8Array<ArrayBufferLike>;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
};
|
|
16
|
+
sel: Mask | null;
|
|
17
|
+
};
|
|
18
|
+
/** The `box` of `image`, `hole` where it lies off the image. */
|
|
19
|
+
export declare const crop: (image: Image, { x, y, width, height }: Rect, hole: number) => Image;
|
|
20
|
+
/**
|
|
21
|
+
* Sprite > Trim's box: the bounds of every index other than the most common corner's, the
|
|
22
|
+
* bottom-right's on a tie (observed). An image of that index alone is kept whole.
|
|
23
|
+
*/
|
|
24
|
+
export declare function trimBox({ data, width, height }: Image): Rect;
|
|
25
|
+
/**
|
|
26
|
+
* Edit > Shift: the `box` of `image` with its cells moved by dx, dy, wrapping inside the box.
|
|
27
|
+
* Off the image it reads 0, the mask color.
|
|
28
|
+
*/
|
|
29
|
+
export declare const wrap: (image: Image, { x, y, width, height }: Rect, dx: number, dy: number) => Image;
|
|
30
|
+
/**
|
|
31
|
+
* A palette remap of `image`: `to(i)` is `remap[i]`, or `i` past its end; `from` sends an index
|
|
32
|
+
* back to the lowest one that went to it, or leaves it. `at`, `was` and `now` are the cells it
|
|
33
|
+
* moves.
|
|
34
|
+
*/
|
|
35
|
+
export declare function remapImage(image: Uint8Array, remap: ArrayLike<number>): {
|
|
36
|
+
to: (i: number) => number;
|
|
37
|
+
from: (i: number) => number;
|
|
38
|
+
at: Uint32Array<ArrayBuffer>;
|
|
39
|
+
was: Uint8Array<ArrayBuffer>;
|
|
40
|
+
now: Uint8Array<ArrayBuffer>;
|
|
41
|
+
};
|
package/dist/image.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// lib/image.ts
|
|
2
|
+
function e(e, t, n, r, i = 0) {
|
|
3
|
+
let a = new Uint8Array(t * n);
|
|
4
|
+
for (let o = 0; o < n; o++) for (let n = 0; n < t; n++) {
|
|
5
|
+
let [s, c] = r(n, o), l = s >= 0 && c >= 0 && s < e.width && c < e.height;
|
|
6
|
+
a[o * t + n] = l ? e.data[c * e.width + s] : i;
|
|
7
|
+
}
|
|
8
|
+
return {
|
|
9
|
+
data: a,
|
|
10
|
+
width: t,
|
|
11
|
+
height: n
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
var t = (e, t) => (e % t + t) % t;
|
|
15
|
+
function n(t, n, r, i) {
|
|
16
|
+
let a = {
|
|
17
|
+
data: t,
|
|
18
|
+
width: n,
|
|
19
|
+
height: r
|
|
20
|
+
};
|
|
21
|
+
switch (i) {
|
|
22
|
+
case "rotate-90cw": return e(a, r, n, (e, t) => [t, r - 1 - e]);
|
|
23
|
+
case "flip-d": return e(a, r, n, (e, t) => [t, e]);
|
|
24
|
+
case "flip-x": return e(a, n, r, (e, t) => [n - 1 - e, t]);
|
|
25
|
+
case "flip-y": return e(a, n, r, (e, t) => [e, r - 1 - t]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function r(e, t, r) {
|
|
29
|
+
let { data: i, width: a, height: o } = e;
|
|
30
|
+
for (let e of r) {
|
|
31
|
+
if (t) {
|
|
32
|
+
let [r, i] = e === "flip-x" ? [a - t.x - t.width, t.y] : e === "flip-y" ? [t.x, o - t.y - t.height] : [o - t.y - t.height, t.x];
|
|
33
|
+
t = {
|
|
34
|
+
x: r,
|
|
35
|
+
y: i,
|
|
36
|
+
...n(t.data, t.width, t.height, e)
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
({data: i, width: a, height: o} = n(i, a, o, e));
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
image: {
|
|
43
|
+
data: i,
|
|
44
|
+
width: a,
|
|
45
|
+
height: o
|
|
46
|
+
},
|
|
47
|
+
sel: t
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
var i = (t, { x: n, y: r, width: i, height: a }, o) => e(t, i, a, (e, t) => [n + e, r + t], o);
|
|
51
|
+
function a({ data: e, width: t, height: n }) {
|
|
52
|
+
let r = (n, r) => e[r * t + n], [i, a] = [t - 1, n - 1], o = [
|
|
53
|
+
r(i, a),
|
|
54
|
+
r(0, 0),
|
|
55
|
+
r(i, 0),
|
|
56
|
+
r(0, a)
|
|
57
|
+
], s = (e) => o.filter((t) => t === e).length, c = o.reduce((e, t) => s(t) > s(e) ? t : e), [l, u, d, f] = [
|
|
58
|
+
t,
|
|
59
|
+
n,
|
|
60
|
+
-1,
|
|
61
|
+
-1
|
|
62
|
+
];
|
|
63
|
+
for (let e = 0; e < n; e++) for (let n = 0; n < t; n++) r(n, e) !== c && ([l, u, d, f] = [
|
|
64
|
+
Math.min(l, n),
|
|
65
|
+
Math.min(u, e),
|
|
66
|
+
Math.max(d, n),
|
|
67
|
+
Math.max(f, e)
|
|
68
|
+
]);
|
|
69
|
+
return d < 0 ? {
|
|
70
|
+
x: 0,
|
|
71
|
+
y: 0,
|
|
72
|
+
width: t,
|
|
73
|
+
height: n
|
|
74
|
+
} : {
|
|
75
|
+
x: l,
|
|
76
|
+
y: u,
|
|
77
|
+
width: d - l + 1,
|
|
78
|
+
height: f - u + 1
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
var o = (n, { x: r, y: i, width: a, height: o }, s, c) => e(n, a, o, (e, n) => [r + t(e - s, a), i + t(n - c, o)]);
|
|
82
|
+
function s(e, t) {
|
|
83
|
+
let n = (e) => e < t.length ? t[e] : e, r = /* @__PURE__ */ new Map();
|
|
84
|
+
for (let e = 0; e < t.length; e++) r.has(t[e]) || r.set(t[e], e);
|
|
85
|
+
let i = (e) => r.get(e) ?? e, a = Uint32Array.from(e.keys()).filter((t) => n(e[t]) !== e[t]), o = Uint8Array.from(a, (t) => e[t]);
|
|
86
|
+
return {
|
|
87
|
+
to: n,
|
|
88
|
+
from: i,
|
|
89
|
+
at: a,
|
|
90
|
+
was: o,
|
|
91
|
+
now: o.map(n)
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export { i as crop, s as remapImage, e as resample, a as trimBox, n as turn, r as turnImage, o as wrap };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Editor, EditorOptions } from './types/index';
|
|
2
|
+
export type * from './types/index';
|
|
3
|
+
export type { KeymapEntry, Keys } from './types/keymap';
|
|
4
|
+
export type { Mask, Rect, SelectionMode } from './types/mask';
|
|
5
|
+
export declare function createEditor(options: EditorOptions): Editor;
|