@openleaf-editor/ui 0.1.0-beta.1 → 0.1.0-beta.2
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/dist/content-css.d.ts +13 -0
- package/dist/content-css.d.ts.map +1 -0
- package/dist/content-css.js +57 -0
- package/dist/content-css.js.map +1 -0
- package/dist/dialog.d.ts +66 -19
- package/dist/dialog.d.ts.map +1 -1
- package/dist/dialog.js +198 -51
- package/dist/dialog.js.map +1 -1
- package/dist/floating.d.ts +25 -0
- package/dist/floating.d.ts.map +1 -0
- package/dist/floating.js +82 -0
- package/dist/floating.js.map +1 -0
- package/dist/help.d.ts +9 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +73 -0
- package/dist/help.js.map +1 -0
- package/dist/i18n.d.ts +31 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +89 -0
- package/dist/i18n.js.map +1 -0
- package/dist/icons.d.ts.map +1 -1
- package/dist/icons.js +4 -0
- package/dist/icons.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/items.d.ts +2 -0
- package/dist/items.d.ts.map +1 -1
- package/dist/items.js +43 -3
- package/dist/items.js.map +1 -1
- package/dist/menu.d.ts +56 -0
- package/dist/menu.d.ts.map +1 -0
- package/dist/menu.js +360 -0
- package/dist/menu.js.map +1 -0
- package/dist/openleaf.css +216 -0
- package/dist/overflow.d.ts +17 -0
- package/dist/overflow.d.ts.map +1 -0
- package/dist/overflow.js +138 -0
- package/dist/overflow.js.map +1 -0
- package/dist/pickers.d.ts +43 -0
- package/dist/pickers.d.ts.map +1 -0
- package/dist/pickers.js +52 -0
- package/dist/pickers.js.map +1 -0
- package/dist/styles.d.ts +1 -1
- package/dist/styles.d.ts.map +1 -1
- package/dist/styles.js +216 -0
- package/dist/styles.js.map +1 -1
- package/dist/toolbar.d.ts +20 -0
- package/dist/toolbar.d.ts.map +1 -1
- package/dist/toolbar.js +105 -17
- package/dist/toolbar.js.map +1 -1
- package/package.json +2 -2
package/dist/overflow.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collapse overflowing toolbar groups into a "More" menu.
|
|
3
|
+
*
|
|
4
|
+
* Wrapping is the default for a reason: a control that moved behind a click is
|
|
5
|
+
* a control the author does not have. Overflow is therefore opt-in. When it is
|
|
6
|
+
* on, groups that do not fit the current width are hidden in the bar and
|
|
7
|
+
* offered in a menu at the end, so a narrow CMS sidebar still has every item
|
|
8
|
+
* without a two-row bar.
|
|
9
|
+
*/
|
|
10
|
+
import { t } from './i18n.js';
|
|
11
|
+
import { iconElement } from './icons.js';
|
|
12
|
+
export class ToolbarOverflow {
|
|
13
|
+
#toolbar;
|
|
14
|
+
#host;
|
|
15
|
+
#more;
|
|
16
|
+
#menu;
|
|
17
|
+
#observer = null;
|
|
18
|
+
constructor(toolbar, host, doc) {
|
|
19
|
+
this.#toolbar = toolbar;
|
|
20
|
+
this.#host = host;
|
|
21
|
+
toolbar.classList.add('ol-toolbar--overflow');
|
|
22
|
+
this.#more = doc.createElement('button');
|
|
23
|
+
this.#more.type = 'button';
|
|
24
|
+
this.#more.className = 'ol-btn ol-overflow-more';
|
|
25
|
+
this.#more.setAttribute('aria-label', t('More'));
|
|
26
|
+
this.#more.setAttribute('aria-haspopup', 'true');
|
|
27
|
+
this.#more.setAttribute('aria-expanded', 'false');
|
|
28
|
+
this.#more.hidden = true;
|
|
29
|
+
this.#more.appendChild(iconElement('more', doc));
|
|
30
|
+
this.#menu = doc.createElement('div');
|
|
31
|
+
this.#menu.className = 'ol-menu ol-overflow-menu';
|
|
32
|
+
this.#menu.setAttribute('role', 'menu');
|
|
33
|
+
this.#menu.hidden = true;
|
|
34
|
+
this.#more.addEventListener('click', () => {
|
|
35
|
+
const open = this.#menu.hidden;
|
|
36
|
+
this.#menu.hidden = !open;
|
|
37
|
+
this.#more.setAttribute('aria-expanded', open ? 'true' : 'false');
|
|
38
|
+
});
|
|
39
|
+
host.appendChild(this.#menu);
|
|
40
|
+
toolbar.appendChild(this.#more);
|
|
41
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
42
|
+
this.#observer = new ResizeObserver(() => this.layout());
|
|
43
|
+
this.#observer.observe(toolbar);
|
|
44
|
+
}
|
|
45
|
+
this.layout();
|
|
46
|
+
}
|
|
47
|
+
reattach() {
|
|
48
|
+
if (!this.#more.isConnected)
|
|
49
|
+
this.#toolbar.appendChild(this.#more);
|
|
50
|
+
this.layout();
|
|
51
|
+
}
|
|
52
|
+
destroy() {
|
|
53
|
+
this.#observer?.disconnect();
|
|
54
|
+
this.#more.remove();
|
|
55
|
+
this.#menu.remove();
|
|
56
|
+
this.#toolbar.classList.remove('ol-toolbar--overflow');
|
|
57
|
+
for (const group of this.#groups())
|
|
58
|
+
group.hidden = false;
|
|
59
|
+
}
|
|
60
|
+
layout() {
|
|
61
|
+
const groups = this.#groups();
|
|
62
|
+
for (const group of groups)
|
|
63
|
+
group.hidden = false;
|
|
64
|
+
this.#more.hidden = true;
|
|
65
|
+
this.#menu.hidden = true;
|
|
66
|
+
this.#menu.replaceChildren();
|
|
67
|
+
const budget = this.#toolbar.clientWidth;
|
|
68
|
+
if (budget === 0)
|
|
69
|
+
return;
|
|
70
|
+
const overflowing = [];
|
|
71
|
+
for (let i = groups.length - 1; i >= 0; i -= 1) {
|
|
72
|
+
const fits = this.#toolbar.scrollWidth <= budget + 1;
|
|
73
|
+
if (fits)
|
|
74
|
+
break;
|
|
75
|
+
const group = groups[i];
|
|
76
|
+
if (!group)
|
|
77
|
+
break;
|
|
78
|
+
group.hidden = true;
|
|
79
|
+
overflowing.unshift(group);
|
|
80
|
+
}
|
|
81
|
+
if (overflowing.length === 0)
|
|
82
|
+
return;
|
|
83
|
+
this.#more.hidden = false;
|
|
84
|
+
for (const group of overflowing) {
|
|
85
|
+
for (const control of group.querySelectorAll('[aria-label], select')) {
|
|
86
|
+
const item = control.cloneNode(true);
|
|
87
|
+
item.removeAttribute('tabindex');
|
|
88
|
+
// cloneNode copies the option elements but not the select's current
|
|
89
|
+
// value, which the toolbar sets as a property rather than an attribute.
|
|
90
|
+
// Without this the menu opens showing the first option instead of the
|
|
91
|
+
// block the caret is actually in.
|
|
92
|
+
if (control instanceof HTMLSelectElement && item instanceof HTMLSelectElement) {
|
|
93
|
+
item.value = control.value;
|
|
94
|
+
}
|
|
95
|
+
this.#menu.appendChild(item);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Cloning controls duplicates listener-less buttons. Activation on a clone is
|
|
99
|
+
// forwarded to the original, which still owns the command.
|
|
100
|
+
this.#menu.onclick = (event) => {
|
|
101
|
+
const target = event.target;
|
|
102
|
+
// A <select> is driven by `change`, not `click`. Forwarding a click here
|
|
103
|
+
// fired before any option was chosen and carried no value with it.
|
|
104
|
+
if (target?.closest('select'))
|
|
105
|
+
return;
|
|
106
|
+
const clone = target?.closest('[data-ol-id]');
|
|
107
|
+
if (!clone)
|
|
108
|
+
return;
|
|
109
|
+
const original = this.#toolbar.querySelector(`[data-ol-id="${clone.dataset['olId']}"]`);
|
|
110
|
+
original?.click();
|
|
111
|
+
this.#close();
|
|
112
|
+
};
|
|
113
|
+
// The clone has no listeners of its own, so a chosen value has to be written
|
|
114
|
+
// onto the real control and announced there. Clicking the original was the
|
|
115
|
+
// previous behaviour and never carried the value, so headings and custom
|
|
116
|
+
// formats could not be applied from the overflow menu at all.
|
|
117
|
+
this.#menu.onchange = (event) => {
|
|
118
|
+
const clone = event.target;
|
|
119
|
+
if (!(clone instanceof HTMLSelectElement))
|
|
120
|
+
return;
|
|
121
|
+
const original = this.#toolbar.querySelector('select');
|
|
122
|
+
if (!original)
|
|
123
|
+
return;
|
|
124
|
+
original.value = clone.value;
|
|
125
|
+
original.dispatchEvent(new Event('change', { bubbles: true }));
|
|
126
|
+
this.#close();
|
|
127
|
+
};
|
|
128
|
+
void this.#host;
|
|
129
|
+
}
|
|
130
|
+
#close() {
|
|
131
|
+
this.#menu.hidden = true;
|
|
132
|
+
this.#more.setAttribute('aria-expanded', 'false');
|
|
133
|
+
}
|
|
134
|
+
#groups() {
|
|
135
|
+
return [...this.#toolbar.querySelectorAll(':scope > .ol-group')];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=overflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overflow.js","sourceRoot":"","sources":["../src/overflow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared pickers: file, image and media, plus optional link and image lists.
|
|
3
|
+
*
|
|
4
|
+
* OpenLeaf has no media library. What it can own is the seam a CMS already has
|
|
5
|
+
* -- "open our file browser and give me a URL" -- so the link dialog, the
|
|
6
|
+
* image dialog and the media dialog all call the same function. Registering
|
|
7
|
+
* three uploaders that each talk to the same endpoint is how this used to go
|
|
8
|
+
* wrong in every other editor.
|
|
9
|
+
*
|
|
10
|
+
* Lists are separate: they are the short, known set of destinations a site
|
|
11
|
+
* wants to offer (the privacy policy, a hero image), not a replacement for
|
|
12
|
+
* the library.
|
|
13
|
+
*/
|
|
14
|
+
export type FilePickerKind = 'file' | 'image' | 'media';
|
|
15
|
+
export interface PickedResource {
|
|
16
|
+
url: string;
|
|
17
|
+
title?: string;
|
|
18
|
+
text?: string;
|
|
19
|
+
alt?: string;
|
|
20
|
+
}
|
|
21
|
+
export type FilePicker = (meta: {
|
|
22
|
+
kind: FilePickerKind;
|
|
23
|
+
host: HTMLElement;
|
|
24
|
+
}) => Promise<PickedResource | null>;
|
|
25
|
+
export interface ListedResource {
|
|
26
|
+
/** Shown in the list. */
|
|
27
|
+
title: string;
|
|
28
|
+
/** The URL inserted. */
|
|
29
|
+
value: string;
|
|
30
|
+
}
|
|
31
|
+
type ListSource = readonly ListedResource[] | (() => readonly ListedResource[]);
|
|
32
|
+
/** Register the shared file picker for every editor on the page. `null` removes it. */
|
|
33
|
+
export declare function registerFilePicker(picker: FilePicker | null): void;
|
|
34
|
+
export declare function filePickerFor(host: HTMLElement | null | undefined): FilePicker | null;
|
|
35
|
+
export declare function registerLinkList(list: ListSource | null): void;
|
|
36
|
+
export declare function registerImageList(list: ListSource | null): void;
|
|
37
|
+
/** Class names offered in the image dialog. Authors can still type others. */
|
|
38
|
+
export declare function registerImageClasses(list: readonly string[] | (() => readonly string[]) | null): void;
|
|
39
|
+
export declare function listedLinks(): ListedResource[];
|
|
40
|
+
export declare function listedImages(): ListedResource[];
|
|
41
|
+
export declare function listedImageClasses(): string[];
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=pickers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pickers.d.ts","sourceRoot":"","sources":["../src/pickers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAA;AAEvD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE;IAC9B,IAAI,EAAE,cAAc,CAAA;IACpB,IAAI,EAAE,WAAW,CAAA;CAClB,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;AAEpC,MAAM,WAAW,cAAc;IAC7B,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,KAAK,UAAU,GAAG,SAAS,cAAc,EAAE,GAAG,CAAC,MAAM,SAAS,cAAc,EAAE,CAAC,CAAA;AAW/E,uFAAuF;AACvF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAElE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,GAAG,IAAI,CAGrF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAE9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAE/D;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,CAAC,MAAM,SAAS,MAAM,EAAE,CAAC,GAAG,IAAI,GACzD,IAAI,CAEN;AAOD,wBAAgB,WAAW,IAAI,cAAc,EAAE,CAE9C;AAED,wBAAgB,YAAY,IAAI,cAAc,EAAE,CAE/C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAG7C"}
|
package/dist/pickers.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared pickers: file, image and media, plus optional link and image lists.
|
|
3
|
+
*
|
|
4
|
+
* OpenLeaf has no media library. What it can own is the seam a CMS already has
|
|
5
|
+
* -- "open our file browser and give me a URL" -- so the link dialog, the
|
|
6
|
+
* image dialog and the media dialog all call the same function. Registering
|
|
7
|
+
* three uploaders that each talk to the same endpoint is how this used to go
|
|
8
|
+
* wrong in every other editor.
|
|
9
|
+
*
|
|
10
|
+
* Lists are separate: they are the short, known set of destinations a site
|
|
11
|
+
* wants to offer (the privacy policy, a hero image), not a replacement for
|
|
12
|
+
* the library.
|
|
13
|
+
*/
|
|
14
|
+
let globalPicker = null;
|
|
15
|
+
let linkList = null;
|
|
16
|
+
let imageList = null;
|
|
17
|
+
let imageClasses = null;
|
|
18
|
+
/** Register the shared file picker for every editor on the page. `null` removes it. */
|
|
19
|
+
export function registerFilePicker(picker) {
|
|
20
|
+
globalPicker = picker;
|
|
21
|
+
}
|
|
22
|
+
export function filePickerFor(host) {
|
|
23
|
+
const own = host?.filePicker;
|
|
24
|
+
return own ?? globalPicker;
|
|
25
|
+
}
|
|
26
|
+
export function registerLinkList(list) {
|
|
27
|
+
linkList = list;
|
|
28
|
+
}
|
|
29
|
+
export function registerImageList(list) {
|
|
30
|
+
imageList = list;
|
|
31
|
+
}
|
|
32
|
+
/** Class names offered in the image dialog. Authors can still type others. */
|
|
33
|
+
export function registerImageClasses(list) {
|
|
34
|
+
imageClasses = list;
|
|
35
|
+
}
|
|
36
|
+
function resolveList(source) {
|
|
37
|
+
if (!source)
|
|
38
|
+
return [];
|
|
39
|
+
return [...(typeof source === 'function' ? source() : source)];
|
|
40
|
+
}
|
|
41
|
+
export function listedLinks() {
|
|
42
|
+
return resolveList(linkList);
|
|
43
|
+
}
|
|
44
|
+
export function listedImages() {
|
|
45
|
+
return resolveList(imageList);
|
|
46
|
+
}
|
|
47
|
+
export function listedImageClasses() {
|
|
48
|
+
if (!imageClasses)
|
|
49
|
+
return [];
|
|
50
|
+
return [...(typeof imageClasses === 'function' ? imageClasses() : imageClasses)];
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=pickers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pickers.js","sourceRoot":"","sources":["../src/pickers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAyBH,IAAI,YAAY,GAAsB,IAAI,CAAA;AAC1C,IAAI,QAAQ,GAAsB,IAAI,CAAA;AACtC,IAAI,SAAS,GAAsB,IAAI,CAAA;AACvC,IAAI,YAAY,GAAyD,IAAI,CAAA;AAM7E,uFAAuF;AACvF,MAAM,UAAU,kBAAkB,CAAC,MAAyB;IAC1D,YAAY,GAAG,MAAM,CAAA;AACvB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAoC;IAChE,MAAM,GAAG,GAAI,IAA0C,EAAE,UAAU,CAAA;IACnE,OAAO,GAAG,IAAI,YAAY,CAAA;AAC5B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAuB;IACtD,QAAQ,GAAG,IAAI,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAuB;IACvD,SAAS,GAAG,IAAI,CAAA;AAClB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,oBAAoB,CAClC,IAA0D;IAE1D,YAAY,GAAG,IAAI,CAAA;AACrB,CAAC;AAED,SAAS,WAAW,CAAC,MAAyB;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAA;IACtB,OAAO,CAAC,GAAG,CAAC,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAChE,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,WAAW,CAAC,QAAQ,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,WAAW,CAAC,SAAS,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC,YAAY;QAAE,OAAO,EAAE,CAAA;IAC5B,OAAO,CAAC,GAAG,CAAC,OAAO,YAAY,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;AAClF,CAAC"}
|
package/dist/styles.d.ts
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
* an integrator can act on. A console warning naming the stylesheet is more
|
|
36
36
|
* useful than a mechanism that quietly does nothing.
|
|
37
37
|
*/
|
|
38
|
-
export declare const CSS = "\n.ol-editor {\n /* Two families, named before either is public API. A singular\n `--openleaf-font` implies \"the\" font, and source view already has a\n monospace surface -- bolting a mono token on beside a singular name later\n is the awkward outcome worth avoiding now. `--openleaf-font` is still\n honoured as a fallback. */\n --ol-font: var(--openleaf-font-ui, var(--openleaf-font, system-ui, -apple-system, \"Segoe UI\", sans-serif));\n --ol-font-mono: var(--openleaf-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);\n --ol-font-size: var(--openleaf-font-size, 14px);\n --ol-radius: var(--openleaf-radius, 4px);\n --ol-text: var(--openleaf-color-text, #1f2328);\n --ol-text-muted: var(--openleaf-color-text-muted, #59636e);\n --ol-surface: var(--openleaf-color-surface, #ffffff);\n --ol-surface-hover: var(--openleaf-color-surface-hover, #f0f1f3);\n --ol-surface-active: var(--openleaf-color-surface-active, #dbe9ff);\n --ol-border: var(--openleaf-color-border, #d1d9e0);\n --ol-accent: var(--openleaf-color-accent, #0550ae);\n --ol-focus: var(--openleaf-color-focus, #0969da);\n --ol-button-size: var(--openleaf-button-size, 32px);\n --ol-icon-size: var(--openleaf-icon-size, 16px);\n --ol-gap: var(--openleaf-gap, 2px);\n /* A 2009 WordPress admin bar sits at z-index 99999 and Drupal's toolbar plays\n similar games. Without a sanctioned escape hatch integrators fix a toolbar\n rendered behind a sticky host header with !important -- the exact thing the\n token API exists to prevent. */\n --ol-z: var(--openleaf-z-index, 1);\n /* Thickness and offset, not just colour: \"you can change the colour but not\n the thickness\" is a poor answer to a Section 508 team citing WCAG 2.2\n Focus Appearance. */\n --ol-focus-width: var(--openleaf-focus-width, 2px);\n --ol-focus-offset: var(--openleaf-focus-offset, 1px);\n\n display: block;\n color: var(--ol-text);\n}\n\n/* Three ways into the dark palette, and one way out of it.\n `data-ol-scheme` is set from the applied skin's declared scheme, and a skin\n that declares one outranks both the attribute and the system -- it has to,\n because its tokens have already replaced the palette outright. Without the\n `:not()` guards a light skin on a dark machine would take these fallbacks for\n every token it did not itself set, which is a light surface carrying dark-mode\n muted text. */\n@media (prefers-color-scheme: dark) {\n .ol-editor:not([data-ol-theme=\"light\"]):not([data-ol-scheme]) {\n --ol-text: var(--openleaf-color-text, #e6edf3);\n --ol-text-muted: var(--openleaf-color-text-muted, #9198a1);\n --ol-surface: var(--openleaf-color-surface, #0d1117);\n --ol-surface-hover: var(--openleaf-color-surface-hover, #21262d);\n --ol-surface-active: var(--openleaf-color-surface-active, #1f3a5f);\n --ol-border: var(--openleaf-color-border, #3d444d);\n --ol-accent: var(--openleaf-color-accent, #79c0ff);\n --ol-focus: var(--openleaf-color-focus, #79c0ff);\n}\n}\n\n.ol-editor[data-ol-theme=\"dark\"]:not([data-ol-scheme]) {\n --ol-text: var(--openleaf-color-text, #e6edf3);\n --ol-text-muted: var(--openleaf-color-text-muted, #9198a1);\n --ol-surface: var(--openleaf-color-surface, #0d1117);\n --ol-surface-hover: var(--openleaf-color-surface-hover, #21262d);\n --ol-surface-active: var(--openleaf-color-surface-active, #1f3a5f);\n --ol-border: var(--openleaf-color-border, #3d444d);\n --ol-accent: var(--openleaf-color-accent, #79c0ff);\n --ol-focus: var(--openleaf-color-focus, #79c0ff);\n}\n\n.ol-editor[data-ol-scheme=\"dark\"] {\n --ol-text: var(--openleaf-color-text, #e6edf3);\n --ol-text-muted: var(--openleaf-color-text-muted, #9198a1);\n --ol-surface: var(--openleaf-color-surface, #0d1117);\n --ol-surface-hover: var(--openleaf-color-surface-hover, #21262d);\n --ol-surface-active: var(--openleaf-color-surface-active, #1f3a5f);\n --ol-border: var(--openleaf-color-border, #3d444d);\n --ol-accent: var(--openleaf-color-accent, #79c0ff);\n --ol-focus: var(--openleaf-color-focus, #79c0ff);\n}\n\n/* Native widget chrome -- the popup a `select` opens, scrollbars, the caret,\n form control backgrounds -- is painted by the browser from `color-scheme`,\n not from any property we can hand an integrator. Left alone it follows the\n page, which is right while the editor's own palette also follows the page and\n wrong the moment either attribute pins the editor to one world. So it is set\n exactly when the editor stops following along, and inherited from the host\n otherwise. */\n.ol-editor[data-ol-theme=\"light\"] { color-scheme: light; }\n.ol-editor[data-ol-theme=\"dark\"] { color-scheme: dark; }\n.ol-editor[data-ol-scheme=\"light\"] { color-scheme: light; }\n.ol-editor[data-ol-scheme=\"dark\"] { color-scheme: dark; }\n\n/* Wrapping, not scrolling and not an overflow menu. Both of those hide\n controls -- one off-screen, one behind a click -- and a formatting control\n the author cannot see is a control they do not have. */\n.ol-editor .ol-toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ol-gap);\n box-sizing: border-box;\n margin: 0;\n padding: 4px;\n border: 1px solid var(--ol-border);\n border-bottom: 0;\n border-radius: var(--ol-radius) var(--ol-radius) 0 0;\n background: var(--ol-surface);\n font: inherit;\n position: relative;\n z-index: var(--ol-z);\n}\n\n.ol-editor .ol-group {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ol-gap);\n}\n\n/* The divider is a BORDER on the group, not a standalone flex item.\n As its own element it could wrap onto the trailing edge of a row with nothing\n after it -- a stranded line floating at the end of a row. Wrapping begins\n around 690-740px, well inside ordinary desktop widths (a CMS sidebar, a\n half-width split pane), so this was not a 360px-only edge case.\n border-inline-start rather than border-left, so it flips under RTL. */\n.ol-editor .ol-group + .ol-group {\n border-inline-start: 1px solid var(--ol-border);\n padding-inline-start: 5px;\n margin-inline-start: 1px;\n}\n\n/* Every property a host reset or `button {}` rule is likely to touch is set\n here explicitly. Specificity is (0,2,0) via the descendant selector, which\n beats a bare element or single-class host rule without resorting to\n !important. */\n.ol-editor .ol-btn {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: var(--ol-button-size);\n height: var(--ol-button-size);\n min-width: var(--ol-button-size);\n min-height: var(--ol-button-size);\n max-width: none;\n padding: 0;\n margin: 0;\n border: 1px solid transparent;\n border-radius: var(--ol-radius);\n background: transparent;\n color: var(--ol-text);\n font: inherit;\n font-family: var(--ol-font);\n font-size: var(--ol-font-size);\n font-weight: 400;\n line-height: 1;\n letter-spacing: normal;\n text-transform: none;\n text-align: center;\n text-decoration: none;\n text-shadow: none;\n box-shadow: none;\n opacity: 1;\n cursor: pointer;\n appearance: none;\n -webkit-appearance: none;\n outline-offset: var(--ol-focus-offset);\n -webkit-tap-highlight-color: transparent;\n transition: background-color 120ms ease, border-color 120ms ease;\n}\n\n.ol-editor .ol-btn:hover {\n background: var(--ol-surface-hover);\n}\n\n/* :focus-visible only, so a mouse click does not leave a ring behind, but the\n ring is never removed for keyboard users. */\n.ol-editor .ol-btn:focus-visible {\n outline: var(--ol-focus-width) solid var(--ol-focus);\n outline-offset: var(--ol-focus-offset);\n}\n\n/* Pressed state is distinguished from hover by THREE signals, not just colour:\n a filled background, a visible border, and an inset shadow that reads as\n physically depressed. Colour alone would fail for a colour-blind author and\n would be invisible in forced-colours mode. */\n.ol-editor .ol-btn[aria-pressed=\"true\"] {\n background: var(--ol-surface-active);\n border-color: var(--ol-accent);\n color: var(--ol-accent);\n box-shadow: inset 0 1px 2px rgb(0 0 0 / 12%);\n}\n\n.ol-editor .ol-btn[aria-pressed=\"true\"]:hover {\n background: var(--ol-surface-active);\n border-color: var(--ol-accent);\n}\n\n/* aria-disabled rather than the disabled attribute: a disabled button is\n removed from the roving tabindex and cannot be reached or announced, so an\n author using a screen reader cannot discover that the control exists. */\n.ol-editor .ol-btn[aria-disabled=\"true\"] {\n opacity: 0.4;\n cursor: default;\n}\n\n.ol-editor .ol-btn[aria-disabled=\"true\"]:hover {\n background: transparent;\n}\n\n.ol-editor .ol-icon {\n width: var(--ol-icon-size);\n height: var(--ol-icon-size);\n display: block;\n pointer-events: none;\n flex: 0 0 auto;\n}\n\n/* Block-type select. Sized and coloured to sit level with the icon buttons so\n it does not read as bolted on, but it stays a native <select> -- a custom\n listbox is a large amount of ARIA that would then owe real screen reader\n testing to be worth anything. */\n.ol-editor .ol-select {\n box-sizing: border-box;\n height: var(--ol-button-size);\n max-width: 11em;\n padding: 0 22px 0 6px;\n margin: 0;\n border: 1px solid var(--ol-border);\n border-radius: var(--ol-radius);\n background-color: transparent;\n background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),\n linear-gradient(135deg, currentColor 50%, transparent 50%);\n background-position: right 10px center, right 6px center;\n background-size: 4px 4px, 4px 4px;\n background-repeat: no-repeat;\n color: var(--ol-text);\n font-family: var(--ol-font);\n font-size: var(--ol-font-size);\n font-weight: 400;\n line-height: 1;\n text-transform: none;\n letter-spacing: normal;\n box-shadow: none;\n cursor: pointer;\n appearance: none;\n -webkit-appearance: none;\n}\n\n.ol-editor .ol-select:hover {\n background-color: var(--ol-surface-hover);\n}\n\n.ol-editor .ol-select:focus-visible {\n outline: var(--ol-focus-width) solid var(--ol-focus);\n outline-offset: var(--ol-focus-offset);\n}\n\n/* The option list is painted by the OS, which does not inherit our tokens, so\n give it explicit colours or dark mode shows black text on black. */\n.ol-editor .ol-select option {\n background: var(--ol-surface);\n color: var(--ol-text);\n}\n\n.ol-editor .ol-content {\n box-sizing: border-box;\n border: 1px solid var(--ol-border);\n border-radius: 0 0 var(--ol-radius) var(--ol-radius);\n background: var(--ol-surface);\n}\n\n/* Deliberately minimal: the content area inherits the host's typography, which\n is the entire reason this project does not use Shadow DOM. Only padding and\n the focus ring are ours. */\n.ol-editor .ol-content .ProseMirror {\n padding: 12px;\n min-height: 8rem;\n outline: none;\n}\n\n.ol-editor .ol-content:focus-within {\n outline: 2px solid var(--ol-focus);\n outline-offset: -1px;\n}\n\n/* Tables.\n These styles live in core, not in the opt-in table plugin, because table\n NODES live in core: every deployment reads and renders tables even where\n editing them is switched off. Unstyled tables would render as runs of\n undelimited text. */\n.ol-editor .ol-content .ProseMirror table {\n border-collapse: collapse;\n table-layout: fixed;\n width: 100%;\n margin: 0 0 1em;\n overflow: hidden;\n}\n\n.ol-editor .ol-content .ProseMirror td,\n.ol-editor .ol-content .ProseMirror th {\n border: 1px solid var(--ol-border);\n padding: 6px 8px;\n vertical-align: top;\n /* A zero-width cell cannot be clicked into, so it cannot be repaired. */\n min-width: 2em;\n position: relative;\n}\n\n.ol-editor .ol-content .ProseMirror th {\n background: var(--ol-surface-hover);\n font-weight: 600;\n text-align: start;\n}\n\n/* prosemirror-tables marks cells in a rectangular selection with this class.\n An ::after overlay rather than a background so it composes with a cell that\n already has one, and so a header cell still reads as a header. */\n.ol-editor .ol-content .ProseMirror .selectedCell::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background: var(--ol-surface-active);\n opacity: 0.4;\n pointer-events: none;\n}\n\n/* The column resize handle, drawn by prosemirror-tables' columnResizing. */\n.ol-editor .ol-content .ProseMirror .column-resize-handle {\n position: absolute;\n right: -2px;\n top: 0;\n bottom: 0;\n width: 4px;\n background: var(--ol-accent);\n pointer-events: none;\n z-index: 20;\n}\n\n.ol-editor .ol-content .ProseMirror.resize-cursor {\n cursor: col-resize;\n}\n\n/* Preserved-but-unrecognised markup, surfaced rather than hidden. */\n.ol-editor .ol-content .ProseMirror-selectednode {\n outline: 2px solid var(--ol-focus);\n outline-offset: 2px;\n border-radius: 2px;\n}\n\n.ol-editor .ol-source {\n box-sizing: border-box;\n display: block;\n width: 100%;\n min-height: 12rem;\n padding: 12px;\n border: 1px solid var(--ol-border);\n border-radius: 0 0 var(--ol-radius) var(--ol-radius);\n background: var(--ol-surface);\n color: var(--ol-text);\n font-family: var(--ol-font-mono);\n font-size: 13px;\n line-height: 1.5;\n resize: vertical;\n white-space: pre-wrap;\n}\n\n/* Directional icons under RTL.\n Group order reverses for free with flexbox, but a curved undo arrow does not:\n in an RTL document \"back\" points the other way. Only genuinely directional\n icons are flipped -- bold and italic must not be mirrored. */\n.ol-editor[dir=\"rtl\"] .ol-icon--directional,\n[dir=\"rtl\"] .ol-editor .ol-icon--directional {\n transform: scaleX(-1);\n}\n\n/* The announcement region. Visually hidden but not display:none, which would\n remove it from the accessibility tree and silence it. */\n.ol-editor .ol-live {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n/* Coarse pointers get a larger target. WCAG 2.2 SC 2.5.8 asks for 24x24 CSS px\n minimum; 32 clears that on a mouse and 40 is comfortable on a thumb. */\n@media (pointer: coarse) {\n .ol-editor {\n --ol-button-size: var(--openleaf-button-size, 40px);\n --ol-gap: var(--openleaf-gap, 4px);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .ol-editor .ol-btn {\n transition: none;\n }\n}\n\n/* Forced colours (Windows high contrast) replaces our palette wholesale. The\n pressed state must not depend on a background we no longer control, so it is\n re-expressed as a border, which the mode preserves. */\n@media (forced-colors: active) {\n .ol-editor .ol-btn {\n border-color: ButtonBorder;\n color: ButtonText;\n }\n .ol-editor .ol-btn[aria-pressed=\"true\"] {\n border-color: Highlight;\n color: Highlight;\n box-shadow: none;\n }\n .ol-editor .ol-btn:focus-visible {\n outline-color: Highlight;\n }\n .ol-editor .ol-btn[aria-disabled=\"true\"] {\n color: GrayText;\n opacity: 1;\n }\n}\n";
|
|
38
|
+
export declare const CSS = "\n.ol-editor {\n /* Two families, named before either is public API. A singular\n `--openleaf-font` implies \"the\" font, and source view already has a\n monospace surface -- bolting a mono token on beside a singular name later\n is the awkward outcome worth avoiding now. `--openleaf-font` is still\n honoured as a fallback. */\n --ol-font: var(--openleaf-font-ui, var(--openleaf-font, system-ui, -apple-system, \"Segoe UI\", sans-serif));\n --ol-font-mono: var(--openleaf-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);\n --ol-font-size: var(--openleaf-font-size, 14px);\n --ol-radius: var(--openleaf-radius, 4px);\n --ol-text: var(--openleaf-color-text, #1f2328);\n --ol-text-muted: var(--openleaf-color-text-muted, #59636e);\n --ol-surface: var(--openleaf-color-surface, #ffffff);\n --ol-surface-hover: var(--openleaf-color-surface-hover, #f0f1f3);\n --ol-surface-active: var(--openleaf-color-surface-active, #dbe9ff);\n --ol-border: var(--openleaf-color-border, #d1d9e0);\n --ol-accent: var(--openleaf-color-accent, #0550ae);\n --ol-focus: var(--openleaf-color-focus, #0969da);\n --ol-button-size: var(--openleaf-button-size, 32px);\n --ol-icon-size: var(--openleaf-icon-size, 16px);\n --ol-gap: var(--openleaf-gap, 2px);\n /* A 2009 WordPress admin bar sits at z-index 99999 and Drupal's toolbar plays\n similar games. Without a sanctioned escape hatch integrators fix a toolbar\n rendered behind a sticky host header with !important -- the exact thing the\n token API exists to prevent. */\n --ol-z: var(--openleaf-z-index, 1);\n /* Thickness and offset, not just colour: \"you can change the colour but not\n the thickness\" is a poor answer to a Section 508 team citing WCAG 2.2\n Focus Appearance. */\n --ol-focus-width: var(--openleaf-focus-width, 2px);\n --ol-focus-offset: var(--openleaf-focus-offset, 1px);\n\n display: block;\n position: relative;\n color: var(--ol-text);\n}\n\n/* Three ways into the dark palette, and one way out of it.\n `data-ol-scheme` is set from the applied skin's declared scheme, and a skin\n that declares one outranks both the attribute and the system -- it has to,\n because its tokens have already replaced the palette outright. Without the\n `:not()` guards a light skin on a dark machine would take these fallbacks for\n every token it did not itself set, which is a light surface carrying dark-mode\n muted text. */\n@media (prefers-color-scheme: dark) {\n .ol-editor:not([data-ol-theme=\"light\"]):not([data-ol-scheme]) {\n --ol-text: var(--openleaf-color-text, #e6edf3);\n --ol-text-muted: var(--openleaf-color-text-muted, #9198a1);\n --ol-surface: var(--openleaf-color-surface, #0d1117);\n --ol-surface-hover: var(--openleaf-color-surface-hover, #21262d);\n --ol-surface-active: var(--openleaf-color-surface-active, #1f3a5f);\n --ol-border: var(--openleaf-color-border, #3d444d);\n --ol-accent: var(--openleaf-color-accent, #79c0ff);\n --ol-focus: var(--openleaf-color-focus, #79c0ff);\n}\n}\n\n.ol-editor[data-ol-theme=\"dark\"]:not([data-ol-scheme]) {\n --ol-text: var(--openleaf-color-text, #e6edf3);\n --ol-text-muted: var(--openleaf-color-text-muted, #9198a1);\n --ol-surface: var(--openleaf-color-surface, #0d1117);\n --ol-surface-hover: var(--openleaf-color-surface-hover, #21262d);\n --ol-surface-active: var(--openleaf-color-surface-active, #1f3a5f);\n --ol-border: var(--openleaf-color-border, #3d444d);\n --ol-accent: var(--openleaf-color-accent, #79c0ff);\n --ol-focus: var(--openleaf-color-focus, #79c0ff);\n}\n\n.ol-editor[data-ol-scheme=\"dark\"] {\n --ol-text: var(--openleaf-color-text, #e6edf3);\n --ol-text-muted: var(--openleaf-color-text-muted, #9198a1);\n --ol-surface: var(--openleaf-color-surface, #0d1117);\n --ol-surface-hover: var(--openleaf-color-surface-hover, #21262d);\n --ol-surface-active: var(--openleaf-color-surface-active, #1f3a5f);\n --ol-border: var(--openleaf-color-border, #3d444d);\n --ol-accent: var(--openleaf-color-accent, #79c0ff);\n --ol-focus: var(--openleaf-color-focus, #79c0ff);\n}\n\n/* Native widget chrome -- the popup a `select` opens, scrollbars, the caret,\n form control backgrounds -- is painted by the browser from `color-scheme`,\n not from any property we can hand an integrator. Left alone it follows the\n page, which is right while the editor's own palette also follows the page and\n wrong the moment either attribute pins the editor to one world. So it is set\n exactly when the editor stops following along, and inherited from the host\n otherwise. */\n.ol-editor[data-ol-theme=\"light\"] { color-scheme: light; }\n.ol-editor[data-ol-theme=\"dark\"] { color-scheme: dark; }\n.ol-editor[data-ol-scheme=\"light\"] { color-scheme: light; }\n.ol-editor[data-ol-scheme=\"dark\"] { color-scheme: dark; }\n\n/* Wrapping, not scrolling and not an overflow menu. Both of those hide\n controls -- one off-screen, one behind a click -- and a formatting control\n the author cannot see is a control they do not have. */\n.ol-editor .ol-toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ol-gap);\n box-sizing: border-box;\n margin: 0;\n padding: 4px;\n border: 1px solid var(--ol-border);\n border-bottom: 0;\n border-radius: var(--ol-radius) var(--ol-radius) 0 0;\n background: var(--ol-surface);\n font: inherit;\n position: relative;\n z-index: var(--ol-z);\n}\n\n.ol-editor .ol-group {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ol-gap);\n}\n\n/* The divider is a BORDER on the group, not a standalone flex item.\n As its own element it could wrap onto the trailing edge of a row with nothing\n after it -- a stranded line floating at the end of a row. Wrapping begins\n around 690-740px, well inside ordinary desktop widths (a CMS sidebar, a\n half-width split pane), so this was not a 360px-only edge case.\n border-inline-start rather than border-left, so it flips under RTL. */\n.ol-editor .ol-group + .ol-group {\n border-inline-start: 1px solid var(--ol-border);\n padding-inline-start: 5px;\n margin-inline-start: 1px;\n}\n\n/* Every property a host reset or `button {}` rule is likely to touch is set\n here explicitly. Specificity is (0,2,0) via the descendant selector, which\n beats a bare element or single-class host rule without resorting to\n !important. */\n.ol-editor .ol-btn {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: var(--ol-button-size);\n height: var(--ol-button-size);\n min-width: var(--ol-button-size);\n min-height: var(--ol-button-size);\n max-width: none;\n padding: 0;\n margin: 0;\n border: 1px solid transparent;\n border-radius: var(--ol-radius);\n background: transparent;\n color: var(--ol-text);\n font: inherit;\n font-family: var(--ol-font);\n font-size: var(--ol-font-size);\n font-weight: 400;\n line-height: 1;\n letter-spacing: normal;\n text-transform: none;\n text-align: center;\n text-decoration: none;\n text-shadow: none;\n box-shadow: none;\n opacity: 1;\n cursor: pointer;\n appearance: none;\n -webkit-appearance: none;\n outline-offset: var(--ol-focus-offset);\n -webkit-tap-highlight-color: transparent;\n transition: background-color 120ms ease, border-color 120ms ease;\n}\n\n.ol-editor .ol-btn:hover {\n background: var(--ol-surface-hover);\n}\n\n/* :focus-visible only, so a mouse click does not leave a ring behind, but the\n ring is never removed for keyboard users. */\n.ol-editor .ol-btn:focus-visible {\n outline: var(--ol-focus-width) solid var(--ol-focus);\n outline-offset: var(--ol-focus-offset);\n}\n\n/* Pressed state is distinguished from hover by THREE signals, not just colour:\n a filled background, a visible border, and an inset shadow that reads as\n physically depressed. Colour alone would fail for a colour-blind author and\n would be invisible in forced-colours mode. */\n.ol-editor .ol-btn[aria-pressed=\"true\"] {\n background: var(--ol-surface-active);\n border-color: var(--ol-accent);\n color: var(--ol-accent);\n box-shadow: inset 0 1px 2px rgb(0 0 0 / 12%);\n}\n\n.ol-editor .ol-btn[aria-pressed=\"true\"]:hover {\n background: var(--ol-surface-active);\n border-color: var(--ol-accent);\n}\n\n/* aria-disabled rather than the disabled attribute: a disabled button is\n removed from the roving tabindex and cannot be reached or announced, so an\n author using a screen reader cannot discover that the control exists. */\n.ol-editor .ol-btn[aria-disabled=\"true\"] {\n opacity: 0.4;\n cursor: default;\n}\n\n.ol-editor .ol-btn[aria-disabled=\"true\"]:hover {\n background: transparent;\n}\n\n.ol-editor .ol-icon {\n width: var(--ol-icon-size);\n height: var(--ol-icon-size);\n display: block;\n pointer-events: none;\n flex: 0 0 auto;\n}\n\n/* Block-type select. Sized and coloured to sit level with the icon buttons so\n it does not read as bolted on, but it stays a native <select> -- a custom\n listbox is a large amount of ARIA that would then owe real screen reader\n testing to be worth anything. */\n.ol-editor .ol-select {\n box-sizing: border-box;\n height: var(--ol-button-size);\n max-width: 11em;\n padding: 0 22px 0 6px;\n margin: 0;\n border: 1px solid var(--ol-border);\n border-radius: var(--ol-radius);\n background-color: transparent;\n background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),\n linear-gradient(135deg, currentColor 50%, transparent 50%);\n background-position: right 10px center, right 6px center;\n background-size: 4px 4px, 4px 4px;\n background-repeat: no-repeat;\n color: var(--ol-text);\n font-family: var(--ol-font);\n font-size: var(--ol-font-size);\n font-weight: 400;\n line-height: 1;\n text-transform: none;\n letter-spacing: normal;\n box-shadow: none;\n cursor: pointer;\n appearance: none;\n -webkit-appearance: none;\n}\n\n.ol-editor .ol-select:hover {\n background-color: var(--ol-surface-hover);\n}\n\n.ol-editor .ol-select:focus-visible {\n outline: var(--ol-focus-width) solid var(--ol-focus);\n outline-offset: var(--ol-focus-offset);\n}\n\n/* The option list is painted by the OS, which does not inherit our tokens, so\n give it explicit colours or dark mode shows black text on black. */\n.ol-editor .ol-select option {\n background: var(--ol-surface);\n color: var(--ol-text);\n}\n\n.ol-editor .ol-content {\n box-sizing: border-box;\n border: 1px solid var(--ol-border);\n border-radius: 0 0 var(--ol-radius) var(--ol-radius);\n background: var(--ol-surface);\n}\n\n/* Deliberately minimal: the content area inherits the host's typography, which\n is the entire reason this project does not use Shadow DOM. Only padding and\n the focus ring are ours. */\n.ol-editor .ol-content .ProseMirror {\n padding: 12px;\n min-height: 8rem;\n outline: none;\n}\n\n.ol-editor .ol-content:focus-within {\n outline: 2px solid var(--ol-focus);\n outline-offset: -1px;\n}\n\n/* Tables.\n These styles live in core, not in the opt-in table plugin, because table\n NODES live in core: every deployment reads and renders tables even where\n editing them is switched off. Unstyled tables would render as runs of\n undelimited text. */\n.ol-editor .ol-content .ProseMirror table {\n border-collapse: collapse;\n table-layout: fixed;\n width: 100%;\n margin: 0 0 1em;\n overflow: hidden;\n}\n\n.ol-editor .ol-content .ProseMirror td,\n.ol-editor .ol-content .ProseMirror th {\n border: 1px solid var(--ol-border);\n padding: 6px 8px;\n vertical-align: top;\n /* A zero-width cell cannot be clicked into, so it cannot be repaired. */\n min-width: 2em;\n position: relative;\n}\n\n/* Presentational valign is otherwise beaten by the rule above, which would\n make the cell-properties dialog a no-op on screen. */\n.ol-editor .ol-content .ProseMirror td[valign=\"middle\"],\n.ol-editor .ol-content .ProseMirror th[valign=\"middle\"] { vertical-align: middle; }\n.ol-editor .ol-content .ProseMirror td[valign=\"bottom\"],\n.ol-editor .ol-content .ProseMirror th[valign=\"bottom\"] { vertical-align: bottom; }\n.ol-editor .ol-content .ProseMirror td[valign=\"baseline\"],\n.ol-editor .ol-content .ProseMirror th[valign=\"baseline\"] { vertical-align: baseline; }\n\n.ol-editor .ol-content .ProseMirror th {\n background: var(--ol-surface-hover);\n font-weight: 600;\n text-align: start;\n}\n\n/* prosemirror-tables marks cells in a rectangular selection with this class.\n An ::after overlay rather than a background so it composes with a cell that\n already has one, and so a header cell still reads as a header. */\n.ol-editor .ol-content .ProseMirror .selectedCell::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background: var(--ol-surface-active);\n opacity: 0.4;\n pointer-events: none;\n}\n\n/* The column resize handle, drawn by prosemirror-tables' columnResizing. */\n.ol-editor .ol-content .ProseMirror .column-resize-handle {\n position: absolute;\n right: -2px;\n top: 0;\n bottom: 0;\n width: 4px;\n background: var(--ol-accent);\n pointer-events: none;\n z-index: 20;\n}\n\n.ol-editor .ol-content .ProseMirror.resize-cursor {\n cursor: col-resize;\n}\n\n.ol-editor .ol-content .ProseMirror img.ol-float-left {\n float: left;\n margin: 0 1em 0.5em 0;\n}\n.ol-editor .ol-content .ProseMirror img.ol-float-right {\n float: right;\n margin: 0 0 0.5em 1em;\n}\n.ol-editor .ol-content .ProseMirror img.ol-align-center {\n display: block;\n margin: 0 auto 0.5em;\n}\n.ol-editor .ol-content .ProseMirror figure {\n margin: 0 0 1em;\n}\n.ol-editor .ol-content .ProseMirror figcaption {\n font-size: .9em;\n opacity: .8;\n margin-top: .35em;\n}\n.ol-editor .ol-content .ProseMirror details {\n border: 1px solid var(--ol-border);\n border-radius: var(--ol-radius);\n padding: .5em .75em;\n margin: 0 0 1em;\n}\n.ol-editor .ol-content .ProseMirror summary {\n cursor: pointer;\n font-weight: 600;\n}\n.ol-editor .ol-content .ProseMirror hr.ol-pagebreak {\n border: 0;\n border-top: 2px dashed var(--ol-border);\n margin: 1.5em 0;\n}\n.ol-editor .ol-content .ProseMirror iframe,\n.ol-editor .ol-content .ProseMirror video,\n.ol-editor .ol-content .ProseMirror audio {\n max-width: 100%;\n}\n\n/* Preserved-but-unrecognised markup, surfaced rather than hidden. */\n.ol-editor .ol-content .ProseMirror-selectednode {\n outline: 2px solid var(--ol-focus);\n outline-offset: 2px;\n border-radius: 2px;\n}\n\n.ol-editor .ol-source {\n box-sizing: border-box;\n display: block;\n width: 100%;\n min-height: 12rem;\n padding: 12px;\n border: 1px solid var(--ol-border);\n border-radius: 0 0 var(--ol-radius) var(--ol-radius);\n background: var(--ol-surface);\n color: var(--ol-text);\n font-family: var(--ol-font-mono);\n font-size: 13px;\n line-height: 1.5;\n resize: vertical;\n white-space: pre-wrap;\n}\n\n/* Directional icons under RTL.\n Group order reverses for free with flexbox, but a curved undo arrow does not:\n in an RTL document \"back\" points the other way. Only genuinely directional\n icons are flipped -- bold and italic must not be mirrored. */\n.ol-editor[dir=\"rtl\"] .ol-icon--directional,\n[dir=\"rtl\"] .ol-editor .ol-icon--directional {\n transform: scaleX(-1);\n}\n\n/* The announcement region. Visually hidden but not display:none, which would\n remove it from the accessibility tree and silence it. */\n.ol-editor .ol-live {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n/* Menubar, menus, floating chrome, visual aids, fullscreen, inline. */\n.ol-editor .ol-menubar {\n display: flex;\n flex-wrap: wrap;\n gap: var(--ol-gap);\n box-sizing: border-box;\n margin: 0;\n padding: 2px 4px;\n border: 1px solid var(--ol-border);\n border-bottom: 0;\n border-radius: var(--ol-radius) var(--ol-radius) 0 0;\n background: var(--ol-surface);\n position: relative;\n z-index: var(--ol-z);\n}\n.ol-editor .ol-menubar + .ol-toolbar {\n border-radius: 0;\n}\n.ol-editor .ol-menu-trigger {\n box-sizing: border-box;\n margin: 0;\n padding: 4px 8px;\n border: 1px solid transparent;\n border-radius: var(--ol-radius);\n background: transparent;\n color: var(--ol-text);\n font: inherit;\n font-family: var(--ol-font);\n font-size: var(--ol-font-size);\n cursor: pointer;\n appearance: none;\n}\n.ol-editor .ol-menu-trigger:hover,\n.ol-editor .ol-menu-trigger[aria-expanded=\"true\"] {\n background: var(--ol-surface-hover);\n}\n.ol-editor .ol-menu-trigger:focus-visible {\n outline: var(--ol-focus-width) solid var(--ol-focus);\n outline-offset: var(--ol-focus-offset);\n}\n.ol-editor .ol-menu {\n position: absolute;\n z-index: calc(var(--ol-z) + 20);\n min-width: 12rem;\n margin: 0;\n padding: 4px;\n border: 1px solid var(--ol-border);\n border-radius: var(--ol-radius);\n background: var(--ol-surface);\n box-shadow: 0 8px 24px rgb(0 0 0 / 12%);\n}\n.ol-editor .ol-menu-item {\n display: block;\n box-sizing: border-box;\n width: 100%;\n margin: 0;\n padding: 6px 10px;\n border: 0;\n border-radius: var(--ol-radius);\n background: transparent;\n color: var(--ol-text);\n font: inherit;\n font-family: var(--ol-font);\n font-size: var(--ol-font-size);\n text-align: start;\n cursor: pointer;\n appearance: none;\n}\n.ol-editor .ol-menu-item:hover,\n.ol-editor .ol-menu-item:focus-visible {\n background: var(--ol-surface-hover);\n outline: none;\n}\n.ol-editor .ol-menu-item[aria-disabled=\"true\"] {\n opacity: 0.4;\n cursor: default;\n}\n.ol-editor .ol-menu-sep {\n height: 1px;\n margin: 4px 0;\n background: var(--ol-border);\n}\n.ol-editor .ol-toolbar.ol-floating {\n position: absolute;\n flex-wrap: nowrap;\n border: 1px solid var(--ol-border);\n border-radius: var(--ol-radius);\n box-shadow: 0 8px 24px rgb(0 0 0 / 12%);\n z-index: calc(var(--ol-z) + 10);\n}\n.ol-editor .ol-toolbar.ol-toolbar--overflow {\n flex-wrap: nowrap;\n overflow: hidden;\n}\n.ol-editor.ol-visual-aids .ol-empty-block {\n outline: 1px dashed var(--ol-border);\n outline-offset: 2px;\n min-height: 1.2em;\n}\n.ol-editor.ol-visual-aids .ol-nbsp {\n background: color-mix(in srgb, var(--ol-accent) 25%, transparent);\n box-shadow: inset 0 -1px 0 var(--ol-accent);\n}\n.ol-editor.ol-visual-aids .ol-hidden-structure {\n outline: 1px dotted var(--ol-accent);\n outline-offset: 2px;\n}\n.ol-editor .ol-noneditable {\n cursor: default;\n background: repeating-linear-gradient(\n -45deg,\n transparent,\n transparent 6px,\n color-mix(in srgb, var(--ol-border) 35%, transparent) 6px,\n color-mix(in srgb, var(--ol-border) 35%, transparent) 7px\n );\n}\n.ol-editor.ol-fullscreen {\n position: fixed;\n inset: 0;\n z-index: 2147483000;\n margin: 0;\n border-radius: 0;\n background: var(--ol-surface);\n display: flex;\n flex-direction: column;\n}\n.ol-editor.ol-fullscreen .ol-content,\n.ol-editor.ol-fullscreen .ol-source {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n}\n.ol-editor.ol-autoresize .ol-content .ProseMirror {\n overflow: hidden;\n}\n.ol-editor.ol-inline:not(.ol-inline-active) .ol-toolbar,\n.ol-editor.ol-inline:not(.ol-inline-active) .ol-menubar {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n clip-path: inset(50%);\n}\n.ol-editor.ol-inline .ol-content {\n border-radius: var(--ol-radius);\n}\n.ol-help-table {\n width: 100%;\n border-collapse: collapse;\n font: inherit;\n}\n.ol-help-table th,\n.ol-help-table td {\n padding: 4px 8px;\n text-align: start;\n vertical-align: top;\n border-bottom: 1px solid var(--openleaf-color-border, #d1d9e0);\n}\n.ol-help-table th {\n font-weight: 600;\n white-space: nowrap;\n}\n\n/* Coarse pointers get a larger target. WCAG 2.2 SC 2.5.8 asks for 24x24 CSS px\n minimum; 32 clears that on a mouse and 40 is comfortable on a thumb. */\n@media (pointer: coarse) {\n .ol-editor {\n --ol-button-size: var(--openleaf-button-size, 40px);\n --ol-gap: var(--openleaf-gap, 4px);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .ol-editor .ol-btn {\n transition: none;\n }\n}\n\n/* Forced colours (Windows high contrast) replaces our palette wholesale. The\n pressed state must not depend on a background we no longer control, so it is\n re-expressed as a border, which the mode preserves. */\n@media (forced-colors: active) {\n .ol-editor .ol-btn {\n border-color: ButtonBorder;\n color: ButtonText;\n }\n .ol-editor .ol-btn[aria-pressed=\"true\"] {\n border-color: Highlight;\n color: Highlight;\n box-shadow: none;\n }\n .ol-editor .ol-btn:focus-visible {\n outline-color: Highlight;\n }\n .ol-editor .ol-btn[aria-disabled=\"true\"] {\n color: GrayText;\n opacity: 1;\n }\n}\n";
|
|
39
39
|
/**
|
|
40
40
|
* Declare that the integrator has linked `openleaf.css` themselves, so no
|
|
41
41
|
* injection is attempted. Call before the first editor is created.
|
package/dist/styles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAqBH,eAAO,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAqBH,eAAO,MAAM,GAAG,mgpBAwmBf,CAAA;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAoCpG;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAM9F"}
|
package/dist/styles.js
CHANGED
|
@@ -87,6 +87,7 @@ export const CSS = `
|
|
|
87
87
|
--ol-focus-offset: var(--openleaf-focus-offset, 1px);
|
|
88
88
|
|
|
89
89
|
display: block;
|
|
90
|
+
position: relative;
|
|
90
91
|
color: var(--ol-text);
|
|
91
92
|
}
|
|
92
93
|
|
|
@@ -335,6 +336,15 @@ export const CSS = `
|
|
|
335
336
|
position: relative;
|
|
336
337
|
}
|
|
337
338
|
|
|
339
|
+
/* Presentational valign is otherwise beaten by the rule above, which would
|
|
340
|
+
make the cell-properties dialog a no-op on screen. */
|
|
341
|
+
.ol-editor .ol-content .ProseMirror td[valign="middle"],
|
|
342
|
+
.ol-editor .ol-content .ProseMirror th[valign="middle"] { vertical-align: middle; }
|
|
343
|
+
.ol-editor .ol-content .ProseMirror td[valign="bottom"],
|
|
344
|
+
.ol-editor .ol-content .ProseMirror th[valign="bottom"] { vertical-align: bottom; }
|
|
345
|
+
.ol-editor .ol-content .ProseMirror td[valign="baseline"],
|
|
346
|
+
.ol-editor .ol-content .ProseMirror th[valign="baseline"] { vertical-align: baseline; }
|
|
347
|
+
|
|
338
348
|
.ol-editor .ol-content .ProseMirror th {
|
|
339
349
|
background: var(--ol-surface-hover);
|
|
340
350
|
font-weight: 600;
|
|
@@ -369,6 +379,47 @@ export const CSS = `
|
|
|
369
379
|
cursor: col-resize;
|
|
370
380
|
}
|
|
371
381
|
|
|
382
|
+
.ol-editor .ol-content .ProseMirror img.ol-float-left {
|
|
383
|
+
float: left;
|
|
384
|
+
margin: 0 1em 0.5em 0;
|
|
385
|
+
}
|
|
386
|
+
.ol-editor .ol-content .ProseMirror img.ol-float-right {
|
|
387
|
+
float: right;
|
|
388
|
+
margin: 0 0 0.5em 1em;
|
|
389
|
+
}
|
|
390
|
+
.ol-editor .ol-content .ProseMirror img.ol-align-center {
|
|
391
|
+
display: block;
|
|
392
|
+
margin: 0 auto 0.5em;
|
|
393
|
+
}
|
|
394
|
+
.ol-editor .ol-content .ProseMirror figure {
|
|
395
|
+
margin: 0 0 1em;
|
|
396
|
+
}
|
|
397
|
+
.ol-editor .ol-content .ProseMirror figcaption {
|
|
398
|
+
font-size: .9em;
|
|
399
|
+
opacity: .8;
|
|
400
|
+
margin-top: .35em;
|
|
401
|
+
}
|
|
402
|
+
.ol-editor .ol-content .ProseMirror details {
|
|
403
|
+
border: 1px solid var(--ol-border);
|
|
404
|
+
border-radius: var(--ol-radius);
|
|
405
|
+
padding: .5em .75em;
|
|
406
|
+
margin: 0 0 1em;
|
|
407
|
+
}
|
|
408
|
+
.ol-editor .ol-content .ProseMirror summary {
|
|
409
|
+
cursor: pointer;
|
|
410
|
+
font-weight: 600;
|
|
411
|
+
}
|
|
412
|
+
.ol-editor .ol-content .ProseMirror hr.ol-pagebreak {
|
|
413
|
+
border: 0;
|
|
414
|
+
border-top: 2px dashed var(--ol-border);
|
|
415
|
+
margin: 1.5em 0;
|
|
416
|
+
}
|
|
417
|
+
.ol-editor .ol-content .ProseMirror iframe,
|
|
418
|
+
.ol-editor .ol-content .ProseMirror video,
|
|
419
|
+
.ol-editor .ol-content .ProseMirror audio {
|
|
420
|
+
max-width: 100%;
|
|
421
|
+
}
|
|
422
|
+
|
|
372
423
|
/* Preserved-but-unrecognised markup, surfaced rather than hidden. */
|
|
373
424
|
.ol-editor .ol-content .ProseMirror-selectednode {
|
|
374
425
|
outline: 2px solid var(--ol-focus);
|
|
@@ -417,6 +468,171 @@ export const CSS = `
|
|
|
417
468
|
border: 0;
|
|
418
469
|
}
|
|
419
470
|
|
|
471
|
+
/* Menubar, menus, floating chrome, visual aids, fullscreen, inline. */
|
|
472
|
+
.ol-editor .ol-menubar {
|
|
473
|
+
display: flex;
|
|
474
|
+
flex-wrap: wrap;
|
|
475
|
+
gap: var(--ol-gap);
|
|
476
|
+
box-sizing: border-box;
|
|
477
|
+
margin: 0;
|
|
478
|
+
padding: 2px 4px;
|
|
479
|
+
border: 1px solid var(--ol-border);
|
|
480
|
+
border-bottom: 0;
|
|
481
|
+
border-radius: var(--ol-radius) var(--ol-radius) 0 0;
|
|
482
|
+
background: var(--ol-surface);
|
|
483
|
+
position: relative;
|
|
484
|
+
z-index: var(--ol-z);
|
|
485
|
+
}
|
|
486
|
+
.ol-editor .ol-menubar + .ol-toolbar {
|
|
487
|
+
border-radius: 0;
|
|
488
|
+
}
|
|
489
|
+
.ol-editor .ol-menu-trigger {
|
|
490
|
+
box-sizing: border-box;
|
|
491
|
+
margin: 0;
|
|
492
|
+
padding: 4px 8px;
|
|
493
|
+
border: 1px solid transparent;
|
|
494
|
+
border-radius: var(--ol-radius);
|
|
495
|
+
background: transparent;
|
|
496
|
+
color: var(--ol-text);
|
|
497
|
+
font: inherit;
|
|
498
|
+
font-family: var(--ol-font);
|
|
499
|
+
font-size: var(--ol-font-size);
|
|
500
|
+
cursor: pointer;
|
|
501
|
+
appearance: none;
|
|
502
|
+
}
|
|
503
|
+
.ol-editor .ol-menu-trigger:hover,
|
|
504
|
+
.ol-editor .ol-menu-trigger[aria-expanded="true"] {
|
|
505
|
+
background: var(--ol-surface-hover);
|
|
506
|
+
}
|
|
507
|
+
.ol-editor .ol-menu-trigger:focus-visible {
|
|
508
|
+
outline: var(--ol-focus-width) solid var(--ol-focus);
|
|
509
|
+
outline-offset: var(--ol-focus-offset);
|
|
510
|
+
}
|
|
511
|
+
.ol-editor .ol-menu {
|
|
512
|
+
position: absolute;
|
|
513
|
+
z-index: calc(var(--ol-z) + 20);
|
|
514
|
+
min-width: 12rem;
|
|
515
|
+
margin: 0;
|
|
516
|
+
padding: 4px;
|
|
517
|
+
border: 1px solid var(--ol-border);
|
|
518
|
+
border-radius: var(--ol-radius);
|
|
519
|
+
background: var(--ol-surface);
|
|
520
|
+
box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
|
|
521
|
+
}
|
|
522
|
+
.ol-editor .ol-menu-item {
|
|
523
|
+
display: block;
|
|
524
|
+
box-sizing: border-box;
|
|
525
|
+
width: 100%;
|
|
526
|
+
margin: 0;
|
|
527
|
+
padding: 6px 10px;
|
|
528
|
+
border: 0;
|
|
529
|
+
border-radius: var(--ol-radius);
|
|
530
|
+
background: transparent;
|
|
531
|
+
color: var(--ol-text);
|
|
532
|
+
font: inherit;
|
|
533
|
+
font-family: var(--ol-font);
|
|
534
|
+
font-size: var(--ol-font-size);
|
|
535
|
+
text-align: start;
|
|
536
|
+
cursor: pointer;
|
|
537
|
+
appearance: none;
|
|
538
|
+
}
|
|
539
|
+
.ol-editor .ol-menu-item:hover,
|
|
540
|
+
.ol-editor .ol-menu-item:focus-visible {
|
|
541
|
+
background: var(--ol-surface-hover);
|
|
542
|
+
outline: none;
|
|
543
|
+
}
|
|
544
|
+
.ol-editor .ol-menu-item[aria-disabled="true"] {
|
|
545
|
+
opacity: 0.4;
|
|
546
|
+
cursor: default;
|
|
547
|
+
}
|
|
548
|
+
.ol-editor .ol-menu-sep {
|
|
549
|
+
height: 1px;
|
|
550
|
+
margin: 4px 0;
|
|
551
|
+
background: var(--ol-border);
|
|
552
|
+
}
|
|
553
|
+
.ol-editor .ol-toolbar.ol-floating {
|
|
554
|
+
position: absolute;
|
|
555
|
+
flex-wrap: nowrap;
|
|
556
|
+
border: 1px solid var(--ol-border);
|
|
557
|
+
border-radius: var(--ol-radius);
|
|
558
|
+
box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
|
|
559
|
+
z-index: calc(var(--ol-z) + 10);
|
|
560
|
+
}
|
|
561
|
+
.ol-editor .ol-toolbar.ol-toolbar--overflow {
|
|
562
|
+
flex-wrap: nowrap;
|
|
563
|
+
overflow: hidden;
|
|
564
|
+
}
|
|
565
|
+
.ol-editor.ol-visual-aids .ol-empty-block {
|
|
566
|
+
outline: 1px dashed var(--ol-border);
|
|
567
|
+
outline-offset: 2px;
|
|
568
|
+
min-height: 1.2em;
|
|
569
|
+
}
|
|
570
|
+
.ol-editor.ol-visual-aids .ol-nbsp {
|
|
571
|
+
background: color-mix(in srgb, var(--ol-accent) 25%, transparent);
|
|
572
|
+
box-shadow: inset 0 -1px 0 var(--ol-accent);
|
|
573
|
+
}
|
|
574
|
+
.ol-editor.ol-visual-aids .ol-hidden-structure {
|
|
575
|
+
outline: 1px dotted var(--ol-accent);
|
|
576
|
+
outline-offset: 2px;
|
|
577
|
+
}
|
|
578
|
+
.ol-editor .ol-noneditable {
|
|
579
|
+
cursor: default;
|
|
580
|
+
background: repeating-linear-gradient(
|
|
581
|
+
-45deg,
|
|
582
|
+
transparent,
|
|
583
|
+
transparent 6px,
|
|
584
|
+
color-mix(in srgb, var(--ol-border) 35%, transparent) 6px,
|
|
585
|
+
color-mix(in srgb, var(--ol-border) 35%, transparent) 7px
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
.ol-editor.ol-fullscreen {
|
|
589
|
+
position: fixed;
|
|
590
|
+
inset: 0;
|
|
591
|
+
z-index: 2147483000;
|
|
592
|
+
margin: 0;
|
|
593
|
+
border-radius: 0;
|
|
594
|
+
background: var(--ol-surface);
|
|
595
|
+
display: flex;
|
|
596
|
+
flex-direction: column;
|
|
597
|
+
}
|
|
598
|
+
.ol-editor.ol-fullscreen .ol-content,
|
|
599
|
+
.ol-editor.ol-fullscreen .ol-source {
|
|
600
|
+
flex: 1 1 auto;
|
|
601
|
+
min-height: 0;
|
|
602
|
+
overflow: auto;
|
|
603
|
+
}
|
|
604
|
+
.ol-editor.ol-autoresize .ol-content .ProseMirror {
|
|
605
|
+
overflow: hidden;
|
|
606
|
+
}
|
|
607
|
+
.ol-editor.ol-inline:not(.ol-inline-active) .ol-toolbar,
|
|
608
|
+
.ol-editor.ol-inline:not(.ol-inline-active) .ol-menubar {
|
|
609
|
+
position: absolute;
|
|
610
|
+
width: 1px;
|
|
611
|
+
height: 1px;
|
|
612
|
+
overflow: hidden;
|
|
613
|
+
clip: rect(0 0 0 0);
|
|
614
|
+
clip-path: inset(50%);
|
|
615
|
+
}
|
|
616
|
+
.ol-editor.ol-inline .ol-content {
|
|
617
|
+
border-radius: var(--ol-radius);
|
|
618
|
+
}
|
|
619
|
+
.ol-help-table {
|
|
620
|
+
width: 100%;
|
|
621
|
+
border-collapse: collapse;
|
|
622
|
+
font: inherit;
|
|
623
|
+
}
|
|
624
|
+
.ol-help-table th,
|
|
625
|
+
.ol-help-table td {
|
|
626
|
+
padding: 4px 8px;
|
|
627
|
+
text-align: start;
|
|
628
|
+
vertical-align: top;
|
|
629
|
+
border-bottom: 1px solid var(--openleaf-color-border, #d1d9e0);
|
|
630
|
+
}
|
|
631
|
+
.ol-help-table th {
|
|
632
|
+
font-weight: 600;
|
|
633
|
+
white-space: nowrap;
|
|
634
|
+
}
|
|
635
|
+
|
|
420
636
|
/* Coarse pointers get a larger target. WCAG 2.2 SC 2.5.8 asks for 24x24 CSS px
|
|
421
637
|
minimum; 32 clears that on a mouse and 40 is comfortable on a thumb. */
|
|
422
638
|
@media (pointer: coarse) {
|
package/dist/styles.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH;;;;;;;GAOG;AACH,MAAM,WAAW,GAAG;;;;;;;;;CASnB,CAAA;AAED,MAAM,CAAC,MAAM,GAAG,GAAG
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"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"}
|
package/dist/toolbar.d.ts
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
* is blind-Tabbing through the rest of the host's form. `Alt+F10` enters,
|
|
29
29
|
* Escape leaves, matching TinyMCE and CKEditor 5 so muscle memory transfers.
|
|
30
30
|
*/
|
|
31
|
+
import { type FormatSpec } from '@openleaf-editor/core';
|
|
31
32
|
import type { EditorState, Transaction } from 'prosemirror-state';
|
|
32
33
|
import type { EditorView } from 'prosemirror-view';
|
|
33
34
|
export interface ToolbarOptions {
|
|
@@ -35,11 +36,30 @@ export interface ToolbarOptions {
|
|
|
35
36
|
label?: string;
|
|
36
37
|
/** Space-separated item ids, `|` for a separator. */
|
|
37
38
|
layout?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Collapse groups that do not fit into a More menu. Off by default: wrapping
|
|
41
|
+
* keeps every control visible, which is the safer accessibility default.
|
|
42
|
+
*/
|
|
43
|
+
overflow?: boolean;
|
|
44
|
+
/** Extra block formats, typically classes from the host's content CSS. */
|
|
45
|
+
formats?: readonly FormatSpec[];
|
|
46
|
+
/**
|
|
47
|
+
* Language for this toolbar's labels, independent of every other editor's.
|
|
48
|
+
* Absent means the document-wide locale.
|
|
49
|
+
*/
|
|
50
|
+
locale?: string | null;
|
|
38
51
|
}
|
|
39
52
|
export declare class Toolbar {
|
|
40
53
|
#private;
|
|
41
54
|
readonly el: HTMLDivElement;
|
|
42
55
|
constructor(host: HTMLElement, doc: Document, options?: ToolbarOptions);
|
|
56
|
+
/**
|
|
57
|
+
* Change this toolbar's language and rebuild its labels.
|
|
58
|
+
*
|
|
59
|
+
* Per toolbar rather than per document, so one editor switching language does
|
|
60
|
+
* not relabel every other editor on the page.
|
|
61
|
+
*/
|
|
62
|
+
setLocale(next: string | null): void;
|
|
43
63
|
/** Attach to a view and build the controls. */
|
|
44
64
|
mount(view: EditorView): void;
|
|
45
65
|
destroy(): void;
|
package/dist/toolbar.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbar.d.ts","sourceRoot":"","sources":["../src/toolbar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;
|
|
1
|
+
{"version":3,"file":"toolbar.d.ts","sourceRoot":"","sources":["../src/toolbar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EASL,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAalD,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;IAC/B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAuDD,qBAAa,OAAO;;IAClB,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;gBAsBf,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,GAAE,cAAmB;IAqC1E;;;;;OAKG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAOpC,+CAA+C;IAC/C,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAS7B,OAAO,IAAI,IAAI;IA+Bf,2DAA2D;IAC3D,IAAI,UAAU,IAAI,cAAc,CAE/B;IAkUD;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,WAAW,GAAG,IAAI;IAkFlD;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IA8F9E,iEAAiE;IACjE,YAAY,IAAI,IAAI;IAYpB,mEAAmE;IACnE,oBAAoB,IAAI,IAAI;CAG7B"}
|