@ideare/kit 0.0.0-stage → 0.1.0-next.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/README.md +148 -2
- package/THIRD_PARTY.md +52 -0
- package/dist/brand/schema.d.ts +265 -0
- package/dist/brand/schema.js +271 -0
- package/dist/check/copy.d.ts +27 -0
- package/dist/check/copy.js +139 -0
- package/dist/check/index.d.ts +54 -0
- package/dist/check/index.js +492 -0
- package/dist/color/contrast.d.ts +41 -0
- package/dist/color/contrast.js +84 -0
- package/dist/color/palette.d.ts +27 -0
- package/dist/color/palette.js +114 -0
- package/dist/color/wcag.d.ts +22 -0
- package/dist/color/wcag.js +50 -0
- package/dist/draft/draft.d.ts +61 -0
- package/dist/draft/draft.js +383 -0
- package/dist/editor/history.d.ts +78 -0
- package/dist/editor/history.js +221 -0
- package/dist/editor/operations.d.ts +112 -0
- package/dist/editor/operations.js +621 -0
- package/dist/files/docs.d.ts +49 -0
- package/dist/files/docs.js +392 -0
- package/dist/files/generate.d.ts +47 -0
- package/dist/files/generate.js +254 -0
- package/dist/files/png.d.ts +40 -0
- package/dist/files/png.js +168 -0
- package/dist/files/raster.d.ts +14 -0
- package/dist/files/raster.js +0 -0
- package/dist/files/templates.d.ts +162 -0
- package/dist/files/templates.js +390 -0
- package/dist/files/tokens.d.ts +22 -0
- package/dist/files/tokens.js +204 -0
- package/dist/fonts/catalog.d.ts +3 -0
- package/dist/fonts/catalog.js +345 -0
- package/dist/fonts/ofl.d.ts +5 -0
- package/dist/fonts/ofl.js +5 -0
- package/dist/fonts/pick.d.ts +33 -0
- package/dist/fonts/pick.js +73 -0
- package/dist/imports/folder.d.ts +80 -0
- package/dist/imports/folder.js +124 -0
- package/dist/imports/unzip.d.ts +32 -0
- package/dist/imports/unzip.js +128 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +34 -0
- package/dist/marks/draw.d.ts +48 -0
- package/dist/marks/draw.js +149 -0
- package/dist/marks/icons.data.d.ts +5 -0
- package/dist/marks/icons.data.js +600 -0
- package/dist/marks/svg.d.ts +46 -0
- package/dist/marks/svg.js +341 -0
- package/dist/node/index.d.ts +13 -0
- package/dist/node/index.js +41 -0
- package/dist/posts/pix.d.ts +19 -0
- package/dist/posts/pix.js +49 -0
- package/dist/posts/templates.d.ts +45 -0
- package/dist/posts/templates.js +868 -0
- package/dist/resvg/index.d.ts +2 -0
- package/dist/resvg/index.js +22 -0
- package/dist/scene/brand-art.d.ts +49 -0
- package/dist/scene/brand-art.js +154 -0
- package/dist/scene/frame.d.ts +89 -0
- package/dist/scene/frame.js +213 -0
- package/dist/scene/grain.d.ts +7 -0
- package/dist/scene/grain.js +7 -0
- package/dist/scene/qr.d.ts +10 -0
- package/dist/scene/qr.js +359 -0
- package/dist/scene/render.d.ts +76 -0
- package/dist/scene/render.js +557 -0
- package/dist/scene/schema.d.ts +271 -0
- package/dist/scene/schema.js +257 -0
- package/dist/sign.d.ts +47 -0
- package/dist/sign.js +88 -0
- package/dist/text/engine.d.ts +128 -0
- package/dist/text/engine.js +245 -0
- package/dist/text/fonts.d.ts +56 -0
- package/dist/text/fonts.js +65 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +2 -0
- package/dist/wasm/index.d.ts +15 -0
- package/dist/wasm/index.js +46 -0
- package/package.json +78 -5
- package/schema/brand.v1.json +442 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type Scene } from "../scene/schema.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Undo and redo for the editor, and the merge with a newer copy from the server (the ideas of
|
|
4
|
+
* smartgenius's editor draft). A step is a list of patches, one per field it changed, never a
|
|
5
|
+
* whole scene: a change that came from the server stays when someone undoes their own edit, and
|
|
6
|
+
* a server write takes only the fields it changed out of the history.
|
|
7
|
+
*
|
|
8
|
+
* A patch's path names one field:
|
|
9
|
+
* - `["scene", prop]`: size, theme, locale, slots, meta...
|
|
10
|
+
* - `["pages"]`: the order of the page ids
|
|
11
|
+
* - `["page", pageId, prop]`: a page's background, grain or name
|
|
12
|
+
* - `["layers", pageId]` and `["layers", pageId, groupId]`: the order of a list of layer ids
|
|
13
|
+
* - `["layer", pageId, layerId, prop]`: one prop of one layer, like its frame or its text
|
|
14
|
+
*
|
|
15
|
+
* A gesture records once, at release, with the scene from the press (editor.md rule E4). Edits
|
|
16
|
+
* that share a group (a typing session, a held arrow key) become one step, until the code that
|
|
17
|
+
* owns the group ends it with endEditGroup.
|
|
18
|
+
*/
|
|
19
|
+
export declare const HISTORY_LIMIT = 50;
|
|
20
|
+
/** One field before and after an edit. A side is missing when the field did not exist. */
|
|
21
|
+
export type ScenePatch = {
|
|
22
|
+
path: readonly string[];
|
|
23
|
+
before?: unknown;
|
|
24
|
+
after?: unknown;
|
|
25
|
+
};
|
|
26
|
+
export type EditHistory = {
|
|
27
|
+
/** Oldest first. */
|
|
28
|
+
undo: ScenePatch[][];
|
|
29
|
+
/** The next step to redo first. */
|
|
30
|
+
redo: ScenePatch[][];
|
|
31
|
+
/** The run of edits the last step belongs to, while it is open. */
|
|
32
|
+
group: string | null;
|
|
33
|
+
};
|
|
34
|
+
export type SceneMerge = {
|
|
35
|
+
/** Your scene with their changes in it, ready to show and save. */
|
|
36
|
+
scene: Scene;
|
|
37
|
+
/** What to compare against from now on: theirs, with the colliding fields left as they were,
|
|
38
|
+
* so your side of a collision still counts as unsaved. */
|
|
39
|
+
base: Scene;
|
|
40
|
+
/** Fields both sides changed in different ways: their change, which `scene` does not have. */
|
|
41
|
+
conflicts: ScenePatch[];
|
|
42
|
+
};
|
|
43
|
+
/** Every field that differs between two scenes. */
|
|
44
|
+
export declare function diffScenes(before: Scene, after: Scene): ScenePatch[];
|
|
45
|
+
/**
|
|
46
|
+
* The scene with each patch's `before` or `after` side set. If the result is no longer a valid
|
|
47
|
+
* scene, the scene comes back unchanged.
|
|
48
|
+
*/
|
|
49
|
+
export declare function applyPatches(scene: Scene, patches: readonly ScenePatch[], side: "before" | "after"): Scene;
|
|
50
|
+
export declare function emptyHistory(): EditHistory;
|
|
51
|
+
/**
|
|
52
|
+
* Record an edit from `before` to `after`. With a `group` equal to the open one, the edit joins
|
|
53
|
+
* the last step, so a typing session or a held arrow key is one Undo.
|
|
54
|
+
*/
|
|
55
|
+
export declare function recordEdit(history: EditHistory, before: Scene, after: Scene, group?: string | null): EditHistory;
|
|
56
|
+
/** Close the open run: the next edit starts a new step, even in the same group. */
|
|
57
|
+
export declare function endEditGroup(history: EditHistory): EditHistory;
|
|
58
|
+
export declare function undoEdit(history: EditHistory, scene: Scene): {
|
|
59
|
+
history: EditHistory;
|
|
60
|
+
scene: Scene;
|
|
61
|
+
};
|
|
62
|
+
export declare function redoEdit(history: EditHistory, scene: Scene): {
|
|
63
|
+
history: EditHistory;
|
|
64
|
+
scene: Scene;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* After the server's copy moved from `before` to `server`, keep the history for every field the
|
|
68
|
+
* server did not change, so an unrelated edit stays undoable after a picture lands.
|
|
69
|
+
*/
|
|
70
|
+
export declare function rebaseHistory(history: EditHistory, before: Scene, server: Scene): EditHistory;
|
|
71
|
+
/**
|
|
72
|
+
* Bring a newer server copy into your unsaved scene. `base` is the copy your edits started from.
|
|
73
|
+
* A field only they changed comes in; a field only you changed stays yours; a field you both
|
|
74
|
+
* changed differently keeps yours and comes back in `conflicts`, so the editor can show their
|
|
75
|
+
* change and offer "Use theirs" (applyPatches with the conflict's `after`) or "Keep mine".
|
|
76
|
+
* Lists of layers and pages merge as a whole: when you both changed one, yours stays.
|
|
77
|
+
*/
|
|
78
|
+
export declare function mergeScenes(draft: Scene, base: Scene, server: Scene): SceneMerge;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { canonical } from "../scene/render.js";
|
|
2
|
+
import { layerSchema, sceneSchema } from "../scene/schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* Undo and redo for the editor, and the merge with a newer copy from the server (the ideas of
|
|
5
|
+
* smartgenius's editor draft). A step is a list of patches, one per field it changed, never a
|
|
6
|
+
* whole scene: a change that came from the server stays when someone undoes their own edit, and
|
|
7
|
+
* a server write takes only the fields it changed out of the history.
|
|
8
|
+
*
|
|
9
|
+
* A patch's path names one field:
|
|
10
|
+
* - `["scene", prop]`: size, theme, locale, slots, meta...
|
|
11
|
+
* - `["pages"]`: the order of the page ids
|
|
12
|
+
* - `["page", pageId, prop]`: a page's background, grain or name
|
|
13
|
+
* - `["layers", pageId]` and `["layers", pageId, groupId]`: the order of a list of layer ids
|
|
14
|
+
* - `["layer", pageId, layerId, prop]`: one prop of one layer, like its frame or its text
|
|
15
|
+
*
|
|
16
|
+
* A gesture records once, at release, with the scene from the press (editor.md rule E4). Edits
|
|
17
|
+
* that share a group (a typing session, a held arrow key) become one step, until the code that
|
|
18
|
+
* owns the group ends it with endEditGroup.
|
|
19
|
+
*/
|
|
20
|
+
export const HISTORY_LIMIT = 50;
|
|
21
|
+
const keyOf = (path) => JSON.stringify(path);
|
|
22
|
+
function same(a, b) {
|
|
23
|
+
return a === b || canonical(a) === canonical(b);
|
|
24
|
+
}
|
|
25
|
+
function put(fields, path, value) {
|
|
26
|
+
if (value === undefined)
|
|
27
|
+
fields.delete(keyOf(path));
|
|
28
|
+
else
|
|
29
|
+
fields.set(keyOf(path), { path, value });
|
|
30
|
+
}
|
|
31
|
+
/** The scene as one entry per field. Values are the scene's own objects, never copies. */
|
|
32
|
+
function flatten(scene) {
|
|
33
|
+
const fields = new Map();
|
|
34
|
+
const props = (prefix, object, skip) => {
|
|
35
|
+
for (const [prop, value] of Object.entries(object))
|
|
36
|
+
if (!skip.includes(prop))
|
|
37
|
+
put(fields, [...prefix, prop], value);
|
|
38
|
+
};
|
|
39
|
+
props(["scene"], scene, ["pages"]);
|
|
40
|
+
put(fields, ["pages"], scene.pages.map((page) => page.id));
|
|
41
|
+
for (const page of scene.pages) {
|
|
42
|
+
props(["page", page.id], page, ["id", "layers"]);
|
|
43
|
+
const walk = (layers, list) => {
|
|
44
|
+
put(fields, list, layers.map((layer) => layer.id));
|
|
45
|
+
for (const layer of layers) {
|
|
46
|
+
props(["layer", page.id, layer.id], layer, ["id", "layers"]);
|
|
47
|
+
if (layer.type === "group")
|
|
48
|
+
walk(layer.layers, ["layers", page.id, layer.id]);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
walk(page.layers, ["layers", page.id]);
|
|
52
|
+
}
|
|
53
|
+
return fields;
|
|
54
|
+
}
|
|
55
|
+
const idsIn = (value) => Array.isArray(value) ? value.filter((id) => typeof id === "string") : [];
|
|
56
|
+
/**
|
|
57
|
+
* The scene the fields describe, or undefined when they no longer make one. A layer whose
|
|
58
|
+
* fields no longer make a valid layer is left out, and so is one that no list holds.
|
|
59
|
+
*/
|
|
60
|
+
function unflatten(fields) {
|
|
61
|
+
const scene = {};
|
|
62
|
+
const pages = new Map();
|
|
63
|
+
const layers = new Map();
|
|
64
|
+
const objectFor = (map, key) => {
|
|
65
|
+
let object = map.get(key);
|
|
66
|
+
if (!object) {
|
|
67
|
+
object = {};
|
|
68
|
+
map.set(key, object);
|
|
69
|
+
}
|
|
70
|
+
return object;
|
|
71
|
+
};
|
|
72
|
+
for (const { path, value } of fields.values()) {
|
|
73
|
+
const [kind, a, b, c] = path;
|
|
74
|
+
if (kind === "scene" && a)
|
|
75
|
+
scene[a] = value;
|
|
76
|
+
else if (kind === "page" && a && b)
|
|
77
|
+
objectFor(pages, a)[b] = value;
|
|
78
|
+
else if (kind === "layer" && a && b && c)
|
|
79
|
+
objectFor(layers, keyOf([a, b]))[c] = value;
|
|
80
|
+
}
|
|
81
|
+
const placed = new Set();
|
|
82
|
+
/** The layers a list of ids names, at `path` (as flatten wrote it). */
|
|
83
|
+
const list = (pageId, path) => idsIn(fields.get(keyOf(path))?.value).flatMap((id) => {
|
|
84
|
+
const key = keyOf([pageId, id]);
|
|
85
|
+
const props = layers.get(key);
|
|
86
|
+
if (!props || placed.has(key))
|
|
87
|
+
return [];
|
|
88
|
+
placed.add(key);
|
|
89
|
+
const layer = props.type === "group"
|
|
90
|
+
? { ...props, id, layers: list(pageId, ["layers", pageId, id]) }
|
|
91
|
+
: { ...props, id };
|
|
92
|
+
const parsed = layerSchema.safeParse(layer);
|
|
93
|
+
return parsed.success ? [parsed.data] : [];
|
|
94
|
+
});
|
|
95
|
+
const parsed = sceneSchema.safeParse({
|
|
96
|
+
...scene,
|
|
97
|
+
pages: idsIn(fields.get(keyOf(["pages"]))?.value).map((id) => ({
|
|
98
|
+
...pages.get(id),
|
|
99
|
+
id,
|
|
100
|
+
layers: list(id, ["layers", id]),
|
|
101
|
+
})),
|
|
102
|
+
});
|
|
103
|
+
return parsed.success ? parsed.data : undefined;
|
|
104
|
+
}
|
|
105
|
+
function diffFields(before, after) {
|
|
106
|
+
const patches = [];
|
|
107
|
+
for (const [key, field] of before) {
|
|
108
|
+
const next = after.get(key);
|
|
109
|
+
if (!same(field.value, next?.value))
|
|
110
|
+
patches.push({ path: field.path, before: field.value, after: next?.value });
|
|
111
|
+
}
|
|
112
|
+
for (const [key, field] of after)
|
|
113
|
+
if (!before.has(key))
|
|
114
|
+
patches.push({ path: field.path, after: field.value });
|
|
115
|
+
return patches;
|
|
116
|
+
}
|
|
117
|
+
/** Every field that differs between two scenes. */
|
|
118
|
+
export function diffScenes(before, after) {
|
|
119
|
+
return diffFields(flatten(before), flatten(after));
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* The scene with each patch's `before` or `after` side set. If the result is no longer a valid
|
|
123
|
+
* scene, the scene comes back unchanged.
|
|
124
|
+
*/
|
|
125
|
+
export function applyPatches(scene, patches, side) {
|
|
126
|
+
if (patches.length === 0)
|
|
127
|
+
return scene;
|
|
128
|
+
const fields = flatten(scene);
|
|
129
|
+
for (const patch of patches)
|
|
130
|
+
put(fields, patch.path, patch[side]);
|
|
131
|
+
return unflatten(fields) ?? scene;
|
|
132
|
+
}
|
|
133
|
+
export function emptyHistory() {
|
|
134
|
+
return { undo: [], redo: [], group: null };
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Record an edit from `before` to `after`. With a `group` equal to the open one, the edit joins
|
|
138
|
+
* the last step, so a typing session or a held arrow key is one Undo.
|
|
139
|
+
*/
|
|
140
|
+
export function recordEdit(history, before, after, group = null) {
|
|
141
|
+
const previous = group !== null && group === history.group ? history.undo.at(-1) : undefined;
|
|
142
|
+
const start = flatten(before);
|
|
143
|
+
// Where the run began: this edit's start with the run's earlier changes taken back.
|
|
144
|
+
if (previous)
|
|
145
|
+
for (const patch of previous)
|
|
146
|
+
put(start, patch.path, patch.before);
|
|
147
|
+
const step = diffFields(start, flatten(after));
|
|
148
|
+
const undo = previous ? history.undo.slice(0, -1) : history.undo;
|
|
149
|
+
// A run that came back to where it began leaves no step.
|
|
150
|
+
if (step.length === 0)
|
|
151
|
+
return previous ? { undo, redo: [], group: null } : history;
|
|
152
|
+
return { undo: [...undo, step].slice(-HISTORY_LIMIT), redo: [], group };
|
|
153
|
+
}
|
|
154
|
+
/** Close the open run: the next edit starts a new step, even in the same group. */
|
|
155
|
+
export function endEditGroup(history) {
|
|
156
|
+
return history.group === null ? history : { ...history, group: null };
|
|
157
|
+
}
|
|
158
|
+
export function undoEdit(history, scene) {
|
|
159
|
+
const step = history.undo.at(-1);
|
|
160
|
+
if (!step)
|
|
161
|
+
return { history, scene };
|
|
162
|
+
return {
|
|
163
|
+
history: { undo: history.undo.slice(0, -1), redo: [step, ...history.redo], group: null },
|
|
164
|
+
scene: applyPatches(scene, step, "before"),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
export function redoEdit(history, scene) {
|
|
168
|
+
const [step, ...rest] = history.redo;
|
|
169
|
+
if (!step)
|
|
170
|
+
return { history, scene };
|
|
171
|
+
return {
|
|
172
|
+
history: { undo: [...history.undo, step], redo: rest, group: null },
|
|
173
|
+
scene: applyPatches(scene, step, "after"),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* After the server's copy moved from `before` to `server`, keep the history for every field the
|
|
178
|
+
* server did not change, so an unrelated edit stays undoable after a picture lands.
|
|
179
|
+
*/
|
|
180
|
+
export function rebaseHistory(history, before, server) {
|
|
181
|
+
const changed = new Set(diffScenes(before, server).map((patch) => keyOf(patch.path)));
|
|
182
|
+
if (changed.size === 0)
|
|
183
|
+
return endEditGroup(history);
|
|
184
|
+
const keep = (steps) => steps
|
|
185
|
+
.map((step) => step.filter((patch) => !changed.has(keyOf(patch.path))))
|
|
186
|
+
.filter((step) => step.length > 0);
|
|
187
|
+
return { undo: keep(history.undo), redo: keep(history.redo), group: null };
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Bring a newer server copy into your unsaved scene. `base` is the copy your edits started from.
|
|
191
|
+
* A field only they changed comes in; a field only you changed stays yours; a field you both
|
|
192
|
+
* changed differently keeps yours and comes back in `conflicts`, so the editor can show their
|
|
193
|
+
* change and offer "Use theirs" (applyPatches with the conflict's `after`) or "Keep mine".
|
|
194
|
+
* Lists of layers and pages merge as a whole: when you both changed one, yours stays.
|
|
195
|
+
*/
|
|
196
|
+
export function mergeScenes(draft, base, server) {
|
|
197
|
+
const mine = flatten(draft);
|
|
198
|
+
const was = flatten(base);
|
|
199
|
+
const theirs = flatten(server);
|
|
200
|
+
if (diffFields(was, mine).length === 0)
|
|
201
|
+
return { scene: server, base: server, conflicts: [] };
|
|
202
|
+
const merged = new Map(mine);
|
|
203
|
+
const nextBase = new Map(theirs);
|
|
204
|
+
const conflicts = [];
|
|
205
|
+
const remote = diffFields(was, theirs);
|
|
206
|
+
for (const patch of remote) {
|
|
207
|
+
const own = mine.get(keyOf(patch.path))?.value;
|
|
208
|
+
if (same(own, patch.before))
|
|
209
|
+
put(merged, patch.path, patch.after);
|
|
210
|
+
else if (!same(own, patch.after)) {
|
|
211
|
+
conflicts.push(patch);
|
|
212
|
+
put(nextBase, patch.path, patch.before);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const scene = unflatten(merged);
|
|
216
|
+
const sceneBase = unflatten(nextBase);
|
|
217
|
+
// ponytail: fields that no longer make a scene together keep yours whole, against theirs.
|
|
218
|
+
if (!scene || !sceneBase)
|
|
219
|
+
return { scene: draft, base: server, conflicts: remote };
|
|
220
|
+
return { scene, base: sceneBase, conflicts };
|
|
221
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { type Guides, type Handle, type Point } from "../scene/frame.ts";
|
|
2
|
+
import type { Frame, Layer, Lock, Scene } from "../scene/schema.ts";
|
|
3
|
+
/**
|
|
4
|
+
* The editor's scene operations: pure functions from a scene to a new scene, with no DOM, so the
|
|
5
|
+
* studio, an agent and a test all edit the same way (docs/spikes/editor.md). Layers are found by
|
|
6
|
+
* id on a page, inside groups too. Positions come in the page's space and are turned into each
|
|
7
|
+
* layer's own parent space here, so a layer inside a turned group still follows the finger.
|
|
8
|
+
* Layers an operation does not touch keep their objects, so an editor can skip them.
|
|
9
|
+
*
|
|
10
|
+
* A gesture is computed from the scene at the press on every frame (`resizeLayers(start, ...)`),
|
|
11
|
+
* never from the last frame, so rounding never adds up.
|
|
12
|
+
*/
|
|
13
|
+
/** What an operation that changes the picked layers gives back: the scene and the new pick. */
|
|
14
|
+
export type Edit = {
|
|
15
|
+
scene: Scene;
|
|
16
|
+
selection: string[];
|
|
17
|
+
};
|
|
18
|
+
export type AlignMode = "left" | "center" | "right" | "top" | "middle" | "bottom";
|
|
19
|
+
export type ZOrder = "front" | "forward" | "backward" | "back";
|
|
20
|
+
/** How far a copy lands from its original, down and to the right, in design units. */
|
|
21
|
+
export declare const DUPLICATE_OFFSET = 24;
|
|
22
|
+
/** The most pages a scene holds, as its schema says. */
|
|
23
|
+
export declare const MAX_PAGES = 20;
|
|
24
|
+
/**
|
|
25
|
+
* Path data scaled by kx across and ky down. ponytail: an arc's radii scale with the axes, which
|
|
26
|
+
* is exact for upright arcs only, and data whose numbers do not split into whole commands (arc
|
|
27
|
+
* flags written with no space, like `a1 1 0 0110 10`) comes back unchanged.
|
|
28
|
+
*/
|
|
29
|
+
export declare function scalePath(d: string, kx: number, ky: number): string;
|
|
30
|
+
/** The page-space frame of a layer and the layer itself, found by id anywhere on the page. */
|
|
31
|
+
export declare function findLayer(scene: Scene, page: number, id: string): {
|
|
32
|
+
layer: Layer;
|
|
33
|
+
frame: Frame;
|
|
34
|
+
} | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* The box the editor draws around the pick: one layer's own frame, turned with it, or the
|
|
37
|
+
* upright box around several. Its `rotate` is where a turn gesture starts.
|
|
38
|
+
*/
|
|
39
|
+
export declare function selectionFrame(scene: Scene, page: number, ids: readonly string[]): Frame | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Where a moving pick can land: the page's edges and middle, and the edges and middles of the
|
|
42
|
+
* other visible layers on the page. Feed it to snapBox with the stage's scale.
|
|
43
|
+
*/
|
|
44
|
+
export declare function snapTargets(scene: Scene, page: number, ids: readonly string[]): Guides;
|
|
45
|
+
/** Put a layer on top of the page. Ids already taken on the page get a number. */
|
|
46
|
+
export declare function addLayer(scene: Scene, page: number, layer: Layer): Edit;
|
|
47
|
+
/** Take layers off the page. Locked ones stay, and stay picked. */
|
|
48
|
+
export declare function removeLayers(scene: Scene, page: number, ids: readonly string[]): Edit;
|
|
49
|
+
/** A copy of each picked layer right above it, moved by `offset` on the page. */
|
|
50
|
+
export declare function duplicateLayers(scene: Scene, page: number, ids: readonly string[], offset?: number): Edit;
|
|
51
|
+
/** Move the picked layers by dx and dy on the page. Layers locked in place stay. */
|
|
52
|
+
export declare function moveLayers(scene: Scene, page: number, ids: readonly string[], dx: number, dy: number): Scene;
|
|
53
|
+
/**
|
|
54
|
+
* Pull a handle of the pick to `to`, a point on the page (the handle's start plus the pointer's
|
|
55
|
+
* travel), from the scene at the press. One layer resizes in its own turned frame with the
|
|
56
|
+
* opposite corner or side held still; a corner also scales its type, radii and strokes, and a
|
|
57
|
+
* group's layers. Several layers, and a group, resize from the corners only: the box around
|
|
58
|
+
* them scales, and every layer in it, about the opposite corner.
|
|
59
|
+
*/
|
|
60
|
+
export declare function resizeLayers(start: Scene, page: number, ids: readonly string[], handle: Handle, to: Point, options?: {
|
|
61
|
+
min?: number;
|
|
62
|
+
keepRatio?: boolean;
|
|
63
|
+
}): Scene;
|
|
64
|
+
/**
|
|
65
|
+
* Turn the pick to `angle` degrees, from the scene at the press. One layer turns about its own
|
|
66
|
+
* center to that angle. Several turn together by `angle` about the center of the box around
|
|
67
|
+
* them, which starts every gesture upright (selectionFrame's `rotate` is 0). Use turnAngle for
|
|
68
|
+
* the angle a handle gives.
|
|
69
|
+
*/
|
|
70
|
+
export declare function rotateLayers(start: Scene, page: number, ids: readonly string[], angle: number): Scene;
|
|
71
|
+
/**
|
|
72
|
+
* Line the pick up: one layer with the page, several with the box around them. It uses each
|
|
73
|
+
* layer's upright box, so a turned layer lines up by what it covers.
|
|
74
|
+
*/
|
|
75
|
+
export declare function alignLayers(scene: Scene, page: number, ids: readonly string[], mode: AlignMode): Scene;
|
|
76
|
+
/**
|
|
77
|
+
* Space three or more layers evenly: the first and the last stay, and the gaps between the
|
|
78
|
+
* others' upright boxes become equal. Layers locked in place are left out.
|
|
79
|
+
*/
|
|
80
|
+
export declare function distributeLayers(scene: Scene, page: number, ids: readonly string[], direction: "horizontal" | "vertical"): Scene;
|
|
81
|
+
/**
|
|
82
|
+
* Change the drawing order: to the front or the back of their list, or one step past the next
|
|
83
|
+
* layer that is not picked. Picked layers keep their order among themselves, and a layer inside
|
|
84
|
+
* a group moves within its group.
|
|
85
|
+
*/
|
|
86
|
+
export declare function reorderLayers(scene: Scene, page: number, ids: readonly string[], order: ZOrder): Scene;
|
|
87
|
+
/**
|
|
88
|
+
* Put two or more layers that share a list into one group, where the top one of them was. The
|
|
89
|
+
* group is the upright box around them, and they keep their place on the page.
|
|
90
|
+
*/
|
|
91
|
+
export declare function groupLayers(scene: Scene, page: number, ids: readonly string[], id?: string): Edit;
|
|
92
|
+
/**
|
|
93
|
+
* Break picked groups apart: their layers take the group's place, keep their place on the page,
|
|
94
|
+
* and take on the group's opacity and hidden state. ponytail: a group's blend mode goes to each
|
|
95
|
+
* layer that has none, which blends them one by one instead of as one picture.
|
|
96
|
+
*/
|
|
97
|
+
export declare function ungroupLayers(scene: Scene, page: number, ids: readonly string[]): Edit;
|
|
98
|
+
/** Lock the picked layers (true: all five locks), unlock them (false), or set some locks. */
|
|
99
|
+
export declare function lockLayers(scene: Scene, page: number, ids: readonly string[], lock: Lock | boolean): Scene;
|
|
100
|
+
/**
|
|
101
|
+
* A text box's new height (from its lines, as someone types), with its turned top-left corner
|
|
102
|
+
* held still, so turned text never slides (rule E2).
|
|
103
|
+
*/
|
|
104
|
+
export declare function setTextHeight(scene: Scene, page: number, id: string, h: number): Scene;
|
|
105
|
+
/** A blank page at `at` (the end by default), on the same background as the page before it. */
|
|
106
|
+
export declare function addPage(scene: Scene, at?: number): Scene;
|
|
107
|
+
/** A copy of a page, right after it. */
|
|
108
|
+
export declare function duplicatePage(scene: Scene, index: number): Scene;
|
|
109
|
+
/** Take a page out. The last page always stays. */
|
|
110
|
+
export declare function removePage(scene: Scene, index: number): Scene;
|
|
111
|
+
/** Move a page from one place in the order to another. */
|
|
112
|
+
export declare function movePage(scene: Scene, from: number, to: number): Scene;
|