@sealpixel/ui 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/LICENSE.md +59 -0
- package/README.md +10 -0
- package/dist/components/lumbra-button.d.ts +28 -0
- package/dist/components/lumbra-button.d.ts.map +1 -0
- package/dist/components/lumbra-button.js +87 -0
- package/dist/components/lumbra-button.js.map +1 -0
- package/dist/components/lumbra-editor.d.ts +226 -0
- package/dist/components/lumbra-editor.d.ts.map +1 -0
- package/dist/components/lumbra-editor.js +873 -0
- package/dist/components/lumbra-editor.js.map +1 -0
- package/dist/components/lumbra-nav.d.ts +48 -0
- package/dist/components/lumbra-nav.d.ts.map +1 -0
- package/dist/components/lumbra-nav.js +159 -0
- package/dist/components/lumbra-nav.js.map +1 -0
- package/dist/components/lumbra-slider.d.ts +48 -0
- package/dist/components/lumbra-slider.d.ts.map +1 -0
- package/dist/components/lumbra-slider.js +168 -0
- package/dist/components/lumbra-slider.js.map +1 -0
- package/dist/components/lumbra-stage.d.ts +92 -0
- package/dist/components/lumbra-stage.d.ts.map +1 -0
- package/dist/components/lumbra-stage.js +344 -0
- package/dist/components/lumbra-stage.js.map +1 -0
- package/dist/components/lumbra-toolbar.d.ts +30 -0
- package/dist/components/lumbra-toolbar.d.ts.map +1 -0
- package/dist/components/lumbra-toolbar.js +127 -0
- package/dist/components/lumbra-toolbar.js.map +1 -0
- package/dist/components/pincel-button.d.ts +28 -0
- package/dist/components/pincel-button.d.ts.map +1 -0
- package/dist/components/pincel-button.js +87 -0
- package/dist/components/pincel-button.js.map +1 -0
- package/dist/components/pincel-editor.d.ts +195 -0
- package/dist/components/pincel-editor.d.ts.map +1 -0
- package/dist/components/pincel-editor.js +794 -0
- package/dist/components/pincel-editor.js.map +1 -0
- package/dist/components/pincel-nav.d.ts +33 -0
- package/dist/components/pincel-nav.d.ts.map +1 -0
- package/dist/components/pincel-nav.js +147 -0
- package/dist/components/pincel-nav.js.map +1 -0
- package/dist/components/pincel-slider.d.ts +48 -0
- package/dist/components/pincel-slider.d.ts.map +1 -0
- package/dist/components/pincel-slider.js +168 -0
- package/dist/components/pincel-slider.js.map +1 -0
- package/dist/components/pincel-stage.d.ts +66 -0
- package/dist/components/pincel-stage.d.ts.map +1 -0
- package/dist/components/pincel-stage.js +233 -0
- package/dist/components/pincel-stage.js.map +1 -0
- package/dist/components/pincel-toolbar.d.ts +30 -0
- package/dist/components/pincel-toolbar.d.ts.map +1 -0
- package/dist/components/pincel-toolbar.js +127 -0
- package/dist/components/pincel-toolbar.js.map +1 -0
- package/dist/components/sealpixel-button.d.ts +28 -0
- package/dist/components/sealpixel-button.d.ts.map +1 -0
- package/dist/components/sealpixel-button.js +117 -0
- package/dist/components/sealpixel-button.js.map +1 -0
- package/dist/components/sealpixel-editor.d.ts +226 -0
- package/dist/components/sealpixel-editor.d.ts.map +1 -0
- package/dist/components/sealpixel-editor.js +1245 -0
- package/dist/components/sealpixel-editor.js.map +1 -0
- package/dist/components/sealpixel-nav.d.ts +48 -0
- package/dist/components/sealpixel-nav.d.ts.map +1 -0
- package/dist/components/sealpixel-nav.js +159 -0
- package/dist/components/sealpixel-nav.js.map +1 -0
- package/dist/components/sealpixel-slider.d.ts +75 -0
- package/dist/components/sealpixel-slider.d.ts.map +1 -0
- package/dist/components/sealpixel-slider.js +269 -0
- package/dist/components/sealpixel-slider.js.map +1 -0
- package/dist/components/sealpixel-stage.d.ts +118 -0
- package/dist/components/sealpixel-stage.d.ts.map +1 -0
- package/dist/components/sealpixel-stage.js +409 -0
- package/dist/components/sealpixel-stage.js.map +1 -0
- package/dist/components/sealpixel-stepper.d.ts +69 -0
- package/dist/components/sealpixel-stepper.d.ts.map +1 -0
- package/dist/components/sealpixel-stepper.js +248 -0
- package/dist/components/sealpixel-stepper.js.map +1 -0
- package/dist/components/sealpixel-toolbar.d.ts +30 -0
- package/dist/components/sealpixel-toolbar.d.ts.map +1 -0
- package/dist/components/sealpixel-toolbar.js +149 -0
- package/dist/components/sealpixel-toolbar.js.map +1 -0
- package/dist/controllers/gesture-controller.d.ts +65 -0
- package/dist/controllers/gesture-controller.d.ts.map +1 -0
- package/dist/controllers/gesture-controller.js +125 -0
- package/dist/controllers/gesture-controller.js.map +1 -0
- package/dist/controllers/session-controller.d.ts +15 -0
- package/dist/controllers/session-controller.d.ts.map +1 -0
- package/dist/controllers/session-controller.js +37 -0
- package/dist/controllers/session-controller.js.map +1 -0
- package/dist/define.d.ts +21 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +27 -0
- package/dist/define.js.map +1 -0
- package/dist/i18n.d.ts +11 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +27 -0
- package/dist/i18n.js.map +1 -0
- package/dist/icons.d.ts +32 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +45 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/locales/de.d.ts +3 -0
- package/dist/locales/de.d.ts.map +1 -0
- package/dist/locales/de.js +132 -0
- package/dist/locales/de.js.map +1 -0
- package/dist/locales/en.d.ts +3 -0
- package/dist/locales/en.d.ts.map +1 -0
- package/dist/locales/en.js +132 -0
- package/dist/locales/en.js.map +1 -0
- package/dist/locales/es.d.ts +3 -0
- package/dist/locales/es.d.ts.map +1 -0
- package/dist/locales/es.js +132 -0
- package/dist/locales/es.js.map +1 -0
- package/dist/locales/fr.d.ts +3 -0
- package/dist/locales/fr.d.ts.map +1 -0
- package/dist/locales/fr.js +132 -0
- package/dist/locales/fr.js.map +1 -0
- package/dist/locales/index.d.ts +6 -0
- package/dist/locales/index.d.ts.map +1 -0
- package/dist/locales/index.js +13 -0
- package/dist/locales/index.js.map +1 -0
- package/dist/locales/ja.d.ts +3 -0
- package/dist/locales/ja.d.ts.map +1 -0
- package/dist/locales/ja.js +132 -0
- package/dist/locales/ja.js.map +1 -0
- package/dist/locales/pt.d.ts +3 -0
- package/dist/locales/pt.d.ts.map +1 -0
- package/dist/locales/pt.js +132 -0
- package/dist/locales/pt.js.map +1 -0
- package/dist/theme.d.ts +19 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +150 -0
- package/dist/theme.js.map +1 -0
- package/dist/tool.d.ts +70 -0
- package/dist/tool.d.ts.map +1 -0
- package/dist/tool.js +2 -0
- package/dist/tool.js.map +1 -0
- package/dist/tools/annotate.d.ts +3 -0
- package/dist/tools/annotate.d.ts.map +1 -0
- package/dist/tools/annotate.js +436 -0
- package/dist/tools/annotate.js.map +1 -0
- package/dist/tools/crop-mask.d.ts +29 -0
- package/dist/tools/crop-mask.d.ts.map +1 -0
- package/dist/tools/crop-mask.js +75 -0
- package/dist/tools/crop-mask.js.map +1 -0
- package/dist/tools/crop.d.ts +11 -0
- package/dist/tools/crop.d.ts.map +1 -0
- package/dist/tools/crop.js +361 -0
- package/dist/tools/crop.js.map +1 -0
- package/dist/tools/delete-handle.d.ts +18 -0
- package/dist/tools/delete-handle.d.ts.map +1 -0
- package/dist/tools/delete-handle.js +61 -0
- package/dist/tools/delete-handle.js.map +1 -0
- package/dist/tools/filter.d.ts +3 -0
- package/dist/tools/filter.d.ts.map +1 -0
- package/dist/tools/filter.js +174 -0
- package/dist/tools/filter.js.map +1 -0
- package/dist/tools/finetune.d.ts +11 -0
- package/dist/tools/finetune.d.ts.map +1 -0
- package/dist/tools/finetune.js +98 -0
- package/dist/tools/finetune.js.map +1 -0
- package/dist/tools/frame.d.ts +3 -0
- package/dist/tools/frame.d.ts.map +1 -0
- package/dist/tools/frame.js +57 -0
- package/dist/tools/frame.js.map +1 -0
- package/dist/tools/index.d.ts +14 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +41 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/redact.d.ts +3 -0
- package/dist/tools/redact.d.ts.map +1 -0
- package/dist/tools/redact.js +252 -0
- package/dist/tools/redact.js.map +1 -0
- package/dist/tools/resize.d.ts +3 -0
- package/dist/tools/resize.d.ts.map +1 -0
- package/dist/tools/resize.js +91 -0
- package/dist/tools/resize.js.map +1 -0
- package/dist/tools/sticker.d.ts +8 -0
- package/dist/tools/sticker.d.ts.map +1 -0
- package/dist/tools/sticker.js +156 -0
- package/dist/tools/sticker.js.map +1 -0
- package/dist/tools/watermark.d.ts +3 -0
- package/dist/tools/watermark.d.ts.map +1 -0
- package/dist/tools/watermark.js +102 -0
- package/dist/tools/watermark.js.map +1 -0
- package/dist/view-mapping.d.ts +23 -0
- package/dist/view-mapping.d.ts.map +1 -0
- package/dist/view-mapping.js +72 -0
- package/dist/view-mapping.js.map +1 -0
- package/package.json +55 -0
- package/themes/default.css +23 -0
- package/themes/high-contrast.css +30 -0
- package/themes/minimal.css +32 -0
- package/themes/nocturne.css +21 -0
- package/themes/studio.css +23 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { RESIZE_DEFAULT_OPTIONS } from '@sealpixel/plugins';
|
|
2
|
+
import { html, nothing } from 'lit';
|
|
3
|
+
import { icons } from '../icons.js';
|
|
4
|
+
import { opId } from './finetune.js';
|
|
5
|
+
/** Whether the two dimensions move together. Kept across panel renders. */
|
|
6
|
+
let linked = true;
|
|
7
|
+
export const resizeTool = {
|
|
8
|
+
id: 'resize',
|
|
9
|
+
icon: icons.resize,
|
|
10
|
+
label: 'tool.resize',
|
|
11
|
+
panel: (ctx) => {
|
|
12
|
+
const target = ctx.document.resize.target;
|
|
13
|
+
const options = ctx.options('resize') ?? RESIZE_DEFAULT_OPTIONS;
|
|
14
|
+
const commit = (patch) => ctx.dispatch({
|
|
15
|
+
type: 'resize.set',
|
|
16
|
+
id: opId(),
|
|
17
|
+
...(target === null ? { fit: options.defaultFit } : {}),
|
|
18
|
+
...patch,
|
|
19
|
+
});
|
|
20
|
+
const num = (e) => {
|
|
21
|
+
const v = e.target.value.trim();
|
|
22
|
+
return v === '' ? null : Math.max(1, Math.round(Number(v)));
|
|
23
|
+
};
|
|
24
|
+
const src = ctx.state.source;
|
|
25
|
+
const ratio = src && src.width > 0 ? src.height / src.width : 1;
|
|
26
|
+
/**
|
|
27
|
+
* With the link closed the two fields are one measurement: typing either
|
|
28
|
+
* side writes both, so the log carries the size that will be rendered
|
|
29
|
+
* rather than one number and a rule for finding the other.
|
|
30
|
+
*/
|
|
31
|
+
const setWidth = (w) => commit(linked && w !== null
|
|
32
|
+
? { width: w, height: Math.max(1, Math.round(w * ratio)) }
|
|
33
|
+
: { width: w });
|
|
34
|
+
const setHeight = (h) => commit(linked && h !== null
|
|
35
|
+
? { width: Math.max(1, Math.round(h / ratio)), height: h }
|
|
36
|
+
: { height: h });
|
|
37
|
+
// The resting value is the source's own size, so a field never sits empty
|
|
38
|
+
// saying nothing about what will come out.
|
|
39
|
+
const shownWidth = target?.width ?? src?.width ?? null;
|
|
40
|
+
const shownHeight = target?.height ?? src?.height ?? null;
|
|
41
|
+
const derived = (own) => (own == null ? 'derived' : '');
|
|
42
|
+
return html `
|
|
43
|
+
<div class="rows">
|
|
44
|
+
<div class="field">
|
|
45
|
+
<span>${ctx.t('resize.size')}</span>
|
|
46
|
+
<div class="dims">
|
|
47
|
+
<input class=${derived(target?.width)} data-field="width" type="number" min="1" max=${options.max?.width ?? nothing} inputmode="numeric" aria-label=${ctx.t('resize.width')} .value=${shownWidth?.toString() ?? ''} @change=${(e) => setWidth(num(e))} />
|
|
48
|
+
<sealpixel-button
|
|
49
|
+
variant="ghost"
|
|
50
|
+
data-action="link"
|
|
51
|
+
?pressed=${linked}
|
|
52
|
+
.label=${ctx.t(linked ? 'resize.linked' : 'resize.unlinked')}
|
|
53
|
+
@click=${() => {
|
|
54
|
+
linked = !linked;
|
|
55
|
+
ctx.refresh();
|
|
56
|
+
}}
|
|
57
|
+
>${linked ? icons.link : icons.linkOff}</sealpixel-button
|
|
58
|
+
>
|
|
59
|
+
<input class=${derived(target?.height)} data-field="height" type="number" min="1" max=${options.max?.height ?? nothing} inputmode="numeric" aria-label=${ctx.t('resize.height')} .value=${shownHeight?.toString() ?? ''} @change=${(e) => setHeight(num(e))} />
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
${
|
|
63
|
+
// A closed link never squeezes the image, so there is nothing for a
|
|
64
|
+
// fit mode to decide.
|
|
65
|
+
linked
|
|
66
|
+
? nothing
|
|
67
|
+
: html `<label class="field">
|
|
68
|
+
<span>${ctx.t('resize.fit')}</span>
|
|
69
|
+
<select data-field="fit" .value=${target?.fit ?? options.defaultFit} @change=${(e) => commit({ fit: e.target.value })}>
|
|
70
|
+
${options.fits.map((f) => html `<option value=${f} ?selected=${(target?.fit ?? options.defaultFit) === f}>${ctx.t(`resize.fit.${f}`)}</option>`)}
|
|
71
|
+
</select>
|
|
72
|
+
</label>`}
|
|
73
|
+
${options.upscale
|
|
74
|
+
? html `<label class="field check">
|
|
75
|
+
<input data-field="upscale" type="checkbox" .checked=${target?.upscale ?? false} @change=${(e) => commit({ upscale: e.target.checked })} />
|
|
76
|
+
<span>${ctx.t('resize.upscale')}</span>
|
|
77
|
+
</label>`
|
|
78
|
+
: nothing}
|
|
79
|
+
<sealpixel-button variant="ghost" data-action="reset" ?disabled=${target === null} .label=${ctx.t('resize.clear')} @click=${() => ctx.dispatch({ type: 'resize.clear', id: opId() })}>
|
|
80
|
+
${ctx.t('resize.clear')}
|
|
81
|
+
</sealpixel-button>
|
|
82
|
+
</div>
|
|
83
|
+
${options.presets.length > 0
|
|
84
|
+
? html `<div class="strip choice" role="group" aria-label=${ctx.t('resize.presets')}>
|
|
85
|
+
${options.presets.map((p) => html `<sealpixel-button data-preset=${p.label} variant="ghost" ?pressed=${target?.width === (p.width ?? null) && target?.height === (p.height ?? null)} @click=${() => commit({ width: p.width ?? null, height: p.height ?? null })}>${p.label}</sealpixel-button>`)}
|
|
86
|
+
</div>`
|
|
87
|
+
: nothing}
|
|
88
|
+
`;
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=resize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resize.js","sourceRoot":"","sources":["../../src/tools/resize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { UiTool } from '../tool.js';
|
|
2
|
+
/**
|
|
3
|
+
* Stickers live in crop space, so the normal (cropped) preview is the right
|
|
4
|
+
* stage. Assets come from the plugin's declarations or from an upload, which
|
|
5
|
+
* is registered on the session and recorded in the log.
|
|
6
|
+
*/
|
|
7
|
+
export declare const stickerTool: UiTool;
|
|
8
|
+
//# sourceMappingURL=sticker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sticker.d.ts","sourceRoot":"","sources":["../../src/tools/sticker.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,YAAY,CAAC;AAyBxD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,MA2JzB,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { STICKER_DEFAULT_OPTIONS } from '@sealpixel/plugins';
|
|
2
|
+
import { html, nothing, svg } from 'lit';
|
|
3
|
+
import { icons } from '../icons.js';
|
|
4
|
+
import { deleteHandle, toPx } from './delete-handle.js';
|
|
5
|
+
import { opId } from './finetune.js';
|
|
6
|
+
const state = {
|
|
7
|
+
selected: null,
|
|
8
|
+
drag: null,
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Stickers live in crop space, so the normal (cropped) preview is the right
|
|
12
|
+
* stage. Assets come from the plugin's declarations or from an upload, which
|
|
13
|
+
* is registered on the session and recorded in the log.
|
|
14
|
+
*/
|
|
15
|
+
export const stickerTool = {
|
|
16
|
+
id: 'sticker',
|
|
17
|
+
icon: icons.sticker,
|
|
18
|
+
label: 'tool.sticker',
|
|
19
|
+
deactivate: () => {
|
|
20
|
+
state.selected = null;
|
|
21
|
+
state.drag = null;
|
|
22
|
+
},
|
|
23
|
+
panel: (ctx) => {
|
|
24
|
+
const doc = ctx.document.sticker;
|
|
25
|
+
const options = ctx.options('sticker') ?? STICKER_DEFAULT_OPTIONS;
|
|
26
|
+
const declared = options.library.length > 0
|
|
27
|
+
? options.library
|
|
28
|
+
: (ctx.session.registry.byId.get('sticker')?.assets ?? []);
|
|
29
|
+
const uploaded = options.upload ? (ctx.state.history.log.assets ?? []) : [];
|
|
30
|
+
const full = options.max !== null && doc.items.length >= options.max;
|
|
31
|
+
const labelOf = (a) => a.label ?? a.id.replace(/^sticker\./, '');
|
|
32
|
+
const sel = doc.items.find((i) => i.id === state.selected) ?? null;
|
|
33
|
+
const add = (asset) => {
|
|
34
|
+
const id = opId();
|
|
35
|
+
ctx.dispatch({
|
|
36
|
+
type: 'sticker.add',
|
|
37
|
+
id,
|
|
38
|
+
asset,
|
|
39
|
+
rect: { x: 0.35, y: 0.35, width: 0.3, height: 0.3 },
|
|
40
|
+
});
|
|
41
|
+
state.selected = id;
|
|
42
|
+
};
|
|
43
|
+
const update = (patch) => sel && ctx.dispatch({ type: 'sticker.update', id: opId(), itemId: sel.id, ...patch });
|
|
44
|
+
const upload = async (e) => {
|
|
45
|
+
const file = e.target.files?.[0];
|
|
46
|
+
if (!file)
|
|
47
|
+
return;
|
|
48
|
+
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
49
|
+
const decl = await ctx.session.addAsset(bytes, {
|
|
50
|
+
id: `sticker.${file.name
|
|
51
|
+
.replace(/\.[^.]+$/, '')
|
|
52
|
+
.replace(/[^a-z0-9-]/gi, '-')
|
|
53
|
+
.toLowerCase()}`,
|
|
54
|
+
});
|
|
55
|
+
add(decl.id);
|
|
56
|
+
};
|
|
57
|
+
return html `
|
|
58
|
+
${options.upload
|
|
59
|
+
? html `<label class="field">
|
|
60
|
+
<span>${ctx.t('sticker.upload')}</span>
|
|
61
|
+
<input data-field="upload" type="file" accept="image/png,image/jpeg,image/webp" ?disabled=${full} @change=${upload} />
|
|
62
|
+
</label>`
|
|
63
|
+
: nothing}
|
|
64
|
+
${declared.length + uploaded.length > 0
|
|
65
|
+
? html `<div class="grid choice" role="list" aria-label=${ctx.t('sticker.library')}>
|
|
66
|
+
${[...declared, ...uploaded].map((a) => html `<sealpixel-button role="listitem" data-asset=${a.id} ?disabled=${full} @click=${() => add(a.id)}>${labelOf(a)}</sealpixel-button>`)}
|
|
67
|
+
</div>`
|
|
68
|
+
: html `<p class="hint">${ctx.t('sticker.hint.empty')}</p>`}
|
|
69
|
+
${sel
|
|
70
|
+
? html `
|
|
71
|
+
<sealpixel-slider data-param="rotation" .label=${ctx.t('sticker.rotation')} .value=${Number(((sel.rotation * 180) / Math.PI).toFixed(1))} .min=${-180} .max=${180} .step=${1} .format=${(v) => `${v.toFixed(0)}°`} @commit=${(e) => update({ rotation: (e.detail * Math.PI) / 180 })}></sealpixel-slider>
|
|
72
|
+
<sealpixel-slider data-param="opacity" .label=${ctx.t('sticker.opacity')} .value=${sel.opacity} .min=${0} .max=${1} .step=${0.01} @commit=${(e) => update({ opacity: e.detail })}></sealpixel-slider>
|
|
73
|
+
<div class="row">
|
|
74
|
+
<sealpixel-button data-action="flip-x" ?pressed=${sel.flipX} @click=${() => update({ flipX: !sel.flipX })}>⇋</sealpixel-button>
|
|
75
|
+
<sealpixel-button data-action="flip-y" ?pressed=${sel.flipY} @click=${() => update({ flipY: !sel.flipY })}>⇅</sealpixel-button>
|
|
76
|
+
</div>
|
|
77
|
+
`
|
|
78
|
+
: null}
|
|
79
|
+
`;
|
|
80
|
+
},
|
|
81
|
+
overlay: (ctx) => {
|
|
82
|
+
const doc = ctx.document.sticker;
|
|
83
|
+
const { width: W, height: H, zoom } = ctx.stage;
|
|
84
|
+
if (!W || !H)
|
|
85
|
+
return svg ``;
|
|
86
|
+
const sw = 1.5 / zoom;
|
|
87
|
+
const hr = 7 / zoom;
|
|
88
|
+
const toN = (e) => {
|
|
89
|
+
const p = ctx.stage.toImage(e.clientX, e.clientY);
|
|
90
|
+
return [p.x / W, p.y / H];
|
|
91
|
+
};
|
|
92
|
+
const begin = (item, mode) => (e) => {
|
|
93
|
+
e.stopPropagation();
|
|
94
|
+
e.preventDefault();
|
|
95
|
+
state.selected = item.id;
|
|
96
|
+
const start = toN(e);
|
|
97
|
+
state.drag = { id: item.id, rect: item.rect, mode, start };
|
|
98
|
+
const move = (ev) => {
|
|
99
|
+
if (!state.drag)
|
|
100
|
+
return;
|
|
101
|
+
const q = toN(ev);
|
|
102
|
+
const dx = q[0] - start[0];
|
|
103
|
+
const dy = q[1] - start[1];
|
|
104
|
+
state.drag.rect =
|
|
105
|
+
mode === 'move'
|
|
106
|
+
? { ...item.rect, x: item.rect.x + dx, y: item.rect.y + dy }
|
|
107
|
+
: {
|
|
108
|
+
...item.rect,
|
|
109
|
+
width: Math.max(0.02, item.rect.width + dx),
|
|
110
|
+
height: Math.max(0.02, item.rect.height + dy),
|
|
111
|
+
};
|
|
112
|
+
ctx.refresh();
|
|
113
|
+
};
|
|
114
|
+
const up = () => {
|
|
115
|
+
window.removeEventListener('pointermove', move);
|
|
116
|
+
window.removeEventListener('pointerup', up);
|
|
117
|
+
window.removeEventListener('pointercancel', up);
|
|
118
|
+
const d = state.drag;
|
|
119
|
+
state.drag = null;
|
|
120
|
+
if (d && JSON.stringify(d.rect) !== JSON.stringify(item.rect)) {
|
|
121
|
+
ctx.dispatch({ type: 'sticker.update', id: opId(), itemId: item.id, rect: d.rect });
|
|
122
|
+
}
|
|
123
|
+
ctx.refresh();
|
|
124
|
+
};
|
|
125
|
+
window.addEventListener('pointermove', move);
|
|
126
|
+
window.addEventListener('pointerup', up);
|
|
127
|
+
window.addEventListener('pointercancel', up);
|
|
128
|
+
};
|
|
129
|
+
const selectedItem = doc.items.find((i) => i.id === state.selected) ?? null;
|
|
130
|
+
return svg `
|
|
131
|
+
<rect data-interactive x="0" y="0" width=${W} height=${H} fill="transparent" @pointerdown=${(e) => {
|
|
132
|
+
e.stopPropagation();
|
|
133
|
+
state.selected = null;
|
|
134
|
+
ctx.refresh();
|
|
135
|
+
}} />
|
|
136
|
+
${doc.items.map((item) => {
|
|
137
|
+
const r = state.drag?.id === item.id ? state.drag.rect : item.rect;
|
|
138
|
+
const selected = state.selected === item.id;
|
|
139
|
+
const cx = (r.x + r.width / 2) * W;
|
|
140
|
+
const cy = (r.y + r.height / 2) * H;
|
|
141
|
+
const deg = (item.rotation * 180) / Math.PI;
|
|
142
|
+
return svg `<g transform=${`rotate(${deg} ${cx} ${cy})`}>
|
|
143
|
+
<rect data-interactive data-item=${item.id} x=${r.x * W} y=${r.y * H} width=${r.width * W} height=${r.height * H} fill="rgba(255,255,255,0.001)" stroke=${selected ? 'var(--sealpixel-color-accent)' : 'rgba(255,255,255,0.6)'} stroke-width=${sw} stroke-dasharray=${selected ? 'none' : `${4 / zoom} ${3 / zoom}`} style="cursor:move" @pointerdown=${begin(item, 'move')} />
|
|
144
|
+
${selected ? svg `<circle data-interactive data-handle="scale" cx=${(r.x + r.width) * W} cy=${(r.y + r.height) * H} r=${hr} fill="white" stroke="var(--sealpixel-color-accent)" stroke-width=${sw} style="cursor:nwse-resize" @pointerdown=${begin(item, 'scale')} />` : null}
|
|
145
|
+
</g>`;
|
|
146
|
+
})}
|
|
147
|
+
${selectedItem
|
|
148
|
+
? deleteHandle(toPx(state.drag?.id === selectedItem.id ? state.drag.rect : selectedItem.rect, W, H), ctx.stage, ctx.t('sticker.delete'), () => {
|
|
149
|
+
state.selected = null;
|
|
150
|
+
ctx.dispatch({ type: 'sticker.remove', id: opId(), itemId: selectedItem.id });
|
|
151
|
+
})
|
|
152
|
+
: nothing}
|
|
153
|
+
`;
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=sticker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sticker.js","sourceRoot":"","sources":["../../src/tools/sticker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watermark.d.ts","sourceRoot":"","sources":["../../src/tools/watermark.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,YAAY,CAAC;AAkCxD,eAAO,MAAM,aAAa,EAAE,MAkF3B,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { WATERMARK_DEFAULT_OPTIONS } from '@sealpixel/plugins';
|
|
2
|
+
import { html, nothing } from 'lit';
|
|
3
|
+
import { icons } from '../icons.js';
|
|
4
|
+
import { opId } from './finetune.js';
|
|
5
|
+
const ANCHORS = ['tl', 'tc', 'tr', 'cl', 'c', 'cr', 'bl', 'bc', 'br'];
|
|
6
|
+
const hex = (c) => `#${[c[0], c[1], c[2]]
|
|
7
|
+
.map((v) => Math.round(v * 255)
|
|
8
|
+
.toString(16)
|
|
9
|
+
.padStart(2, '0'))
|
|
10
|
+
.join('')}`;
|
|
11
|
+
const fromHex = (h, a = 1) => [
|
|
12
|
+
Number.parseInt(h.slice(1, 3), 16) / 255,
|
|
13
|
+
Number.parseInt(h.slice(3, 5), 16) / 255,
|
|
14
|
+
Number.parseInt(h.slice(5, 7), 16) / 255,
|
|
15
|
+
a,
|
|
16
|
+
];
|
|
17
|
+
export const watermarkTool = {
|
|
18
|
+
id: 'watermark',
|
|
19
|
+
icon: icons.watermark,
|
|
20
|
+
label: 'tool.watermark',
|
|
21
|
+
panel: (ctx) => {
|
|
22
|
+
const wm = ctx.document.watermark.watermark;
|
|
23
|
+
const set = (patch) => ctx.dispatch({ type: 'watermark.set', id: opId(), ...patch });
|
|
24
|
+
const text = wm?.source.kind === 'text' ? wm.source : null;
|
|
25
|
+
const options = ctx.options('watermark') ?? WATERMARK_DEFAULT_OPTIONS;
|
|
26
|
+
const declared = options.image
|
|
27
|
+
? [
|
|
28
|
+
...(ctx.session.registry.byId.get('watermark')?.assets ?? []),
|
|
29
|
+
...(ctx.session.registry.byId.get('sticker')?.assets ?? []),
|
|
30
|
+
...(ctx.state.history.log.assets ?? []),
|
|
31
|
+
]
|
|
32
|
+
: [];
|
|
33
|
+
const fonts = ctx.session.registry.byId.get('annotate')?.assets ?? [];
|
|
34
|
+
const defaultFont = fonts[0]?.id ?? 'font.roboto';
|
|
35
|
+
const d = options.defaults;
|
|
36
|
+
const fresh = wm === null
|
|
37
|
+
? {
|
|
38
|
+
...(d.anchor ? { anchor: d.anchor } : {}),
|
|
39
|
+
...(d.margin !== undefined ? { margin: d.margin } : {}),
|
|
40
|
+
...(d.scale !== undefined ? { scale: d.scale } : {}),
|
|
41
|
+
...(d.opacity !== undefined ? { opacity: d.opacity } : {}),
|
|
42
|
+
...(d.tile !== undefined ? { tile: d.tile } : {}),
|
|
43
|
+
}
|
|
44
|
+
: {};
|
|
45
|
+
const anchors = ANCHORS.filter((a) => options.anchors.includes(a));
|
|
46
|
+
if (options.lock) {
|
|
47
|
+
return html `<p class="hint" data-locked>${ctx.t('watermark.locked')}</p>`;
|
|
48
|
+
}
|
|
49
|
+
return html `
|
|
50
|
+
<div class="row choice">
|
|
51
|
+
${options.text
|
|
52
|
+
? html `<sealpixel-button data-source="text" ?pressed=${text !== null} @click=${() => set({ ...fresh, source: { kind: 'text', text: text?.text ?? ctx.t('watermark.defaultText'), font: text?.font ?? defaultFont, color: text?.color ?? [1, 1, 1, 1] } })}>${ctx.t('watermark.text')}</sealpixel-button>`
|
|
53
|
+
: nothing}
|
|
54
|
+
${declared.map((a) => html `<sealpixel-button data-source=${a.id} ?pressed=${wm?.source.kind === 'asset' && wm.source.asset === a.id} @click=${() => set({ ...fresh, source: { kind: 'asset', asset: a.id } })}>${a.label ?? a.id.replace(/^(sticker|asset|watermark)\./, '')}</sealpixel-button>`)}
|
|
55
|
+
${wm ? html `<sealpixel-button data-action="clear" variant="ghost" @click=${() => ctx.dispatch({ type: 'watermark.clear', id: opId() })}>${ctx.t('watermark.clear')}</sealpixel-button>` : null}
|
|
56
|
+
</div>
|
|
57
|
+
${wm
|
|
58
|
+
? html `
|
|
59
|
+
<div class="rows">
|
|
60
|
+
${text
|
|
61
|
+
? html `<label class="field"><span>${ctx.t('watermark.textValue')}</span><input data-field="text" type="text" .value=${text.text} @change=${(e) => set({ source: { ...text, text: e.target.value || ' ' } })} /></label>
|
|
62
|
+
<label class="field"><span>${ctx.t('watermark.color')}</span><input data-field="color" type="color" .value=${hex(text.color)} @change=${(e) => set({ source: { ...text, color: fromHex(e.target.value) } })} /></label>`
|
|
63
|
+
: null}
|
|
64
|
+
<label class="field">
|
|
65
|
+
<span>${ctx.t('watermark.anchor')}</span>
|
|
66
|
+
<select
|
|
67
|
+
data-field="anchor"
|
|
68
|
+
?disabled=${wm.tile !== null}
|
|
69
|
+
@change=${(e) => set({ anchor: e.target.value })}
|
|
70
|
+
>
|
|
71
|
+
${anchors.map((a) => html `<option data-anchor=${a} value=${a} ?selected=${wm.anchor === a}>${ANCHOR_GLYPH[a]} ${ctx.t(`watermark.anchor.${a}`)}</option>`)}
|
|
72
|
+
</select>
|
|
73
|
+
</label>
|
|
74
|
+
<sealpixel-slider data-param="scale" .label=${ctx.t('watermark.scale')} .value=${wm.scale} .min=${options.scaleRange.min} .max=${options.scaleRange.max} .step=${options.scaleRange.step} .format=${(v) => `${Math.round(v * 100)}%`} @commit=${(e) => set({ scale: e.detail })}></sealpixel-slider>
|
|
75
|
+
${
|
|
76
|
+
// Tiling repeats the mark across the image, so there is no edge
|
|
77
|
+
// to keep a margin from; the gap between repeats replaces it.
|
|
78
|
+
wm.tile
|
|
79
|
+
? html `<sealpixel-slider data-param="tile-rotation" .label=${ctx.t('watermark.tileRotation')} .value=${Number(((wm.tile.rotation * 180) / Math.PI).toFixed(0))} .min=${-90} .max=${90} .step=${1} .format=${(v) => `${v.toFixed(0)}°`} @commit=${(e) => set({ tile: { ...wm.tile, rotation: (e.detail * Math.PI) / 180 } })}></sealpixel-slider>
|
|
80
|
+
<sealpixel-stepper data-param="tile-gap" .label=${ctx.t('watermark.tileGap')} .value=${wm.tile.gapX} .min=${0} .max=${400} .step=${1} unit="px" @commit=${(e) => set({ tile: { ...wm.tile, gapX: e.detail, gapY: e.detail } })}></sealpixel-stepper>`
|
|
81
|
+
: html `<sealpixel-stepper data-param="margin" .label=${ctx.t('watermark.margin')} .value=${wm.margin} .min=${0} .max=${200} .step=${1} unit="px" @commit=${(e) => set({ margin: e.detail })}></sealpixel-stepper>`}
|
|
82
|
+
<label class="field check">
|
|
83
|
+
<input data-field="tile" type="checkbox" .checked=${wm.tile !== null} @change=${(e) => set({ tile: e.target.checked ? { gapX: 24, gapY: 24, rotation: -0.4 } : null })} />
|
|
84
|
+
<span>${ctx.t('watermark.tile')}</span>
|
|
85
|
+
</label>
|
|
86
|
+
</div>`
|
|
87
|
+
: null}
|
|
88
|
+
`;
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
const ANCHOR_GLYPH = {
|
|
92
|
+
tl: '↖',
|
|
93
|
+
tc: '↑',
|
|
94
|
+
tr: '↗',
|
|
95
|
+
cl: '←',
|
|
96
|
+
c: '•',
|
|
97
|
+
cr: '→',
|
|
98
|
+
bl: '↙',
|
|
99
|
+
bc: '↓',
|
|
100
|
+
br: '↘',
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=watermark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watermark.js","sourceRoot":"","sources":["../../src/tools/watermark.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Geometry } from '@sealpixel/core';
|
|
2
|
+
/** SVG-style affine: x' = a·x + c·y + e, y' = b·x + d·y + f. */
|
|
3
|
+
export type Affine = [number, number, number, number, number, number];
|
|
4
|
+
export declare const IDENTITY: Affine;
|
|
5
|
+
/** `outer ∘ inner`: applies `inner` first. */
|
|
6
|
+
export declare function compose(outer: Affine, inner: Affine): Affine;
|
|
7
|
+
export declare function apply(m: Affine, x: number, y: number): {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function invert(m: Affine): Affine;
|
|
12
|
+
/** Uniform scale factor of the affine (√|det|): source px per preview px. */
|
|
13
|
+
export declare function scaleOf(m: Affine): number;
|
|
14
|
+
export declare function sameAffine(a: Affine | null, b: Affine | null, eps?: number): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Maps preview (proxy output) pixels of the rendered log back to logical
|
|
17
|
+
* source pixels, walking the stage geometry in reverse. Crop supplies its
|
|
18
|
+
* inverse affine, resize a scale or (with cover) a source rectangle; every
|
|
19
|
+
* other stage keeps its size. The stage uses it to keep the same source
|
|
20
|
+
* region in view when the preview switches between cropped and uncropped.
|
|
21
|
+
*/
|
|
22
|
+
export declare function previewToSource(g: Geometry): Affine;
|
|
23
|
+
//# sourceMappingURL=view-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-mapping.d.ts","sourceRoot":"","sources":["../src/view-mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,gEAAgE;AAChE,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtE,eAAO,MAAM,QAAQ,EAAE,MAA2B,CAAC;AAEnD,8CAA8C;AAC9C,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAW5D;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAE/E;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CASxC;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,SAAO,GAAG,OAAO,CAGlF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAsBnD"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export const IDENTITY = [1, 0, 0, 1, 0, 0];
|
|
2
|
+
/** `outer ∘ inner`: applies `inner` first. */
|
|
3
|
+
export function compose(outer, inner) {
|
|
4
|
+
const [a1, b1, c1, d1, e1, f1] = outer;
|
|
5
|
+
const [a2, b2, c2, d2, e2, f2] = inner;
|
|
6
|
+
return [
|
|
7
|
+
a1 * a2 + c1 * b2,
|
|
8
|
+
b1 * a2 + d1 * b2,
|
|
9
|
+
a1 * c2 + c1 * d2,
|
|
10
|
+
b1 * c2 + d1 * d2,
|
|
11
|
+
a1 * e2 + c1 * f2 + e1,
|
|
12
|
+
b1 * e2 + d1 * f2 + f1,
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
export function apply(m, x, y) {
|
|
16
|
+
return { x: m[0] * x + m[2] * y + m[4], y: m[1] * x + m[3] * y + m[5] };
|
|
17
|
+
}
|
|
18
|
+
export function invert(m) {
|
|
19
|
+
const [a, b, c, d, e, f] = m;
|
|
20
|
+
const det = a * d - b * c;
|
|
21
|
+
if (!det)
|
|
22
|
+
return IDENTITY;
|
|
23
|
+
const ia = d / det;
|
|
24
|
+
const ib = -b / det;
|
|
25
|
+
const ic = -c / det;
|
|
26
|
+
const id = a / det;
|
|
27
|
+
return [ia, ib, ic, id, -(ia * e + ic * f), -(ib * e + id * f)];
|
|
28
|
+
}
|
|
29
|
+
/** Uniform scale factor of the affine (√|det|): source px per preview px. */
|
|
30
|
+
export function scaleOf(m) {
|
|
31
|
+
return Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])) || 1;
|
|
32
|
+
}
|
|
33
|
+
export function sameAffine(a, b, eps = 1e-6) {
|
|
34
|
+
if (!a || !b)
|
|
35
|
+
return a === b;
|
|
36
|
+
return a.every((v, i) => Math.abs(v - b[i]) < eps);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Maps preview (proxy output) pixels of the rendered log back to logical
|
|
40
|
+
* source pixels, walking the stage geometry in reverse. Crop supplies its
|
|
41
|
+
* inverse affine, resize a scale or (with cover) a source rectangle; every
|
|
42
|
+
* other stage keeps its size. The stage uses it to keep the same source
|
|
43
|
+
* region in view when the preview switches between cropped and uncropped.
|
|
44
|
+
*/
|
|
45
|
+
export function previewToSource(g) {
|
|
46
|
+
let m = IDENTITY;
|
|
47
|
+
for (const s of [...g.stages].reverse()) {
|
|
48
|
+
let step;
|
|
49
|
+
if (s.transform)
|
|
50
|
+
step = s.transform;
|
|
51
|
+
else if (s.cropRect) {
|
|
52
|
+
const [x, y, w, h] = s.cropRect;
|
|
53
|
+
step = [w / s.actualOut.width, 0, 0, h / s.actualOut.height, x, y];
|
|
54
|
+
}
|
|
55
|
+
else if (s.actualIn.width !== s.actualOut.width || s.actualIn.height !== s.actualOut.height) {
|
|
56
|
+
step = [
|
|
57
|
+
s.actualIn.width / s.actualOut.width,
|
|
58
|
+
0,
|
|
59
|
+
0,
|
|
60
|
+
s.actualIn.height / s.actualOut.height,
|
|
61
|
+
0,
|
|
62
|
+
0,
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
continue;
|
|
67
|
+
m = compose(step, m);
|
|
68
|
+
}
|
|
69
|
+
const k = 1 / (g.scale || 1);
|
|
70
|
+
return compose([k, 0, 0, k, 0, 0], m);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=view-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-mapping.js","sourceRoot":"","sources":["../src/view-mapping.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sealpixel/ui",
|
|
3
|
+
"version": "1.0.0-rc.0",
|
|
4
|
+
"description": "Default, themeable Sealpixel editor UI as Web Components (Lit). Optional: the core is headless.",
|
|
5
|
+
"license": "BUSL-1.1",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/9feet/sealpixel.git",
|
|
9
|
+
"directory": "packages/ui"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://docs.sealpixel.dev",
|
|
12
|
+
"bugs": "https://github.com/9feet/sealpixel/issues",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"sideEffects": [
|
|
15
|
+
"./dist/components/*.js",
|
|
16
|
+
"./dist/define.js"
|
|
17
|
+
],
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"themes",
|
|
21
|
+
"README.md"
|
|
22
|
+
],
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./define": {
|
|
29
|
+
"types": "./dist/define.d.ts",
|
|
30
|
+
"default": "./dist/define.js"
|
|
31
|
+
},
|
|
32
|
+
"./locales/*": {
|
|
33
|
+
"default": "./dist/locales/*.js"
|
|
34
|
+
},
|
|
35
|
+
"./package.json": "./package.json",
|
|
36
|
+
"./themes/*": "./themes/*"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"lit": "^3.3.0",
|
|
40
|
+
"@sealpixel/core": "1.0.0-rc.0",
|
|
41
|
+
"@sealpixel/plugins": "1.0.0-rc.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^24.0.0",
|
|
45
|
+
"typescript": "^5.9.0",
|
|
46
|
+
"vitest": "^4.0.0",
|
|
47
|
+
"@sealpixel/wasm": "1.0.0-rc.0",
|
|
48
|
+
"@sealpixel/config": "0.0.0"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsc -p tsconfig.build.json",
|
|
52
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
53
|
+
"test": "vitest run"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* Default tokens (graphite + coral). Included in the component; here for hosts that want the values as a starting point. */
|
|
2
|
+
sealpixel-editor {
|
|
3
|
+
--sealpixel-color-bg: #0f1117;
|
|
4
|
+
--sealpixel-color-surface: #161923;
|
|
5
|
+
--sealpixel-color-surface-2: #1f2330;
|
|
6
|
+
--sealpixel-color-surface-3: #2a2f3d;
|
|
7
|
+
--sealpixel-color-border: #2b3040;
|
|
8
|
+
--sealpixel-color-fg: #eef0f6;
|
|
9
|
+
--sealpixel-color-fg-muted: #a3a9b8;
|
|
10
|
+
--sealpixel-color-accent: #ff6f4c;
|
|
11
|
+
--sealpixel-color-accent-fg: #1c0d08;
|
|
12
|
+
--sealpixel-color-accent-soft: rgba(255, 111, 76, 0.16);
|
|
13
|
+
--sealpixel-color-danger: #ef5a5a;
|
|
14
|
+
--sealpixel-color-focus: #ff9b7e;
|
|
15
|
+
--sealpixel-radius: 12px;
|
|
16
|
+
--sealpixel-radius-sm: 8px;
|
|
17
|
+
--sealpixel-space: 8px;
|
|
18
|
+
--sealpixel-font: "Inter", system-ui, sans-serif;
|
|
19
|
+
--sealpixel-font-size: 14px;
|
|
20
|
+
--sealpixel-toolbar-size: 72px;
|
|
21
|
+
--sealpixel-panel-size: 112px;
|
|
22
|
+
--sealpixel-touch-target: 44px;
|
|
23
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* High contrast: WCAG AAA text contrast, thick focus rings, no translucency. */
|
|
2
|
+
sealpixel-editor {
|
|
3
|
+
--sealpixel-color-bg: #000000;
|
|
4
|
+
--sealpixel-color-surface: #000000;
|
|
5
|
+
--sealpixel-color-surface-2: #1a1a1a;
|
|
6
|
+
--sealpixel-color-surface-3: #333333;
|
|
7
|
+
--sealpixel-color-accent-soft: #333300;
|
|
8
|
+
--sealpixel-shadow: none;
|
|
9
|
+
--sealpixel-shadow-sm: none;
|
|
10
|
+
--sealpixel-shadow-raised: none;
|
|
11
|
+
--sealpixel-color-border: #ffffff;
|
|
12
|
+
--sealpixel-color-fg: #ffffff;
|
|
13
|
+
--sealpixel-color-fg-muted: #ffff00;
|
|
14
|
+
--sealpixel-color-accent: #ffff00;
|
|
15
|
+
--sealpixel-color-accent-fg: #000000;
|
|
16
|
+
--sealpixel-color-danger: #ff6666;
|
|
17
|
+
--sealpixel-color-focus: #00ffff;
|
|
18
|
+
--sealpixel-radius: 4px;
|
|
19
|
+
--sealpixel-radius-sm: 2px;
|
|
20
|
+
--sealpixel-font-size: 16px;
|
|
21
|
+
--sealpixel-touch-target: 48px;
|
|
22
|
+
--sealpixel-stage-checker-a: #333333;
|
|
23
|
+
--sealpixel-stage-checker-b: #000000;
|
|
24
|
+
color-scheme: dark;
|
|
25
|
+
}
|
|
26
|
+
sealpixel-editor *:focus-visible,
|
|
27
|
+
sealpixel-editor::part(button):focus-visible {
|
|
28
|
+
outline: 3px solid #00ffff;
|
|
29
|
+
outline-offset: 3px;
|
|
30
|
+
}
|