@openleaf-editor/ui 0.1.0-beta.0 → 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.
Files changed (62) hide show
  1. package/dist/content-css.d.ts +13 -0
  2. package/dist/content-css.d.ts.map +1 -0
  3. package/dist/content-css.js +57 -0
  4. package/dist/content-css.js.map +1 -0
  5. package/dist/dialog.d.ts +87 -2
  6. package/dist/dialog.d.ts.map +1 -1
  7. package/dist/dialog.js +358 -68
  8. package/dist/dialog.js.map +1 -1
  9. package/dist/floating.d.ts +25 -0
  10. package/dist/floating.d.ts.map +1 -0
  11. package/dist/floating.js +82 -0
  12. package/dist/floating.js.map +1 -0
  13. package/dist/help.d.ts +9 -0
  14. package/dist/help.d.ts.map +1 -0
  15. package/dist/help.js +73 -0
  16. package/dist/help.js.map +1 -0
  17. package/dist/i18n.d.ts +31 -0
  18. package/dist/i18n.d.ts.map +1 -0
  19. package/dist/i18n.js +89 -0
  20. package/dist/i18n.js.map +1 -0
  21. package/dist/icons.d.ts +1 -1
  22. package/dist/icons.d.ts.map +1 -1
  23. package/dist/icons.js +17 -1
  24. package/dist/icons.js.map +1 -1
  25. package/dist/index.d.ts +10 -3
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +10 -3
  28. package/dist/index.js.map +1 -1
  29. package/dist/items.d.ts +2 -0
  30. package/dist/items.d.ts.map +1 -1
  31. package/dist/items.js +81 -4
  32. package/dist/items.js.map +1 -1
  33. package/dist/menu.d.ts +56 -0
  34. package/dist/menu.d.ts.map +1 -0
  35. package/dist/menu.js +360 -0
  36. package/dist/menu.js.map +1 -0
  37. package/dist/openleaf.css +216 -0
  38. package/dist/overflow.d.ts +17 -0
  39. package/dist/overflow.d.ts.map +1 -0
  40. package/dist/overflow.js +138 -0
  41. package/dist/overflow.js.map +1 -0
  42. package/dist/pickers.d.ts +43 -0
  43. package/dist/pickers.d.ts.map +1 -0
  44. package/dist/pickers.js +52 -0
  45. package/dist/pickers.js.map +1 -0
  46. package/dist/registry.d.ts +49 -8
  47. package/dist/registry.d.ts.map +1 -1
  48. package/dist/registry.js +14 -0
  49. package/dist/registry.js.map +1 -1
  50. package/dist/styles.d.ts +1 -1
  51. package/dist/styles.d.ts.map +1 -1
  52. package/dist/styles.js +216 -0
  53. package/dist/styles.js.map +1 -1
  54. package/dist/toolbar.d.ts +20 -0
  55. package/dist/toolbar.d.ts.map +1 -1
  56. package/dist/toolbar.js +181 -21
  57. package/dist/toolbar.js.map +1 -1
  58. package/dist/upload.d.ts +95 -0
  59. package/dist/upload.d.ts.map +1 -0
  60. package/dist/upload.js +104 -0
  61. package/dist/upload.js.map +1 -0
  62. package/package.json +2 -2
@@ -0,0 +1,17 @@
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
+ export declare class ToolbarOverflow {
11
+ #private;
12
+ constructor(toolbar: HTMLElement, host: HTMLElement, doc: Document);
13
+ reattach(): void;
14
+ destroy(): void;
15
+ layout(): void;
16
+ }
17
+ //# sourceMappingURL=overflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overflow.d.ts","sourceRoot":"","sources":["../src/overflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,qBAAa,eAAe;;gBAOd,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ;IAmClE,QAAQ,IAAI,IAAI;IAKhB,OAAO,IAAI,IAAI;IAQf,MAAM,IAAI,IAAI;CA6Ef"}
@@ -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"}
@@ -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"}
@@ -25,21 +25,44 @@ export interface ToolbarContext {
25
25
  /** The `<openleaf-editor>` element, for dispatching events or hosting dialogs. */
26
26
  host: HTMLElement;
27
27
  }
