@lvl99dotcom/paintcanvas 0.5.0 → 0.7.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 +2 -2
- package/dist/lib/brushes/configRanges/index.d.ts +17 -0
- package/dist/lib/brushes/configRanges/index.js +31 -1
- package/dist/lib/brushes/params/index.d.ts +2 -1
- package/dist/lib/brushes/params/index.js +7 -4
- package/dist/lib/brushes/types/index.d.ts +8 -0
- package/dist/lib/classes/Layer/index.d.ts +10 -0
- package/dist/lib/classes/Layer/index.js +15 -1
- package/dist/lib/classes/LayerAutosave/index.d.ts +9 -15
- package/dist/lib/classes/LayerAutosave/index.js +30 -43
- package/dist/lib/classes/LayerStack/index.d.ts +15 -0
- package/dist/lib/classes/LayerStack/index.js +26 -2
- package/dist/lib/classes/PaintCanvas/index.d.ts +36 -5
- package/dist/lib/classes/PaintCanvas/index.js +45 -14
- package/dist/lib/classes/PngEncoder/index.d.ts +41 -0
- package/dist/lib/classes/PngEncoder/index.js +104 -0
- package/dist/lib/classes/ProfileGraphs/index.d.ts +87 -0
- package/dist/lib/classes/ProfileGraphs/index.js +148 -0
- package/dist/lib/classes/SettingsAutosave/index.d.ts +1 -1
- package/dist/lib/classes/SettingsAutosave/index.js +2 -1
- package/dist/lib/classes/UiSettings/index.d.ts +24 -2
- package/dist/lib/classes/UiSettings/index.js +32 -7
- package/dist/lib/messages/schema.d.ts +720 -0
- package/dist/lib/presets/schema.d.ts +360 -0
- package/dist/lib/presets/schema.js +8 -1
- package/dist/lib/profiles/index.d.ts +61 -0
- package/dist/lib/profiles/index.js +131 -0
- package/dist/lib/profiles/schema.d.ts +73 -0
- package/dist/lib/profiles/schema.js +53 -0
- package/dist/lib/rendering/sample/index.d.ts +11 -0
- package/dist/lib/rendering/sample/index.js +36 -5
- package/dist/lib/settings/index.d.ts +2 -1
- package/dist/lib/settings/index.js +4 -1
- package/dist/lib/settings/schema.d.ts +53 -1
- package/dist/lib/settings/schema.js +9 -2
- package/dist/lib/storage/index.d.ts +26 -0
- package/dist/lib/storage/index.js +38 -1
- package/dist/lib/validation/validators.generated.js +13061 -3675
- package/dist/lib/version/index.d.ts +25 -0
- package/dist/lib/version/index.js +35 -0
- package/dist/locales/en-GB.js +35 -0
- package/dist/locales/en-US.js +35 -0
- package/dist/locales/fr.js +35 -0
- package/dist/locales/ja.js +35 -0
- package/dist/locales/ko.js +35 -0
- package/dist/locales/zh-Hans.js +35 -0
- package/dist/locales/zh-Hant.js +35 -0
- package/dist/package.js +1 -1
- package/dist/ui/ask/index.d.ts +48 -0
- package/dist/ui/ask/index.js +67 -0
- package/dist/ui/base/index.d.ts +8 -1
- package/dist/ui/base/index.js +19 -4
- package/dist/ui/elements/PaintCanvas/index.d.ts +13 -3
- package/dist/ui/elements/PaintCanvas/index.js +25 -6
- package/dist/ui/elements/PaintCanvas/style.js +1 -1
- package/dist/ui/elements/PcAppSettings/index.d.ts +15 -7
- package/dist/ui/elements/PcAppSettings/index.js +53 -62
- package/dist/ui/elements/PcBrushConfig/index.d.ts +26 -14
- package/dist/ui/elements/PcBrushConfig/index.js +214 -145
- package/dist/ui/elements/PcBrushConfig/style.js +1 -1
- package/dist/ui/elements/PcBrushTest/index.d.ts +1 -0
- package/dist/ui/elements/PcBrushTest/index.js +15 -9
- package/dist/ui/elements/PcBrushTest/style.js +1 -1
- package/dist/ui/elements/PcButton/index.d.ts +12 -3
- package/dist/ui/elements/PcButton/index.js +18 -10
- package/dist/ui/elements/PcButtonMenu/index.d.ts +88 -0
- package/dist/ui/elements/PcButtonMenu/index.js +125 -0
- package/dist/ui/elements/PcCanvas/index.d.ts +15 -1
- package/dist/ui/elements/PcCanvas/index.js +42 -19
- package/dist/ui/elements/PcCanvas/style.js +1 -1
- package/dist/ui/elements/PcClipboardTools/index.d.ts +11 -7
- package/dist/ui/elements/PcClipboardTools/index.js +30 -29
- package/dist/ui/elements/PcDialog/index.d.ts +46 -10
- package/dist/ui/elements/PcDialog/index.js +102 -51
- package/dist/ui/elements/PcDialogWindow/index.d.ts +141 -0
- package/dist/ui/elements/PcDialogWindow/index.js +385 -0
- package/dist/ui/elements/PcInputSettings/index.d.ts +2 -1
- package/dist/ui/elements/PcInputSettings/index.js +9 -15
- package/dist/ui/elements/PcLayerItem/index.d.ts +21 -6
- package/dist/ui/elements/PcLayerItem/index.js +53 -26
- package/dist/ui/elements/PcLayerItem/style.js +1 -1
- package/dist/ui/elements/PcPanelBrushes/index.d.ts +3 -2
- package/dist/ui/elements/PcPanelBrushes/index.js +7 -5
- package/dist/ui/elements/PcPanelBrushes/style.js +1 -1
- package/dist/ui/elements/PcPanelColours/index.js +2 -2
- package/dist/ui/elements/PcPanelColours/style.js +1 -1
- package/dist/ui/elements/PcPanelLayers/index.js +1 -1
- package/dist/ui/elements/PcPanelLayers/style.js +1 -1
- package/dist/ui/elements/PcProfileEditor/index.d.ts +103 -0
- package/dist/ui/elements/PcProfileEditor/index.js +259 -0
- package/dist/ui/elements/PcProfileGraph/index.d.ts +84 -0
- package/dist/ui/elements/PcProfileGraph/index.js +317 -0
- package/dist/ui/elements/PcShortcutSettings/index.js +9 -13
- package/dist/ui/elements/PcSliderRange/index.d.ts +147 -0
- package/dist/ui/elements/PcSliderRange/index.js +308 -0
- package/dist/ui/elements/PcStats/index.d.ts +19 -4
- package/dist/ui/elements/PcStats/index.js +29 -13
- package/dist/ui/elements/PcToggleCheckbox/index.d.ts +13 -2
- package/dist/ui/elements/PcToggleCheckbox/index.js +27 -8
- package/dist/ui/elements/PcToolSettings/index.d.ts +1 -0
- package/dist/ui/elements/PcToolSettings/index.js +14 -14
- package/dist/ui/elements/PcVersion/index.d.ts +12 -0
- package/dist/ui/elements/PcVersion/index.js +43 -0
- package/dist/ui/icons/images/icon-profile-graph@2x.js +3 -0
- package/dist/ui/icons/index.d.ts +1 -1
- package/dist/ui/icons/index.js +2 -0
- package/dist/ui/index.d.ts +9 -2
- package/dist/ui/index.js +9 -2
- package/dist/ui/layout/index.d.ts +2 -2
- package/dist/ui/layout/index.js +2 -2
- package/dist/ui/styles/index.d.ts +21 -1
- package/dist/ui/styles/index.js +73 -14
- package/locales/en-GB.json +35 -0
- package/locales/en-US.json +35 -0
- package/locales/fr.json +35 -0
- package/locales/ja.json +35 -0
- package/locales/ko.json +35 -0
- package/locales/zh-Hans.json +35 -0
- package/locales/zh-Hant.json +35 -0
- package/package.json +25 -23
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { PcElement } from "../../base";
|
|
2
|
+
import { type PillSize } from "../../styles";
|
|
2
3
|
import "../PcIcon";
|
|
3
4
|
/** How a button looks */
|
|
4
5
|
export type ButtonVariant = "accent" | "cancel" | "dismiss" | "pill" | "icon";
|
|
5
6
|
/**
|
|
6
|
-
* A button: affirmative (`accent`, the default), cancelling (`cancel`), a quiet text button (`dismiss`), a
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* A button: affirmative (`accent`, the default), cancelling (`cancel`), a quiet text button (`dismiss`), a pill (`pill`,
|
|
8
|
+
* the same as `accent`), or a boxed icon button (`icon`, which needs a `label` for screen readers). Its text goes in its
|
|
9
|
+
* content. All but icon buttons are pills, of the `size` given (`pill` by default; see `PILL_SIZE_STYLES`). Clicks
|
|
10
|
+
* reach listeners on the element; a disabled button sends none.
|
|
9
11
|
*
|
|
10
12
|
* @example
|
|
11
13
|
* html`<pc-button variant="cancel" @click=${close}>Cancel</pc-button>`
|
|
14
|
+
* html`<pc-button size="pill-l">Start</pc-button>`
|
|
12
15
|
* html`<pc-button variant="icon" icon="undo" label="Undo"></pc-button>`
|
|
13
16
|
*/
|
|
14
17
|
export declare class PcButton extends PcElement {
|
|
@@ -17,6 +20,10 @@ export declare class PcButton extends PcElement {
|
|
|
17
20
|
type: StringConstructor;
|
|
18
21
|
reflect: boolean;
|
|
19
22
|
};
|
|
23
|
+
size: {
|
|
24
|
+
type: StringConstructor;
|
|
25
|
+
reflect: boolean;
|
|
26
|
+
};
|
|
20
27
|
icon: {
|
|
21
28
|
type: StringConstructor;
|
|
22
29
|
};
|
|
@@ -43,6 +50,8 @@ export declare class PcButton extends PcElement {
|
|
|
43
50
|
};
|
|
44
51
|
static styles: import("lit").CSSResultGroup[];
|
|
45
52
|
variant: ButtonVariant;
|
|
53
|
+
/** How big the pill is (not for icon buttons) */
|
|
54
|
+
size: PillSize;
|
|
46
55
|
/** Name of an icon to show before the text (or alone, for an icon button) */
|
|
47
56
|
icon?: string;
|
|
48
57
|
/** The button's name for screen readers, when its content doesn't say it (e.g. an icon button) */
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { PcElement, defineElement } from "../../base/index.js";
|
|
2
|
+
import { PILL_SIZES, pillSizeDeclarations } from "../../styles/index.js";
|
|
2
3
|
import "../PcIcon/index.js";
|
|
3
|
-
import { css, html, nothing } from "lit";
|
|
4
|
+
import { css, html, nothing, unsafeCSS } from "lit";
|
|
4
5
|
// src/ui/elements/PcButton/index.ts
|
|
6
|
+
/** Each pill size, for the buttons that are pills (all but icon buttons) */
|
|
7
|
+
var SIZE_STYLES = unsafeCSS(PILL_SIZES.map((size) => `:host([size="${size}"]) button { ${pillSizeDeclarations(size)} }`).join("\n"));
|
|
5
8
|
/**
|
|
6
|
-
* A button: affirmative (`accent`, the default), cancelling (`cancel`), a quiet text button (`dismiss`), a
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
+
* A button: affirmative (`accent`, the default), cancelling (`cancel`), a quiet text button (`dismiss`), a pill (`pill`,
|
|
10
|
+
* the same as `accent`), or a boxed icon button (`icon`, which needs a `label` for screen readers). Its text goes in its
|
|
11
|
+
* content. All but icon buttons are pills, of the `size` given (`pill` by default; see `PILL_SIZE_STYLES`). Clicks
|
|
12
|
+
* reach listeners on the element; a disabled button sends none.
|
|
9
13
|
*
|
|
10
14
|
* @example
|
|
11
15
|
* html`<pc-button variant="cancel" @click=${close}>Cancel</pc-button>`
|
|
16
|
+
* html`<pc-button size="pill-l">Start</pc-button>`
|
|
12
17
|
* html`<pc-button variant="icon" icon="undo" label="Undo"></pc-button>`
|
|
13
18
|
*/
|
|
14
19
|
var PcButton = class extends PcElement {
|
|
@@ -18,6 +23,10 @@ var PcButton = class extends PcElement {
|
|
|
18
23
|
type: String,
|
|
19
24
|
reflect: true
|
|
20
25
|
},
|
|
26
|
+
size: {
|
|
27
|
+
type: String,
|
|
28
|
+
reflect: true
|
|
29
|
+
},
|
|
21
30
|
icon: { type: String },
|
|
22
31
|
label: { type: String },
|
|
23
32
|
disabled: {
|
|
@@ -38,9 +47,8 @@ var PcButton = class extends PcElement {
|
|
|
38
47
|
flex: 1;
|
|
39
48
|
align-items: center;
|
|
40
49
|
justify-content: center;
|
|
50
|
+
box-sizing: border-box;
|
|
41
51
|
gap: var(--pc-space-1);
|
|
42
|
-
min-height: var(--pc-control-size);
|
|
43
|
-
padding: var(--pc-space-1) var(--pc-space-3);
|
|
44
52
|
border: 0;
|
|
45
53
|
/* A joined button group gives each button its corners */
|
|
46
54
|
border-radius: var(--pc-group-radius, var(--pc-radius-pill));
|
|
@@ -48,10 +56,11 @@ var PcButton = class extends PcElement {
|
|
|
48
56
|
color: var(--pc-accent-text);
|
|
49
57
|
font: inherit;
|
|
50
58
|
font-family: var(--pc-font);
|
|
51
|
-
|
|
59
|
+
${unsafeCSS(pillSizeDeclarations("pill"))}
|
|
52
60
|
font-weight: bold;
|
|
53
61
|
cursor: pointer;
|
|
54
62
|
}
|
|
63
|
+
${SIZE_STYLES}
|
|
55
64
|
button:hover:not(:disabled) {
|
|
56
65
|
filter: brightness(1.15);
|
|
57
66
|
}
|
|
@@ -76,12 +85,10 @@ var PcButton = class extends PcElement {
|
|
|
76
85
|
filter: none;
|
|
77
86
|
text-decoration: underline;
|
|
78
87
|
}
|
|
79
|
-
:host([variant="pill"]) button {
|
|
80
|
-
min-height: 30px;
|
|
81
|
-
}
|
|
82
88
|
:host([variant="icon"]) button {
|
|
83
89
|
min-height: 0;
|
|
84
90
|
padding: 2px;
|
|
91
|
+
line-height: normal;
|
|
85
92
|
border: 1px solid var(--pc-border);
|
|
86
93
|
border-radius: var(--pc-group-radius, var(--pc-radius-small));
|
|
87
94
|
background: var(--pc-surface);
|
|
@@ -101,6 +108,7 @@ var PcButton = class extends PcElement {
|
|
|
101
108
|
constructor() {
|
|
102
109
|
super();
|
|
103
110
|
this.variant = "accent";
|
|
111
|
+
this.size = "pill";
|
|
104
112
|
this.disabled = false;
|
|
105
113
|
}
|
|
106
114
|
/** Move keyboard focus to the button */
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { PcElement } from "../../base";
|
|
2
|
+
import { type PillSize } from "../../styles";
|
|
3
|
+
import type { MenuItem } from "../PcMenu";
|
|
4
|
+
import "../PcContextMenu";
|
|
5
|
+
/** An action in a button menu: what `pc-select` gives, its label and whether it can be done now */
|
|
6
|
+
export type ButtonMenuItem = Pick<MenuItem, "value" | "label" | "disabled">;
|
|
7
|
+
/**
|
|
8
|
+
* Whether the window is narrower than a width (CSS pixels). False without a width or `matchMedia`.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* isNarrowerThan(900); // true in a 600px-wide window
|
|
12
|
+
*/
|
|
13
|
+
export declare const isNarrowerThan: (width: number | undefined, matchMedia?: ((query: string) => {
|
|
14
|
+
matches: boolean;
|
|
15
|
+
}) | undefined) => boolean;
|
|
16
|
+
/**
|
|
17
|
+
* A row of pill buttons for actions, which can become one ⋮ menu (`pc-context-menu`): while `menu` is set, or while the
|
|
18
|
+
* window is narrower than `menu-below` (CSS pixels; only when set). Fires `pc-select` (detail: `{ value }`) when an
|
|
19
|
+
* action is chosen either way.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* html`<pc-button-menu label="More actions" menu-below="900" size="pill-s"
|
|
23
|
+
* .items=${[{ value: "cut", label: "Cut" }, { value: "paste", label: "Paste", disabled: true }]}
|
|
24
|
+
* @pc-select=${(e) => run(e.detail.value)}></pc-button-menu>`
|
|
25
|
+
*/
|
|
26
|
+
export declare class PcButtonMenu extends PcElement {
|
|
27
|
+
static properties: {
|
|
28
|
+
items: {
|
|
29
|
+
attribute: boolean;
|
|
30
|
+
};
|
|
31
|
+
label: {
|
|
32
|
+
type: StringConstructor;
|
|
33
|
+
};
|
|
34
|
+
size: {
|
|
35
|
+
type: StringConstructor;
|
|
36
|
+
};
|
|
37
|
+
menu: {
|
|
38
|
+
type: BooleanConstructor;
|
|
39
|
+
reflect: boolean;
|
|
40
|
+
};
|
|
41
|
+
menuBelow: {
|
|
42
|
+
type: NumberConstructor;
|
|
43
|
+
attribute: string;
|
|
44
|
+
};
|
|
45
|
+
narrowWindow: {
|
|
46
|
+
state: boolean;
|
|
47
|
+
};
|
|
48
|
+
translations: {
|
|
49
|
+
attribute: boolean;
|
|
50
|
+
};
|
|
51
|
+
icons: {
|
|
52
|
+
attribute: boolean;
|
|
53
|
+
};
|
|
54
|
+
theme: {
|
|
55
|
+
type: StringConstructor;
|
|
56
|
+
reflect: boolean;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
static styles: import("lit").CSSResultGroup[];
|
|
60
|
+
/** The actions, in order */
|
|
61
|
+
items: ButtonMenuItem[];
|
|
62
|
+
/** What the ⋮ button is called (e.g. "More actions") */
|
|
63
|
+
label: string;
|
|
64
|
+
/** The buttons' pill size (`pill` by default) */
|
|
65
|
+
size: PillSize;
|
|
66
|
+
/** Whether the actions are always one ⋮ menu */
|
|
67
|
+
menu: boolean;
|
|
68
|
+
/** Window width (CSS pixels) below which the actions are one ⋮ menu; none by default */
|
|
69
|
+
menuBelow?: number;
|
|
70
|
+
/** Whether the window is narrower than `menuBelow` */
|
|
71
|
+
narrowWindow: boolean;
|
|
72
|
+
/** Follows the window's width while `menuBelow` is set */
|
|
73
|
+
private query?;
|
|
74
|
+
private readonly onQueryChange;
|
|
75
|
+
constructor();
|
|
76
|
+
/** Whether the actions show as one ⋮ menu now */
|
|
77
|
+
get showsMenu(): boolean;
|
|
78
|
+
connectedCallback(): void;
|
|
79
|
+
disconnectedCallback(): void;
|
|
80
|
+
protected willUpdate(changed: Map<PropertyKey, unknown>): void;
|
|
81
|
+
/** Follow whether the window is narrower than `menuBelow` (when set and the browser can tell) */
|
|
82
|
+
private watchWidth;
|
|
83
|
+
/** Stop following the window's width */
|
|
84
|
+
private stopWatchingWidth;
|
|
85
|
+
/** Tell listeners an action was chosen */
|
|
86
|
+
private select;
|
|
87
|
+
render(): import("lit").TemplateResult<1> | import("lit").TemplateResult<1>[];
|
|
88
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { PcElement, defineElement, emit } from "../../base/index.js";
|
|
2
|
+
import { PILLS_CSS } from "../../styles/index.js";
|
|
3
|
+
import "../PcContextMenu/index.js";
|
|
4
|
+
import { css, html, unsafeCSS } from "lit";
|
|
5
|
+
// src/ui/elements/PcButtonMenu/index.ts
|
|
6
|
+
/**
|
|
7
|
+
* Whether the window is narrower than a width (CSS pixels). False without a width or `matchMedia`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* isNarrowerThan(900); // true in a 600px-wide window
|
|
11
|
+
*/
|
|
12
|
+
var isNarrowerThan = (width, matchMedia = typeof window.matchMedia === "function" ? (query) => window.matchMedia(query) : void 0) => width !== void 0 && width > 0 && matchMedia !== void 0 && matchMedia(`(width < ${width}px)`).matches;
|
|
13
|
+
/**
|
|
14
|
+
* A row of pill buttons for actions, which can become one ⋮ menu (`pc-context-menu`): while `menu` is set, or while the
|
|
15
|
+
* window is narrower than `menu-below` (CSS pixels; only when set). Fires `pc-select` (detail: `{ value }`) when an
|
|
16
|
+
* action is chosen either way.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* html`<pc-button-menu label="More actions" menu-below="900" size="pill-s"
|
|
20
|
+
* .items=${[{ value: "cut", label: "Cut" }, { value: "paste", label: "Paste", disabled: true }]}
|
|
21
|
+
* @pc-select=${(e) => run(e.detail.value)}></pc-button-menu>`
|
|
22
|
+
*/
|
|
23
|
+
var PcButtonMenu = class extends PcElement {
|
|
24
|
+
static properties = {
|
|
25
|
+
...PcElement.properties,
|
|
26
|
+
items: { attribute: false },
|
|
27
|
+
label: { type: String },
|
|
28
|
+
size: { type: String },
|
|
29
|
+
menu: {
|
|
30
|
+
type: Boolean,
|
|
31
|
+
reflect: true
|
|
32
|
+
},
|
|
33
|
+
menuBelow: {
|
|
34
|
+
type: Number,
|
|
35
|
+
attribute: "menu-below"
|
|
36
|
+
},
|
|
37
|
+
narrowWindow: { state: true }
|
|
38
|
+
};
|
|
39
|
+
static styles = [
|
|
40
|
+
PcElement.styles,
|
|
41
|
+
unsafeCSS(PILLS_CSS),
|
|
42
|
+
css`
|
|
43
|
+
:host {
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
gap: var(--pc-space-2);
|
|
47
|
+
}
|
|
48
|
+
:host([hidden]) {
|
|
49
|
+
display: none;
|
|
50
|
+
}
|
|
51
|
+
`
|
|
52
|
+
];
|
|
53
|
+
/** Follows the window's width while `menuBelow` is set */
|
|
54
|
+
query;
|
|
55
|
+
onQueryChange = (event) => {
|
|
56
|
+
this.narrowWindow = event.matches;
|
|
57
|
+
};
|
|
58
|
+
constructor() {
|
|
59
|
+
super();
|
|
60
|
+
this.items = [];
|
|
61
|
+
this.label = "";
|
|
62
|
+
this.size = "pill";
|
|
63
|
+
this.menu = false;
|
|
64
|
+
this.narrowWindow = false;
|
|
65
|
+
}
|
|
66
|
+
/** Whether the actions show as one ⋮ menu now */
|
|
67
|
+
get showsMenu() {
|
|
68
|
+
return this.menu || this.narrowWindow;
|
|
69
|
+
}
|
|
70
|
+
connectedCallback() {
|
|
71
|
+
super.connectedCallback();
|
|
72
|
+
this.watchWidth();
|
|
73
|
+
}
|
|
74
|
+
disconnectedCallback() {
|
|
75
|
+
super.disconnectedCallback();
|
|
76
|
+
this.stopWatchingWidth();
|
|
77
|
+
}
|
|
78
|
+
willUpdate(changed) {
|
|
79
|
+
super.willUpdate(changed);
|
|
80
|
+
if (changed.has("menuBelow") && this.isConnected) this.watchWidth();
|
|
81
|
+
}
|
|
82
|
+
/** Follow whether the window is narrower than `menuBelow` (when set and the browser can tell) */
|
|
83
|
+
watchWidth() {
|
|
84
|
+
this.stopWatchingWidth();
|
|
85
|
+
this.narrowWindow = isNarrowerThan(this.menuBelow);
|
|
86
|
+
if (!this.menuBelow || typeof window.matchMedia !== "function") return;
|
|
87
|
+
this.query = window.matchMedia(`(width < ${this.menuBelow}px)`);
|
|
88
|
+
this.query.addEventListener?.("change", this.onQueryChange);
|
|
89
|
+
}
|
|
90
|
+
/** Stop following the window's width */
|
|
91
|
+
stopWatchingWidth() {
|
|
92
|
+
this.query?.removeEventListener?.("change", this.onQueryChange);
|
|
93
|
+
this.query = void 0;
|
|
94
|
+
}
|
|
95
|
+
/** Tell listeners an action was chosen */
|
|
96
|
+
select(value) {
|
|
97
|
+
emit(this, "pc-select", { value });
|
|
98
|
+
}
|
|
99
|
+
render() {
|
|
100
|
+
if (this.showsMenu) return html`<pc-context-menu
|
|
101
|
+
class="more"
|
|
102
|
+
label=${this.label}
|
|
103
|
+
.items=${this.items.map(({ value, label, disabled }) => ({
|
|
104
|
+
value,
|
|
105
|
+
label,
|
|
106
|
+
disabled
|
|
107
|
+
}))}
|
|
108
|
+
@pc-select=${(event) => {
|
|
109
|
+
event.stopPropagation();
|
|
110
|
+
this.select(event.detail.value);
|
|
111
|
+
}}
|
|
112
|
+
></pc-context-menu>`;
|
|
113
|
+
return this.items.map(({ value, label, disabled }) => html`<button
|
|
114
|
+
type="button"
|
|
115
|
+
class="${this.size} ${value}"
|
|
116
|
+
data-value=${value}
|
|
117
|
+
?disabled=${disabled}
|
|
118
|
+
@click=${() => this.select(value)}
|
|
119
|
+
>
|
|
120
|
+
${label}
|
|
121
|
+
</button>`);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
defineElement("pc-button-menu", PcButtonMenu);
|
|
125
|
+
export { PcButtonMenu, isNarrowerThan };
|
|
@@ -15,6 +15,8 @@ export declare const HANDLE_GRAB_DISTANCE = 8;
|
|
|
15
15
|
export declare const ANTS_INTERVAL = 100;
|
|
16
16
|
/** In focus pen mode, how long after a pen lifts touches are still ignored (milliseconds) */
|
|
17
17
|
export declare const PEN_LIFT_GRACE_MS = 500;
|
|
18
|
+
/** The most device pixels per CSS pixel the canvases on screen use (see `PcCanvas.pixelRatio`) */
|
|
19
|
+
export declare const MAX_PIXEL_RATIO = 2;
|
|
18
20
|
/**
|
|
19
21
|
* Space covered by the toolbar and chat on a screen of the given width.
|
|
20
22
|
*
|
|
@@ -92,7 +94,10 @@ export declare class PcCanvas extends PcElement {
|
|
|
92
94
|
insets?: Insets;
|
|
93
95
|
/** The insets in effect (see `insets`) */
|
|
94
96
|
private get activeInsets();
|
|
95
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* Device pixels per CSS pixel for the canvases on screen, at most `MAX_PIXEL_RATIO`: phones with 3 have 2.25 times
|
|
99
|
+
* the pixels to draw and put on screen for little visible difference (replaceable for tests).
|
|
100
|
+
*/
|
|
96
101
|
pixelRatio: () => number;
|
|
97
102
|
private changes;
|
|
98
103
|
/** Whether anything but the stroke in progress changed since the last update (so everything is redrawn) */
|
|
@@ -116,6 +121,8 @@ export declare class PcCanvas extends PcElement {
|
|
|
116
121
|
private antsOffset;
|
|
117
122
|
/** Viewport that has been fitted once (so resizing doesn't refit) */
|
|
118
123
|
private fittedViewport?;
|
|
124
|
+
/** The screen canvas whose 2D context has been made (see `prepareScene`) */
|
|
125
|
+
private preparedCanvas?;
|
|
119
126
|
private frame;
|
|
120
127
|
/** Animation frame drawing only the brush cursor, if requested */
|
|
121
128
|
private overlayFrame;
|
|
@@ -163,6 +170,13 @@ export declare class PcCanvas extends PcElement {
|
|
|
163
170
|
connectedCallback(): void;
|
|
164
171
|
disconnectedCallback(): void;
|
|
165
172
|
firstUpdated(): void;
|
|
173
|
+
/**
|
|
174
|
+
* Make a new screen canvas's 2D context where the app's canvases draw (see `PaintCanvas.rendering`). Drawn from layers
|
|
175
|
+
* kept in regular memory (`cpu`), keeping the screen canvas there too means each frame copies only the area that
|
|
176
|
+
* changed, instead of sending whole layers to the GPU. The first context decides that; later `getContext("2d")` calls
|
|
177
|
+
* get this one, so the screen canvas is made again when the app's rendering differs (see `render`).
|
|
178
|
+
*/
|
|
179
|
+
private prepareScene;
|
|
166
180
|
/**
|
|
167
181
|
* Note what changed: the stroke in progress (and the area it changed), or anything else.
|
|
168
182
|
*/
|
|
@@ -21,6 +21,7 @@ import "../../../lib/rendering/sample/index.js";
|
|
|
21
21
|
import { gestureAction } from "../../../lib/utils/gestures/index.js";
|
|
22
22
|
import { snapToPixelGrid } from "../../../lib/brushes/params/index.js";
|
|
23
23
|
import { html, unsafeCSS } from "lit";
|
|
24
|
+
import { keyed } from "lit/directives/keyed.js";
|
|
24
25
|
// src/ui/elements/PcCanvas/index.ts
|
|
25
26
|
/** Toolbar width in CSS pixels (kept clear when fitting the canvas) */
|
|
26
27
|
var TOOLBAR_WIDTH = 50;
|
|
@@ -39,6 +40,8 @@ var HANDLE_GRAB_DISTANCE = 8;
|
|
|
39
40
|
var ANTS_INTERVAL = 100;
|
|
40
41
|
/** In focus pen mode, how long after a pen lifts touches are still ignored (milliseconds) */
|
|
41
42
|
var PEN_LIFT_GRACE_MS = 500;
|
|
43
|
+
/** The most device pixels per CSS pixel the canvases on screen use (see `PcCanvas.pixelRatio`) */
|
|
44
|
+
var MAX_PIXEL_RATIO = 2;
|
|
42
45
|
/**
|
|
43
46
|
* Space covered by the toolbar and chat on a screen of the given width.
|
|
44
47
|
*
|
|
@@ -131,8 +134,11 @@ var PcCanvas = class extends PcElement {
|
|
|
131
134
|
const app = this.app;
|
|
132
135
|
return this.insets ?? interfaceInsets(app.viewport.width, app.interfaceVisible);
|
|
133
136
|
}
|
|
134
|
-
/**
|
|
135
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Device pixels per CSS pixel for the canvases on screen, at most `MAX_PIXEL_RATIO`: phones with 3 have 2.25 times
|
|
139
|
+
* the pixels to draw and put on screen for little visible difference (replaceable for tests).
|
|
140
|
+
*/
|
|
141
|
+
pixelRatio = () => Math.min(window.devicePixelRatio || 1, 2);
|
|
136
142
|
changes = new ChangeController(this, () => [
|
|
137
143
|
this.app,
|
|
138
144
|
this.app?.brush,
|
|
@@ -167,6 +173,8 @@ var PcCanvas = class extends PcElement {
|
|
|
167
173
|
antsOffset = 0;
|
|
168
174
|
/** Viewport that has been fitted once (so resizing doesn't refit) */
|
|
169
175
|
fittedViewport;
|
|
176
|
+
/** The screen canvas whose 2D context has been made (see `prepareScene`) */
|
|
177
|
+
preparedCanvas;
|
|
170
178
|
frame = 0;
|
|
171
179
|
/** Animation frame drawing only the brush cursor, if requested */
|
|
172
180
|
overlayFrame = 0;
|
|
@@ -242,6 +250,7 @@ var PcCanvas = class extends PcElement {
|
|
|
242
250
|
this.frame = 0;
|
|
243
251
|
}
|
|
244
252
|
firstUpdated() {
|
|
253
|
+
this.prepareScene();
|
|
245
254
|
if (typeof ResizeObserver !== "undefined") {
|
|
246
255
|
this.resizeObserver = new ResizeObserver(() => this.syncSize());
|
|
247
256
|
this.resizeObserver.observe(this);
|
|
@@ -249,6 +258,18 @@ var PcCanvas = class extends PcElement {
|
|
|
249
258
|
this.syncSize();
|
|
250
259
|
}
|
|
251
260
|
/**
|
|
261
|
+
* Make a new screen canvas's 2D context where the app's canvases draw (see `PaintCanvas.rendering`). Drawn from layers
|
|
262
|
+
* kept in regular memory (`cpu`), keeping the screen canvas there too means each frame copies only the area that
|
|
263
|
+
* changed, instead of sending whole layers to the GPU. The first context decides that; later `getContext("2d")` calls
|
|
264
|
+
* get this one, so the screen canvas is made again when the app's rendering differs (see `render`).
|
|
265
|
+
*/
|
|
266
|
+
prepareScene() {
|
|
267
|
+
const canvas = this.canvas;
|
|
268
|
+
if (!canvas || canvas === this.preparedCanvas) return;
|
|
269
|
+
this.preparedCanvas = canvas;
|
|
270
|
+
canvas.getContext("2d", { willReadFrequently: this.app?.rendering !== "gpu" });
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
252
273
|
* Note what changed: the stroke in progress (and the area it changed), or anything else.
|
|
253
274
|
*/
|
|
254
275
|
sceneChanged(target) {
|
|
@@ -260,6 +281,7 @@ var PcCanvas = class extends PcElement {
|
|
|
260
281
|
} else if (!(this.committing && target === app?.layers)) this.fullChange = true;
|
|
261
282
|
}
|
|
262
283
|
updated(changed) {
|
|
284
|
+
this.prepareScene();
|
|
263
285
|
const resized = this.syncSize();
|
|
264
286
|
const onlyStroke = changed.size === 0 && !this.fullChange && !resized;
|
|
265
287
|
this.requestDraw(onlyStroke ? this.strokeArea : void 0);
|
|
@@ -884,6 +906,7 @@ var PcCanvas = class extends PcElement {
|
|
|
884
906
|
if (!ctx) return;
|
|
885
907
|
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
886
908
|
const sampling = this.sampling;
|
|
909
|
+
this.sampler.hidden = !sampling;
|
|
887
910
|
if (!sampling) return;
|
|
888
911
|
const ratio = this.pixelRatio();
|
|
889
912
|
ctx.save();
|
|
@@ -1024,26 +1047,26 @@ var PcCanvas = class extends PcElement {
|
|
|
1024
1047
|
});
|
|
1025
1048
|
}
|
|
1026
1049
|
render() {
|
|
1027
|
-
return html`<canvas
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1050
|
+
return html`${keyed(this.app?.rendering ?? "cpu", html`<canvas
|
|
1051
|
+
class="scene"
|
|
1052
|
+
aria-label=${this.t("paintCanvas.canvas.label")}
|
|
1053
|
+
@pointerdown=${this.onPointerDown}
|
|
1054
|
+
@pointermove=${this.onPointerMove}
|
|
1055
|
+
@pointerup=${this.onPointerUp}
|
|
1056
|
+
@pointercancel=${this.onPointerCancel}
|
|
1057
|
+
@touchstart=${this.onTouchStart}
|
|
1058
|
+
@pointerleave=${this.onPointerLeave}
|
|
1059
|
+
@wheel=${this.onWheel}
|
|
1060
|
+
@gesturestart=${this.onGestureStart}
|
|
1061
|
+
@gesturechange=${this.onGestureChange}
|
|
1062
|
+
@gestureend=${(e) => e.preventDefault()}
|
|
1063
|
+
@dblclick=${() => this.app?.applyLasso(this.app.lasso.close())}
|
|
1064
|
+
@contextmenu=${(e) => e.preventDefault()}
|
|
1065
|
+
></canvas>`)}
|
|
1043
1066
|
<canvas class="outlines" aria-hidden="true"></canvas>
|
|
1044
1067
|
<canvas class="overlay" aria-hidden="true"></canvas>
|
|
1045
1068
|
<canvas class="sampler" aria-hidden="true"></canvas>`;
|
|
1046
1069
|
}
|
|
1047
1070
|
};
|
|
1048
1071
|
defineElement("pc-canvas", PcCanvas);
|
|
1049
|
-
export { ANTS_INTERVAL, CHAT_WIDTH_RATIO, HANDLE_GRAB_DISTANCE, LASSO_TOOLS, PEN_LIFT_GRACE_MS, PcCanvas, SAMPLER_HEIGHT, SAMPLER_WIDTH, TOOLBAR_WIDTH, TOUCH_SAMPLER_GAP, cursorFor, interfaceInsets, samplerPosition };
|
|
1072
|
+
export { ANTS_INTERVAL, CHAT_WIDTH_RATIO, HANDLE_GRAB_DISTANCE, LASSO_TOOLS, MAX_PIXEL_RATIO, PEN_LIFT_GRACE_MS, PcCanvas, SAMPLER_HEIGHT, SAMPLER_WIDTH, TOOLBAR_WIDTH, TOUCH_SAMPLER_GAP, cursorFor, interfaceInsets, samplerPosition };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// src/ui/elements/PcCanvas/style.css?inline
|
|
2
|
-
var style_default = ":host {\n display: block;\n position: absolute;\n inset: 0;\n touch-action: none;\n}\ncanvas {\n display: block;\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n}\ncanvas.outlines,\ncanvas.sampler {\n pointer-events: none;\n}\ncanvas.overlay {\n pointer-events: none;\n /* Inverts what is underneath so the brush outline is visible on any colour */\n mix-blend-mode: difference;\n}\n";
|
|
2
|
+
var style_default = ":host {\n display: block;\n position: absolute;\n inset: 0;\n touch-action: none;\n}\ncanvas {\n display: block;\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n}\ncanvas[hidden] {\n display: none;\n}\ncanvas.outlines,\ncanvas.sampler {\n pointer-events: none;\n}\ncanvas.overlay {\n pointer-events: none;\n /* Inverts what is underneath so the brush outline is visible on any colour */\n mix-blend-mode: difference;\n}\n";
|
|
3
3
|
export { style_default as default };
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { nothing } from "lit";
|
|
2
2
|
import { PcElement } from "../../base";
|
|
3
3
|
import PaintCanvas, { Tool } from "../../../lib/classes/PaintCanvas";
|
|
4
|
-
import "../
|
|
4
|
+
import "../PcButtonMenu";
|
|
5
5
|
/** The tools that cut, copy and paste are shown for: the brush, eraser, lassos and Move tool */
|
|
6
6
|
export declare const CLIPBOARD_TOOLS: readonly Tool[];
|
|
7
|
+
/** Window width (CSS pixels) below which the clipboard tools are one ⋮ menu */
|
|
8
|
+
export declare const CLIPBOARD_MENU_BELOW = 900;
|
|
7
9
|
/**
|
|
8
|
-
* Cut, copy and paste buttons for the canvas's masked image data, shown for the brush, eraser, lassos and
|
|
9
|
-
* (see `CLIPBOARD_TOOLS`).
|
|
10
|
-
*
|
|
10
|
+
* Cut, copy, copy merged and paste buttons for the canvas's masked image data, shown for the brush, eraser, lassos and
|
|
11
|
+
* Move tool (see `CLIPBOARD_TOOLS`). "Copy merged" copies the shown layers mixed as shown (see `PaintCanvas.copyMerged`).
|
|
12
|
+
* Cut and both copies work while there's a mask and no transform is pending; paste while there's copied image data.
|
|
13
|
+
* They're one ⋮ menu instead while the window is narrower than `CLIPBOARD_MENU_BELOW` (900px), or while `narrow` (see
|
|
14
|
+
* `pc-button-menu`).
|
|
11
15
|
*
|
|
12
16
|
* `<paint-canvas>` puts it at the end of its top pane, after the tool settings.
|
|
13
17
|
*
|
|
@@ -36,13 +40,13 @@ export declare class PcClipboardTools extends PcElement {
|
|
|
36
40
|
};
|
|
37
41
|
static styles: import("lit").CSSResultGroup[];
|
|
38
42
|
app?: PaintCanvas;
|
|
39
|
-
/** Whether the buttons are one ⋮ menu (e.g. while the layout is narrow) */
|
|
43
|
+
/** Whether the buttons are one ⋮ menu whatever the window's width (e.g. while the layout is narrow) */
|
|
40
44
|
narrow: boolean;
|
|
41
45
|
private changes;
|
|
42
46
|
constructor();
|
|
43
|
-
/** Cut, copy and paste, each with whether it can be done now */
|
|
47
|
+
/** Cut, copy, copy merged and paste, each with whether it can be done now */
|
|
44
48
|
private actions;
|
|
45
49
|
/** Hide for tools without clipboard actions (e.g. zoom) */
|
|
46
50
|
protected willUpdate(): void;
|
|
47
|
-
render(): import("lit").TemplateResult<1> | typeof nothing
|
|
51
|
+
render(): import("lit").TemplateResult<1> | typeof nothing;
|
|
48
52
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Tool } from "../../../lib/classes/PaintCanvas/tool.js";
|
|
2
2
|
import { PcElement, defineElement } from "../../base/index.js";
|
|
3
3
|
import ChangeController from "../../ChangeController/index.js";
|
|
4
|
-
import { PILLS_CSS } from "../../styles/index.js";
|
|
5
4
|
import "../../../lib/classes/PaintCanvas/index.js";
|
|
6
|
-
import "../
|
|
7
|
-
import { css, html, nothing
|
|
5
|
+
import "../PcButtonMenu/index.js";
|
|
6
|
+
import { css, html, nothing } from "lit";
|
|
8
7
|
// src/ui/elements/PcClipboardTools/index.ts
|
|
9
8
|
/** The tools that cut, copy and paste are shown for: the brush, eraser, lassos and Move tool */
|
|
10
9
|
var CLIPBOARD_TOOLS = [
|
|
@@ -16,10 +15,14 @@ var CLIPBOARD_TOOLS = [
|
|
|
16
15
|
Tool.FreeformLasso,
|
|
17
16
|
Tool.Move
|
|
18
17
|
];
|
|
18
|
+
/** Window width (CSS pixels) below which the clipboard tools are one ⋮ menu */
|
|
19
|
+
var CLIPBOARD_MENU_BELOW = 900;
|
|
19
20
|
/**
|
|
20
|
-
* Cut, copy and paste buttons for the canvas's masked image data, shown for the brush, eraser, lassos and
|
|
21
|
-
* (see `CLIPBOARD_TOOLS`).
|
|
22
|
-
*
|
|
21
|
+
* Cut, copy, copy merged and paste buttons for the canvas's masked image data, shown for the brush, eraser, lassos and
|
|
22
|
+
* Move tool (see `CLIPBOARD_TOOLS`). "Copy merged" copies the shown layers mixed as shown (see `PaintCanvas.copyMerged`).
|
|
23
|
+
* Cut and both copies work while there's a mask and no transform is pending; paste while there's copied image data.
|
|
24
|
+
* They're one ⋮ menu instead while the window is narrower than `CLIPBOARD_MENU_BELOW` (900px), or while `narrow` (see
|
|
25
|
+
* `pc-button-menu`).
|
|
23
26
|
*
|
|
24
27
|
* `<paint-canvas>` puts it at the end of its top pane, after the tool settings.
|
|
25
28
|
*
|
|
@@ -35,15 +38,11 @@ var PcClipboardTools = class extends PcElement {
|
|
|
35
38
|
reflect: true
|
|
36
39
|
}
|
|
37
40
|
};
|
|
38
|
-
static styles = [
|
|
39
|
-
PcElement.styles,
|
|
40
|
-
unsafeCSS(PILLS_CSS),
|
|
41
|
-
css`
|
|
41
|
+
static styles = [PcElement.styles, css`
|
|
42
42
|
:host {
|
|
43
43
|
display: flex;
|
|
44
44
|
flex: none;
|
|
45
45
|
align-items: center;
|
|
46
|
-
gap: 8px;
|
|
47
46
|
padding: 4px 8px;
|
|
48
47
|
background: var(--pc-bar);
|
|
49
48
|
border-bottom: 1px solid var(--pc-surface-active);
|
|
@@ -51,8 +50,7 @@ var PcClipboardTools = class extends PcElement {
|
|
|
51
50
|
:host([hidden]) {
|
|
52
51
|
display: none;
|
|
53
52
|
}
|
|
54
|
-
`
|
|
55
|
-
];
|
|
53
|
+
`];
|
|
56
54
|
changes = new ChangeController(this, () => this.app ? [
|
|
57
55
|
this.app,
|
|
58
56
|
this.app.selection,
|
|
@@ -62,7 +60,7 @@ var PcClipboardTools = class extends PcElement {
|
|
|
62
60
|
super();
|
|
63
61
|
this.narrow = false;
|
|
64
62
|
}
|
|
65
|
-
/** Cut, copy and paste, each with whether it can be done now */
|
|
63
|
+
/** Cut, copy, copy merged and paste, each with whether it can be done now */
|
|
66
64
|
actions(app) {
|
|
67
65
|
const noCopy = !app.selection.active || app.transform.pending;
|
|
68
66
|
return [
|
|
@@ -78,6 +76,12 @@ var PcClipboardTools = class extends PcElement {
|
|
|
78
76
|
disabled: noCopy,
|
|
79
77
|
run: () => app.copy()
|
|
80
78
|
},
|
|
79
|
+
{
|
|
80
|
+
name: "copy-merged",
|
|
81
|
+
label: this.t("paintCanvas.common.copyMerged"),
|
|
82
|
+
disabled: noCopy,
|
|
83
|
+
run: () => app.copyMerged()
|
|
84
|
+
},
|
|
81
85
|
{
|
|
82
86
|
name: "paste",
|
|
83
87
|
label: this.t("paintCanvas.common.paste"),
|
|
@@ -94,25 +98,22 @@ var PcClipboardTools = class extends PcElement {
|
|
|
94
98
|
const app = this.app;
|
|
95
99
|
if (!app || this.hidden) return nothing;
|
|
96
100
|
const actions = this.actions(app);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
+
return html`<pc-button-menu
|
|
102
|
+
size="pill-s"
|
|
103
|
+
label=${this.t("paintCanvas.toolSettings.moreActions")}
|
|
104
|
+
menu-below=${900}
|
|
105
|
+
?menu=${this.narrow}
|
|
106
|
+
.items=${actions.map(({ name, label, disabled }) => ({
|
|
101
107
|
value: name,
|
|
102
108
|
label,
|
|
103
109
|
disabled
|
|
104
110
|
}))}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
?disabled=${action.disabled}
|
|
111
|
-
@click=${action.run}
|
|
112
|
-
>
|
|
113
|
-
${action.label}
|
|
114
|
-
</button>`);
|
|
111
|
+
@pc-select=${(event) => {
|
|
112
|
+
event.stopPropagation();
|
|
113
|
+
actions.find((action) => action.name === event.detail.value)?.run();
|
|
114
|
+
}}
|
|
115
|
+
></pc-button-menu>`;
|
|
115
116
|
}
|
|
116
117
|
};
|
|
117
118
|
defineElement("pc-clipboard-tools", PcClipboardTools);
|
|
118
|
-
export { CLIPBOARD_TOOLS, PcClipboardTools };
|
|
119
|
+
export { CLIPBOARD_MENU_BELOW, CLIPBOARD_TOOLS, PcClipboardTools };
|