28
+ /**
29
+ * A control a `custom` item builds for itself.
30
+ *
31
+ * The contract is narrow on purpose. A custom item owns its own markup, so it
32
+ * can be a colour grid or a table-size picker, but it does not get to own the
33
+ * toolbar's keyboard model: the element it returns must contain exactly one
34
+ * focusable `button.ol-btn`, because that is what the roving tabindex walks. A
35
+ * control with two focusable buttons in the bar would make the toolbar two tab
36
+ * stops where the author expects one; a control with none would be unreachable
37
+ * by keyboard. Anything else the control needs -- a popover, a grid of swatches
38
+ * -- belongs outside the toolbar element, in the top layer or on the host.
39
+ */
40
+ export interface ToolbarControl {
41
+ /** The element placed in the toolbar. */
42
+ el: HTMLElement;
43
+ /**
44
+ * Reflect the editor state. Called on every transaction, so it must be cheap
45
+ * and must not throw; a throw is caught and logged once, like a predicate.
46
+ */
47
+ update?: (state: EditorState) => void;
48
+ /** Release listeners, and remove anything the control put in the document. */
49
+ destroy?: () => void;
50
+ }
28
51
  export interface ToolbarItemSpec {
29
52
  /** Stable id used in the `toolbar` layout attribute. */
30
53
  id: string;
31
54
  /**
32
55
  * What kind of control this is.
33
56
  *
34
- * Present from day one even though **only `button` is implemented** -- the
35
- * block-type control is special-cased by id, not by type. A flat spec models
36
- * a button and nothing else, and adding this discriminant *after* the config
37
- * shape is public is precisely the breaking change the registry exists to
38
- * avoid. Colour grids, table-insert popovers and link editors will all be
39
- * `custom`.
57
+ * `button` is the common case. `custom` hands the item a chance to build its
58
+ * own DOM through `render`, which is how the colour picker exists at all: a
59
+ * swatch grid is not a button, and modelling it as one would have meant
60
+ * special-casing it in the toolbar by id, the way the block-type `select`
61
+ * still is.
40
62
  *
41
- * Declaring an unimplemented variant logs a warning rather than failing
42
- * quietly as a button.
63
+ * `select` remains unimplemented, and the block-type control is special-cased
64
+ * by id rather than being one. Declaring it logs a warning rather than
65
+ * rendering a plausible-looking button that is not the control asked for.
43
66
  */
44
67
  type?: 'button' | 'select' | 'custom';
45
68
  /** Accessible name. Kept constant across states -- the platform announces pressed. */
@@ -54,6 +77,11 @@ export interface ToolbarItemSpec {
54
77
  command?: Command;
55
78
  /** For items needing more than the editor state -- dialogs, mode switches. */
56
79
  run?: (ctx: ToolbarContext) => void;
80
+ /**
81
+ * For `type: 'custom'`: build the control. Required for that type, ignored
82
+ * otherwise.
83
+ */
84
+ render?: (ctx: ToolbarContext) => ToolbarControl;
57
85
  isActive?: (state: EditorState) => boolean;
58
86
  /** Defaults to asking `command` whether it would apply. */
59
87
  isEnabled?: (state: EditorState) => boolean;
@@ -82,4 +110,17 @@ export declare function clearToolbarItems(): void;
82
110
  * so it is not hit by accident.
83
111
  */
84
112
  export declare const DEFAULT_LAYOUT: string;
113
+ /**
114
+ * The default layout with the colour controls in it.
115
+ *
116
+ * Not the default, and deliberately not: the colour picker ships in an opt-in
117
+ * bundle, and naming an item that is not registered logs a warning for every
118
+ * deployment that did not load it. An integrator who loads the colour bundle
119
+ * either uses this layout or names `textColour` and `highlightColour` in their own.
120
+ *
121
+ * The colour bundle does NOT rewrite the default layout on install. Installing a
122
+ * plugin must not silently rearrange somebody's toolbar -- that is the whole
123
+ * reason capability and layout are separate concerns here.
124
+ */
125
+ export declare const LAYOUT_WITH_COLOUR: string;
85
126
  //# sourceMappingURL=registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAA;IAChB,kFAAkF;IAClF,IAAI,EAAE,WAAW,CAAA;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAA;IACV;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;IACrC,sFAAsF;IACtF,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC1B,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,8EAA8E;IAC9E,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAA;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAA;IAC1C,2DAA2D;IAC3D,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAA;IAC3C,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAcD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAGjE;AAcD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAG/D;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEtE;AAED,wBAAgB,eAAe,IAAI,eAAe,EAAE,CAEnD;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,QAEgE,CAAA"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAA;IAChB,kFAAkF;IAClF,IAAI,EAAE,WAAW,CAAA;CAClB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,EAAE,EAAE,WAAW,CAAA;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAA;IACrC,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAA;IACV;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;IACrC,sFAAsF;IACtF,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC1B,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,8EAA8E;IAC9E,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAA;IACnC;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,cAAc,CAAA;IAChD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAA;IAC1C,2DAA2D;IAC3D,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAA;IAC3C,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAcD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAGjE;AAcD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAG/D;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEtE;AAED,wBAAgB,eAAe,IAAI,eAAe,EAAE,CAEnD;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,QAGgE,CAAA;AAE3F;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,QAG9B,CAAA"}
package/dist/registry.js CHANGED
@@ -73,5 +73,19 @@ export function clearToolbarItems() {
73
73
  * so it is not hit by accident.
74
74
  */
75
75
  export const DEFAULT_LAYOUT = 'undo redo | blockType | bold italic underline strikethrough code | ' +
76
+ 'alignLeft alignCenter alignRight alignJustify | ' +
76
77
  'bulletList orderedList blockquote codeBlock | link unlink image horizontalRule | source';
78
+ /**
79
+ * The default layout with the colour controls in it.
80
+ *
81
+ * Not the default, and deliberately not: the colour picker ships in an opt-in
82
+ * bundle, and naming an item that is not registered logs a warning for every
83
+ * deployment that did not load it. An integrator who loads the colour bundle
84
+ * either uses this layout or names `textColour` and `highlightColour` in their own.
85
+ *
86
+ * The colour bundle does NOT rewrite the default layout on install. Installing a
87
+ * plugin must not silently rearrange somebody's toolbar -- that is the whole
88
+ * reason capability and layout are separate concerns here.
89
+ */
90
+ export const LAYOUT_WITH_COLOUR = DEFAULT_LAYOUT.replace('alignLeft', 'textColour highlightColour | alignLeft');
77
91
  //# sourceMappingURL=registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAiDH,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAA;AAEnD;;;;;;;GAOG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAA;AAEvC,MAAM,UAAU,gBAAgB,CAAC,QAAoB;IACnD,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACvB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;AACzC,CAAC;AAED,SAAS,MAAM;IACb,4EAA4E;IAC5E,2EAA2E;IAC3E,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,QAAQ,EAAE,CAAA;QACZ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,oDAAoD,EAAE,KAAK,CAAC,CAAA;QAC5E,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAqB;IACvD,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;IAC3B,MAAM,EAAE,CAAA;AACV,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;AAC/B,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,iBAAiB;IAC/B,QAAQ,CAAC,KAAK,EAAE,CAAA;IAChB,MAAM,EAAE,CAAA;AACV,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,cAAc,GACzB,qEAAqE;IACrE,yFAAyF,CAAA"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AA8EH,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAA;AAEnD;;;;;;;GAOG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAA;AAEvC,MAAM,UAAU,gBAAgB,CAAC,QAAoB;IACnD,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACvB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;AACzC,CAAC;AAED,SAAS,MAAM;IACb,4EAA4E;IAC5E,2EAA2E;IAC3E,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,QAAQ,EAAE,CAAA;QACZ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,oDAAoD,EAAE,KAAK,CAAC,CAAA;QAC5E,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAqB;IACvD,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;IAC3B,MAAM,EAAE,CAAA;AACV,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;AAC/B,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,iBAAiB;IAC/B,QAAQ,CAAC,KAAK,EAAE,CAAA;IAChB,MAAM,EAAE,CAAA;AACV,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,cAAc,GACzB,qEAAqE;IACrE,kDAAkD;IAClD,yFAAyF,CAAA;AAE3F;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,CACtD,WAAW,EACX,wCAAwC,CACzC,CAAA"}
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.
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAqBH,eAAO,MAAM,GAAG,4xdAgZf,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"}
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"}